Files
glide/glide3x/sst1/init/init96/initmcrx.c
sezero 16a4feb6e6 sst1,initmcrx (initMCRXSetVideo): make Macronix Rush cards function under DOS
achieved by commenting out the INIT_ACCESS_DIRECT ifdef.  maybe just defining
INIT_ACCESS_DIRECT works too? that adds a initAT3DWait(100) call for the AT3D
cards. to be revisited / tested in future...
2018-08-05 12:02:59 +03:00

617 lines
15 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
**
*/
#include <3dfx.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#ifndef __linux__
#ifdef __DJGPP__
#include <fxdpmi.h>
#else
#include <conio.h>
#endif
#else
#include <fxpci.h>
#define _inp(port) pioInByte(port);
#define _outp(port,data) pioOutByte(port, data);
#define _outpw(port,data) pioOutWord(port, data);
#endif
#ifdef __DOS32__
#ifdef __DJGPP__
#include <dos.h>
#else
#include <i86.h>
#endif
#endif
#ifdef __WIN32__
#include <windows.h>
#endif /* __WIN32__ */
#define INIT_MCRX_LIB
#define FX_DLL_DEFINITION
#include <fxdll.h>
#include <gdebug.h>
#include <init.h>
#include <initvga.h>
#include "fxinit96.h"
#include "initmcrx.h"
#ifndef BIT
#define BIT(a) (1 << a)
#endif
/* Global Data */
static Init96HALData mcrxHALData = {
0x2000000,
initMCRXAperture,
initMCRXSetVideo,
initMCRXEnableRegs,
initMCRXDisableRegs,
initMCRXWrapFIFO,
initMCRXUseTiles,
initMCRXGetInfo,
NULL, /* initMCRXSwapTiles */
NULL
};
#if 0 /* ??? needed??? XXX */
static FxBool tiling;
#endif
/*-------------------------------------------------------------------
Function: intiMCRXGetHALData
Date: 09-May-97
Implementor(s): dow
Library: Init Code for MCRX
Description:
Arguments:
Return:
address of mcrxHALData
-------------------------------------------------------------------*/
INITMCRXENTRY(initMCRXGetHALData, Init96HALData *, (void) )
{
#define FN_NAME "intiMCRXGetHALData"
return &mcrxHALData;
#undef FN_NAME
} /* intiMCRXGetHALData */
/*-------------------------------------------------------------------
Function: initMCRXAperture
Date: 3-May-97
Implementor(s): dow
Library: Init Code for MCRX
Description:
Initialize rd pointers to access apertures
Arguments:
Return:
-------------------------------------------------------------------*/
INITMCRXENTRY(initMCRXAperture, FxBool , (InitRegisterDesc *rd) )
{
#define FN_NAME "initMCRXAperture"
FxBool
rVal = FXTRUE;
GDBG_INFO((80, "%s:\n", FN_NAME));
rd->hwDep.VG96RegDesc.partnerRegPtr = (FxU32 *)
((FxU32) rd->hwDep.VG96RegDesc.baseAddress +
0x2000000 - 0x20000);
GDBG_INFO((80, "%s: Setting partnerRegPtr to 0x%x\n",
FN_NAME, rd->hwDep.VG96RegDesc.partnerRegPtr));
#if 1
rd->hwDep.VG96RegDesc.serialStatus = (FxU32 *)
((FxU32) rd->hwDep.VG96RegDesc.partnerRegPtr + 0x700);
#else
GDBG_INFO((80, "%s: Working around invalid serial status\n", FN_NAME));
rd->hwDep.VG96RegDesc.serialStatus =
&rd->hwDep.VG96RegDesc.baseAddress[0x100000];
#endif
GDBG_INFO((80, "%s: Setting seial status to 0x%x\n", FN_NAME, rd->hwDep.VG96RegDesc.serialStatus));
/* BOGUS */
rd->hwDep.VG96RegDesc.fifoApertureBase =
(FxU32 *) (((FxU32)rd->hwDep.VG96RegDesc.baseAddress) + 0x400000);
GDBG_INFO((80, "%s: returning TRUE\n", FN_NAME));
return rVal;
#undef FN_NAME
} /* initMCRXAperture */
/* FIXME !! jdt - need to add more resolutions to dos */
INITMCRXENTRY(initMCRXSetVideo, FxBool, (GrScreenResolution_t res, GrScreenRefresh_t refresh, FxU32 *xr, FxU32 *yr ))
{
#define FN_NAME "initMCRXSetVideo"
FxBool rv = FXTRUE;
#if /*defined(INIT_ACCESS_DIRECT) &&*/ defined(__DOS32__)
union REGS r0, r1;
#endif
GDBG_INFO((80, "%s: \n", FN_NAME));
#if /*defined(INIT_ACCESS_DIRECT) &&*/ defined(__DOS32__)
switch( res ) {
case GR_RESOLUTION_320x200:
/* Set up VESA Mode 0x136 - 320x200x16 */
r1.w.ax = 0x4f02;
r1.w.bx = 0x0136;
*xr = 320;
*yr = 200;
rv = FXTRUE;
break;
case GR_RESOLUTION_320x240:
/* Set up VESA Mode 0x137 - 320x240x16 */
r1.w.ax = 0x4f02;
r1.w.bx = 0x0137;
*xr = 320;
*yr = 240;
rv = FXTRUE;
break;
case GR_RESOLUTION_512x384:
/* Set up VESA Mode 0x139 - 512x384x16 */
r1.w.ax = 0x4f02;
r1.w.bx = 0x0139;
*xr = 512;
*yr = 384;
rv = FXTRUE;
break;
case GR_RESOLUTION_640x480:
/* Set up VESA Mode 0x111 - 640x480x16 */
r1.w.ax = 0x4f02;
r1.w.bx = 0x0111;
*xr = 640;
*yr = 480;
rv = FXTRUE;
break;
case GR_RESOLUTION_800x600:
/* Set up VESA Mode 0x114 - 800x600x16 */
r1.w.ax = 0x4f02;
r1.w.bx = 0x0114;
*xr = 800;
*yr = 600;
rv = FXTRUE;
break;
default:
rv = FXFALSE;
break;
}
if (rv == FXTRUE) {
GDBG_INFO((80, "initMCRXSetVideo: Enabling VESA modes\n"));
r0.w.ax = 0x6483;
r0.w.bx = 0x0060;
int386( 0x10, &r0, &r0 );
GDBG_INFO((80, "initMCRXSetVideo: Setting video mode %dx%dx16\n",
*xr, *yr));
int386( 0x10, &r1, &r1 );
}
#endif
GDBG_INFO((80, "%s: returning %s\n", FN_NAME, rv?"TRUE":"FALSE"));
return rv;
#undef FN_NAME
} /* initMCRXSetVideo */
/*-------------------------------------------------------------------
Function: initMCRXEnableRegs
Date: 07-Feb-97
Implementor(s): dow
Library: Init Code for MCRX
Description:
Do all setup necessary to enable direct writes to JR Space
Arguments:
rd - pointer to register description
Return:
True if success, False if Failure
-------------------------------------------------------------------*/
INITMCRXENTRY(initMCRXEnableRegs, FxBool, (InitRegisterDesc *rd))
{
#define FN_NAME "initMCRXEnableRegs"
FxU32
tmp, u;
FxU8
crtcIndex;
FxU16
protState;
const char *envVal;
GDBG_INFO((80, "%s:\n", FN_NAME));
GDBG_INFO((80, "%s: Unprotect\n", FN_NAME));
GDBG_INFO((80, "%s: Save CRTC Index\n", FN_NAME));
INP(0x3c4, crtcIndex);
GDBG_INFO((80, "%s: Save Extended Registers Protection State\n",
FN_NAME));
OUTP(0x3d4, 0x19);
INP(0x3d5, protState);
protState <<= 8;
protState |= 0x19;
GDBG_INFO((80, "%s: Enabling Access to Extended Registers\n", FN_NAME));
OUTPW(0x3d4, 0x8819);
/* Getting initial values of the mclock for later restore */
GDBG_INFO((80, "%s: Getting macronix mclock registers\n", FN_NAME));
OUTP(0x3C4, 0x1A);
INP(0x3C5, rd->hwDep.VG96RegDesc.mclockHi);
OUTP(0x3C4, 0x1B);
INP(0x3C5, rd->hwDep.VG96RegDesc.mclockLo);
GDBG_INFO((80, "%s: mclock registers: (0x%X : 0x%X)\n", FN_NAME,
(FxU32)rd->hwDep.VG96RegDesc.mclockHi, (FxU32)rd->hwDep.VG96RegDesc.mclockHi));
GDBG_INFO((80, "%s: Enabling FBI Jr.\n", FN_NAME));
OUTPW(0x3C4, 0x001F);
GDBG_INFO((80, "%s: Setting clock to 50MHz\n", FN_NAME));
OUTPW(0x3c4, 0x011a);
OUTPW(0x3c4, 0x061b);
/* Macronix reset propogation */
GDBG_INFO((80, "%s: Macronix reset\n", FN_NAME));
OUTPW(0x3c4, 0x081c);
OUTPW(0x3c4, 0x001c);
GDBG_INFO((80, "%s: Hard Reset of FBI Jr.\n", FN_NAME));
OUTPW(0x3d4, 0x0029);
OUTPW(0x3d4, 0x0129);
GDBG_INFO((80, "%s: Enabling PUMA\n", FN_NAME));
CRTC_GET(0x28, tmp);
tmp |= 1;
if ((envVal = myGetenv("MCRX_28")) &&
(sscanf(envVal, "%x", &u) == 1))
tmp = u;
CRTC_SET(0x28, tmp);
GDBG_INFO((80, "%s: Restoring Protection\n", FN_NAME));
OUTP(0x3d4, protState);
GDBG_INFO((80, "%s: Restoring Sequencer Index\n", FN_NAME));
OUTP(0x3c4, crtcIndex);
return FXTRUE;
#undef FN_NAME
} /* initMCRXEnableRegs */
/* FIXME!!! jdt - puma/ram timing fixes need to go here */
INITMCRXENTRY(initMCRXDisableRegs,FxBool,(InitRegisterDesc *rd))
{
#define FN_NAME "initMCRXDisableRegs"
FxU8
seqSave, crtcSave;
FxU16
protState;
FxU32
tmp;
GDBG_INFO((80, "%s:\n", FN_NAME));
GDBG_INFO((80, "%s: Saving Sequencer Index\n", FN_NAME));
INP(0x3c4, seqSave);
GDBG_INFO((80, "%s: Saving CRTC Index\n", FN_NAME));
INP(0x3d4, crtcSave);
GDBG_INFO((80, "%s: Saving Protection State\n", FN_NAME));
OUTP(0x3d4, 0x19);
INP(0x3d5, protState);
protState <<= 9;
protState |= 0x19;
GDBG_INFO((80, "%s: Enabling access to extended registers\n", FN_NAME));
OUTPW(0x3d4, 0x8819);
/* Reset 3Dfx chip via macronix */
GDBG_INFO((80, "%s: Reset 3Dfx via macronix\n", FN_NAME));
OUTPW(0x3d4, 0x0029);
OUTPW(0x3d4, 0x0129);
GDBG_INFO((80, "%s: Disabling PUMA\n", FN_NAME));
CRTC_GET(0x28, tmp);
GDBG_INFO((80, "%s: crtc 0x28: 0x%X\n", FN_NAME, tmp));
tmp &= ~1;
CRTC_SET(0x28, tmp);
GDBG_INFO((80, "%s: Turning off FBI Jr.\n", FN_NAME));
OUTPW(0x3c4, 0x061f);
/* Restore the mclock */
{
FxU16 tempMclock;
GDBG_INFO((80, "%s: Restoring mclock\n", FN_NAME));
tempMclock = (0x1A | (rd->hwDep.VG96RegDesc.mclockHi << 8));
OUTPW(0x3C4, tempMclock);
tempMclock = (0x1B | (rd->hwDep.VG96RegDesc.mclockLo << 8));
OUTPW(0x3C4, tempMclock);
/* Macronix MCLK reset propogation */
OUTPW(0x3C4, 0x081C);
OUTPW(0x3C4, 0x001C);
}
GDBG_INFO((80, "%s: Restoring Protection\n", FN_NAME));
OUTPW(0x3df, protState);
GDBG_INFO((80, "%s: Restoring CRTC Index\n", FN_NAME));
OUTP(0x3d4, crtcSave);
GDBG_INFO((80, "%s: Restoring Sequencer Index\n", FN_NAME));
OUTP(0x3c4, seqSave);
return FXTRUE;
#undef FN_NAME
} /* initMCRXDisableRegs */
/*-------------------------------------------------------------------
Function: initMCRXWrapFIFO
Date: 20-Feb-97
Implementor(s): tarolli
Library: Init Code for MCRX
Description:
Arguments:
Return:
-------------------------------------------------------------------*/
INITMCRXENTRY(initMCRXWrapFIFO, FxBool, (InitRegisterDesc *rd, InitFIFOData *fd) )
{
#define FN_NAME "initMCRXWrapFIFO"
return FXFALSE;
#undef FN_NAME
} /* initMCRXWrapFIFO */
#define MAX_BUF 3
static unsigned char magic[MAX_BUF][3] = {
{ 0x0d, 0x0c, 0x21 },
{ 0x71, 0x72, 0x73 },
/* chd - Fixme!
* Bogus numbers. Does triple buffering work on Macronix?
*
* dpc - 23 jan 1998 -
* Donny just told me this so hopefully this will work.
*/
{ 0x74, 0x75, 0x76 }
};
INITMCRXENTRY(initMCRXSwapTiles, FxBool, (InitRegisterDesc* rd))
{
#define FN_NAME "initMCRXSwapTiles"
FxU8 crtcSwapStatus;
FxU8 crtcSwapControl;
/* Get the # of buffers swapping */
OUTP(0x3D4, 0x70);
INP(0x3D5, crtcSwapControl);
/* Get the current active buffer setting */
OUTP(0x3D4, 0x7A);
INP(0x3D5, crtcSwapStatus);
/* Bits 0-1 indicate the current active buffer. Check to see if we
* need to wrap this and go to the next buffer.
*/
{
const FxU8 bufferBits = (crtcSwapStatus & 0x03);
const FxU8 maxBufferBits = (((crtcSwapControl & 0x08) == 0) ? 1 : 2);
crtcSwapStatus = ((crtcSwapStatus & ~0x03) |
((bufferBits == maxBufferBits) ? 0x00 : bufferBits + 1));
CRTC_SET(0x7A, crtcSwapStatus);
}
/* We have no way of knowing that this worked so of course we always
* return success.
*/
return FXTRUE;
#undef FN_NAME
}
/*-------------------------------------------------------------------
Function: initMCRXUseTiles
Date: 07-Feb-97 (Moved into initMCRX from init96)
Implementor(s): pgj, dow
Library: Init Code for MCRX
Description:
Arguments:
atmm: Pointer to base of MCRX
buffers: Pointer to array of offsets to buffers
nBuffers: Total number of buffers
backBuffer: FB offset of back buffer
strideInBytes: Tile width in bytes
Return:
1 if successful, 2 if renderbuffers need to be swapped.
-------------------------------------------------------------------*/
#ifdef H3D
INITMCRXENTRY(initMCRXUseTiles, int, (InitRegisterDesc *rd,
FxU32 *buffers,
FxU32 nBuffers,
FxU32 strideInBytes,
FxU32 Width, FxU32 Height, FxU32 PageFlipping))
#else
INITMCRXENTRY(initMCRXUseTiles, int, (InitRegisterDesc *rd,
FxU32 *buffers,
FxU32 nBuffers,
FxU32 strideInBytes,
FxU32 Width, FxU32 Height))
#endif
{
#define FN_NAME "initMCRXUseTiles"
int ret = 1;
unsigned int i;
FxU32
dwordOffset;
FxU8
regVal;
FxU32
tmp;
const char *envVal;
GDBG_INFO((80, "%s:\n", FN_NAME));
regVal = _inp(VGA_MISC_OUTPUT_READ);
/* Mask off bit 7 */
regVal |= (1<<7);
_outp(VGA_MISC_OUTPUT_WRITE, regVal);
/*---------------------------------
CONFIGURE TILES
---------------------------------*/
for (i=0; i < nBuffers; i++) {
FxU32
buf = buffers[i];
GDBG_INFO((80, "%s: Setting up buffer %d\n", FN_NAME, i));
dwordOffset = buf >> 2;
GDBG_INFO((80, "%s: Buffer[%d] = 0x%x, dwordOffset = 0x%x\n",
FN_NAME, i, buf, dwordOffset));
GDBG_INFO((80, "%s: Writing bits 0-7 of buffer 0 offset\n", FN_NAME));
tmp = (FxU8) (dwordOffset & 0xff);
CRTC_SET(magic[i][0], tmp);
GDBG_INFO((80, "%s: Writing bits 8-15 of buffer 0 offset\n", FN_NAME));
tmp = (FxU8) ((dwordOffset >> 8) & 0xff);
CRTC_SET(magic[i][1], tmp);
GDBG_INFO((80, "%s: Writing bits 16-19 of buffer 0 offset\n", FN_NAME));
tmp = (FxU8) ((dwordOffset >> 16) & 0xf);
CRTC_SET(magic[i][2], tmp);
}
GDBG_INFO((80, "%s: Setting up Swap Control\n", FN_NAME));
tmp = 0x01;
/* dpc - 26 han 1998
* If we are triple buffering we need to enable this on the actual
* macronix part as well. This is set by enabling bit 3 of the crtc
* register.
*/
if (nBuffers == 3) tmp |= 0x08;
mcrxHALData.initSwapTiles = initMCRXSwapTiles;
if ((envVal = myGetenv("MRCX_71")) &&
(sscanf(envVal, "%x", &i) == 1))
tmp = i;
CRTC_SET(0x70, tmp);
/* Reset the current display buffer bits (0-1) */
{
FxU8 crtcSwapBuffer;
OUTP(0x3D4, 0x7A);
INP(0x3D5, crtcSwapBuffer);
crtcSwapBuffer &= ~0x03;
CRTC_SET(0x7A, crtcSwapBuffer);
}
return ret;
#undef FN_NAME
} /* initMCRXUseTiles */
/*-------------------------------------------------------------------
Function: initMCRXGetInfo
Date: 28-Apr-97
Implementor(s): pgj, dow
Library: Init Code for MCRX
Description:
get information about MCRX
Arguments:
info - pointer to info struct
Return:
True if success, False if Failure
-------------------------------------------------------------------*/
INITMCRXENTRY(initMCRXGetInfo,FxBool,(VG96Info *info))
{
#define FN_NAME "initMCRXGetInfo"
FxU32 mBytesPow;
FxU8 res;
GDBG_INFO((80, "%s:\n", FN_NAME));
CRTC_GET(0x1a, res);
/* We care about bit 5 & 6 */
mBytesPow = ((res >> 5) & 3);
info->vgaChip = 0;
info->vg96Rev = 0;
info->nTFX = 1;
info->tfxRev = 1;
info->tfxRam = 2;
info->vg96Ram = (0x100000 << mBytesPow);
GDBG_INFO((80, "%s: frame buffer has 0x%x bytes\n", FN_NAME, info->vg96Ram));
return FXTRUE;
#undef FN_NAME
} /* initMCRXGetInfo */