Files
glide/glide3x/sst1/init/init96/init96.c

2265 lines
65 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
**
*/
#undef FX_DLL_ENABLE /* so that we don't dllexport the symbols */
/* ANSI Headers */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#if defined(__DOS32__) || defined(INIT96VGASWAP)
#include <conio.h>
#endif
#ifdef __DOS32__
#ifdef __DJGPP__
#include <dos.h>
#else
#include <i86.h>
#endif
#endif
#ifdef __WIN32__
#include <windows.h>
#endif
#ifdef INIT96VGASWAP
#include "initvga.h"
#endif
#if defined(__WATCOMC__)
#define _inp inp
#define _outp outp
#endif
#ifdef __DJGPP__
#include <fxdpmi.h>
#endif
/* 3Dfx Headers */
#include <3dfx.h>
#include <fxpci.h>
#include <gdebug.h>
#include <sst.h>
#define FX_DLL_DEFINITION
#include <fxdll.h>
#include <init.h>
/* Local Headers */
#include "init96.h"
#include "fxinit96.h"
#include "initat3d.h"
#if 0
#include "init9685.h"
#include "initmrti.h"
#endif
#include "initmcrx.h"
#ifdef GDBG_INFO_ON
static char *bufTypeNames[] = {
"INIT_BUFFER_FRONTBUFFER",
"INIT_BUFFER_BACKBUFFER",
"INIT_BUFFER_AUXBUFFER",
"INIT_BUFFER_DEPTHBUFFER",
"INIT_BUFFER_ALPHABUFFER",
"INIT_BUFFER_TRIPLEBUFFER",
"INIT_BUFFER_FIFOBUFFER",
"INIT_BUFFER_SCREENBUFFER",
"INIT_BUFFER_TEXTUREBUFFER"
};
#endif
/*==================== Local Constants ====================*/
#define NUM_BUFS 6
#define SST96_MEMMAP_TEXTURE_MEMORY_OFFSET (0x6 << 20) /* +5 MB */
#define SST96_COMMAND_REGS(X) ( ((char*)(X))+(4<<20) )
#define MAXTRIES 10000
#define FIFOLAG 128
/*-------------------------------------------------------------------
Module Data
-------------------------------------------------------------------*/
volatile FxU32 *sstHW;
volatile Sstregs *sstPtr;
typedef struct _BufInfo {
/* DISPLAY Stuff */
FxI32 dfb; /* Was fbN */
FxI32 dfbBase; /* Base of Buffers */
FxI32 dfbTop; /* Tops of Buffers */
FxI32 dfbStride; /* Strides */
/* RENDER stuff */
FxI32 rfb; /* was rfbN */
} BufInfo, *BufInfoPtr;
#define RFB 0
#define DFB 1
extern FxBool tripleBuffering;
#define ADVANCE_BUFFERS(kind)\
{\
kind##FrontIdx = (kind##FrontIdx < maxBufIdx) ? kind##FrontIdx + 1 : 0;\
kind##BackIdx = (kind##BackIdx < maxBufIdx) ? kind##BackIdx + 1 : 0;\
kind##RenderIdx = (kind##RenderIdx < maxBufIdx) ? kind##RenderIdx + 1 : 0;\
}
#define rfbTripleIdx ((rfbBackIdx + 1) % maxBuffer)
#define MAX_BUF 3
BufInfo bI[MAX_BUF];
static FxI32
maxBuffer = 2,
maxBufIdx,
/* DISPLAY Stuff */
/* The following two are indices into the above */
dfbFrontIdx = 0,
dfbBackIdx = 1,
dfbRenderIdx = 1,
/* RENDER stuff */
rfbFrontIdx = 0,
rfbBackIdx = 1,
rfbRenderIdx = 1;
static FxI32
ab0, ab0Top, ab0Base, ab0Stride;
static InitOriginLocation_t cachedYOrigin;
static InitSwapType_t cachedSwapType;
static FxU32 fifoStart, fifoEnd;
volatile FxU32 *fifovirt; /* start virtual address */
volatile FxU32 fifophys; /* start physical address */
volatile FxU32 fifomax; /* in bytes */
volatile FxU32 fifocur; /* how much used up so far */
volatile FxU32 *fifoptr; /* current pointer */
volatile FxU32 fifosize; /* how much of 4kbytes used up */
volatile FxU32 fifolfb; /* use LFB, use hostblt if 0. */
#if SST96_ALT_FIFO_WRAP && GDBG_INFO_ON
/* Statistics about how many times we wrapped/waited for
* the fifo.
*/
static FxU32 numWraps;
static FxU32 numJuJuStalls;
static FxU32 numStalls;
#endif /* GDBG_INFO_ON && SST96_ALT_FIFO_WRAP */
Init96HALData *curHALData;
#ifdef __DOS32__
static FxU16
oldVidMode;
#endif
static FxU32
devNum,
physAddr,
fifoMTRRNum = 0xffffffff;
/*-----------Debuging Info Data------------------------------*/
#ifdef GDBG_INFO_ON
/* NOTE:
This array is HIGHLY important to debugging. Delete it at your
extreme peril.
*/
const char *iRegNames[] = {
"status", /* 0x00 */
"reserved001", /* 0x01 */
"vAx", /* 0x02 */
"vAy", /* 0x03 */
"vBx", /* 0x04 */
"vBy", /* 0x05 */
"vCx", /* 0x06 */
"vCy", /* 0x07 */
"r", /* 0x08 */
"drdx", /* 0x09 */
"drdy", /* 0x0a */
"g", /* 0x0b */
"dgdx", /* 0x0c */
"dgdy", /* 0x0d */
"b", /* 0x0e */
"dbdx", /* 0x0f */
"dbdy", /* 0x10 */
"z", /* 0x11 */
"dzdx", /* 0x12 */
"dzdy", /* 0x13 */
"a", /* 0x14 */
"dadx", /* 0x15 */
"dady", /* 0x16 */
"s", /* 0x17 */
"dsdx", /* 0x18 */
"dsdy", /* 0x19 */
"t", /* 0x1a */
"dtdx", /* 0x1b */
"dtdy", /* 0x1c */
"w", /* 0x1d */
"dwdx", /* 0x1e */
"dwdy", /* 0x1f */
"triangleCMD", /* 0x20 */
"reserved021", /* 0x21 */
"FvAx", /* 0x22 */
"FvAy", /* 0x23 */
"FvBx", /* 0x24 */
"FvBy", /* 0x25 */
"FvCx", /* 0x26 */
"FvCy", /* 0x27 */
"Fr", /* 0x28 */
"Fdrdx", /* 0x29 */
"Fdrdy", /* 0x2a */
"Fg", /* 0x2b */
"Fdgdx", /* 0x2c */
"Fdgdy", /* 0x2d */
"Fb", /* 0x2e */
"Fdbdx", /* 0x2f */
"Fdbdy", /* 0x30 */
"Fz", /* 0x31 */
"Fdzdx", /* 0x32 */
"Fdzdy", /* 0x33 */
"Fa", /* 0x34 */
"Fdadx", /* 0x35 */
"Fdady", /* 0x36 */
"Fs", /* 0x37 */
"Fdsdx", /* 0x38 */
"Fdsdy", /* 0x39 */
"Ft", /* 0x3a */
"Fdtdx", /* 0x3b */
"Fdtdy", /* 0x3c */
"Fw", /* 0x3d */
"Fdwdx", /* 0x3e */
"Fdwdy", /* 0x3f */
"FtriangleCMD", /* 0x40 */
"reserved041", /* 0x41 */
"nopCMD", /* 0x42 */
"reserved043", /* 0x43 */
"fastfillCMD", /* 0x44 */
"reserved045", /* 0x45 */
"swapbufferCMD", /* 0x46 */
"reserved047", /* 0x47 */
"swappendCMD", /* 0x48 */
"reserved049", /* 0x49 */
"reserved04A", /* 0x4a */
"reserved04B", /* 0x4b */
"reserved04C", /* 0x4c */
"reserved04D", /* 0x4d */
"reserved04E", /* 0x4e */
"reserved04F", /* 0x4f */
"fbzColorPath", /* 0x50 */
"fogMode", /* 0x51 */
"alphaMode", /* 0x52 */
"reserved053", /* 0x53 */
"fbzMode", /* 0x54 */
"stipple", /* 0x55 */
"color0", /* 0x56 */
"color1", /* 0x57 */
"fogColor", /* 0x58 */
"zaColor", /* 0x59 */
"chromaKey", /* 0x5a */
"chromaRange", /* 0x5b */
"reserved05C", /* 0x5c */
"reserved05D", /* 0x5d */
"reserved05E", /* 0x5e */
"reserved05F", /* 0x5f */
"colBufferSetup", /* 0x60 */
"auxBufferSetup", /* 0x61 */
"clipLeftRight0", /* 0x62 */
"clipTopBottom0", /* 0x63 */
"clipLeftRight1", /* 0x64 */
"clipTopBottom1", /* 0x65 */
"reserved066", /* 0x66 */
"reserved067", /* 0x67 */
"reserved068", /* 0x68 */
"reserved069", /* 0x69 */
"reserved06A", /* 0x6a */
"reserved06B", /* 0x6b */
"reserved06C", /* 0x6c */
"reserved06D", /* 0x6d */
"reserved06E", /* 0x6e */
"reserved06F", /* 0x6f */
"fogTable0001", /* 0x70 */
"fogTable0203", /* 0x71 */
"fogTable0405", /* 0x72 */
"fogTable0607", /* 0x73 */
"fogTable0809", /* 0x74 */
"fogTable0A0B", /* 0x75 */
"fogTable0C0D", /* 0x76 */
"fogTable0E0F", /* 0x77 */
"fogTable1011", /* 0x78 */
"fogTable1213", /* 0x79 */
"fogTable1415", /* 0x7a */
"fogTable1617", /* 0x7b */
"fogTable1819", /* 0x7c */
"fogTable1A1B", /* 0x7d */
"fogTable1C1D", /* 0x7e */
"fogTable1E1F", /* 0x7f */
"fogTable2021", /* 0x80 */
"fogTable2223", /* 0x81 */
"fogTable2425", /* 0x82 */
"fogTable2627", /* 0x83 */
"fogTable2829", /* 0x84 */
"fogTable2A2B", /* 0x85 */
"fogTable2C2D", /* 0x86 */
"fogTable2E2F", /* 0x87 */
"fogTable3031", /* 0x88 */
"fogTable3233", /* 0x89 */
"fogTable3435", /* 0x8a */
"fogTable3637", /* 0x8b */
"fogTable3839", /* 0x8c */
"fogTable3A3B", /* 0x8d */
"fogTable3C3D", /* 0x8e */
"fogTable3E3F", /* 0x8f */
"fbijrInit0", /* 0x90 */
"fbijrInit1", /* 0x91 */
"fbijrInit2", /* 0x92 */
"fbijrInit3", /* 0x93 */
"fbijrInit4", /* 0x94 */
"fbijrInit5", /* 0x95 */
"reserved096", /* 0x96 */
"reserved097", /* 0x97 */
"reserved098", /* 0x98 */
"reserved099", /* 0x99 */
"reserved09A", /* 0x9a */
"reserved09B", /* 0x9b */
"reserved09C", /* 0x9c */
"reserved09D", /* 0x9d */
"reserved09E", /* 0x9e */
"reserved09F", /* 0x9f */
"fbijrVersion", /* 0xa0 */
"fbiPixelsIn", /* 0xa1 */
"fbiChromaFail", /* 0xa2 */
"fbiZfuncFail", /* 0xa3 */
"fbiAfuncFail", /* 0xa4 */
"fbiPixelsOut", /* 0xa5 */
"reserved0A6", /* 0xa6 */
"reserved0A7", /* 0xa7 */
"reserved0A8", /* 0xa8 */
"reserved0A9", /* 0xa9 */
"reserved0AA", /* 0xaa */
"reserved0AB", /* 0xab */
"reserved0AC", /* 0xac */
"reserved0AD", /* 0xad */
"reserved0AE", /* 0xae */
"reserved0AF", /* 0xaf */
"reserved0B0", /* 0xb0 */
"reserved0B1", /* 0xb1 */
"reserved0B2", /* 0xb2 */
"reserved0B3", /* 0xb3 */
"reserved0B4", /* 0xb4 */
"reserved0B5", /* 0xb5 */
"reserved0B6", /* 0xb6 */
"reserved0B7", /* 0xb7 */
"reserved0B8", /* 0xb8 */
"reserved0B9", /* 0xb9 */
"reserved0BA", /* 0xba */
"reserved0BB", /* 0xbb */
"reserved0BC", /* 0xbc */
"reserved0BD", /* 0xbd */
"reserved0BE", /* 0xbe */
"texChipSel", /* 0xbf */
"textureMode", /* 0xc0 */
"tLOD", /* 0xc1 */
"tDetail", /* 0xc2 */
"texBaseAddr", /* 0xc3 */
"texBaseAddr1", /* 0xc4 */
"texBaseAddr2", /* 0xc5 */
"texBaseAddr38", /* 0xc6 */
"trexInit0", /* 0xc7 */
"trexInit1", /* 0xc8 */
"nccTable0_0", /* 0xc9 */
"nccTable0_1", /* 0xca */
"nccTable0_2", /* 0xcb */
"nccTable0_3", /* 0xcc */
"nccTable0_4", /* 0xcd */
"nccTable0_5", /* 0xce */
"nccTable0_6", /* 0xcf */
"nccTable0_7", /* 0xd0 */
"nccTable0_8", /* 0xd1 */
"nccTable0_9", /* 0xd2 */
"nccTable0_A", /* 0xd3 */
"nccTable0_B", /* 0xd4 */
"nccTable1_0", /* 0xd5 */
"nccTable1_1", /* 0xd6 */
"nccTable1_2", /* 0xd7 */
"nccTable1_3", /* 0xd8 */
"nccTable1_4", /* 0xd9 */
"nccTable1_5", /* 0xda */
"nccTable1_6", /* 0xdb */
"nccTable1_7", /* 0xdc */
"nccTable1_8", /* 0xdd */
"nccTable1_9", /* 0xde */
"nccTable1_A", /* 0xdf */
"nccTable1_B", /* 0xe0 */
"reserved0E1", /* 0xe1 */
"reserved0E2", /* 0xe2 */
"reserved0E3", /* 0xe3 */
"reserved0E4", /* 0xe4 */
"reserved0E5", /* 0xe5 */
"reserved0E6", /* 0xe6 */
"reserved0E7", /* 0xe7 */
"reserved0E8", /* 0xe8 */
"reserved0E9", /* 0xe9 */
"reserved0EA", /* 0xea */
"reserved0EB", /* 0xeb */
"reserved0EC", /* 0xec */
"reserved0ED", /* 0xed */
"reserved0EE", /* 0xee */
"reserved0EF", /* 0xef */
"reserved0F0", /* 0xf0 */
"reserved0F1", /* 0xf1 */
"reserved0F2", /* 0xf2 */
"reserved0F3", /* 0xf3 */
"reserved0F4", /* 0xf4 */
"reserved0F5", /* 0xf5 */
"reserved0F6", /* 0xf6 */
"reserved0F7", /* 0xf7 */
"reserved0F8", /* 0xf8 */
"reserved0F9", /* 0xf9 */
"reserved0FA", /* 0xfa */
"reserved0FB", /* 0xfb */
"reserved0FC", /* 0xfc */
"reserved0FD", /* 0xfd */
"reserved0FE", /* 0xfe */
"reserved0FF" /* 0xff */
};
#endif
#define VG96STRIDE(stride) (((stride >> 3) & 0x1ff )<< 22)
#ifdef GDBG_INFO_ON
FxU32
get96(FxU32 *addr)
{
FxU32
index,
ret;
char *regName;
ret = *GETREADADDR2(addr);
index = GETINDEXFROMADDR(addr);
regName = iRegNames[index];
GDBG_INFO((120, "GET: Register: %s (0x%x) Address: 0x%x Value: 0x%x\n",
regName, GETINDEXFROMADDR(addr), addr, ret));
return ret;
} /* get96 */
#endif
/* structure offset */
#define SETO(base,offset,value) (*(((FxU32 *)(base))+((offset) >> 2)) = (value))
#define GETO(base,offset) (*(((FxU32 *)(base))+((offset) << 8)))
/* register indices */
#define SETI(base,index,value) (*(((FxU32 *)(base))+(index)) = (value))
#define GETI(base,index) (*(((FxU32 *)(base))+((index) << 10)))
/* structure field names */
#define SETF(base2,field,value) (((Sstregs*)(base2))->field = (value))
#define GETF(base,field) (GETO(base,offsetof(Sstregs,field)))
#define GETREGVALFROMENV(val, envStr, constant)\
{\
const char *envVal;\
unsigned int u; \
val = constant;\
if ( (envVal = myGetenv(envStr)) && \
(sscanf(envVal, "%x", &u) == 1) ) { \
val = u; \
GDBG_INFO((80,\
"%s: The environment variable %s == 0x%x overloaded a register value\n", \
FN_NAME, envStr, val));\
}\
}
static FxBool
init96LoadBufRegs(int nBuffers,
InitBufDesc_t *pBufDesc,
int xRes, int yRes,
InitRegisterDesc *rd);
static void init96SetupRendering(InitRegisterDesc *regDesc,
GrScreenResolution_t sRes);
#define XY_ONE (1<<SST_XY_FRACBITS)
/* draw a right angle triangle */
static void
drawTriangle(volatile Sstregs *sst, int x, int y, int tSize)
{
SET(sstPtr->vA.x, x);
SET(sstPtr->vA.y, y);
SET(sstPtr->vB.x, x+XY_ONE*tSize);
SET(sstPtr->vB.y, y);
SET(sstPtr->vC.x, x);
SET(sstPtr->vC.y, y+XY_ONE*tSize/2);
SET(sstPtr->s, 0);
SET(sstPtr->t, 0);
SET(sstPtr->w, 1);
SET(sstPtr->dsdx, 255);
SET(sstPtr->dtdx, 0);
SET(sstPtr->dwdx, 0);
SET(sstPtr->dsdy, 255);
SET(sstPtr->dtdy, 0);
SET(sstPtr->dwdy, 0);
SET(sstPtr->triangleCMD, 1);
}
#define SENSE0 0xbaaf
#define SENSE1 0xabcd
#define VG96_TEXTURE_OFFSET 0x600000
#define SST96_TEX_PTR(a) \
((FxU32 *) (((FxU32) a) + VG96_TEXTURE_OFFSET))
static FxBool sense(FxU32 *sstbase, VG96Info *info, FxU32 tmu,
FxU32 mem, FxU32 init)
{
volatile Sstregs *sst = (Sstregs *) sstbase;
FxU32 *texAddr = (FxU32 *)SST96_TEX_PTR(sstbase);
FxBool same = FXFALSE;
FxU16 fmem, orgmem;
/* set the Init0 register to enable ? MBytes of memory */
#define WAITLOOP {\
int nWaits;\
FxU32 waitRes;\
for (nWaits = 0; nWaits < 50000; nWaits++) {\
waitRes = sstHW[0x100000];\
if (waitRes & 0x80000000) break;\
}\
}
orgmem = *(FxU16 *)sstbase;
WAITLOOP;
/* base address for lod0 */
mem = mem - ((FXBIT(14) + FXBIT(12) + FXBIT(10) + FXBIT(8) + FXBIT(6) + FXBIT(4) + FXBIT(2) + 1)*8); /* 8X */
SET(sstPtr->texBaseAddr, mem>>3);
*(texAddr + (8 << 15)) = init;
/*
write to 2 consequtive locations in lod0 to alter the data
on the memory signals
*/
WAITLOOP;
*(texAddr + (0)) = 0xffffffff;
WAITLOOP;
*(texAddr + (1)) = 0xffffffff;
WAITLOOP;
drawTriangle(sst,0,0,2); /* draw a 4x4 right triangle */
WAITLOOP;
fmem = *(FxU16 *)sstbase;
WAITLOOP;
if (fmem == init)
same = FXTRUE;
*(FxU16 *)sstbase = orgmem;
return same;
}
FX_EXPORT FxBool FX_CSTYLE
Init96GetTmuMemory(FxU32 *sstbase, VG96Info *info, FxU32 tmu,
FxU32 *TmuMemorySize)
{
FxU32 data;
if(myGetenv(("SST96_TMUMEM_SIZE"))) {
*TmuMemorySize = atoi(myGetenv(("SST96_TMUMEM_SIZE")));
return(FXTRUE);
}
SET(sstPtr->trexInit0, 0x05441);
SET(sstPtr->colBufferSetup, 0x28000000); /* color buffer */
SET(sstPtr->fbzMode, SST_RGBWRMASK);
SET(sstPtr->fbzColorPath, SST_RGBSEL_TREXOUT | SST_CC_PASS | SST_ENTEXTUREMAP);
SET(sstPtr->textureMode, SST_RGB565 | SST_TC_REPLACE | SST_TCA_REPLACE);
/* set lod8 */
SET(sstPtr->tLOD, ((8 << 2) | (8 << 7)));
/*
first see if we have 4 Mbytes by writing a texel at 2MB followed by
a texel at 1MB and 0MB and then rendering using the texel at 2MB
if we have less memory it should not render correctly since we trash
the memory locations it would wrap to
*/
data = sense(sstbase,info,tmu,0x200000, SENSE0);
if (data) {
data = sense(sstbase,info,tmu,0x200000, SENSE1);
if (data) {
*TmuMemorySize = 4;
return(FXTRUE);
}
}
data = sense(sstbase,info,tmu,0x100000, SENSE0);
if (data) {
data = sense(sstbase,info,tmu,0x100000, SENSE1);
if (data) {
*TmuMemorySize = 2;
return(FXTRUE);
}
}
data = sense(sstbase,info,tmu,0x000000, SENSE0);
if (data) {
data = sense(sstbase,info,tmu,0x000000, SENSE1);
if (data) {
*TmuMemorySize = 1;
return(FXTRUE);
}
}
#undef WAITLOOP
return(FXFALSE);
}
/*---------------------------------------------------------------------------
NOTES:
assumes that board and registers are initialized
destroys part of the framebuffer
---------------------------------------------------------------------------*/
FX_EXPORT FxBool FX_CSTYLE
sst96InitGetTmuInfo(FxU32 *sstbase, VG96Info *info)
{
sstPtr =
(volatile Sstregs *)(SST96_COMMAND_REGS(sstbase));
if(Init96GetTmuMemory(sstbase, info, 0, &info->tfxRam) == FXFALSE)
return(FXFALSE);
return(FXTRUE);
}
/*-------------------------------------------------------------------
Function: init96MapBoard
Date: 10/17
Implementor(s): jdt, dow
Library: init96
Description:
Looks for an SST-96 enabled VGA board on the system and maps that
boards physical address into linear memory.
Arguments:
rd: Register descriptions
vID: Vendor ID
dID: Device ID
Return:
linear pointer to base of VGA board. 0 if fail
-------------------------------------------------------------------*/
INITVG96ENTRY(init96MapBoard, FxBool , (void *rd, void *info, FxU16 vID, FxU16 dID) )
{
#define FN_NAME "init96MapBoard"
InitRegisterDesc
*regDesc = (InitRegisterDesc *) rd;
VG96Info *vg96Info = (VG96Info *) info;
FxU32
vendorID = vID,
deviceID = dID;
GDBG_INFO((80, "SST-96 Initialization code\n"));
/* !!! FIXME hack for vxd bug */
putenv( "SST_DUALHEAD=1" );
switch (vID) {
case AT3DVID:
curHALData = initAT3DGetHALData();
break;
case MCRXVID:
curHALData = initMCRXGetHALData();
break;
}
GDBG_INFO((80, "init96MapBoard: Mapping card into linear memory\n"));
regDesc->hwDep.VG96RegDesc.baseAddress =
pciMapCardMulti( vendorID, deviceID, curHALData->memSize, &devNum, 0 , 0);
if (regDesc->hwDep.VG96RegDesc.baseAddress == NULL) {
#ifdef __WIN32__
MessageBox(NULL, pciGetErrorString(), NULL, MB_OK);
#else
{
#ifdef __linux__
fprintf(stderr, "Failed to map board: %s\n", pciGetErrorString());
exit(1);
#else
/* Set Mode 3 before going */
union REGS
inR, outR;
inR.w.ax = 0x0003;
int386(0x10, &inR, &outR);
fprintf(stderr, "%s\n", pciGetErrorString());
#endif
}
#endif /* __WIN32__ */
exit(1);
return FXFALSE;
}
/* need to initialize sstHW ASAP */
sstHW = regDesc->hwDep.VG96RegDesc.baseAddress;
GDBG_INFO((80, "%s: Mapped Voodoo Rush board at 0x%x\n",
FN_NAME, regDesc->hwDep.VG96RegDesc.baseAddress));
if (curHALData->initGetInfo)
(*curHALData->initGetInfo)(vg96Info);
fifoptr = regDesc->hwDep.VG96RegDesc.fifoApertureBase;
GDBG_INFO((88, "init96MapBoard sstHW = %x\n", sstHW));
/* CHD NOTE: The routine init96SetupRendering MUST Be called from this
routine or all hell brakes loose.
*/
/* detect tmu memory size */
#ifdef __linux__
{
FxBool rv=FXTRUE;
GrScreenResolution_t res = GR_RESOLUTION_640x480;
if (curHALData->initAperture)
(*curHALData->initAperture)(regDesc);
if ( curHALData->initEnableRegs )
rv = curHALData->initEnableRegs( regDesc );
if ( !rv )
return FXFALSE;
init96SetupRendering(regDesc, res);
sst96InitGetTmuInfo((FxU32 *)sstHW, vg96Info);
}
#else
#ifdef __DOS32__
{
/* In dos mode, we do it the way it is supposed to be.
In windows mode, calling initEnableRegs() will change the clock
rate and it makes the refresh looks bad. So we still use the
init96SetVideo() to set up the rendering mode etc.
*/
GrScreenResolution_t res = GR_RESOLUTION_640x480;
FxBool rv = FXTRUE;
if (curHALData->initAperture)
(*curHALData->initAperture)(regDesc);
{
union REGS
inR, outR;
inR.w.ax = 0x4f03;
int386(0x10, &inR, &outR);
oldVidMode = outR.w.bx;
GDBG_INFO((80, "%s: Saving Current video mode (0x%x).\n",
FN_NAME, oldVidMode));
}
if ( !rv )
return FXFALSE;
if ( curHALData->initEnableRegs )
rv = curHALData->initEnableRegs( regDesc );
if ( !rv )
return FXFALSE;
init96SetupRendering(regDesc, res);
sst96InitGetTmuInfo((FxU32 *)sstHW, vg96Info);
}
#else
{
int xres=1, yres=1, fbStride;
GrScreenResolution_t res = GR_RESOLUTION_NONE;
FxBool rv = FXTRUE;
rv = init96SetVideo(0, res,
0, 2, 1,
2, 1, regDesc,
&xres, &yres, &fbStride );
if ( !rv )
return FXFALSE;
sst96InitGetTmuInfo((FxU32 *)sstHW, vg96Info);
init96RestoreVideo(regDesc);
}
#endif
#endif
GDBG_INFO((80, "init96MapBoard: returning FXTRUE\n"));
return FXTRUE;
#undef FN_NAME
} /* init96MapBoard */
#ifndef GDBG_INFO_ON
#define WAITLOOP {\
int nWaits;\
volatile FxU32 waitRes;\
for (nWaits = 0; nWaits < 100000; nWaits++) {\
waitRes = GET(sstHW[0x90 + 0x100000]);\
if (waitRes & 0x80000000) break;\
}\
}
#else
#define WAITLOOP {\
int nWaits;\
volatile FxU32 waitRes;\
for (nWaits = 0; nWaits < 50000; nWaits++) {\
waitRes = sstHW[0x100000];\
if (waitRes & 0x80000000) break;\
}\
}
#endif
#define SWAPPENDING(status) ((status & 0x70) >> 4)
/*-------------------------------------------------------------------
Function: init96SetupRendering
Date: 03-Sep-97
Implementor(s): dow
Library: Init Code for 96
Description:
Arguments:
Return:
-------------------------------------------------------------------*/
static void
init96SetupRendering(InitRegisterDesc *regDesc, GrScreenResolution_t sRes)
{
#define FN_NAME "init96SetupRendering"
FxU32 regVal;
sstHW = regDesc->hwDep.VG96RegDesc.baseAddress;
sstPtr =
(volatile Sstregs *)(SST96_COMMAND_REGS(regDesc->hwDep.VG96RegDesc.baseAddress));
/*------------------------------------------------------------
Initialize Jr and TMU
------------------------------------------------------------*/
GDBG_INFO((80, "%s: Software reset\n", FN_NAME));
SET(sstHW[0x90 + 0x100000], 0xf601); /* (0xf601) init0, sw reset. */
WAITLOOP;
GDBG_INFO((80, "%s: Zero Out CMD FIFO registers\n", FN_NAME));
SET(sstHW[0x100000 + 0x95], 0);
SET(sstHW[0x100000 + 0x94], 0);
SET(sstHW[0x100000 + 0x93], 0);
GDBG_INFO((80, "%s: Setting up Mem FIFO\n", FN_NAME));
GETREGVALFROMENV(regVal, "SST96_FBIJRINIT2", 0x70d20);
SET(sstHW[0x92 + 0x100000], regVal);
/* Off for Host Blt, On for LFB command traffic
Low Priority Request Aging - wait 64 cycles
before answering low priority requests from
AT3D on PUMA - 3F may not be optimal, should
be tweaked later, !!JDT
[24] - PUMA Texture Address Space Mode - 0x1 - 2MB
[23] - PUMA Texture Base Address Mode - 0x1 - 6MB
[12:7] - PUMA Low Priority Grant Limit Cnt - 0x0
[6] - PUMA Low Prorirty Grant Limit Enable - 0x0
[5:0] - PUMA Low Priority Request Delay Cnt - 0x1f - 32 ccls
Setting to 0x3f ( max ) seems to cripple windows/d3d
maybe blt operations suffer???
*/
GDBG_INFO((80, "%s: Setting low priority request aging.\n", FN_NAME));
/*
* If we're running at a high resolution, don't starve AT3D's
* video refresh. XXX FIXME for AT3d only
*/
if (sRes == GR_RESOLUTION_NONE) {
/* set the lpr delay to 0. It was 0x10 and the video refresh was not correct */
GETREGVALFROMENV(regVal, "SST96_FBIJRINIT1", 0x01800000);
SET(sstHW[0x91 + 0x100000], regVal);
} else {
GETREGVALFROMENV(regVal, "SST96_FBIJRINIT1", 0x0180003f);
if (myGetenv("SST96_MEMORYHINT")) {
regVal |= (0x1f << 13);
}
SET(sstHW[0x91 + 0x100000],regVal);
}
/* Come out of Reset
[17] - Serial Status Xfer Mode - 0x0 - rising edge
[16:12] - TREX-To-FBI High Water Mark - 0xf
[11:8] - TREX-To-FBI Bus Clock Delay - 0x6
*/
GDBG_INFO((80, "%s: Coming out of FBI reset\n", FN_NAME));
GETREGVALFROMENV(regVal, "SST96_FBIJRINIT0", 0xf600);
SET(sstHW[0x90 + 0x100000], regVal); /* Bit 1 disables tmu */
WAITLOOP;
GDBG_INFO((80, "%s: Setting TMU FT & TF delays\n", FN_NAME));
{
FxU32 trexinit0, trexinit1;
if( !myGetenv(("SST_TREX0INIT0")) ||
(sscanf(myGetenv(("SST_TREX0INIT0")), "%i", &trexinit0) != 1) ) {
trexinit0 = 0x05441; /* TREXINIT0 */
}
if( !myGetenv(("SST_TREX0INIT1")) ||
(sscanf(myGetenv(("SST_TREX0INIT1")), "%i", &trexinit1) != 1) ) {
trexinit1 = 0x3643c; /* TREXINIT1 */
}
SET(sstHW[0xc7 + 0x100000], trexinit0); /* TREXINIT0 */
SET(sstHW[0xc8 + 0x100000], trexinit1); /* TREXINIT1 */
}
WAITLOOP;
#undef FN_NAME
} /* init96SetupRendering */
/*-------------------------------------------------------------------
Function: initSet96Video
Date: 10/17
Implementor(s): jdt, murali
Library: init96
Description:
1 - Set video mode
2 - Enable Direct Writes to Jr
3 - Put Jr registers in Reset
3 - Set up Color Buffer Registers
Arguments
Return:
FXFALSE - fail
FXTRUE - pass
-------------------------------------------------------------------*/
INITVG96ENTRY(init96SetVideo, FxBool ,
( FxU32 hWnd,
GrScreenResolution_t sRes,
GrScreenRefresh_t vRefresh,
InitColorFormat_t cFormat,
InitOriginLocation_t yOrigin,
int nColBuffers,
int nAuxBuffers,
InitRegisterDesc *regDesc,
int *xres,
int *yres,
int *fbStride) )
{
#define FN_NAME "init96SetVideo"
FxBool rv = FXTRUE;
InitSwapType_t swapType = 0;
InitBufDesc_t bufDesc[NUM_BUFS];
FxU32 nTries = 0, status;
FxU32 regVal;
int i;
for (i = 0; i < NUM_BUFS; i++)
bufDesc[i].bufType = INIT_BUFFER_NONE;
if (myGetenv("SST96_FORCE_TRIPLE"))
nColBuffers = 3;
GDBG_INFO((80, "%s: %d Color Buffers\n", FN_NAME, nColBuffers));
GDBG_INFO((80, "(%s) hWnd=%x, sRes=%d, yOrg=%d, ncb=%d, nab=%d\n",
FN_NAME, hWnd, sRes, yOrigin, nColBuffers, nAuxBuffers));
/* YO! Fix this comment
XXX this needs to be moved to post SetVideo code ??? */
GDBG_INFO((80, "%s: Initializing Command Aperture\n", FN_NAME));
if (curHALData->initAperture)
(*curHALData->initAperture)(regDesc);
#ifdef __DOS32__
{
union REGS
inR, outR;
inR.w.ax = 0x4f03;
int386(0x10, &inR, &outR);
oldVidMode = outR.w.bx;
GDBG_INFO((80, "%s: Saving Current video mode (0x%x).\n",
FN_NAME, oldVidMode));
}
#endif /* __DOS32__ */
/*-------------------------------------
Set Video Mode
-------------------------------------*/
/* this goes through the dxdrvr.c which is a misnomer
which will persist for the time being, in dos
this does not have anything to do with directX */
#ifdef __linux__
if (!linOpen(hWnd, sRes, vRefresh, cFormat, yOrigin,
nColBuffers, nAuxBuffers, bufDesc,
xres, yres, &swapType)) {
#else
if (!dxOpen(hWnd, sRes, vRefresh, cFormat, yOrigin,
nColBuffers, nAuxBuffers, bufDesc,
xres, yres, &swapType)) {
#endif
GDBG_INFO((80, "Failed dxOpen\n"));
rv = FXFALSE;
goto BAIL;
}
#ifdef GDBG_INFO_ON
for (i = 0; i < nColBuffers; i++) {
GDBG_INFO((80, "%s: bufDesc[%d]:\n", FN_NAME, i));
GDBG_INFO((80, "%s: bufDesc.bufType = %s\n",
FN_NAME, bufTypeNames[bufDesc[i].bufType]));
GDBG_INFO((80, "%s: bufDesc.bufOffset = 0x%x\n",
FN_NAME, bufDesc[i].bufOffset ));
GDBG_INFO((80, "%s: bufDesc.bufStride = 0x%x\n",
FN_NAME, bufDesc[i].bufStride));
GDBG_INFO((80, "%s: bufDesc.bufBPP = 0x%x\n",
FN_NAME, bufDesc[i].bufBPP));
}
#endif
if ( !rv ) goto BAIL;
/*-------------------------------------
Enable Direct Writes to JR
-------------------------------------*/
if ( curHALData->initEnableRegs )
rv = curHALData->initEnableRegs( regDesc );
if ( !rv ) goto BAIL;
init96SetupRendering(regDesc, sRes);
cachedYOrigin = yOrigin; /* Used later for init96Control */
cachedSwapType = swapType;
/*
** Set Up Color Buffer Registers & triple buffering if necessary.
*/
maxBuffer = (nColBuffers < 2) ? 2 : nColBuffers;
maxBufIdx = maxBuffer - 1;
GDBG_INFO((80, "%s: maxBuffer = %d, maxBufIdx = %d\n",
FN_NAME, maxBuffer, maxBufIdx));
/* Send as many swapbuffers as status says are necessary */
{
FxU32
pending = 7; /* # Swaps pending */
GDBG_INFO((80,
"%s: Sending %d swapbufferCMDs\n",
FN_NAME,
pending));
while (pending) {
FxU32
tries = 0;
GDBG_INFO((80, "%s: %d swaps pending\n", FN_NAME, pending)) ;
status = sstHW[0x100000];
pending = SWAPPENDING(status);
while (pending--) {
SET(sstPtr->swapbufferCMD, 1);
status = sstHW[0x100000]; /* bug #1152 */
ADVANCE_BUFFERS(dfb);
WAITLOOP;
}
do {
++tries;
status = sstHW[0x100000];
GDBG_INFO((120, "%s: Serial status = 0x%x\n", FN_NAME, status));
pending = SWAPPENDING(status);
if (tries > MAXTRIES) {
GDBG_INFO((80, "%s: Bailing out after %d tries to get swap buffer pending to decrement\n", FN_NAME, tries));
rv = FXFALSE;
goto BAIL;
}
} while (pending);
}
/* Clear counters with a NOP */
SET(sstHW[0x42 + 0x100000], 1); /* NOP cmd */
/* Wait for idle */
do {
if (nTries > MAXTRIES) {
GDBG_INFO((80,
"%s: Bailing out and returning false after %d checks for idle.\n", FN_NAME, nTries-1));
return FXFALSE;
}
++nTries;
status = sstHW[0x100000];
GDBG_INFO((80,
"%s: Serial status after soft reset: 0x%x\n",
FN_NAME,
status));
} while (status & 0x1);
} /* end of swap buffer block */
if (tripleBuffering) {
GETREGVALFROMENV(regVal, "SST96_FBIJRINIT0", 0xf600);
regVal |= (1 << 2);
GDBG_INFO((80, "%s: Enabling triple buffering.\n", FN_NAME));
/* dram read to write fast timing enable. bit 7 */
if (myGetenv("SST96_MEMORYHINT")) {
regVal |= (0x1 << 7);
}
SET(sstHW[0x90 + 0x100000], regVal); /* Bit 1 disables tmu */
}
/* Need to be converted to indices dfbFront.... rfbFront.... */
dfbFrontIdx = 0;
dfbBackIdx = 1;
dfbRenderIdx = dfbBackIdx;
rfbFrontIdx = 0;
rfbBackIdx = 1;
rfbRenderIdx = rfbBackIdx;
rv = init96LoadBufRegs(NUM_BUFS, bufDesc, *xres, *yres, regDesc);
if ( !rv ) {
GDBG_INFO((80, "Failed init96LoadBufRegs\n"));
goto BAIL;
}
/*-------------------------------------
Set up Page Flipping
-------------------------------------*/
WAITLOOP;
#if !defined( INIT96VGASWAP ) && !defined( __linux__ )
{
FxU32 buf[MAX_BUF];
int i;
for (i=0; i<maxBuffer; i++) buf[i] = bI[i].dfb;
/* Explicitly clear swap control things */
curHALData->initSwapTiles = NULL;
if (curHALData->initUseTiles && (swapType == INIT_SWAP_FLIP)) {
#ifdef H3D
(*curHALData->initUseTiles)(regDesc,
buf,
maxBuffer,
bI[0].dfbStride,
*xres,
*yres,
GR_RESOLUTION_IS_AUTOFLIPPED(sRes) );
#else
(*curHALData->initUseTiles)(regDesc,
buf,
maxBuffer,
bI[0].dfbStride,
*xres,
*yres );
#endif
}
}
#endif
*fbStride = (bI[1].dfbStride>>1);
GDBG_INFO(( 200, "frame buffer stride: %d\n", *fbStride ));
BAIL:
return rv;
#undef FN_NAME
} /* init96SetVideo */
/*-------------------------------------------------------------------
Function: init96RestoreVideo
Date: 3/16
Implementor(s): jdt
Library: init96
Description:
Disable Direct Hardware Access
Restore the video to it's initial state
Arguments:
none
Return:
none
-------------------------------------------------------------------*/
INITVG96ENTRY(init96RestoreVideo, void, ( InitRegisterDesc *regDesc )) {
#define FN_NAME "init96RestoreVideo"
if ( curHALData->initDisableRegs )
curHALData->initDisableRegs( regDesc );
#if defined( __WIN32__ ) && !defined( INIT_HOOPTI )
dxClose();
#elif defined( __DOS32__ )
{
static union REGS
inR, outR;
GDBG_INFO((80, "%s: Restoring VESA Mode 0x%x\n", FN_NAME, oldVidMode));
inR.w.ax = 0x4f02;
inR.w.bx = oldVidMode;
int386( 0x10, &inR, &outR );
}
#elif defined( __linux__ )
linClose();
#endif
#undef FN_NAME
} /* init96RestoreVideo */
/*-------------------------------------------------------------------
Function: init96EnableTransport
Date: 3/17
Implementor(s): jdt
Library: init96
Description:
Enable the JR command transport and return pertinant fifo
information to the caller
Arguments:
info - structure to fill with info about the FIFO
Return:
FXTRUE - succeed
FXFALSE - fail
-------------------------------------------------------------------*/
INITVG96ENTRY(init96EnableTransport, FxBool, ( InitFIFOData *info, InitRegisterDesc* regDesc))
{
#define FN_NAME "init96EnableTransport"
FxBool rv = FXTRUE;
FxU32 lo, hi, sz, th;
FxU32
fifoPhysBaseAddress,
fifoPhysSize;
FxBool
res;
PciMemType
fifoMemType;
GDBG_INFO((80, "%s\n", FN_NAME));
/*------------------------------------------------------------
Enable the Off Chip Fifo
------------------------------------------------------------*/
/* These are defined in sst.c for now */
lo = (fifoStart >> 12); /* physaddr of 1st 4k page */
hi = (fifoEnd >> 12); /* physaddr of last 4k page */
sz = (hi - lo + 1) << 12; /* bytes */
th = (hi - lo) - 3; /* threshold, in 4k pages. */
/* Generate virtual addresses for the pointers. */
fifovirt = (FxU32 *)&sstHW[lo << 10];
fifophys = lo << 12;
fifomax = sz;
fifocur = 0;
fifoptr = fifovirt;
fifosize = 4096; /* initially, set to 4k */
fifolfb = 1;
/* First disable the off-chip fifo */
GDBG_INFO((80, "%s: Disabling off-chip FIFO\n", FN_NAME));
SET(sstHW[0x100000 + 0x93], 0);
/* FbijrInit4 - 0x94 - entry count */
SET(sstHW[0x100000 + 0x94], 0);
/* FbijrInit5 - 0x95 - read pointer */
SET(sstHW[0x100000 + 0x95], lo << 9);
/* Default size to page checking mode.
*
* NB: This will get overwritten later if we're using
* the other wrapping code.
*/
info->hwDep.vg96FIFOData.fifoSize = fifosize;
/* Store fifo data to info */
info->hwDep.vg96FIFOData.fifoVirt = (FxU32*)fifovirt;
info->hwDep.vg96FIFOData.fifoMax = fifomax;
info->hwDep.vg96FIFOData.fifoPhys = fifophys;
info->hwDep.vg96FIFOData.fifoCur = fifocur;
info->hwDep.vg96FIFOData.fifoLfb = fifolfb;
/* Set up alternate wrapping values.
*
* NB: This *MUST* come before the processor dependent
* fifo ptr advancing that we do below.
*/
#if SST96_ALT_FIFO_WRAP
/* Assume hw is still at the start of the fifo */
info->hwDep.vg96FIFOData.fifoRead = (FxU32)fifovirt;
info->hwDep.vg96FIFOData.roomToEnd = fifomax;
info->hwDep.vg96FIFOData.fifoSize =
info->hwDep.vg96FIFOData.roomToReadPtr = fifomax - sizeof(FxU32);
info->hwDep.vg96FIFOData.regDesc = regDesc;
#endif /* SST96_ALT_FIFO_WRAP */
#if GL_X86
if (info->cpuType == 6) {
/*
** Now, write 128 DWORDS of NULL to the FIFO, so the FIFO read
** pointer trails the FIFO write pointer by 128 DWORDS. The state
** setting code fences every 128 DWORDS.
*/
GDBG_INFO((125, "%s: Advancing write pointer 128 DWORDS beyond read.\n",
FN_NAME));
do {
*fifoptr++ = 0L;
info->hwDep.vg96FIFOData.fifoSize -= 4;
} while (((FxU32) fifoptr) & 0xff);
} else {
GDBG_INFO((125, "%s: No need for write pointer advance.\n",
FN_NAME));
}
#endif
/*
** NOTE TO ALL FOOLS WHO TREAD HERE
**
** It is VITALLY important to enable the FIFO AFTER the
** P6 Lag Of Love(tm), instead of before, otherwise the FIFO will
** become horribly corrupted.
*/
/* FbiJrInit3 - 0x93 - Load up offchip fifo register */
GDBG_INFO((80, "%s: Loading up of offchip fifo register\n", FN_NAME));
SET(sstHW[0x100000 + 0x93], 1 | (lo << 1) | (hi << 11) | (th << 21));
/* Set the fifo ptr now that we really know where its going to start
* for the client code.
*/
info->hwDep.vg96FIFOData.fifoPtr = (FxU32*)fifoptr;
/* Turn on Write combining for the FIFO */
pciGetConfigData(PCI_BASE_ADDRESS_0, devNum, &physAddr);
fifoPhysBaseAddress = physAddr + fifoStart;
fifoPhysSize = fifoEnd - fifoStart;
fifoMemType = PciMemTypeWriteCombining;
res = pciFindMTRRMatch(fifoPhysBaseAddress, fifoPhysSize,
fifoMemType, &fifoMTRRNum);
if (!res) {
res = pciFindFreeMTRR(&fifoMTRRNum);
}
if (res)
pciSetMTRR(fifoMTRRNum, fifoPhysBaseAddress, fifoPhysSize, fifoMemType);
else {
GDBG_INFO((80, "%s: Couldn't get free or used MTRR!\n"));
}
return rv;
#undef FN_NAME
} /* init96EnableTransport */
/*-------------------------------------------------------------------
Function: init96DisableTransport
Date: 3/16
Implementor(s): jdt
Library: init96
Description:
Put the command transport in a safe state
Arguments:
Return:
-------------------------------------------------------------------*/
INITVG96ENTRY(init96DisableTransport, void, ( void ))
{
#define FN_NAME "init96DisableTransport"
while (*(volatile FxU32 *)sstPtr & 1);
SET(sstHW[0x100000 + 0x90], 0xf601); /* (0xf601) init0, sw reset. */
SET(sstHW[0x100000 + 0x95], 0);
SET(sstHW[0x100000 + 0x94], 0);
SET(sstHW[0x100000 + 0x93], 0);
#if SST96_ALT_FIFO_WRAP
GDBG_INFO((80, "%s: Fifo Statistics - Wrapped:%ld Stalled:%ld\n",
numWraps, numStalls));
#endif /* SST96_ALT_FIFO_WRAP */
/* Clear the MTRR */
pciSetMTRR(fifoMTRRNum, 0, 0, 0);
#undef FN_NAME
} /* init96DisableTransport */
/*-------------------------------------------------------------------
Function: init96Swap
Date: 13-Feb-97
Implementor(s): jdt, dow, murali
Library: Init Code for VG96
Description:
Performs VG96 buffer swap
Arguments:
code: usually vsync wait option
wcb: method for writing to hardware
Return:
-------------------------------------------------------------------*/
INITVG96ENTRY(init96Swap, void ,
(FxU32 code, InitRegisterDesc *rd, Init96WriteMethod *wcb) )
{
#define FN_NAME "init96Swap"
FxU32 status;
GDBG_INFO((80, "init96Swap()\n"));
/*
* For improved speed we take the following steps
* 1. remove the status checking
* 2. modify grBufferNumPending so it does not need to do P6 nudge code
* 3. add one p6 nudge code
* Here is step 1. Goto grBufferNumPending() in gglide.c to continue.
*
do {
GDBG_INFO((120, "%s: Serial status = 0x%x\n", FN_NAME, status));
status = *rd->hwDep.VG96RegDesc.serialStatus;
} while (status & 0x1);
*/
if (cachedSwapType == INIT_SWAP_FLIP) {
#ifdef __linux__
FxU32
offset;
/* Wait for idle */
do {
status = sstHW[0x100000];
} while (status & 0x1);
offset = bI[rfbRenderIdx].dfbBase;
linFlip(offset);
#else
#ifndef INIT96VGASWAP
/* Direct Write to the Swap Pending register */
GDBG_INFO((80, "init96Swap: Sending sapppendCMD\n"));
GDBG_INFO((80, " Direct Write of register 0x%x with value 0x%x\n", ((((FxU32) (&sstPtr->swappendCMD)) - (((FxU32) sstPtr) + 0x100000)) >> 2), 1));
sstPtr->swappendCMD = 0x1;
{
static FxBool gotEnv = FXFALSE;
static FxBool overrideSwap;
static FxU32 overrideVal;
if (gotEnv == FXFALSE) {
const char *envVal;
if ((envVal = myGetenv("SST96_INITSWAPCOUNT")) != NULL) {
sscanf(envVal, "%x", &overrideVal);
GDBG_INFO((80, "%s: environment SST96_INITSWAPCOUNT (0x%x) overrode code\n",
FN_NAME, overrideVal));
overrideSwap = FXTRUE;
}
gotEnv = FXTRUE;
}
if (overrideSwap == FXTRUE)
code = overrideVal;
}
GDBG_INFO((80, "%s: Sending swapbufferCMD (0x%x) via FIFO callback\n",
FN_NAME, code));
wcb( (FxU32*)&(sstPtr->swapbufferCMD), 1 );
status = sstHW[0x100000]; /* bug #1152 */
/* Use arrays & rotate for triple buffering */
#else /* Swapping With VGA */
/*
* This is for swapping by changing the VGA serial start register.
* a.k.a "Page flipping"
*/
FxU32
offset;
FxU8
tmp,
serialOverflow;
GDBG_INFO((210, "%s: Swapping With VGA\n", FN_NAME));
/* Wait for idle */
do {
status = sstPtr->status & 0x1;
} while (status & 0x1);
offset = bI[rfbRenderIdx].dfb;
GDBG_INFO((80, "%s: Swapping to offset 0x%x\n", FN_NAME, offset));
/* Fetch serial overflow and clear low nibble for serial start */
CRTC_GET(AR_CRTC_SERIAL_OVERFLOW_INDEX, serialOverflow);
serialOverflow &= 0xF0;
/* Make sure scanout within active display */
do {
INP(VGA_INPUT_STATUS_1C, tmp);
} while (tmp & VIS1C_PIXEL_DISPLAY_INACTIVE);
/* Set serial address */
/* For some reason unknown to me, this is set to the byte offset / 4,
or perhaps the offset in dwords */
/* Top nibble */
tmp = (FxU8) ((offset >> (2+16)) & 0x0F);
CRTC_SET(AR_CRTC_SERIAL_OVERFLOW_INDEX, serialOverflow | tmp);
/* Middle byte */
tmp = (FxU8) ((offset >> (2+8)) & 0xFF);
CRTC_SET(VR_CRTC_SERIAL_START_ADDRESS_HI_INDEX, tmp);
/* Low byte */
tmp = (FxU8) ((offset >> 2) & 0xFF);
CRTC_SET(VR_CRTC_SERIAL_START_ADDRESS_LO_INDEX, tmp);
/* Save away */
do {
INP(VGA_INPUT_STATUS_1C, tmp);
} while (tmp & VIS1C_VERTICAL_RETRACE_ACTIVE);
do {
INP(VGA_INPUT_STATUS_1C, tmp);
} while (!(tmp & VIS1C_VERTICAL_RETRACE_ACTIVE));
#endif
#endif
/* dpc - 26 jan 1998
* Some hw, macronix, requires that we diddle w/ even more bits
* when we do the swap.
*/
if(curHALData->initSwapTiles != NULL) (*curHALData->initSwapTiles)(rd);
ADVANCE_BUFFERS(rfb);
GDBG_INFO((80, "%s: Setting colBufferSetup (0x%x, 0%x) via FIFO callback\n",
FN_NAME, bI[rfbRenderIdx].rfb,
bI[rfbRenderIdx].rfb));
wcb( (FxU32*)&(sstPtr->colBufferSetup), bI[rfbRenderIdx].rfb );
} else {
while ((*rd->hwDep.VG96RegDesc.serialStatus) & 0x1);
#ifdef __linux__
do {
status = sstHW[0x100000];
} while (status & 0x1);
linSwap(code);
#else
dxSwap(code);
#endif
}
GDBG_INFO((80, "%s: returning\n", FN_NAME));
return;
#undef FN_NAME
} /* init96Swap */
/*-------------------------------------------------------------------
Function: init96Idle
Date: 13-Feb-97
Implementor(s): dow, jdt, murali
Library: Init Code for VG96
Description:
Arguments:
Return:
-------------------------------------------------------------------*/
INITVG96ENTRY(init96Idle, void , (Init96WriteMethod *wcb) )
{
#define FN_NAME "init96Idle"
volatile FxU32 *statReg = (volatile FxU32 *) &sstPtr->status;
wcb((FxU32*)&sstPtr->nopCMD, 0);
while ( (*statReg) & 0x1 ) { };
#undef FN_NAME
} /* init96Idle */
/*-------------------------------------------------------------------
Function: init96GetBufferPtr
Date: 2/25
Implementor(s): jdt
Library: init code for vg96
Description:
Get a pointer to a specified buffer ( changes at swaps )
Arguments:
buffer - constant defining buffer
Return:
void opinter to buffer
-------------------------------------------------------------------*/
#define LFB_OFFSET( X ) ( X & 0x3fffff ) /* was 0x1fffff */
INITVG96ENTRY(init96GetBufferPtr, void*, (InitBuffer_t buffer, int *strideBytes))
{
#define FN_NAME "init96GetBufferPtr"
void *rv = 0;
GDBG_INFO((80,"%s\n", FN_NAME));
switch( buffer ) {
case INIT_BUFFER_FRONTBUFFER:
GDBG_INFO((80, " get front buffer pointer" ));
rv = (void*)(((char*)sstHW)+bI[rfbFrontIdx].dfbBase);
*strideBytes = bI[rfbFrontIdx].dfbStride;
break;
case INIT_BUFFER_TRIPLEBUFFER:
rv = (void*)(((char*)sstHW)+bI[rfbTripleIdx].dfbBase);
*strideBytes = bI[rfbTripleIdx].dfbStride;
GDBG_INFO((80, " get triple buffer pointer" ));
break;
case INIT_BUFFER_BACKBUFFER:
rv = (void*)(((char*)sstHW)+bI[rfbBackIdx].dfbBase);
*strideBytes = bI[rfbBackIdx].dfbStride;
GDBG_INFO((80, " get back buffer pointer" ));
break;
case INIT_BUFFER_AUXBUFFER:
rv = (void*)(((char*)sstHW) + LFB_OFFSET(ab0Base));
/* [dBorca]
* used to be ab0, but I changed it to ab0Base.
* VG96STRIDE(ab0Stride) doesn't really matter,
* because we stripped off the high bits anyway!
*/
*strideBytes = ab0Stride;
GDBG_INFO((80, " get aux buffer pointer" ));
break;
}
GDBG_INFO((80, "%s: strideBytes %.05d\n", FN_NAME, *strideBytes ));
GDBG_INFO((80, "%s: returning 0x%x\n", FN_NAME, rv ));
return rv;
#undef FN_NAME
} /* init96GetBufferPtr */
#undef LFB_OFFSET
/*-------------------------------------------------------------------
Function: init96RenderBuffer
Date: 2/25
Implementor(s): jdt
Library: init96
Description:
Set the current render buffer
Arguments:
buffer - which buffer to send render ops to
Return:
none
-------------------------------------------------------------------*/
INITVG96ENTRY(init96RenderBuffer, void, (InitBuffer_t buffer,Init96WriteMethod *wcb))
{
#define FN_NAME "init96RenderBuffer"
GDBG_INFO((80,"%s\n", FN_NAME));
/* Mess around with indeces here i.e. rfbRender = rfbBack ....*/
switch( buffer ) {
case INIT_BUFFER_BACKBUFFER:
rfbRenderIdx = rfbBackIdx;
break;
case INIT_BUFFER_FRONTBUFFER:
rfbRenderIdx = rfbFrontIdx;
break;
}
wcb( (FxU32*)&(sstPtr->colBufferSetup), bI[rfbRenderIdx].rfb );
#undef FN_NAME
} /* init96RenderBuffer */
/*-------------------------------------------------------------------
Function: init96Origin
Date: 2/26
Implementor(s): jdt
Library: init96
Description:
Set the yOrigin
Arguments:
origin
Return:
none
-------------------------------------------------------------------*/
INITVG96ENTRY(init96Origin, void, (InitOriginLocation_t origin,Init96WriteMethod *wcb))
{
#define FN_NAME "init96Origin"
int i;
GDBG_INFO((80,"%s\n", FN_NAME));
/* Once the bases and tops are set, this is pretty straight forward */
switch ( origin ) {
case INIT_ORIGIN_UPPER_LEFT:
for (i=0; i<maxBuffer; i++) {
bI[i].rfb = bI[i].dfbBase | VG96STRIDE(bI[i].dfbStride);
}
ab0 = ab0Base | VG96STRIDE(ab0Stride);
break;
case INIT_ORIGIN_LOWER_LEFT:
for (i=0; i<maxBuffer; i++) {
bI[i].rfb = bI[i].dfbTop | VG96STRIDE(bI[i].dfbStride);
}
ab0 = ab0Top | VG96STRIDE(ab0Stride);
break;
}
wcb( (FxU32*)&(sstPtr->colBufferSetup), bI[rfbRenderIdx].rfb);
wcb( (FxU32*)&(sstPtr->auxBufferSetup), ab0 );
#undef FN_NAME
} /* init96Origin */
/*-------------------------------------------------------------------
Function: init96ResyncBuffers
Date: 07-Mar-97
Implementor(s): murali
Library: Init Code for VG96
Description:
Performs VG96 buffer resync buffers
Arguments:
Return:
-------------------------------------------------------------------*/
INITVG96ENTRY(init96Control, FxBool , ( FxU32 code, InitRegisterDesc *regDesc))
{
#define FN_NAME "init96Control"
int xRes, yRes;
InitBufDesc_t bufDesc[5];
GDBG_INFO((80, "(%s)\n", FN_NAME));
if ( !sstHW ) return FXFALSE;
#ifdef __linux__
if (!linControl(code, bufDesc, &xRes, &yRes)) {
#else
if (!dxControl(code, bufDesc, &xRes, &yRes)) {
#endif
GDBG_INFO((80, "dxControl failed!\n"));
return FXFALSE;
}
if (!init96LoadBufRegs(NUM_BUFS, bufDesc, xRes, yRes, regDesc)) {
GDBG_INFO((80, "init96LoadBufRegs failed\n"));
}
GDBG_INFO((80, "%s: Returning TRUE\n", FN_NAME));
return (yRes << 16) | (xRes);
#undef FN_NAME
} /* init96Control */
#if SST96_ALT_FIFO_WRAP
#define MIN(__x, __y) (((__x) < (__y)) ? (__x) : (__y))
#define MAX(__x, __y) (((__x) < (__y)) ? (__y) : (__x))
/* Macro to get the hw's read ptr located somewhere in the frame
* buffer address space.
*/
#define SST96_HW_FIFO(__hwP, __regP) ((FxU32)(__hwP) + \
(*((volatile FxU32*)(((FxU32)(__regP)) + (0x95 << 12))) << 3))
INITVG96ENTRY(init96WrapFIFO,
FxBool,
(InitRegisterDesc* rd, InitFIFOData* fifoP))
{
#define FN_NAME "init96WrapFIFO"
const FxI32 blockSize = fifoP->hwDep.vg96FIFOData.blockSize;
#if GDBG_INFO_ON
/* no ASSERT macro. Just die if debugging is on. */
if (blockSize == 0xDEADBEEF) *(FxU32*)NULL = 0x00;
#endif
{
const FxI32 writes = (MIN(fifoP->hwDep.vg96FIFOData.roomToReadPtr,
fifoP->hwDep.vg96FIFOData.roomToEnd) -
fifoP->hwDep.vg96FIFOData.fifoSize);
fifoP->hwDep.vg96FIFOData.roomToReadPtr -= writes;
fifoP->hwDep.vg96FIFOData.roomToEnd -= writes;
}
again:
/* do we need to stall? */
{
FxU32 lastHwRead = fifoP->hwDep.vg96FIFOData.fifoRead;
FxI32 roomToReadPtr = fifoP->hwDep.vg96FIFOData.roomToReadPtr;
while (roomToReadPtr < blockSize) {
const FxU32 curReadPtr = SST96_HW_FIFO(sstHW, sstPtr);
const FxU32 curReadDist = curReadPtr - lastHwRead;
roomToReadPtr += curReadDist;
if (lastHwRead > curReadPtr) roomToReadPtr += fifoP->hwDep.vg96FIFOData.fifoMax;
lastHwRead = curReadPtr;
}
GDBG_INFO((80, FN_NAME"_Wait : (0x%X : 0x%X) : (0x%X : 0x%X)\n",
(FxU32)fifoP->hwDep.vg96FIFOData.fifoPtr, blockSize,
fifoP->hwDep.vg96FIFOData.roomToReadPtr,
fifoP->hwDep.vg96FIFOData.roomToEnd));
fifoP->hwDep.vg96FIFOData.fifoRead = lastHwRead;
fifoP->hwDep.vg96FIFOData.roomToReadPtr = roomToReadPtr;
}
/* wrap to front */
if (fifoP->hwDep.vg96FIFOData.roomToEnd <= blockSize) {
/* Pad out all of the fifo, save the last entry, w/ NUL ops. The
* last entry is written once we know that we are not going to
* overflow the entry count. Oh, for the cvg JMP packet type.
*/
#define kFifoPadDelay (sizeof(FxU32) << 1)
#if GDBG_INFO_ON
#define JU_JU_STALL numJuJuStalls++
#else
#define JU_JU_STALL /* Do Nothing */
#endif
{
volatile FxU32* fifoPtr = fifoP->hwDep.vg96FIFOData.fifoPtr;
const FxU32 wrapAddr = ((FxU32)fifoP->hwDep.vg96FIFOData.fifoVirt +
fifoP->hwDep.vg96FIFOData.fifoMax);
/* Do the padding up to the last entry or so. */
while((FxU32)fifoPtr < wrapAddr - kFifoPadDelay) *fifoPtr++ = 0x00UL;
/* Bad ju-ju awaits the person who wraps the fifo when the hw
* ptr is at the start of the fifo. (I've seen it happen, and
* it is not pretty.)
*/
{
volatile FxU32* serialStatus =
fifoP->hwDep.vg96FIFOData.regDesc->hwDep.VG96RegDesc.serialStatus;
if ((*serialStatus & 0x80) != 0x00) {
GDBG_INFO((85, FN_NAME": fifo close to full. Waiting(0x%X)...\n", numJuJuStalls));
while((*serialStatus & 0x80) != 0x00) JU_JU_STALL;
GDBG_INFO((85, FN_NAME": fifo drained (0x%X)\n", numJuJuStalls));
}
}
/* Finish the padding of the rest of the fifo to the end */
while((FxU32)fifoPtr < wrapAddr) *fifoPtr++ = 0x00UL;
}
#undef JU_JU_STALL
#undef kFifoPadDelay
GDBG_INFO((80, FN_NAME"_Wrap : (0x%X : 0x%X) : (0x%X : 0x%X)\n",
(FxU32)fifoP->hwDep.vg96FIFOData.fifoPtr, blockSize,
fifoP->hwDep.vg96FIFOData.roomToReadPtr,
fifoP->hwDep.vg96FIFOData.roomToEnd));
fifoP->hwDep.vg96FIFOData.roomToReadPtr -= fifoP->hwDep.vg96FIFOData.roomToEnd;
fifoP->hwDep.vg96FIFOData.roomToEnd = fifoP->hwDep.vg96FIFOData.fifoMax;
/* Reset fifo ptr to start */
fifoP->hwDep.vg96FIFOData.fifoPtr = fifoP->hwDep.vg96FIFOData.fifoVirt;
goto again;
}
/* compute room left */
fifoP->hwDep.vg96FIFOData.roomToEnd -= blockSize;
fifoP->hwDep.vg96FIFOData.roomToReadPtr -= blockSize;
fifoP->hwDep.vg96FIFOData.fifoSize = MIN(fifoP->hwDep.vg96FIFOData.roomToReadPtr,
fifoP->hwDep.vg96FIFOData.roomToEnd) + blockSize;
GDBG_INFO((80, FN_NAME": (0x%X : 0x%X) : (0x%X : 0x%X) : 0x%X\n",
(FxU32)fifoP->hwDep.vg96FIFOData.fifoPtr, blockSize,
fifoP->hwDep.vg96FIFOData.roomToReadPtr,
fifoP->hwDep.vg96FIFOData.roomToEnd,
fifoP->hwDep.vg96FIFOData.fifoSize));
#if GDBG_INFO_ON
fifoP->hwDep.vg96FIFOData.blockSize = 0xDEADBEEF;
#endif
return FXTRUE;
#undef FN_NAME
}
#else /* !SST96_ALT_FIFO_WRAP */
/*-------------------------------------------------------------------
Function: init96FIFOWait
Date: 12-Jun-97
Implementor(s): dow
Library: Init Code for VG96
Description:
Waits for 0x80 in status
Arguments:
rd: Description of registers.
Return:
Nothing
-------------------------------------------------------------------*/
static void
init96FIFOWait(InitRegisterDesc *rd)
{
#define FN_NAME "init96FIFOWait"
volatile FxU32 *pstatus;
/* Check for more room. */
pstatus = (volatile FxU32 *) rd->hwDep.VG96RegDesc.serialStatus;
if (*pstatus & 0x80) { /* 0x80 is the FIFO threshold */
int timeout;
again:
for (timeout = 0; timeout < 10000000; timeout++) {
if ((*pstatus & 0x80) == 0) break;
}
if (*pstatus & 0x80) {
GDBG_INFO((80, "Lost patience in %s. Status is 0x%x\n",
FN_NAME, *pstatus));
goto again;
}
}
#undef FN_NAME
} /* init96FIFOWait */
/*-------------------------------------------------------------------
Function: init96WrapFIFO
Date: 13-Feb-97
Implementor(s): dow
Library: Init Code for VG96
Description:
Wraps the VG96 FIFO
Arguments:
rd: Description of registers.
Return:
FXTRUE if successful.
-------------------------------------------------------------------*/
INITVG96ENTRY(init96WrapFIFO, FxBool , (InitRegisterDesc *rd, InitFIFOData *fifoData) )
{
#define FN_NAME "init96WrapFIFO"
FxBool rVal;
GDBG_INFO((80,"%s\n", FN_NAME));
while (fifoData->hwDep.vg96FIFOData.fifoSize > 0) {
*fifoData->hwDep.vg96FIFOData.fifoPtr++ = 0L;
fifoData->hwDep.vg96FIFOData.fifoSize -= 4;
}
fifoData->hwDep.vg96FIFOData.fifoCur += 4096;
/* Wrap back to beginning? */
if (fifoData->hwDep.vg96FIFOData.fifoCur >= fifoData->hwDep.vg96FIFOData.fifoMax ) {
static int fifowraps = 0;
fifoData->hwDep.vg96FIFOData.fifoCur = 0;
if ((fifowraps = (fifowraps + 1) & 0xf) == 0) {
GDBG_INFO((80, "%s: Wrapping %s FIFO\n",
FN_NAME,
(fifoData->hwDep.vg96FIFOData.fifoLfb
? "LFB"
: "Video Aperture")));
}
if (fifoData->hwDep.vg96FIFOData.fifoLfb)
fifoData->hwDep.vg96FIFOData.fifoPtr = fifoData->hwDep.vg96FIFOData.fifoVirt;
}
/* */
{
FxU32
fbiJrInit5;
GDBG_INFO((125, "%s: Write = 0x%x\n", FN_NAME,
(FxU32) fifoData->hwDep.vg96FIFOData.fifoPtr -
(FxU32) fifoData->hwDep.vg96FIFOData.fifoVirt));
fbiJrInit5 = *((volatile FxU32 *) (((FxU32) sstPtr) + (0x95 << 12)));
GDBG_INFO((125, "%s: Read = 0x%x\n", FN_NAME,
(fbiJrInit5 << 3) -
(
(FxU32) fifoData->hwDep.vg96FIFOData.fifoVirt -
(FxU32) rd->hwDep.VG96RegDesc.baseAddress
)
));
}
GDBG_INFO((80, "%s: Waiting for more room.\n", FN_NAME));
init96FIFOWait(rd);
/*
** if we get here, then there's room in the FIFO
*/
GDBG_INFO((80, "%s: Got more room.\n", FN_NAME));
/* At this point, we have atleast 1 more page of fifo. */
fifoData->hwDep.vg96FIFOData.fifoSize = 4096;
rVal = FXTRUE;
GDBG_INFO((80, "%s: returning %s\n", FN_NAME, rVal ? "FXTRUE" : "FXFALSE"));
return rVal;
#undef FN_NAME
} /* init96WrapFIFO */
#endif /* !SST96_ALT_FIFO_WRAP */
/*
* This function is used only locally, so none of Chris's decorations
* Load colbufSetup and auxBufSetup registers, given a InitBufDesc_t
*/
static FxBool
init96LoadBufRegs(int nBuffers, InitBufDesc_t *pBufDesc, int xRes,
int yRes, InitRegisterDesc *rd)
{
#define FN_NAME "init96LoadBufRegs"
InitBufDesc_t *pFront = NULL;
InitBufDesc_t *pBack = NULL;
InitBufDesc_t *pTriple = NULL;
InitBufDesc_t *pAux = NULL;
InitBufDesc_t *pFifo = NULL;
int i;
GDBG_INFO((80, "(%s) w = %d, h = %d, n = %d\n",
FN_NAME, xRes, yRes, nBuffers));
if ( !sstHW ) return FXFALSE;
/* Take pBufDesc apart */
while (nBuffers-- > 0) {
switch (pBufDesc->bufType) {
case INIT_BUFFER_FRONTBUFFER:
GDBG_INFO((80, "%s: %s: 0x%x\n",
FN_NAME, bufTypeNames[pBufDesc->bufType], pBufDesc));
pFront = pBufDesc;
break;
case INIT_BUFFER_BACKBUFFER:
GDBG_INFO((80, "%s: %s: 0x%x\n",
FN_NAME, bufTypeNames[pBufDesc->bufType], pBufDesc));
pBack = pBufDesc;
break;
case INIT_BUFFER_AUXBUFFER:
GDBG_INFO((80, "%s: %s: 0x%x\n",
FN_NAME, bufTypeNames[pBufDesc->bufType], pBufDesc));
pAux = pBufDesc;
break;
case INIT_BUFFER_FIFOBUFFER:
GDBG_INFO((80, "%s: %s: 0x%x\n",
FN_NAME, bufTypeNames[pBufDesc->bufType], pBufDesc));
pFifo = pBufDesc;
break;
case INIT_BUFFER_TRIPLEBUFFER:
GDBG_INFO((80, "%s: %s: 0x%x\n",
FN_NAME, bufTypeNames[pBufDesc->bufType], pBufDesc));
pTriple = pBufDesc;
break;
default:
break;
}
pBufDesc++;
}
if (pFront == NULL) return FXFALSE;
if (pBack == NULL) pBack = pFront;
if (pTriple == NULL) pTriple = pFront;
if (pAux == NULL) pAux = pFront;
GDBG_INFO((80,"pFront = %.08x, pBack = %.08x, pTriple = %.08x, pAux = %.08x, pFifo = %.08x\n",
pFront, pBack, pTriple, pAux, pFifo));
if (myGetenv("SST96_FORCEALIGN")) {
FxU32 F, B, T, A;
if (sscanf(myGetenv("SST96_FORCEALIGN"), "%x,%x,%x,%x", &F, &B, &T, &A) == 4)
{
GDBG_INFO((80, "!!!!!GROSS HACK... forcing values!!!!!\n"));
pFront->bufOffset = F;
pBack->bufOffset = B;
pTriple->bufOffset = T;
pAux->bufOffset = A;
}
}
if (pFront) {
GDBG_INFO((80,"F = %.08x, s= %6d\n", pFront->bufOffset, pFront->bufStride));
}
if (pBack) {
GDBG_INFO((80,"B = %.08x, s= %6d\n", pBack ->bufOffset, pBack ->bufStride));
}
if (pTriple) {
GDBG_INFO((80,"T = %.08x, s= %6d\n", pTriple ->bufOffset, pTriple ->bufStride));
}
if (pAux) {
GDBG_INFO((80,"A = %.08x, s= %6d\n", pAux ->bufOffset, pAux ->bufStride));
}
if (pFifo) {
GDBG_INFO((80,"C = %.08x, s= %6d\n", pFifo ->bufOffset, pFifo ->bufStride));
}
/* Fill the arrays here */
bI[0].dfbBase = pFront->bufOffset;
bI[0].dfbStride = pFront->bufStride;
bI[0].dfbTop = pFront->bufOffset + (yRes-1) * pFront->bufStride;
bI[1].dfbBase = pBack->bufOffset;
bI[1].dfbStride = pBack->bufStride;
bI[1].dfbTop = pBack->bufOffset + (yRes-1) * pBack->bufStride;
if (pTriple) {
bI[2].dfbBase = pTriple->bufOffset;
bI[2].dfbStride = pTriple->bufStride;
bI[2].dfbTop = pTriple->bufOffset + (yRes-1) * pTriple->bufStride;
}
ab0Base = pAux->bufOffset;
ab0Stride = pAux ->bufStride;
ab0Top = pAux->bufOffset + (yRes-1) * pAux->bufStride;
for (i=0; i<maxBuffer; i++) {
bI[i].dfb = bI[i].dfbBase | VG96STRIDE(bI[i].dfbStride);
}
if (cachedYOrigin == INIT_ORIGIN_UPPER_LEFT) {
for (i=0; i<maxBuffer; i++) {
bI[i].rfb = bI[i].dfbBase | VG96STRIDE(bI[i].dfbStride);
}
ab0 = ab0Base | VG96STRIDE(ab0Stride);
} else { /* cachedYOrigin == INIT_ORIGIN_LOWER_LEFT */
for (i=0; i<maxBuffer; i++) {
GDBG_INFO((80, "%s: Buffer %d stride = 0x%x\n",
FN_NAME, i, bI[i].dfbStride));
bI[i].rfb = bI[i].dfbTop | VG96STRIDE(bI[i].dfbStride);
GDBG_INFO((80, "%s: setting render buffer %d = 0x%x\n",
FN_NAME, i, bI[i].rfb));
}
ab0 = ab0Top | VG96STRIDE(ab0Stride);
}
GDBG_INFO((80,"%s: dfb0 = %.08x, dfb1 = %.08x, dfb2 = %.08x, ab0 = %.08x\n",
FN_NAME, bI[0].dfb, bI[1].dfb, bI[2].dfb, ab0));
GDBG_INFO((80,"%s: rfb0 = %.08x, rfb1 = %.08x, rfb2 = %.08x, ab0 = %.08x\n",
FN_NAME, bI[0].rfb, bI[1].rfb, bI[2].rfb, ab0));
GDBG_INFO((80,"%s: Setting 0x60 to %.08x, 0x61 to %.08x\n",
FN_NAME, bI[dfbRenderIdx].dfb, ab0));
SET(sstHW[0x60 + 0x100000], bI[rfbRenderIdx].rfb);
SET(sstHW[0x61 + 0x100000], ab0);
if (pFifo == NULL) {
GDBG_INFO((80, "init96LoadBufRegs: Bad pFifo\n"));
return FXFALSE;
}
if (pFifo) {
fifoStart = pFifo->bufOffset;
fifoEnd = pFifo->bufOffset + pFifo->bufStride;
}
GDBG_INFO((80, "%s: Returning TRUE\n", FN_NAME));
return FXTRUE;
#undef FN_NAME
} /* init96LoadBufRegs */
/*-------------------------------------------------------------------
Function: init96GetFBVram
Date: 24-Apr-97
Implementor(s): pgj
Library: Test for 2Mb or 4Mb board
Description: This routine returns the number of bytes of VRAM
on the board. Currently only 2 or 4 MB are returned on
success. Zero is returned of the board is not mapped.
XXX This should be refined in the future. XXX
Arguments: none
Return: n, where n == available VRAM in bytes on the board
-------------------------------------------------------------------*/
INITVG96ENTRY(init96GetFBVram, FxU32 , (void) )
{
#define FN_NAME "init96GetFBVram"
VG96Info info;
if (curHALData->initGetInfo) {
(*curHALData->initGetInfo)(&info);
GDBG_INFO((80, "%s: returning %d bytes\n", FN_NAME, info.vg96Ram));
return info.vg96Ram;
} else {
GDBG_INFO((80, "%s: curHALData not valid!!!\n", FN_NAME));
return 0;
}
#undef FN_NAME
} /* init96GetFBVram */