1186 lines
36 KiB
C
1186 lines
36 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$
|
|
**
|
|
** Utility routines for SST-1 Initialization code
|
|
**
|
|
*/
|
|
#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
|
|
#define FX_DLL_DEFINITION
|
|
#include <fxdll.h>
|
|
#include <sst1vid.h>
|
|
#include <sst1init.h>
|
|
|
|
#include "canopus.h"
|
|
|
|
/*
|
|
** sst1InitIdle():
|
|
** Return idle condition of SST-1
|
|
**
|
|
** Returns:
|
|
** FXTRUE if SST-1 is idle (fifos are empty, graphics engines are idle)
|
|
** FXFALSE if SST-1 has not been mapped
|
|
**
|
|
*/
|
|
FX_EXPORT FxBool FX_CSTYLE sst1InitIdle(FxU32 *sstbase)
|
|
{
|
|
if(!sstbase)
|
|
return(FXFALSE);
|
|
|
|
if(sst1InitCheckBoard(sstbase) == FXFALSE)
|
|
return(FXFALSE);
|
|
|
|
if(!initIdleEnabled)
|
|
return(FXTRUE);
|
|
|
|
if(sst1CurrentBoard->fbiLfbLocked) {
|
|
if(sst1CurrentBoard->sliSlaveVirtAddr == (FxU32 *) NULL)
|
|
// SLI not enabled...
|
|
sst1InitPciFifoIdleLoop(sstbase);
|
|
else {
|
|
// Check idle for Master...
|
|
sst1InitPciFifoIdleLoop(sstbase);
|
|
// Check idle for Slave...
|
|
sst1InitPciFifoIdleLoop(sst1CurrentBoard->sliSlaveVirtAddr);
|
|
}
|
|
} else {
|
|
if(sst1CurrentBoard->sliSlaveVirtAddr == (FxU32 *) NULL)
|
|
// SLI not enabled...
|
|
sst1InitIdleLoop(sstbase, FXTRUE);
|
|
else {
|
|
// Check idle for Master...
|
|
sst1InitIdleLoop(sstbase, FXTRUE);
|
|
|
|
// Check idle for Slave...
|
|
// Note that the Slave does not need another NOP command, because
|
|
// it will snoop the NOP command sent to the Master above.
|
|
// Sending a NOP command to the Slave also confuses the callback
|
|
// write routines for the command fifo which are not setup to
|
|
// handle any other base addresses other than the Master's...
|
|
sst1InitIdleLoop(sst1CurrentBoard->sliSlaveVirtAddr, FXFALSE);
|
|
}
|
|
}
|
|
return(FXTRUE);
|
|
}
|
|
|
|
static FxBool
|
|
sst1InitIdleWithTimeoutLoop(FxU32 *sstbase, FxBool issueNOP, FxU32 timeout)
|
|
{
|
|
FxU32 cntr, loop;
|
|
SstRegs *sst = (SstRegs *) sstbase;
|
|
|
|
if(issueNOP) ISET(sst->nopCMD, 0x0);
|
|
|
|
cntr = loop = 0;
|
|
while(++loop < timeout) {
|
|
if(!(sst1InitReturnStatus(sstbase) & SST_BUSY)) {
|
|
if(++cntr >= 3)
|
|
break;
|
|
} else
|
|
cntr = 0;
|
|
}
|
|
|
|
return (loop < timeout);
|
|
}
|
|
|
|
FxBool
|
|
sst1InitIdleFBIWithTimeout(FxU32 *sstbase, FxBool issueNop, FxU32 timeout)
|
|
{
|
|
int retVal;
|
|
|
|
if(!sstbase)
|
|
return(FXFALSE);
|
|
|
|
if(!sst1InitCheckBoard(sstbase))
|
|
return(FXFALSE);
|
|
|
|
if(sst1CurrentBoard->sliSlaveVirtAddr == (FxU32 *) NULL) {
|
|
// SLI not enabled...
|
|
retVal = sst1InitIdleWithTimeoutLoop(sstbase, issueNop, timeout);
|
|
} else {
|
|
// Check idle for Master...
|
|
if(!sst1InitIdleWithTimeoutLoop(sstbase, issueNop, timeout))
|
|
return(FXFALSE);
|
|
|
|
// Check idle for Slave...
|
|
// Note that the Slave does not need another NOP command, because
|
|
// it will snoop the NOP command sent to the Master above.
|
|
// Sending a NOP command to the Slave also confuses the callback
|
|
// write routines for the command fifo which are not setup to
|
|
// handle any other base addresses other than the Master's...
|
|
retVal = sst1InitIdleWithTimeoutLoop(sst1CurrentBoard->sliSlaveVirtAddr,
|
|
FXFALSE,
|
|
timeout);
|
|
}
|
|
|
|
return retVal;
|
|
}
|
|
|
|
FX_EXPORT FxBool FX_CSTYLE sst1InitIdleNoNOP(FxU32 *sstbase)
|
|
{
|
|
if(!sstbase)
|
|
return(FXFALSE);
|
|
|
|
if(sst1InitCheckBoard(sstbase) == FXFALSE)
|
|
return(FXFALSE);
|
|
|
|
if(!initIdleEnabled)
|
|
return(FXTRUE);
|
|
|
|
if(sst1CurrentBoard->fbiLfbLocked) {
|
|
if(sst1CurrentBoard->sliSlaveVirtAddr == (FxU32 *) NULL)
|
|
// SLI not enabled...
|
|
sst1InitPciFifoIdleLoop(sstbase);
|
|
else {
|
|
// Check idle for Master...
|
|
sst1InitPciFifoIdleLoop(sstbase);
|
|
// Check idle for Slave...
|
|
sst1InitPciFifoIdleLoop(sst1CurrentBoard->sliSlaveVirtAddr);
|
|
}
|
|
} else {
|
|
if(sst1CurrentBoard->sliSlaveVirtAddr == (FxU32 *) NULL)
|
|
// SLI not enabled...
|
|
sst1InitIdleLoop(sstbase, FXFALSE);
|
|
else {
|
|
// Check idle for Master...
|
|
sst1InitIdleLoop(sstbase, FXFALSE);
|
|
// Check idle for Slave...
|
|
sst1InitIdleLoop(sst1CurrentBoard->sliSlaveVirtAddr, FXFALSE);
|
|
}
|
|
}
|
|
return(FXTRUE);
|
|
}
|
|
|
|
void sst1InitIdleLoop(FxU32 *sstbase, FxBool issueNOP)
|
|
{
|
|
FxU32 cntr;
|
|
SstRegs *sst = (SstRegs *) sstbase;
|
|
|
|
if(issueNOP)
|
|
ISET(sst->nopCMD, 0x0);
|
|
|
|
cntr = 0;
|
|
while(1) {
|
|
if(!(sst1InitReturnStatus(sstbase) & SST_BUSY)) {
|
|
if(++cntr >= 3)
|
|
break;
|
|
} else
|
|
cntr = 0;
|
|
}
|
|
}
|
|
|
|
void sst1InitPciFifoIdleLoop(FxU32 *sstbase)
|
|
{
|
|
FxU32 cntr;
|
|
|
|
cntr = 0;
|
|
while(1) {
|
|
if(((sst1InitReturnStatus(sstbase) & SST_FIFOLEVEL)) == 0x3f) {
|
|
// Since sst1InitPciFifoIdleLoop is only called when we're trying
|
|
// to "fake" idle during lfb locks, wait for 6 passes to give the
|
|
// hardware time to drain
|
|
if(++cntr >= 6)
|
|
break;
|
|
} else
|
|
cntr = 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** sst1InitIdleFBI():
|
|
** Return idle condition of FBI (ignoring idle status of TMU)
|
|
**
|
|
** Returns:
|
|
** FXTRUE if FBI is idle (fifos are empty, graphics engines are idle)
|
|
** FXFALSE if FBI has not been mapped
|
|
**
|
|
*/
|
|
FX_EXPORT FxBool FX_CSTYLE sst1InitIdleFBI(FxU32 *sstbase)
|
|
{
|
|
FxU32 cntr;
|
|
SstRegs *sst = (SstRegs *) sstbase;
|
|
|
|
if(!sst)
|
|
return(FXFALSE);
|
|
|
|
ISET(sst->nopCMD, 0x0);
|
|
cntr = 0;
|
|
while(1) {
|
|
if(!(sst1InitReturnStatus(sstbase) & SST_FBI_BUSY)) {
|
|
if(++cntr >= 3)
|
|
break;
|
|
} else
|
|
cntr = 0;
|
|
}
|
|
return(FXTRUE);
|
|
}
|
|
|
|
/*
|
|
** sst1InitIdleFBINoNOP():
|
|
** Return idle condition of FBI (ignoring idle status of TMU)
|
|
** sst1InitIdleFBINoNOP() differs from sst1InitIdleFBI() in that no NOP command
|
|
** is issued to flush the graphics pipeline.
|
|
**
|
|
** Returns:
|
|
** FXTRUE if FBI is idle (fifos are empty, graphics engines are idle)
|
|
** FXFALSE if FBI has not been mapped
|
|
**
|
|
*/
|
|
FX_EXPORT FxBool FX_CSTYLE sst1InitIdleFBINoNOP(FxU32 *sstbase)
|
|
{
|
|
FxU32 cntr;
|
|
SstRegs *sst = (SstRegs *) sstbase;
|
|
|
|
if(!sst)
|
|
return(FXFALSE);
|
|
|
|
// ISET(sst->nopCMD, 0x0);
|
|
cntr = 0;
|
|
while(1) {
|
|
if(!(sst1InitReturnStatus(sstbase) & SST_FBI_BUSY)) {
|
|
if(++cntr > 5)
|
|
break;
|
|
} else
|
|
cntr = 0;
|
|
}
|
|
return(FXTRUE);
|
|
}
|
|
|
|
// Included so compiler doesn't optimize out loop code waiting on status bits
|
|
FX_EXPORT FxU32 FX_CSTYLE sst1InitReturnStatus(FxU32 *sstbase)
|
|
{
|
|
SstRegs *sst = (SstRegs *) sstbase;
|
|
|
|
return(IGET(sst->status));
|
|
}
|
|
|
|
|
|
/*
|
|
** sst1InitClearSwapPending():
|
|
** Clear any swaps pending in the status register
|
|
** NOTE: The video unit of FBI must be initialized before calling this routine
|
|
**
|
|
** Returns:
|
|
** FXTRUE
|
|
**
|
|
*/
|
|
FX_ENTRY FxBool FX_CALL sst1InitClearSwapPending(FxU32 *sstbase)
|
|
{
|
|
SstRegs *sst = (SstRegs *) sstbase;
|
|
FxU32 displayedBuffer, i;
|
|
|
|
INIT_PRINTF(("sst1InitClearSwapPending() WARNING: Clearing pending swapbufferCMDs...\n"));
|
|
|
|
sst1InitIdle(sstbase);
|
|
displayedBuffer =
|
|
(IGET(sst->status) & SST_DISPLAYED_BUFFER) >>
|
|
SST_DISPLAYED_BUFFER_SHIFT;
|
|
|
|
// Wait until vsync is inactive to guarantee that swaps queue in the
|
|
// PCI fifo properly
|
|
while(!(IGET(sst->status) & SST_VRETRACE) ||
|
|
((IGET(sst->vRetrace) & 0xfff) > 100) || ((IGET(sst->vRetrace) & 0xfff)
|
|
< 10))
|
|
;
|
|
|
|
// First swap syncs to Vsync...Subsequent ones do not...
|
|
ISET(sst->swapbufferCMD, 0x1);
|
|
ISET(sst->nopCMD, 0x0);
|
|
for(i=0; i<17; i++) {
|
|
ISET(sst->swapbufferCMD, 0x0);
|
|
ISET(sst->nopCMD, 0x0);
|
|
}
|
|
if(displayedBuffer) {
|
|
ISET(sst->swapbufferCMD, 0x0);
|
|
ISET(sst->nopCMD, 0x0);
|
|
}
|
|
sst1InitIdle(sstbase);
|
|
|
|
return(FXTRUE);
|
|
}
|
|
|
|
/*
|
|
** sst1InitVgaPassCtrl():
|
|
** Control VGA passthrough setting
|
|
**
|
|
**
|
|
*/
|
|
FX_EXPORT FxBool FX_CSTYLE sst1InitVgaPassCtrl(FxU32 *sstbase, FxU32 enable)
|
|
{
|
|
SstRegs *sst = (SstRegs *) sstbase;
|
|
|
|
if(sst1InitCheckBoard(sstbase) == FXFALSE)
|
|
return(FXFALSE);
|
|
|
|
//if (sst1CurrentBoard->singleBrdSLISlave) {
|
|
// enable = 1;
|
|
//}
|
|
|
|
if(enable) {
|
|
// VGA controls monitor
|
|
ISET(sst->fbiInit0, (IGET(sst->fbiInit0) & ~SST_EN_VGA_PASSTHRU) |
|
|
sst1CurrentBoard->vgaPassthruEnable);
|
|
ISET(sst->fbiInit1, IGET(sst->fbiInit1) | SST_VIDEO_BLANK_EN);
|
|
} else {
|
|
// SST-1 controls monitor
|
|
ISET(sst->fbiInit0, (IGET(sst->fbiInit0) & ~SST_EN_VGA_PASSTHRU) |
|
|
sst1CurrentBoard->vgaPassthruDisable);
|
|
ISET(sst->fbiInit1, IGET(sst->fbiInit1) & ~SST_VIDEO_BLANK_EN);
|
|
}
|
|
|
|
return(FXTRUE);
|
|
}
|
|
|
|
/*
|
|
** sst1InitResetTmus():
|
|
** Reset TMUs
|
|
**
|
|
*/
|
|
FX_EXPORT FxBool FX_CSTYLE sst1InitResetTmus(FxU32 *sstbase)
|
|
{
|
|
volatile int delay;
|
|
SstRegs *sst = (SstRegs *) sstbase;
|
|
FxU32 allowTexturing = (GETENV(("SSTV2_TEXMAP_DISABLE"))) ? 0 : 1;
|
|
|
|
if(!sst)
|
|
return(FXFALSE);
|
|
|
|
if(sst1InitCheckBoard(sstbase) == FXFALSE)
|
|
return(FXFALSE);
|
|
|
|
// Ignore stalls on FT Bus
|
|
ISET(sst->fbiInit3, IGET(sst->fbiInit3) | SST_TEXMAP_DISABLE);
|
|
// Delay
|
|
for(delay=0;delay<10000;)
|
|
delay++;
|
|
|
|
// while(++cntr < 6) {
|
|
|
|
INIT_PRINTF(("sst1InitResetTmus(): Reset Graphics "));
|
|
|
|
do
|
|
{
|
|
INIT_PRINTF(("."));
|
|
|
|
// Set Default initialization values for all TMUs...
|
|
ISET(SST_TREX(sst,0)->trexInit0, sst1CurrentBoard->tmuInit0[0]);
|
|
ISET(SST_TREX(sst,1)->trexInit0, sst1CurrentBoard->tmuInit0[1]);
|
|
// Delay
|
|
for(delay=0;delay<10000;)
|
|
delay++;
|
|
|
|
ISET(SST_TREX(sst,0)->trexInit1, sst1CurrentBoard->tmuInit1[0]);
|
|
ISET(SST_TREX(sst,1)->trexInit1, sst1CurrentBoard->tmuInit1[1]);
|
|
// Delay
|
|
for(delay=0;delay<10000;)
|
|
delay++;
|
|
|
|
// Reset TMU FIFOs and graphics core for all TMUs...
|
|
ISET(SST_TREX(sst,0)->trexInit1, sst1CurrentBoard->tmuInit1[0] | SST_TEX_RESET_FIFO | SST_TEX_RESET_GRX);
|
|
ISET(SST_TREX(sst,1)->trexInit1, sst1CurrentBoard->tmuInit1[1] | SST_TEX_RESET_FIFO | SST_TEX_RESET_GRX);
|
|
// Delay
|
|
for(delay=0;delay<10000;)
|
|
delay++;
|
|
|
|
ISET(SST_TREX(sst,1)->trexInit1, sst1CurrentBoard->tmuInit1[1]);
|
|
|
|
// Allow unreset to propagate backwards...
|
|
// Delay
|
|
for(delay=0;delay<10000;)
|
|
delay++;
|
|
|
|
ISET(SST_TREX(sst,0)->trexInit1, sst1CurrentBoard->tmuInit1[0]);
|
|
// Delay
|
|
for(delay=0;delay<10000;)
|
|
delay++;
|
|
|
|
// Reset in the downstream TMU may cause glitches in FBI's TF FIFO
|
|
// Waiting for Idle in FBI will not stall on something in the TF FIFO,
|
|
// as the TF FIFO empty signal is not part of FBI's "busy" bit
|
|
// sst1InitIdleFBIWithTimeout(sstbase, FXTRUE, 100000);
|
|
sst1InitResetFbi(sstbase);
|
|
/*
|
|
fbiInit0 = IGET(sst->fbiInit0) | SST_GRX_RESET | SST_PCI_FIFO_RESET;
|
|
|
|
ISET(sst->fbiInit0, fbiInit0);
|
|
// Delay
|
|
for(delay=0;delay<10000;)
|
|
delay++;
|
|
|
|
fbiInit0 &= ~SST_PCI_FIFO_RESET;
|
|
ISET(sst->fbiInit0, fbiInit0);
|
|
// Delay
|
|
for(delay=0;delay<10000;)
|
|
delay++;
|
|
|
|
fbiInit0 &= ~SST_GRX_RESET;
|
|
ISET(sst->fbiInit0, fbiInit0);
|
|
// Delay
|
|
for(delay=0;delay<10000;)
|
|
delay++;
|
|
*/
|
|
|
|
if(allowTexturing)
|
|
{
|
|
ISET(sst->fbiInit3, IGET(sst->fbiInit3) & ~SST_TEXMAP_DISABLE);
|
|
for(delay=0;delay<10000;)
|
|
delay++;
|
|
}
|
|
|
|
delay = 0;
|
|
|
|
while( sst1InitReturnStatus(sstbase) & (SST_TMU_BUSY | SST_FBI_BUSY) && (delay < 50000) )
|
|
delay++;
|
|
|
|
}while( delay == 50000 );
|
|
|
|
INIT_PRINTF(("\n"));
|
|
|
|
// INIT_PRINTF(("sst1InitResetTmus(): Could not reset graphics (0x%08lx)\n", ret));
|
|
// else
|
|
// break;
|
|
// }
|
|
// if(cntr == 6) {
|
|
// INIT_PRINTF(("sst1InitResetTmus(): Could not reset TMUs...\n"));
|
|
// return(FXFALSE);
|
|
// }
|
|
|
|
// Fix problem where first Texture downloads to TMU weren't being
|
|
// received properly
|
|
ISET(*(long *) (0xf00000 + (long) sstbase), 0xdeadbeef);
|
|
sst1InitIdle(sstbase);
|
|
|
|
return(FXTRUE);
|
|
}
|
|
|
|
/*
|
|
** sst1InitResetFbi():
|
|
** Reset FBI graphics engine and frontend PCI Fifo...
|
|
**
|
|
*/
|
|
FX_EXPORT FxBool FX_CSTYLE sst1InitResetFbi(FxU32 *sstbase)
|
|
{
|
|
volatile int delay;
|
|
// int i;
|
|
FxU32 fbiInit0;
|
|
SstRegs *sst = (SstRegs *) sstbase;
|
|
/*
|
|
for(i=0;i<20000;i++) sst1InitReturnStatus(sstbase);
|
|
ISET(sst->fbiInit0, IGET(sst->fbiInit0) | SST_GRX_RESET | SST_PCI_FIFO_RESET);
|
|
for(i=0;i<20000;i++) sst1InitReturnStatus(sstbase);
|
|
ISET(sst->fbiInit0, IGET(sst->fbiInit0) & ~SST_PCI_FIFO_RESET);
|
|
for(i=0;i<20000;i++) sst1InitReturnStatus(sstbase);
|
|
ISET(sst->fbiInit0, IGET(sst->fbiInit0) & ~SST_GRX_RESET);
|
|
for(i=0;i<20000;i++) sst1InitReturnStatus(sstbase);
|
|
*/
|
|
fbiInit0 = IGET(sst->fbiInit0) | SST_GRX_RESET | SST_PCI_FIFO_RESET;
|
|
|
|
ISET(sst->fbiInit0, fbiInit0);
|
|
// Delay
|
|
for(delay=0;delay<10000;)
|
|
delay++;
|
|
|
|
fbiInit0 &= ~SST_PCI_FIFO_RESET;
|
|
ISET(sst->fbiInit0, fbiInit0);
|
|
// Delay
|
|
for(delay=0;delay<10000;)
|
|
delay++;
|
|
|
|
fbiInit0 &= ~SST_GRX_RESET;
|
|
ISET(sst->fbiInit0, fbiInit0);
|
|
// Delay
|
|
for(delay=0;delay<10000;)
|
|
delay++;
|
|
|
|
return(FXTRUE);
|
|
}
|
|
|
|
#if SET_BSWAP
|
|
#if __POWERPC__ && defined(__MWERKS__)
|
|
#define GET(s) __lwbrx(s, 0 )
|
|
#define SET(d, s) __stwbrx((s), (d), 0);
|
|
#else /* !__MWERKS__ */
|
|
#error "Define byte swapped macros for GET/SET"
|
|
#endif /* !__MWERKS__ */
|
|
#else /* !SET_BSWAP */
|
|
#ifdef GET
|
|
#undef GET
|
|
#endif
|
|
#ifdef SET
|
|
#undef SET
|
|
#endif
|
|
#define GET(s) (*s)
|
|
#define SET(d, s) ((*d) = s)
|
|
#endif /* !SET_BSWAP */
|
|
|
|
/*
|
|
** sst1InitWrite32():
|
|
** Write 32-bit Word to specified address
|
|
**
|
|
*/
|
|
FX_EXPORT void FX_CSTYLE sst1InitWrite32(FxU32 *addr, FxU32 data)
|
|
{
|
|
/* If the client software is using the command fifo then they are
|
|
* responsible for passing a callback that can be used to put
|
|
* register writes from the init code into the command fifo that
|
|
* they are managing. However, some registers cannot be accessed via
|
|
* the command fifo, and, inconveniently, these are not contiguously
|
|
* allocated.
|
|
*/
|
|
const FxU32 addrOffset = ((const FxU32)addr - (const FxU32)sst1CurrentBoard->virtAddr[0]);
|
|
FxBool directWriteP = ((sst1CurrentBoard == NULL) ||
|
|
(sst1CurrentBoard->set32 == NULL) ||
|
|
sst1CurrentBoard->fbiLfbLocked ||
|
|
(addrOffset == 0x004) || /* intrCtrl */
|
|
((addrOffset >= 0x1E0) && (addrOffset <= 0x200)) || /* cmdFifoBase ... fbiInit4 */
|
|
((addrOffset >= 0x208) && (addrOffset <= 0x224)) || /* backPorch ... vSync */
|
|
((addrOffset >= 0x22C) && (addrOffset <= 0x23C)) || /* dacData ... borderColor */
|
|
((addrOffset >= 0x244) && (addrOffset <= 0x24C))); /* fbiInit5 ... fbiInit7 */
|
|
|
|
if (directWriteP) {
|
|
P6FENCE;
|
|
SET(addr, data);
|
|
P6FENCE;
|
|
} else {
|
|
(*sst1CurrentBoard->set32)(addr, data);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** sst1InitRead32():
|
|
** Read 32-bit Word from specified address
|
|
**
|
|
*/
|
|
FX_EXPORT FxU32 FX_CSTYLE sst1InitRead32(FxU32 *addr)
|
|
{
|
|
P6FENCE;
|
|
return GET(addr);
|
|
}
|
|
|
|
/*
|
|
**
|
|
** sst1InitCmdFifo():
|
|
|
|
** Setup Command Fifo.
|
|
**
|
|
** The 'enable' parameter either enables or disables the Command Fifo.
|
|
**
|
|
** Upon return, the 'virtAddrStart' parameter is filled with the starting
|
|
** virtual address where command fifo packets should be stored. The
|
|
** 'memAddrStart' parameter is filled with the address of where the command
|
|
** fifo is stored in frame buffer memory. The 'memAddrStart' value is often
|
|
** used by the JMP command to jump to the beginning of the command fifo.
|
|
** The 'size' parameter is filled with the size of the command fifo.
|
|
** The values of 'virtAddrstart', 'memAddrStart' and 'size'
|
|
** are dependent on the amount of frame buffer memory detected as well as the
|
|
** video resolution setup by sst1InitVideo(). 'virtAddrstart',
|
|
** 'memAddrStart' and 'size' are all specified in bytes.
|
|
**
|
|
*/
|
|
FX_ENTRY FxBool FX_CALL sst1InitCmdFifo(FxU32 *sstbase, FxBool enable,
|
|
FxU32 *virtAddrStart, FxU32 *memAddrStart, FxU32 *size, FxSet32Proc set32Proc)
|
|
{
|
|
SstRegs *sst = (SstRegs *) sstbase;
|
|
FxU32 fbiInit, fifoStart, fifoSize;
|
|
FxBool directExec = (GETENV(("SSTV2_CMDFIFO_DIRECT"))) ? FXTRUE : FXFALSE;
|
|
FxBool disableHoles = (GETENV(("SSTV2_CMDFIFO_NOHOLES"))) ? FXTRUE : FXFALSE;
|
|
|
|
if(!sst)
|
|
return(FXFALSE);
|
|
|
|
if(sst1InitCheckBoard(sstbase) == FXFALSE)
|
|
return(FXFALSE);
|
|
|
|
if(sst1CurrentBoard->fbiCmdFifoEn || (IGET(sst->fbiInit7) & SST_EN_CMDFIFO))
|
|
sst1InitIdleNoNOP(sstbase);
|
|
else
|
|
sst1InitIdle(sstbase);
|
|
|
|
if(enable == FXFALSE) {
|
|
// Remove any client set callbacks before continuing since
|
|
// these must go straight to the hw.
|
|
sst1CurrentBoard->set32 = NULL;
|
|
sst1CurrentBoard->fbiCmdFifoEn = 0;
|
|
|
|
// Disable Command Fifo
|
|
INIT_PRINTF(("sst1InitCmdFifo(): Disabling Command Fifo...\n"));
|
|
ISET(sst->fbiInit7, IGET(sst->fbiInit7) & ~SST_EN_CMDFIFO);
|
|
|
|
// Reset graphics core to force disable to take effect...
|
|
ISET(sst->fbiInit0, IGET(sst->fbiInit0) | SST_GRX_RESET |
|
|
SST_EN_LFB_MEMFIFO | SST_EN_TEX_MEMFIFO);
|
|
sst1InitReturnStatus(sstbase);
|
|
sst1InitReturnStatus(sstbase);
|
|
sst1InitReturnStatus(sstbase);
|
|
ISET(sst->fbiInit0, IGET(sst->fbiInit0) & ~SST_GRX_RESET);
|
|
|
|
if(sst1CurrentBoard->sliSlaveVirtAddr) {
|
|
SstRegs *slaveSst = (SstRegs *) sst1CurrentBoard->sliSlaveVirtAddr;
|
|
|
|
ISET(slaveSst->fbiInit7, IGET(slaveSst->fbiInit7) & ~SST_EN_CMDFIFO);
|
|
// Reset graphics core to force disable to take effect...
|
|
ISET(slaveSst->fbiInit0, IGET(slaveSst->fbiInit0) | SST_GRX_RESET |
|
|
SST_EN_LFB_MEMFIFO | SST_EN_TEX_MEMFIFO);
|
|
sst1InitReturnStatus(sst1CurrentBoard->sliSlaveVirtAddr);
|
|
sst1InitReturnStatus(sst1CurrentBoard->sliSlaveVirtAddr);
|
|
sst1InitReturnStatus(sst1CurrentBoard->sliSlaveVirtAddr);
|
|
ISET(slaveSst->fbiInit0, IGET(slaveSst->fbiInit0) & ~SST_GRX_RESET);
|
|
|
|
if(sst1InitCheckBoard(sst1CurrentBoard->sliSlaveVirtAddr) == FXFALSE)
|
|
return(FXFALSE);
|
|
sst1CurrentBoard->set32 = NULL;
|
|
sst1CurrentBoard->fbiCmdFifoEn = 0;
|
|
}
|
|
return(FXTRUE);
|
|
}
|
|
|
|
sst1InitIdle(sstbase);
|
|
fbiInit = IGET(sst->fbiInit4);
|
|
fifoStart =
|
|
(fbiInit & SST_MEM_FIFO_ROW_BASE) >> SST_MEM_FIFO_ROW_BASE_SHIFT;
|
|
fifoStart <<= 12; // Convert page-address into byte-address
|
|
|
|
if(sst1CurrentBoard->fbiMemSize == 4)
|
|
fifoSize = (1024 - (fifoStart >> 12)) << 12;
|
|
else if(sst1CurrentBoard->fbiMemSize == 2)
|
|
fifoSize = (512 - (fifoStart >> 12)) << 12;
|
|
else
|
|
fifoSize = (256 - (fifoStart >> 12)) << 12;
|
|
if(fifoSize > (256<<10))
|
|
fifoSize = (256<<10);
|
|
|
|
*virtAddrStart = (FxU32) (((FxU32) sstbase) + SST_CMDFIFO_ADDR);
|
|
*memAddrStart = fifoStart;
|
|
*size = fifoSize;
|
|
|
|
if(!sst1InitCmdFifoDirect(sstbase, 0,
|
|
fifoStart, fifoSize,
|
|
directExec, disableHoles,
|
|
set32Proc)) {
|
|
INIT_PRINTF(("sst1InitCmdFifo(): sst1InitCmdFifoDirect() failed...\n"));
|
|
return(FXFALSE);
|
|
}
|
|
|
|
if(sst1CurrentBoard->sliSlaveVirtAddr) {
|
|
if(!sst1InitCmdFifoDirect(sst1CurrentBoard->sliSlaveVirtAddr, 0,
|
|
fifoStart, fifoSize,
|
|
directExec, disableHoles,
|
|
set32Proc)) {
|
|
INIT_PRINTF(("sst1InitCmdFifo(): sst1InitCmdFifoDirect() failed for SLI Slave...\n"));
|
|
return(FXFALSE);
|
|
}
|
|
}
|
|
|
|
INIT_PRINTF(("sst1InitCmdFifo() exiting with status %d...\n", FXTRUE));
|
|
return(FXTRUE);
|
|
}
|
|
|
|
/*
|
|
**
|
|
** sst1InitCmdFifoDirect():
|
|
** Explicitly initialize Command FIFO. This routine is typically not
|
|
** called directly from apps, but is included so that csim diags can
|
|
** call it directly.
|
|
**
|
|
** The 'start' and 'size' parameters are specified in bytes.
|
|
** The 'which' parameter is not used, but is included for H3 compatibility.
|
|
**
|
|
*/
|
|
FX_ENTRY FxBool FX_CALL sst1InitCmdFifoDirect(FxU32 *sstbase, FxU32 which,
|
|
FxU32 start, FxU32 size, FxBool directExec, FxBool disableHoles,
|
|
FxSet32Proc set32Proc)
|
|
{
|
|
SstRegs *sst = (SstRegs *) sstbase;
|
|
FxU32 fbiInit7, initEnable, n;
|
|
FxU32 pageStart = start >> 12;
|
|
FxU32 pageEnd = (start+size-1) >> 12;
|
|
|
|
if(!sst)
|
|
return(FXFALSE);
|
|
|
|
if(sst1InitCheckBoard(sstbase) == FXFALSE)
|
|
return(FXFALSE);
|
|
|
|
// sst1Initidle() routines must be properly executed...
|
|
initIdleEnabled = 1;
|
|
|
|
INIT_PRINTF(("sst1InitCmdFifoDirect(): Start:0x%x bytes, Size:%d(0x%x) bytes\n",
|
|
start, size, size));
|
|
INIT_PRINTF(("sst1InitCmdFifoDirect(): DirectExec:%d, DisableHoles:%d\n",
|
|
directExec, disableHoles));
|
|
INIT_PRINTF(("sst1InitCmdFifoDirect(): pageStart:%d, pageEnd:%d\n",
|
|
pageStart, pageEnd));
|
|
INIT_PRINTF(("sst1InitCmdFifoDirect(): set32Proc: 0x%X\n",
|
|
(FxU32)set32Proc));
|
|
|
|
if(sst1CurrentBoard->fbiCmdFifoEn || (IGET(sst->fbiInit7) & SST_EN_CMDFIFO))
|
|
sst1InitIdleNoNOP(sstbase);
|
|
else
|
|
sst1InitIdle(sstbase);
|
|
// Disable memory-backed fifo, and disallow lfb and texture writes
|
|
// through command fifo...
|
|
ISET(sst->fbiInit0, (IGET(sst->fbiInit0) &
|
|
~(SST_MEM_FIFO_EN | SST_EN_LFB_MEMFIFO | SST_EN_TEX_MEMFIFO)));
|
|
sst1InitReturnStatus(sstbase);
|
|
|
|
fbiInit7 = IGET(sst->fbiInit7);
|
|
fbiInit7 &= ~(SST_EN_CMDFIFO |
|
|
SST_EN_CMDFIFO_OFFSCREEN | SST_CMDFIFO_DISABLE_HOLES |
|
|
SST_CMDFIFO_REGS_SYNC_WRITES | SST_CMDFIFO_REGS_SYNC_READS |
|
|
SST_CMDFIFO_RDFETCH_THRESH | SST_CMDFIFO_PCI_TIMEOUT);
|
|
fbiInit7 |= SST_CMDFIFO_REGS_SYNC_WRITES | SST_CMDFIFO_REGS_SYNC_READS |
|
|
(0x10<<SST_CMDFIFO_RDFETCH_THRESH_SHIFT) |
|
|
(127<<SST_CMDFIFO_PCI_TIMEOUT_SHIFT);
|
|
ISET(sst->fbiInit7, fbiInit7); // turn off the command fifo
|
|
sst1InitReturnStatus(sstbase);
|
|
|
|
// Disable all writes to the PCI fifo while we're setting up CMDFIFO
|
|
PCICFG_RD(SST1_PCI_INIT_ENABLE, initEnable);
|
|
PCICFG_WR(SST1_PCI_INIT_ENABLE,
|
|
((initEnable & ~(SST_INITWR_EN | SST_PCI_FIFOWR_EN)) | SST_INITWR_EN));
|
|
|
|
// Setup command fifo...
|
|
ISET(sst->cmdFifoBase, (pageEnd << SST_CMDFIFO_END_SHIFT) | pageStart);
|
|
sst1InitReturnStatus(sstbase); // prevent PCI bursts...
|
|
ISET(sst->cmdFifoReadPtr, start);
|
|
sst1InitReturnStatus(sstbase);
|
|
ISET(sst->cmdFifoAmin, start-4);
|
|
sst1InitReturnStatus(sstbase);
|
|
ISET(sst->cmdFifoAmax, start-4);
|
|
sst1InitReturnStatus(sstbase);
|
|
ISET(sst->cmdFifoDepth, 0);
|
|
sst1InitReturnStatus(sstbase);
|
|
ISET(sst->cmdFifoHoles, 0);
|
|
sst1InitReturnStatus(sstbase);
|
|
sst1InitIdle(sstbase);
|
|
|
|
// Turn on command fifo...
|
|
ISET(sst->fbiInit7, fbiInit7 | SST_EN_CMDFIFO |
|
|
(directExec ? 0 : SST_EN_CMDFIFO_OFFSCREEN) |
|
|
(disableHoles ? SST_CMDFIFO_DISABLE_HOLES : 0));
|
|
// Can't perform sst1InitIdle() here because it will generate
|
|
// writes to the CMDFIFO since the CMDFIFO is now enabled...
|
|
sst1InitReturnStatus(sstbase);
|
|
|
|
// Enable writes to be pushed onto the CMDFIFO...
|
|
PCICFG_WR(SST1_PCI_INIT_ENABLE,
|
|
(initEnable | SST_INITWR_EN | SST_PCI_FIFOWR_EN));
|
|
|
|
sst1CurrentBoard->fbiCmdFifoEn = 1;
|
|
if(GETENV(("SSTV2_IGNORE_IDLE")))
|
|
initIdleEnabled = 0;
|
|
|
|
/* Set the client callbacks, if necessary. */
|
|
sst1CurrentBoard->set32 = set32Proc;
|
|
|
|
return(FXTRUE);
|
|
}
|
|
|
|
/*
|
|
**
|
|
** sst1InitLfbLock():
|
|
** Used to workaround a hw bug when performing lfb and texture writes when
|
|
** the command fifo is enabled. The routines sst1InitLfbLock() and
|
|
** sst1InitLfbUnlock() dynamically disable the command fifo so that lfb
|
|
** and texture accesses do not pass through the command fifo.
|
|
** WARNING: No register writes of any kind may be performed between a
|
|
** sst1InitLfbLock() and sst1InitLfbUnlock() pair -- only lfb reads and
|
|
** writes are allowed.
|
|
*/
|
|
FX_ENTRY FxBool FX_CALL sst1InitLfbLock(FxU32* sstbase)
|
|
{
|
|
if(!sstbase)
|
|
return(FXFALSE);
|
|
|
|
if(sst1InitCheckBoard(sstbase) == FXFALSE)
|
|
return(FXFALSE);
|
|
|
|
// Idle the hardware...
|
|
sst1InitIdle(sstbase);
|
|
|
|
if(sst1InitLfbLockDirect(sstbase) == FXFALSE)
|
|
return(FXFALSE);
|
|
|
|
if(sst1CurrentBoard->sliSlaveVirtAddr) {
|
|
// SLI Enabled
|
|
if(sst1InitLfbLockDirect(sst1CurrentBoard->sliSlaveVirtAddr) == FXFALSE)
|
|
return(FXFALSE);
|
|
}
|
|
|
|
return(FXTRUE);
|
|
}
|
|
|
|
FX_ENTRY FxBool FX_CALL sst1InitLfbLockDirect(FxU32* sstbase)
|
|
{
|
|
SstRegs *sst = (SstRegs *) sstbase;
|
|
|
|
if(!sst)
|
|
return(FXFALSE);
|
|
|
|
if(sst1InitCheckBoard(sstbase) == FXFALSE)
|
|
return(FXFALSE);
|
|
|
|
if((!(IGET(sst->fbiInit7) & SST_EN_CMDFIFO) &&
|
|
!sst1CurrentBoard->fbiCmdFifoEn) || sst1CurrentBoard->fbiLfbLocked)
|
|
return(FXTRUE);
|
|
|
|
// Force direct writes...
|
|
sst1CurrentBoard->fbiLfbLocked = 1;
|
|
|
|
ISET(sst->fbiInit7, IGET(sst->fbiInit7) & ~SST_EN_CMDFIFO_OFFSCREEN);
|
|
sst1InitReturnStatus(sstbase);
|
|
sst1InitReturnStatus(sstbase);
|
|
sst1InitReturnStatus(sstbase);
|
|
|
|
return(FXTRUE);
|
|
}
|
|
|
|
/*
|
|
**
|
|
** sst1InitLfbUnlock():
|
|
** Used to workaround a hw bug when performing lfb and texture writes when
|
|
** the command fifo is enabled. The routines sst1InitLfbLock() and
|
|
** sst1InitLfbUnlock() dynamically disable the command fifo so that lfb
|
|
** and texture accesses do not pass through the command fifo.
|
|
** WARNING: No register writes of any kind may be performed between a
|
|
** sst1InitLfbLock() and sst1InitLfbUnlock() pair -- only lfb reads and
|
|
** writes are allowed.
|
|
*/
|
|
|
|
FX_ENTRY FxBool FX_CALL sst1InitLfbUnlock(FxU32* sstbase)
|
|
{
|
|
if(!sstbase)
|
|
return(FXFALSE);
|
|
|
|
if(sst1InitCheckBoard(sstbase) == FXFALSE)
|
|
return(FXFALSE);
|
|
|
|
// Idle the hardware. Since lfb lock is set, a NOP will not be issued, and
|
|
// sst1InitPciFifoIdleLoop() will be used instead of sst1InitIdleLoop()...
|
|
sst1InitIdle(sstbase);
|
|
|
|
if(sst1CurrentBoard->sliSlaveVirtAddr) {
|
|
// SLI Enabled
|
|
if(sst1InitLfbUnlockDirect(sst1CurrentBoard->sliSlaveVirtAddr) ==
|
|
FXFALSE)
|
|
return(FXFALSE);
|
|
}
|
|
if(sst1InitLfbUnlockDirect(sstbase) == FXFALSE)
|
|
return(FXFALSE);
|
|
|
|
// After the command fifo is re-enabled, make sure the chip is really idle...
|
|
sst1InitIdle(sstbase);
|
|
|
|
return(FXTRUE);
|
|
}
|
|
|
|
FX_ENTRY FxBool FX_CALL sst1InitLfbUnlockDirect(FxU32* sstbase)
|
|
{
|
|
SstRegs *sst = (SstRegs *) sstbase;
|
|
|
|
if(!sst)
|
|
return(FXFALSE);
|
|
|
|
if(sst1InitCheckBoard(sstbase) == FXFALSE)
|
|
return(FXFALSE);
|
|
|
|
if(!sst1CurrentBoard->fbiCmdFifoEn || !sst1CurrentBoard->fbiLfbLocked)
|
|
return(FXTRUE);
|
|
|
|
ISET(sst->fbiInit7, IGET(sst->fbiInit7) | SST_EN_CMDFIFO_OFFSCREEN);
|
|
|
|
sst1CurrentBoard->fbiLfbLocked = 0;
|
|
|
|
sst1InitReturnStatus(sstbase);
|
|
sst1InitReturnStatus(sstbase);
|
|
sst1InitReturnStatus(sstbase);
|
|
|
|
return(FXTRUE);
|
|
}
|
|
|
|
/*
|
|
**
|
|
** sst1InitPrintInitRegs():
|
|
** Print Initialization Registers
|
|
**
|
|
*/
|
|
FX_EXPORT void FX_CSTYLE sst1InitPrintInitRegs(FxU32 *sstbase)
|
|
{
|
|
SstRegs *sst = (SstRegs *) sstbase;
|
|
|
|
INIT_PRINTF(("FBI Initialization Registers:\n"));
|
|
INIT_PRINTF(("-----------------------------\n"));
|
|
INIT_PRINTF(("fbiInit0:0x%08x fbiInit1:0x%08x\n",
|
|
IGET(sst->fbiInit0), IGET(sst->fbiInit1)));
|
|
INIT_PRINTF(("fbiInit2:0x%08x fbiInit3:0x%08x\n",
|
|
IGET(sst->fbiInit2), IGET(sst->fbiInit3)));
|
|
INIT_PRINTF(("fbiInit4:0x%08x fbiInit5:0x%08x\n",
|
|
IGET(sst->fbiInit4), IGET(sst->fbiInit5)));
|
|
INIT_PRINTF(("fbiInit6:0x%08x fbiInit7:0x%08x\n",
|
|
IGET(sst->fbiInit6), IGET(sst->fbiInit7)));
|
|
INIT_PRINTF(("videoDimensions:0x%08x\n\n",
|
|
IGET(sst->videoDimensions)));
|
|
INIT_PRINTF(("FBI Command Fifo Registers:\n"));
|
|
INIT_PRINTF(("---------------------------\n"));
|
|
INIT_PRINTF(("cmdFifoBase: 0x%08x\tcmdFifoBump:0x%x\n",
|
|
IGET(sst->cmdFifoBase), IGET(sst->cmdFifoBump)));
|
|
INIT_PRINTF(("cmdFifoReadPtr: 0x%08x\tcmdFifoAmin:0x%x\n",
|
|
IGET(sst->cmdFifoReadPtr), IGET(sst->cmdFifoAmin)));
|
|
INIT_PRINTF(("cmdFifoAmax: 0x%08x\tcmdFifoDepth:0x%x\n",
|
|
IGET(sst->cmdFifoAmax), IGET(sst->cmdFifoDepth)));
|
|
INIT_PRINTF(("cmdFifoHoles: 0x%08x\n", IGET(sst->cmdFifoHoles)));
|
|
}
|
|
|
|
/*
|
|
**
|
|
** sst1InitMeasureSiProcess():
|
|
** Use silicon process register to measure silicon performance
|
|
**
|
|
*/
|
|
FX_EXPORT FxU32 FX_CSTYLE sst1InitMeasureSiProcess(FxU32 *sstbase, FxU32 which)
|
|
{
|
|
FxU32 n, siProcess, nandOsc, norOsc;
|
|
FxU32 pciCntrLoad = 0xfff;
|
|
FxU32 cntr;
|
|
|
|
if(sst1InitCheckBoard(sstbase) == FXFALSE)
|
|
return(FXFALSE);
|
|
|
|
if(GETENV(("SSTV2_SIPROCESS_CNTR"))) {
|
|
SSCANF(GETENV(("SSTV2_SIPROCESS_CNTR")), "%ld", &pciCntrLoad);
|
|
INIT_PRINTF(("sst1InitMeasureSiProcess(): Using PCI Counter preload value of 0x%x...\n", pciCntrLoad));
|
|
}
|
|
|
|
if(!which) {
|
|
////////////////////////////////
|
|
// Test NAND oscillator tree...
|
|
////////////////////////////////
|
|
PCICFG_WR(SST1_PCI_SIPROCESS,
|
|
(pciCntrLoad<<SST_SIPROCESS_PCI_CNTR_SHIFT) |
|
|
SST_SIPROCESS_OSC_CNTR_RESET_N | SST_SIPROCESS_OSC_NAND_SEL);
|
|
|
|
// Allow oscillator to run...
|
|
PCICFG_RD(SST1_PCI_SIPROCESS, siProcess);
|
|
PCICFG_WR(SST1_PCI_SIPROCESS,
|
|
(pciCntrLoad<<SST_SIPROCESS_PCI_CNTR_SHIFT) |
|
|
SST_SIPROCESS_OSC_CNTR_RUN | SST_SIPROCESS_OSC_NAND_SEL);
|
|
|
|
// Loop until PCI counter decrements to 0
|
|
cntr = 0 ;
|
|
do {
|
|
++cntr;
|
|
PCICFG_RD(SST1_PCI_SIPROCESS, siProcess);
|
|
} while(siProcess & SST_SIPROCESS_PCI_CNTR);
|
|
|
|
PCICFG_RD(SST1_PCI_SIPROCESS, siProcess);
|
|
siProcess &= SST_SIPROCESS_OSC_CNTR;
|
|
nandOsc = siProcess;
|
|
if(nandOsc < 3000)
|
|
nandOsc <<= 1; // Running on 66 MHz PCI...
|
|
sst1CurrentBoard->fbiNandTree = nandOsc;
|
|
|
|
INIT_PRINTF(("sst1InitInfo(): NAND-tree: %d\n", nandOsc));
|
|
} else {
|
|
////////////////////////////////
|
|
// Test NOR oscillator tree...
|
|
////////////////////////////////
|
|
PCICFG_WR(SST1_PCI_SIPROCESS,
|
|
(pciCntrLoad<<SST_SIPROCESS_PCI_CNTR_SHIFT) |
|
|
SST_SIPROCESS_OSC_CNTR_RESET_N | SST_SIPROCESS_OSC_NOR_SEL);
|
|
|
|
// Allow oscillator to run...
|
|
PCICFG_RD(SST1_PCI_SIPROCESS, siProcess);
|
|
PCICFG_WR(SST1_PCI_SIPROCESS,
|
|
(pciCntrLoad<<SST_SIPROCESS_PCI_CNTR_SHIFT) |
|
|
SST_SIPROCESS_OSC_CNTR_RUN | SST_SIPROCESS_OSC_NOR_SEL);
|
|
|
|
// Loop until PCI counter decrements to 0
|
|
cntr = 0 ;
|
|
do {
|
|
++cntr;
|
|
PCICFG_RD(SST1_PCI_SIPROCESS, siProcess);
|
|
} while(siProcess & SST_SIPROCESS_PCI_CNTR);
|
|
|
|
PCICFG_RD(SST1_PCI_SIPROCESS, siProcess);
|
|
siProcess &= SST_SIPROCESS_OSC_CNTR;
|
|
norOsc = siProcess;
|
|
if(norOsc < 3000)
|
|
norOsc <<= 1; // Running on 66 MHz PCI...
|
|
sst1CurrentBoard->fbiNorTree = norOsc;
|
|
|
|
INIT_PRINTF(("sst1InitInfo(): NOR-tree : %d\n", norOsc));
|
|
}
|
|
return(siProcess);
|
|
}
|
|
|
|
/*
|
|
**
|
|
** sst1InitCalcTClkDelay()
|
|
** Calculate optimal TF/TT Clock delay values
|
|
**
|
|
*/
|
|
FX_EXPORT FxBool FX_CSTYLE sst1InitCalcTClkDelay(FxU32 *sstbase,
|
|
FxU32 tmuNumber, FxU32 tClkDelay)
|
|
{
|
|
SstRegs *sst = (SstRegs *) sstbase;
|
|
volatile FxU32 *texAddr;
|
|
|
|
if(sst1InitCheckBoard(sstbase) == FXFALSE)
|
|
return(FXFALSE);
|
|
|
|
ISET(sst->tLOD, 0x0);
|
|
ISET(sst->tDetail, 0x0);
|
|
ISET(sst->texBaseAddr, 0x0);
|
|
ISET(sst->fogMode, 0x0);
|
|
ISET(sst->alphaMode, 0x0);
|
|
ISET(sst->fbzMode, SST_ENCHROMAKEY);
|
|
ISET(sst->fbzColorPath, SST_RGBSEL_TREXOUT | SST_CC_PASS | SST_ENTEXTUREMAP);
|
|
//texAddr = (numTmu<<(21-2)) + (FxU32 *) SST_TEX_ADDRESS(sst);
|
|
texAddr = (0<<(21-2)) + (FxU32 *) SST_TEX_ADDRESS(sst);
|
|
ISET(texAddr[0], 0x0);
|
|
texAddr = (1<<(21-2)) + (FxU32 *) SST_TEX_ADDRESS(sst);
|
|
ISET(texAddr[0], 0x0);
|
|
texAddr = (2<<(21-2)) + (FxU32 *) SST_TEX_ADDRESS(sst);
|
|
ISET(texAddr[0], 0x0);
|
|
|
|
ISET(SST_TREX(sst,tmuNumber)->trexInit1,
|
|
(sst1CurrentBoard->tmuInit1[tmuNumber] & ~SST_TEX_TF_CLK_DEL_ADJ) |
|
|
(tClkDelay<<SST_TEX_TF_CLK_DEL_ADJ_SHIFT));
|
|
|
|
if(!sst1InitIdleFBIWithTimeout(sstbase, FXTRUE, 10000))
|
|
return(FXFALSE);
|
|
|
|
// Reset pixel stat registers
|
|
ISET(sst->nopCMD, 0x3);
|
|
sst1InitCheckTmuMemConst(sstbase, tmuNumber, 0xff0000);
|
|
sst1InitCheckTmuMemConst(sstbase, tmuNumber, 0x00ffff);
|
|
sst1InitCheckTmuMemConst(sstbase, tmuNumber, 0xf0f0f0);
|
|
sst1InitCheckTmuMemConst(sstbase, tmuNumber, 0x0f0f0f);
|
|
sst1InitCheckTmuMemConst(sstbase, tmuNumber, 0x55aa55);
|
|
sst1InitCheckTmuMemConst(sstbase, tmuNumber, 0xaa55aa);
|
|
sst1InitCheckTmuMemConst(sstbase, tmuNumber, 0x5a5a5a);
|
|
sst1InitCheckTmuMemConst(sstbase, tmuNumber, 0xa5a5a5);
|
|
|
|
if(!sst1InitIdleFBIWithTimeout(sstbase, FXTRUE, 10000))
|
|
return(FXFALSE);
|
|
|
|
if(IGET(sst->stats.fbiChromaFail))
|
|
return(FXFALSE);
|
|
else
|
|
return(FXTRUE);
|
|
}
|
|
|
|
#define COLOR32TOCOLOR24_6666(X) \
|
|
((((X >> 2) & 0x3F) << 0) | \
|
|
(((X >> 10) & 0x3F) << 6) | \
|
|
(((X >> 18) & 0x3F) << 12) | \
|
|
(((X >> 26) & 0x3F) << 18))
|
|
#define COLOR24_6666TOCOLOR32(X) \
|
|
(((((X >> 0) & 0x3F) << 2) | (((X >> 4) & 0x3) << 0)) | \
|
|
((((X >> 6) & 0x3F) << 10) | (((X >> 10) & 0x3) << 8)) | \
|
|
((((X >> 12) & 0x3F) << 18) | (((X >> 16) & 0x3) << 16)) | \
|
|
((((X >> 18) & 0x3F) << 26) | (((X >> 22) & 0x3) << 24)))
|
|
|
|
void sst1InitCheckTmuMemConst(FxU32 *sstbase, FxU32 tmuNumber,
|
|
FxU32 dataExpect32)
|
|
{
|
|
SstRegs *sst = (SstRegs *) sstbase;
|
|
FxU32 dataExpect6666 = COLOR32TOCOLOR24_6666(dataExpect32);
|
|
FxU32 dataExpect6666To32 = COLOR24_6666TOCOLOR32(dataExpect6666) & 0xffffff;
|
|
|
|
ISET(sst->chromaKey, dataExpect6666To32);
|
|
ISET(sst->chromaRange, dataExpect6666To32 | SST_ENCHROMARANGE |
|
|
SST_CHROMARANGE_BLUE_EX | SST_CHROMARANGE_GREEN_EX |
|
|
SST_CHROMARANGE_RED_EX | SST_CHROMARANGE_BLOCK_OR);
|
|
|
|
if(!tmuNumber) {
|
|
ISET(sst->textureMode, SST_P8_ARGB6666 | SST_TC_REPLACE | SST_TCA_ZERO);
|
|
} else if(tmuNumber == 1) {
|
|
// Force downstream TMU to passthrough upstream data
|
|
ISET(SST_TREX(sst,0)->textureMode, SST_P8_ARGB6666 | SST_TC_PASS |
|
|
SST_TCA_PASS);
|
|
ISET(SST_TREX(sst,1)->textureMode, SST_P8_ARGB6666 | SST_TC_REPLACE |
|
|
SST_TCA_ZERO);
|
|
ISET(SST_TREX(sst,2)->textureMode, SST_P8_ARGB6666 | SST_TC_REPLACE |
|
|
SST_TCA_ZERO);
|
|
} else {
|
|
// Force downstream TMUs to passthrough upstream data
|
|
ISET(SST_TREX(sst,0)->textureMode, SST_P8_ARGB6666 | SST_TC_PASS |
|
|
SST_TCA_PASS);
|
|
ISET(SST_TREX(sst,1)->textureMode, SST_P8_ARGB6666 | SST_TC_PASS |
|
|
SST_TCA_PASS);
|
|
ISET(SST_TREX(sst,2)->textureMode, SST_P8_ARGB6666 | SST_TC_REPLACE |
|
|
SST_TCA_ZERO);
|
|
}
|
|
// Specify color in palette entry 0...
|
|
//sst->nccTable0[4]=BIT(31) | ((index>>1)<<24) | (palette[index] & 0xffffff);
|
|
ISET(sst->nccTable0[4], BIT(31) | COLOR32TOCOLOR24_6666(dataExpect32));
|
|
sst1InitDrawRectUsingTris(sstbase, 0, 0, 128);
|
|
|
|
return;
|
|
}
|
|
|
|
void sst1InitDrawRectUsingTris(FxU32 *sstbase, FxU32 x, FxU32 y, FxU32 tSize)
|
|
{
|
|
SstRegs *sst = (SstRegs *) sstbase;
|
|
|
|
ISET(sst->vA.x, (x<<SST_XY_FRACBITS));
|
|
ISET(sst->vA.y, (y<<SST_XY_FRACBITS));
|
|
ISET(sst->vB.x, ((x+tSize)<<SST_XY_FRACBITS));
|
|
ISET(sst->vB.y, (y<<SST_XY_FRACBITS));
|
|
ISET(sst->vC.x, ((x+tSize)<<SST_XY_FRACBITS));
|
|
ISET(sst->vC.y, ((y+tSize)<<SST_XY_FRACBITS));
|
|
ISET(sst->s, 0);
|
|
ISET(sst->t, 0);
|
|
ISET(sst->w, 0);
|
|
ISET(sst->r, (0xff<<SST_XY_INTBITS));
|
|
ISET(sst->g, 0);
|
|
ISET(sst->b, 0);
|
|
ISET(sst->dsdx, 0);
|
|
ISET(sst->dtdx, 0);
|
|
ISET(sst->dwdx, 0);
|
|
ISET(sst->dsdy, 0);
|
|
ISET(sst->dtdy, 0);
|
|
ISET(sst->dwdy, 0);
|
|
ISET(sst->triangleCMD, 0);
|
|
ISET(sst->vB.x, (x<<SST_XY_FRACBITS));
|
|
ISET(sst->vB.y, ((y+tSize)<<SST_XY_FRACBITS));
|
|
ISET(sst->triangleCMD, 0xFFFFFFFF);
|
|
}
|
|
|
|
#ifdef __WIN32__
|
|
#pragma optimize ("",on)
|
|
#endif
|