Files
glide/glide3x/sst1/init/initvg/util.c

363 lines
10 KiB
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
**
** Utility routines for SST-1 Initialization code
**
*/
#undef FX_DLL_ENABLE /* so that we don't dllexport the symbols */
#ifndef __GNUC__
#pragma optimize ("",off)
#endif
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <sst.h>
#define FX_DLL_DEFINITION
#include <fxdll.h>
#include <sst1vid.h>
#include <sst1init.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(!sst1InitSliEnabled)
sst1InitIdleLoop(sstbase);
else {
FxU32 j, n;
if(sst1InitCheckBoard(sstbase) == FXFALSE)
return(FXFALSE);
/* Check idle for Master... */
sst1InitIdleLoop(sstbase);
/* Cause slave to drive PCI bus */
PCICFG_RD(SST1_PCI_INIT_ENABLE, j);
PCICFG_WR(SST1_PCI_INIT_ENABLE, j | SST_SCANLINE_SLV_OWNPCI);
if(sst1InitCheckBoard(sst1InitSliSlaveVirtAddr) == FXFALSE)
return(FXFALSE);
PCICFG_RD(SST1_PCI_INIT_ENABLE, j);
PCICFG_WR(SST1_PCI_INIT_ENABLE, j | SST_SCANLINE_SLV_OWNPCI);
/* Check idle for Slave... */
sst1InitIdleLoop(sstbase);
/* Restore normal SLI conditions */
PCICFG_RD(SST1_PCI_INIT_ENABLE, j);
PCICFG_WR(SST1_PCI_INIT_ENABLE, j & ~SST_SCANLINE_SLV_OWNPCI);
if(sst1InitCheckBoard(sstbase) == FXFALSE)
return(FXFALSE);
PCICFG_RD(SST1_PCI_INIT_ENABLE, j);
PCICFG_WR(SST1_PCI_INIT_ENABLE, j & ~SST_SCANLINE_SLV_OWNPCI);
}
return(FXTRUE);
}
void sst1InitIdleLoop(FxU32 *sstbase)
{
FxU32 cntr;
volatile Sstregs *sst = (Sstregs *) sstbase;
ISET(sst->nopCMD, 0x0);
cntr = 0;
while(1) {
if(!(sst1InitReturnStatus(sstbase) & SST_BUSY)) {
if(++cntr >= 3)
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;
volatile 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;
volatile 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)
{
volatile 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)
{
volatile 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)
{
volatile Sstregs *sst = (Sstregs *) sstbase;
if(sst1InitCheckBoard(sstbase) == FXFALSE)
return(FXFALSE);
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 after changing graphics clocks
** Occasionally when changing the frequency of the graphics clock, the TMUs
** get in an unknown state. sst1InitResetTmus() cleans up the problem.
**
*/
FxBool sst1InitResetTmus(FxU32 *sstbase)
{
volatile Sstregs *sst = (Sstregs *) sstbase;
FxU32 n;
/* Clear FBI registers */
ISET(sst->fbzColorPath, 0x0);
ISET(sst->fogMode, 0x0);
ISET(sst->alphaMode, 0x0);
ISET(sst->fbzMode, 0x0);
ISET(sst->lfbMode, 0x0);
ISET(sst->fogColor, 0x0);
ISET(sst->zaColor, 0x0);
ISET(sst->chromaKey, 0x0);
ISET(sst->stipple, 0x0);
ISET(sst->c0, 0x0);
ISET(sst->c1, 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);
/* Set downstream TMU to intentionally overflow TT Fifo... */
ISET(SST_TREX(sst,0)->trexInit1, sst1CurrentBoard->tmuInit1[0] &
~SST_TEX_TT_FIFO_SIL);
sst1InitIdleFBINoNOP(sstbase);
/* Draw 256-pixel textured triangle to overflow TT fifo in downstream */
/* TMU. Create numerous page misses in downstream TMU so upstream TMU */
/* is always running faster */
ISET(sst->fbzColorPath, SST_ENTEXTUREMAP);
ISET(sst->fbzMode, SST_DRAWBUFFER_FRONT);
ISET(sst->vA.x, 0);
ISET(sst->vA.y, 0);
ISET(sst->vB.x, (25<<SST_XY_FRACBITS));
ISET(sst->vB.y, 0);
ISET(sst->vC.x, 0);
ISET(sst->vC.y, (25<<SST_XY_FRACBITS));
ISET(sst->s, 0x0);
ISET(sst->t, 0x0);
ISET(sst->w, 0x0);
ISET(sst->dwdx, 0x0);
ISET(sst->dwdy, 0x0);
ISET(SST_TREX(sst,0)->dsdx, (69<<SST_ST_FRACBITS));
ISET(SST_TREX(sst,0)->dsdy, (69<<SST_ST_FRACBITS));
ISET(SST_TREX(sst,0)->dsdx, (69<<SST_ST_FRACBITS));
ISET(SST_TREX(sst,0)->dsdy, (69<<SST_ST_FRACBITS));
ISET(SST_TREX(sst,1)->dsdx, (0<<SST_ST_FRACBITS));
ISET(SST_TREX(sst,1)->dsdy, (0<<SST_ST_FRACBITS));
ISET(SST_TREX(sst,1)->dsdx, (0<<SST_ST_FRACBITS));
ISET(SST_TREX(sst,1)->dsdy, (0<<SST_ST_FRACBITS));
ISET(sst->triangleCMD, 0x0);
ISET(sst->nopCMD, 0x1); /* This will reset pixel counter registers... */
/* Wait for command to execute... */
for(n=0; n<25000; n++)
sst1InitReturnStatus(sstbase);
/* Upstream TMU is now idle */
/* Set downstream TMU to always accept upstream data */
/* This will flush pending pixels in the downstream TMU */
ISET(SST_TREX(sst,0)->trexInit1, sst1CurrentBoard->tmuInit1[0] |
SST_TEX_RG_TTCII_INH | SST_TEX_USE_RG_TTCII_INH);
for(n=0; n<100; n++)
sst1InitReturnStatus(sstbase);
/* Wait for command to execute... */
for(n=0; n<25000; n++)
sst1InitReturnStatus(sstbase);
/* Restore registers */
ISET(SST_TREX(sst,0)->trexInit1, sst1CurrentBoard->tmuInit1[0]);
ISET(sst->fbzColorPath, 0x0);
ISET(sst->fbzMode, 0x0);
for(n=0; n<100; n++)
sst1InitReturnStatus(sstbase);
if(sst1InitReturnStatus(sstbase) & SST_TREX_BUSY) {
INIT_PRINTF(("sst1InitResetTmus(): Could not reset TMUs...\n"));
return(FXFALSE);
} else
return(FXTRUE);
}
/*
** sst1InitWrite32():
** Write 32-bit Word to specified address
**
*/
FX_EXPORT void FX_CSTYLE sst1InitWrite32(FxU32 *addr, FxU32 data)
{
P6FENCE;
*addr = data;
P6FENCE;
}
/*
** sst1InitRead32():
** Read 32-bit Word from specified address
**
*/
FX_EXPORT FxU32 FX_CSTYLE sst1InitRead32(FxU32 *addr)
{
P6FENCE;
return(*addr);
}
#ifndef __GNUC__
#pragma optimize ("",on)
#endif