home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 1999 January
/
pcwk_01_1999.iso
/
Tajnepp
/
MCLK093
/
TRIDENT.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1997-05-04
|
5KB
|
175 lines
/* trident.cpp 12/30/96 0.92ß
*
* Includes class definitions for Trident Microsystems
* v0.85b First public release, completely non-functional
* v0.91b working MCLK code for 96XX (haven't tested 9440)
* v0.92b noticed bug under Win95-OSR2 where screen-corruption can happen
* can't seem to fix it
* source-code based on information compiled in VGADOC4B.ZIP
*/
#include "trident.h"
#include<dos.h>
#include<string.h>
#include<stdio.h>
#include<stdlib.h>
#include<iostreams.h>
message
_TR9440::_info( void )
{
sprintf( msg.text, "" );
return msg;
}
/*
void
_TR9440::setmode(uchar mode)
{
switch ( mode ) {
case _NEW: // Set Trident _SR registers to "NEW" mode
outportb( _SRindex, 0x0B ); // Reading forces NEW mode
inportb( _SRIO );
inportb( _SRIO ); // Two 8-bit reads = 16-bit read
break;
case _OLD: // Set Trident _SR registers to "OLD" mode
outportb( _SRindex, 0x0B ); // Writing forces OLD mode
outportb( _SRIO, 0 ); // Two 8-bit writes = 16-bit write
outportb( _SRIO, 0 );
break;
default:
fprintf( stderr, "\n_TR9440::setmode( mode ) error!" );
exit( EXIT_FAILURE );
}
}
*/
int
_TR9440::read_mclk( void ) // Reads MCLK bytes into one int
{
// Trident MCLK-word is at port 0x43C6 and 0x43C7 (16-bits total)
int _43C6 = inportb( 0x43C6 );
int _43C7 = inportb( 0x43C7 );
// No, you can't just do int mclk = inport( 0x43C6 )... doesn't work!
return ( _43C7 << 8 ) | _43C6 ;
}
double
_TR9440::get_mclkfreq()
{
double freq;
int mclk = read_mclk(); // Read MCLK word
uchar mult2 = (mclk & 0x0200) ? 0 : 1; // Multiply by 2?
uchar divisor = mclk & 0x0007 ; // lowest three bits 0000 0000 0000 0XXX
uchar scale = ( mclk & 0x01F8 ) >> 3; // 0000 000X XXXX X000
freq = _OSC * (scale + 4.0 ) / ( divisor + 2.0 );
//
// v0.91b
// I don't know if this is 100% accurate--I reverse-engineered the
// dram-clock formula
//
// _OSC = 14.31818 MHz (reference frequency)
// ( B + 4 ) * ( _A )
// DCLK (MHz) = _OSC * ------------------
// ( C + 2 )
//
//
// port 0x43C6 and 0x43C7 form 16-bit binary MCLK "word" (Intel-style)
// MCLK( 15:0 ) = ???? ??AB BBBB BCCC <- 16-bit word
// 5432 1098 7654 3210 <- bit#
//
// "A" single-bit flag ( 0 = scale up by 2, 1 = no effect )
// "B" 6-bit "scale" factor
// "C" 3-bit "divisor" factor
// "?" don't really know
if ( mult2 )
freq *= 2.0 ; // if mult2 is set, double freq
return freq;
}
void // MCLK programming for Trident 9440/96xx
_TR9440::_mclk( int cmd )
{
int mclk;
uchar _SR0E; // Register _SR0E, temp-holding place
if ( cmd == _QUERY ) {
strcpy( msg.text, "0 9440/96xx MCLK programming\n" );
return;
}
mclk = read_mclk(); // New MCLK 16-bit value
uchar mult2 = (mclk & 0x0200) ? 0 : 1; // Multiply by 2?
uchar divisor = mclk & 0x0007 ; // lowest three bits 0000 0000 0000 0XXX
uchar scale = ( mclk & 0x01F8 ) >> 3; // 0000 000X XXXX X000
sprintf( msg.text, "Old MCLK = %.2fMHz (%04X)", get_mclkfreq(),
read_mclk() );
sprintf( msg.temp, "\nscale = %d (dec), divisor = %X, mult2 = %d (dec)",
scale, divisor, mult2 );
strcat( msg.text, msg.temp );
if ( num_param < 3 && cmd == _SET ) {
strcat( msg.text, "\nError! THREE parameters required!");
cmd = _HELP; }
else if ( num_param >= 3 ) {
mult2 = ( (uchar)atoi( param[ 2 ] ) ) & 0x01;
divisor = ( (uchar)atoi( param[ 1 ] ) ) & 0x07;
scale = ( (uchar)atoi( param[ 0 ] ) ) & 0x3F;
}
if ( param[ 0 ] != NULL ) // Only the 1st parameter is used
if ( sscanf( param[ 0 ], " %x", &mclk ) == 0 )
cmd = _HELP; // Error, no value scanned
switch ( cmd ) {
case _SET :
uchar mhigh = inportb( 0x43C7 ) & 0xFC; // preserve top 6 bits
uchar mlow = ( scale << 3 ) | divisor;
mhigh = mhigh | ( mult2 ? 0 : 0x02 ) | ( scale >> 5 ) ;
_SR0E = read_SR( 0x0E ); // XX00 0000
write_SR( 0x0E, _SR0E | 0x82 ); // 1XXX XX1X
// To update MCLK, bits 1 & 7 must be SET
outportb( 0x43C6, mlow );
outportb( 0x43C7, mhigh );
write_SR( 0x0E, _SR0E ); // Restore _SR0E to original value!
mclk = read_mclk();
sprintf( msg.temp, "\n\nNew MCLK = %.2fMHz (%04X) ",
get_mclkfreq(), mclk );
mult2 = (mclk & 0x0200) ? 0 : 1;
divisor = mclk & 0x0007 ;
scale = ( mclk & 0x01F8 ) >> 3;
strcat( msg.text, msg.temp );
sprintf( msg.temp,
"\nscale = %d (dec), divisor = %X, mult2 = %d (dec)",
scale, divisor, mult2 );
strcat( msg.text, msg.temp );
break;
case _GET : case _HELP: sprintf( msg.temp, "%s%s%s%s%s",
"\n Note: Trident 9440/96xx MCLK max = 80MHz",
"\n\t mclk = 14.31818MHz * ( scale+4 ) / ( divisor+2 )",
", (if mult2=1, * 2 )",
"\n\t Input: mclk /0 SCALE DIVISOR MULT2 (3 parameters)",
"\n\t scale = 0-63, divisor = 0-7, mult2 = 0 or 1" );
strcat( msg.text, msg.temp );
break;
/* --CODE TAKEN FROM VGADOC4B.ZIP
43C6h W(R/W): Memory Clock (9440)
bit 0-15 Selects the memory clock. 2C6h = 50MHz, 307h = 58MHz, 87h = 64MHz
8Eh = 75MHz
Note: 3C4h index Eh (new) bits 1 & 7 must be set to update this register
*/
default:
sprintf( msg.text, "_TR9440::_mclk(cmd) UNRECOGNIZED cmd.");
status = EXIT_FAILURE;
}
}