home *** CD-ROM | disk | FTP | other *** search
- /* 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;
- }
- }