home *** CD-ROM | disk | FTP | other *** search
- /* s3.cpp 05/04/97 0.93ß
- *
- * S3 class declarations
- *
- * As of current, support includes...
- * S3-801/805 ( 4 settings, untested)
- * S3-Vision864/866/868 ( 4 settings, partially tested)
- * S3-Trio32/Trio64 ( 4 settings, untested)
- *
- * S3 SDAC MCLK programming ( non-chipset specific, should work any S3 )
- * TI-VP3025/3026 MCLK programming ( only for 964/968 chipsets )
- * S3 Trio (32/64/64V+) MCLK programming
- * S3 Virge and VirgeVX MCLK programming (actually same as Trio MCLK)
- *
- * new in v0.83
- * +created _S3::_868, _S3::_968 objects, primarily so the ::_info
- * routine will correctly discriminate EDO/burst/1-cycle RAM
- * v0.84 +fixed _S3 init code, so extended SR registers are unlocked
- * +also added 2MCLK/3MCLK write control for S3 Trio chipsets
- * v0.86 +fixed the S3 SDAC RAMDAC detection code...
- * v0.87 +fixed the S3 SDAC detection code...REALLY! It should no
- * longer hang non-SDAC cards.
- * v0.88 +added MCLK routine for _Virge and _VirgeVX classes
- * v0.90 cosmetic change to reported-text in _864::_fxn1()
- * v0.92 cosmetic changes (no new code)
- * v0.93 added code for TIVP3025 RAMDAC (S3 964/968 only)
- * TIVP3025 code doesn't work yet
- * 93b modified _s3::_s3() and added _s3::~_s3() to clean-up
- * the modifications made to certain S3 registers
- * modified TIVP3025/26 detection code
- */
-
- #include "s3.h"
-
- #include<dos.h>
- #include<string.h>
- #include<stdio.h>
- #include<stdlib.h>
- #include<math.h>
- #include<iostreams.h>
-
-
- _S3::_S3( vga_info info ) : vga( info ) // Constructor
- {
- uchar DAC; // temp variable for special RAMDAC detection purposes
- uchar temp; // scratch pad
-
- save_cr38 = read_CR( 0x38 ); // Preserve register value
- save_cr39 = read_CR( 0x39 ); // ...
- save_cr45 = read_CR( 0x45 ); // ...
- save_cr55 = read_CR( 0x55 ); // ...
- save_sr08 = read_SR( 0x08 ); // ...
- write_CR( 0x38, 0x48 ); // Unlock S3 VGA registers
- write_CR( 0x39, 0xA5 ); // Unlock S3 801/805 registers
- write_SR( 0x08, 0x06 ); // Unlock ext SR registers
-
- sdac = FALSE;
- tivpdac = FALSE;
-
- // v0.86 The preceding two lines were added, to correctly force the
- // following loop to operate correctly. The write-operation resets
- // the SDAC's internal counter, so now we can read it exactly 4 times.
-
- int i=0; // Initialize loop counter
- do {
- DAC = inportb( _DACmask );
- temp = inportb( _DACmask );
- } while ( temp != DAC && i++ < 255 );
-
- // v0.87 added the i < 255 ... non-SDAC S3's should no longer hang
-
- // in case DACmask was preloaded to return _DACID, we reset the
- // counter (wait until consecutive read is equal to previous read)
-
- if ( i < 255 ) {
- i = 0;
- do {
- DAC = inportb( _DACmask );
- } while ( temp == DAC && i++ < 255 );
- }
-
- if ( DAC == 0x70 || DAC == 0x73 ) { // S3 SDAC detected
- if ( DAC == 0x70 )
- strcat( id.chipset, " + SDAC (ID 0x70)" );
- else
- strcat( id.chipset, " + SDAC (ID 0x73)" );
- sdac = TRUE; // S3 SDAC RAMDAC is present
- }
-
- if ( sdac == FALSE )
- { // Check for TIVP 3025 RAMDAC
- // The TIVP 3025 RAMDAC's ID-byte is at indirect register 0x3F
- // The indirect registers are accessed through "INDEX" and "DATA"
- // RS[2:0]=110 "INDEX" , RS[2:0]=111 "DATA"
-
- write_bit( _CRindex, 0x33, 4, 0 ); // Unlock DAC writes
-
- write_bit( _CRindex, 0x55, 0, 1 ); // set DAC extension, RS2=1
- write_bit( _CRindex, 0x55, 1, 0 ); // clear DAC extension, RS3=0
- write_bit( _CRindex, 0x45, 5, 0 ); // set RS3/ODF to RS3
- outportb( _DACmask, 0x3F ); // Write 0x3F to "INDEX" (RS[110])
- DAC=inportb( _DACindexR ); // Read ID byte from "DATA" (RS[111])
- outportb( _DACmask, 0xFF ); // Restore DACmask to 0xFF
-
- if ( DAC == 0x25 )
- {
- tivpdac = TRUE;
- strcat( id.chipset, " + TIVP3025" );
- }
- else if ( DAC == 0x26 ) // added TIVP3026 detection, v0.93b
- {
- tivpdac = TRUE;
- strcat( id.chipset, " + TIVP3026" );
- }
- }
-
- }
-
-
- void
- _S3::mclk_help( void ) // Display help for S3 DAC/ Trio MCLK programming
- {
- sprintf( msg.temp, "\nFormula for S3 MCLK driver... %s%s%s",
- "(3 parameters, M, N, R)\n\t( M + 2 )\n\t--------- * 14.31818MHz",
- "\n\t(N+2)*2^R\n\n\tConstraint: 135MHz < 2^R * 14.31818MHz < 270MHz",
- "\n\t and... 1<=M<=127 1<=N<=31 0<=R<=3" );
- }
-
-
- _S3::~_S3() // Destructor added to clean-up MCLK's register fiddling
- {
- write_CR( 0x38, save_cr38 ); // Restore register value
- write_CR( 0x39, save_cr39 ); // ... v0.93b
- write_CR( 0x45, save_cr45 );
- write_CR( 0x55, save_cr55 ); // ...
- write_SR( 0x08, save_sr08 );
- }
-
- /* PLL
- *
- * Calculates MCLK frequency from M, N, _FREF, and R values
- * returns double value MHz, works for S3 SDAC and S3Trio
- */
- double
- _S3::_PLL( uchar M, uchar N, uchar R )
- {
- double Rval;
-
- switch ( R ) {
- case 0: case 1: case 2: case 3:
- Rval = pow( 2.0, R ); // Rval = 2 ^ R;
-
- break; // <- how'd I forget to put this here... //
- default:
- Rval=0; // Error!
- }
- return ( ( M + 2.0 ) * _OSC ) / ( ( N + 2.0 ) * Rval );
- /* ( M + 2 )
- * --------- * _FREF ... _FREF = 14.31818 MHz
- * (N+2)*2^R
- *
- * constraint: 135MHz < 2^R * _FREF < 270MHz
- * and... N >= 1
- */
- }
-
-
- message
- _S3::_ramtype( uchar mask )
- { // mask determines which values are valid, i.e. not "RESERVED"
- uchar _CR36 = read_CR( 0x36 );
- _CR36 = ( _CR36 >> 2 ) & 0x03; // 7654 3210 -> 0000 0032, bits 3-2
-
- switch ( _CR36 ) {
- case 0: if ( ( mask & 0x01 ) ) // If bit0 is SET
- sprintf( msg.text, "1-cycle EDO RAM" );
- else
- sprintf( msg.text, "RESERVED [ CR36(3:2) = 00 ]" );
- break;
- case 1: if ( ( mask & 0x02 ) ) // If bit1 is SET
- sprintf( msg.text, "Burst-mode RAM" );
- else
- sprintf( msg.text, "RESERVED [ CR36(3:2) = 01 ]" );
- break;
- case 2: sprintf( msg.text, "2-cycle EDO RAM" );
- break;
- case 3: if ( ( mask & 0x08 ) ) // If bit 3 is SET
- sprintf( msg.text, "fast-page mode RAM");
- else
- sprintf( msg.text, "RESERVED [ CR36(3:2) = 04 ]" );
- break;
- default: sprintf( msg.text, "UNKNOWN [ 0x%02X ]", mask );
- }
- status = EXIT_SUCCESS;
- return msg;
- }
-
-
- void
- _S3::_mclk( int cmd ) // MCLK programming for S3 SDAC chips
- {
- if ( cmd == _QUERY && sdac == TRUE ) {
- sprintf( msg.text,"0 S3 SDAC MCLK programming\n" );
- return; }
- else if ( sdac == FALSE ) {
- sprintf( msg.text,"0 MCLK function NOT available\n" );
- return;
- }
-
- uchar _CR33 = read_bit( _CRindex, 0x33, 4 ); // Remember LOCK DACW v0.84
-
- uchar _M, _N, _R, byte1, byte2;
- write_bit( _CRindex, 0x55, 0, 1 ); // Enable DAC extension RS2
- outportb( _DACindexR, 0x0A ); // Set to PLL CLK1 parameter
-
- byte1 = inportb( _DACIO );
- byte2 = inportb( _DACIO );
- _M = byte1 & 0x7F;
- _N = byte2 & 0x1F;
- _R = ( byte2 >> 5 ) & 0x03;
- sprintf( msg.text,"Old MCLK = %.2fMHz ( M=%u, N=%u, R=%u ) ",
- _PLL( _M, _N, _R ), _M, _N, _R );
-
- if ( num_param < 3 && cmd == _SET ) {
- strcat( msg.text, "\n...not enough parameters, need total of 3." );
- cmd = _HELP; } // Not enough parameters. }
- else {
- _M = (uchar)atoi( param[ 0 ] ) & 0x7F;
- _N = (uchar)atoi( param[ 1 ] ) & 0x1F ;
- _R = (uchar)atoi( param[ 2 ] );
- byte1 = ( byte1 & 0x80 ) | _M;
- _R = ( _R << 5 ) & 0X60;
- byte2 = ( byte2 & 0x80 ) | _N | _R;
- }
-
- switch ( cmd ) {
- case _SET: write_bit( _CRindex, 0x33, 4, 0 );
- // enable RAMDAC writes
- write_bit( _CRindex, 0x55, 0, 1 ); // actv RS2
- outportb( _DACindexW, 0x0A ); // Set to PLL CLK1
- outportb( _DACIO, byte1 ); // Write 1st byte
- outportb( _DACIO, byte2 ); // Write 2nd byte
-
- write_bit( _CRindex, 0x55, 0, 1 );
- // Enable DAC extension RS2
- outportb( _DACindexR, 0x0A ); // Set to PLL CLK1 parameter
- byte1 = inportb( _DACIO );
- byte2 = inportb( _DACIO );
- _M = byte1 & 0x7F;
- _N = byte2 & 0x1F;
- _R = ( byte2 >> 5 ) & 0x03;
-
- sprintf(msg.temp,"\nNew MCLK = %.2fMHz ( M=%u, N=%u, R=%u ) ",
- _PLL( _M, _N, _R ), _M, _N, _R );
- strcat( msg.text, msg.temp );
- outportb( _DACIO, byte1 );
- write_bit( _CRindex, 0x33, 4, _CR33 ); // Restore bit4
- break;
- case _GET: case _HELP:
- strcat( msg.text, "\nS3 SDAC MCLK programming" );
- mclk_help(); // Get mclk help, put in msg.temp
- strcat( msg.text, msg.temp );
- break;
- default:
- sprintf( msg.text, "_S3::_mclk(cmd) UNRECOGNIZED cmd.");
- status = EXIT_FAILURE;
- }
-
-
- }
-
-
- void
- _S3::_fxn1( int cmd ) // WST CTL, EWRT POST Write-wait state control
- {
- if ( cmd == _QUERY ) {
- sprintf( msg.text,"1 S3-801/805 WST CTL, EWRT POST\n%s",
- " (2 items : write-wait state, write-buffer controls)\n" );
- return;
- }
-
- uchar _bit2 = read_bit( _CRindex, 0x40, 2 ),
- _bit3 = read_bit( _CRindex, 0x40, 3 );
-
- sprintf(msg.text,"Old WST-CTL wait-states = %uT, buffer = %sd",_bit2,
- bitstat( _bit3 ) );
-
- if ( num_param < 2 && cmd == _SET ) {
- strcat( msg.text, "\nError! TWO parameters required!");
- cmd = _HELP; }
- else if ( num_param >= 2 ) {
- _bit2 = ( (uchar)atoi( param[ 0 ] ) ) & 0x01;
- _bit3 = ( (uchar)atoi( param[ 1 ] ) ) & 0x01;
- }
-
- switch ( cmd ) {
- case _SET:
- write_bit( _CRindex, 0x40, 2, _bit2 );
- write_bit( _CRindex, 0x40, 3, _bit3 );
- sprintf( msg.temp,"\nNew WST-CTL = %uT, buffer = %sd", _bit2,
- bitstat( _bit3 ) );
- strcat ( msg.text, msg.temp );
- break;
- case _HELP: case _GET:
- sprintf( msg.temp, "\nWrite Wait State Control\n\t%s%s",
- "0 = no wait\n\t1 = one wait-state\nEnable Fast-Write ",
- "buffer\n\t0 = DISABLE\n\t1 = ENABLE");
- strcat( msg.text, msg.temp );
- break;
- default:
- sprintf( msg.text, "_S3::_fxn1(cmd) UNRECOGNIZED cmd.");
- status = EXIT_FAILURE;
- }
- }
-
-
- void
- _S3::_fxn2( int cmd ) // Decode wait control, 386/486 local bus
- { // bits 5-4 of _CR40
- if ( cmd == _QUERY ) {
- strcpy( msg.text, "2 S3-805 Decode wait control (local bus)\n" );
- return;
- }
-
- uchar _CR40 = ( read_CR( 0x40 ) >> 4 ) & 0x03 ;
- uchar new_CR40= 0x02; // 3 wait states, default
-
- if ( param[ 0 ] != NULL )
- new_CR40 = (uchar)atoi( param[ 0 ] );
-
- sprintf( msg.text, "Old Decode = %uT wait-states (WS) ", shift (_CR40 ));
-
- switch ( cmd ) {
- case _SET: _CR40 = read_CR ( 0x40 ) & 0xCF; // XX00 XXXX
- write_CR( 0x40, _CR40 | ( ( new_CR40 << 4 ) & 0x30 ) );
- sprintf(msg.temp,"\n...now set to %uT WS ",shift(new_CR40 ));
- strcat( msg.text, msg.temp );
- break;
- case _HELP: case _GET:
- sprintf( msg.temp,"\nDecode wait Control (local bus only)%s",
- "\n\t0 = 0WS\n\t1 = 1WS\n\t2 = 3WS\n\t3 = 2WS");
- strcat( msg.text, msg.temp );
- break;
- default:
- sprintf( msg.text, "_S3::_fxn3(cmd) UNRECOGNIZED cmd.");
- status = EXIT_FAILURE;
- }
- }
-
-
- void
- _S3::_fxn3( int cmd ) // Read Wait control
- { // bits 7-6 of _CR40
- if ( cmd == _QUERY ) {
- strcpy( msg.text,
- "3 S3-801/805 Read-wait state control (local bus/ISA)\n" );
- return;
- }
-
- uchar _CR40 = ( read_CR( 0x40 ) >> 6 ) & 0x03;
- uchar new_CR40= 0x02; // 3 wait states, default
-
- if ( param[ 0 ] != NULL )
- new_CR40 = (uchar)atoi( param[ 0 ] );
-
- sprintf( msg.text, "Old Read Wait Control = %u waitstates (WS) ",
- shift (_CR40 ) );
-
- switch ( cmd ) {
- case _SET: _CR40 = read_CR ( 0x40 ) & 0x3F; // 00XX XXXX
- write_CR( 0x40, _CR40 | ( ( new_CR40 << 6 ) & 0xC0 ) );
- sprintf(msg.temp,"\nNow set to %uT WS ", shift ( new_CR40 ));
- strcat( msg.text, msg.temp );
- break;
- case _HELP: case _GET:
- sprintf( msg.temp,"\nRead Wait Control\n\t%s",
- "0 = 0WS\n\t1 = 1WS\n\t2 = 3WS\n\t3 = 2WS");
- strcat( msg.text, msg.temp );
- break;
- default:
- sprintf( msg.text, "_S3::_fxn3(cmd) UNRECOGNIZED cmd.");
- status = EXIT_FAILURE;
- }
- }
-
-
- void
- _S3::_fxn4( int cmd ) // Read-ahead cache
- { // bits 5-4 of _CR40
- if ( cmd == _QUERY ) {
- strcpy( msg.text, "4 S3-801/805 Read ahead cache size\n" );
- return;
- }
-
- uchar _CR54 = read_CR( 0x54 ) & 0x07 ;
- uchar new_CR54= 0x07; // Maximum allowed
-
- if ( param[ 0 ] != NULL )
- new_CR54 = (uchar)atoi( param[ 0 ] );
-
- sprintf( msg.text, "Old Cache size set to %u accesses, and %sd", _CR54,
- bitstat( read_bit( _CRindex, 0x58, 2 ) ) );
-
- switch ( cmd ) {
- case _SET: _CR54 = read_CR ( 0x54 ) & 0xF8; // XXXX X000
- write_CR( 0x54, _CR54 | ( new_CR54 & 0x07 ) );
- sprintf(msg.temp,"\nCache set to %u accesses", read_CR( 0x54)
- & 0x07 ) ;
- write_bit( _CRindex, 0x58, 2, 1 ); // Enable read-ahead
- strcat( msg.text, msg.temp );
- break;
- case _HELP: case _GET:
- sprintf( msg.temp,"\nRead ahead cache (auto-enabled if %s",
- "modified)\n\tAcceptable values = 0, 1, 3, 7");
- strcat( msg.text, msg.temp );
- break;
- default:
- sprintf( msg.text, "_S3::_fxn3(cmd) UNRECOGNIZED cmd.");
- status = EXIT_FAILURE;
- }
- }
-
-
- //--------------------S3 805i class definitions---------------------------
-
- void
- _805i::_fxn5( int cmd ) // Memory interleave control
- { // bit5 of _CR53, memory interleave control
- if ( cmd == _QUERY ) {
- strcpy( msg.text,"5 S3-805i memory interleave (2mb only)\n");
- return;
- }
-
- uchar new_CR53 = 0x0; // Disable interleaving by default
-
- if ( param[ 0 ] != NULL )
- new_CR53 = ( (uchar)atoi( param[ 0 ] ) ) & 0x01;
-
- sprintf(msg.text,"Interleaving is %sd",
- bitstat( read_bit( _CRindex, 0x53, 5 ) ) );
-
- switch ( cmd ) {
- case _SET:
- write_bit( _CRindex, 0x53, 5, new_CR53 );
- sprintf( msg.temp, "\n...now %sd",
- bitstat ( read_bit( _CRindex, 0x53, 5 ) ) );
- strcat ( msg.text, msg.temp );
- break;
- case _HELP: case _GET:
- sprintf( msg.temp, "\nMemory interleaving control\n\t%s",
- "0 = disabled\n\t1 = enabled (requires 2mb video RAM)");
- strcat( msg.text, msg.temp );
- break;
- default:
- sprintf( msg.text, "_805i::_fxn5(cmd) UNRECOGNIZED cmd.");
- status = EXIT_FAILURE;
- }
- }
-
-
- //---------- S3 '64 and Trio chipsets -------------------------------------//
-
-
- message
- _864::_info( void )
- {
- return _ramtype( 0x0C ) ;
- // Call _ramtype, allowing case2 & 3
- }
-
- /*
- void
- _864::_fxn1( int cmd ) // Ready Control delay (VL-BUS only )
- { // bit4 of _CR40
- if ( cmd == _QUERY ) {
- strcpy( msg.text,
- "1 S3-864/964/Trio RDY CTL wait control (VL-bus only)\n");
- return;
- }
-
- uchar _CR40 = read_bit( _CRindex, 0x40, 4 );
- uchar new_CR40= 0x01;
-
- if ( param[ 0 ] != NULL )
- new_CR40 = ( (uchar)atoi( param[ 0 ] ) ) & 0x01;
-
- sprintf(msg.text,"Old RDY-CTL = %uT wait state(s) ", _CR40 );
-
- switch ( cmd ) {
- case _SET:
- write_bit( _CRindex, 0x40, 4, new_CR40 );
- sprintf( msg.temp,"\nNew RDY-CTL=%uT", new_CR40 );
- strcat ( msg.text, msg.temp );
- break;
- case _HELP: case _GET:
- sprintf( msg.temp, "\nVL-bus RDY Control delay\n\t%s",
- "0T no-wait = 0d\n\t1T One-wait= 1d");
- strcat( msg.text, msg.temp );
- break;
- default:
- sprintf( msg.text, "_864::_fxn1(cmd) UNRECOGNIZED cmd.");
- status = EXIT_FAILURE;
- }
- }
- */
-
-
- void
- _864::_fxn1( int cmd ) // Memory page mode control )
- { // bits3-2 of _CR36
- if ( cmd == _QUERY ) {
- strcpy( msg.text,
- "1 S3-86x/96x/Trio memory page-mode control\n");
- return;
- }
-
- uchar _CR36 = read_CR( 0x36 ) & 0xF3; // XXXX 00XX
- uchar new_CR36 = _CR36 & 0x03;
-
- if ( param[ 0 ] != NULL )
- new_CR36 = ( (uchar)atoi( param[ 0 ] ) ) & 0x03;
-
- switch ( cmd ) {
- case _SET:
- write_CR( 0x36, ( new_CR36 << 2 ) | _CR36 );
- sprintf( msg.temp,"\nSelected RAM access-mode %u", new_CR36 );
- strcat ( msg.text, msg.temp );
- break;
- case _HELP: case _GET:
- sprintf( msg.temp, "S3 86x/96x/Trio access-mode control%s%s%s",
- "\n\t0 = 1-cycle EDO (866/868/968)\n\t1 = burst DRAM ",
- "(866/868/968)\n\t2 = 2-cycle EDO",
- "\n\t3 = fast-page mode timing");
- strcat( msg.text, msg.temp );
- break;
- default:
- sprintf( msg.text, "_864::_fxn1(cmd) UNRECOGNIZED cmd.");
- status = EXIT_FAILURE;
- }
- }
-
-
- void
- _864::_fxn2( int cmd ) // Ready Control delay (VL-BUS only )
- { // bits 1-0 of _CR68
- if ( cmd == _QUERY ) {
- strcpy( msg.text,
- "2 S3-864/964/Trio CAS', OE' strech time, WE' delay\n" );
- return;
- }
-
-
- uchar _CR68 = read_CR( 0x68 ) & 0x03;
- uchar new_CR68= 0x0; // maximum delay default
-
- if ( param[ 0 ] != NULL )
- new_CR68 = ( (uchar)atoi( param[ 0 ] ) ) & 0x03;
-
- sprintf(msg.text,"Old stretch/delay value = %02X (see table) ", _CR68 );
-
- switch ( cmd ) {
- case _SET: _CR68 = read_CR( 0x68 ) & 0xFC; // XXXX XX00
- write_CR( 0x68, _CR68 | new_CR68 );
- sprintf( msg.temp,"\nNew delay value = %02X ", new_CR68 );
- strcat ( msg.text, msg.temp );
- break;
- case _HELP: case _GET:
- sprintf( msg.temp, "\nDRAM timing delays/stretches%s",
- "\n\t0 = 6.5ns\n\t1 = 5ns\n\t2 = 3.5ns\n\t3 = 0ns");
- strcat( msg.text, msg.temp );
- break;
- default:
- sprintf( msg.text, "_864::_fxn2(cmd) UNRECOGNIZED cmd.");
- status = EXIT_FAILURE;
- }
- }
-
-
- // Does not work for 86X/Trio chipsets!!! Timing MUST be set to RDYIN'!
- /*
- void
- _864::_fxn3( int cmd ) // Write latching delay (VL-BUS only )
- { // bit5 of _CR40, 1= SRDY', 0 = RDYIN'
- if ( cmd == _QUERY ) {
- strcpy( msg.text,
- "3 S3-864/964 Write latching delay (VL-bus only)\n");
- return;
- }
-
- uchar _CR40 = read_bit( _CRindex, 0x40, 5 );
- uchar new_CR40= 0x01;
- sprintf( msg.text,"Old Write latch delay = (%ud, latch on ",_CR40 );
- if ( _CR40 )
- strcat( msg.text, "SRDY' )" );
- else
- strcat( msg.text, "RDYIN' )" );
-
- if ( param[ 0 ] != NULL )
- new_CR40 = (uchar)atoi( param[ 0 ] );
-
- switch ( cmd ) {
- case _SET:
- write_bit( _CRindex, 0x40, 5, new_CR40 );
- sprintf(msg.temp,"\nNew Write latch delay=%ud ", new_CR40 );
- if ( new_CR40 )
- strcat( msg.temp, "SRDY' )" );
- else
- strcat( msg.temp, "RDYIN' )" );
- strcat ( msg.text, msg.temp );
- break;
- case _HELP: case _GET:
- sprintf( msg.temp, "\nVL-bus Write latch delay\n\t%s",
- "RDYIN' = 0d\n\tSRDY' = 1d (faster?)");
- strcat( msg.text, msg.temp );
- break;
- default:
- sprintf( msg.text, "_864::_fxn3(cmd) UNRECOGNIZED cmd.");
- status = EXIT_FAILURE;
- }
- } */
-
-
- void
- _864::_fxn3( int cmd ) // Bus turnaround time
- { // bits7-6 of _CR40
- if ( cmd == _QUERY ) {
- strcpy( msg.text,
- "3 S3-864/964 Bus turnaround non-overlap (VL-bus only)\n");
- return;
- }
-
- uchar _CR40 = ( read_CR( 0x40 ) >> 6 ) & 0x03,
- new_CR40;
- sprintf( msg.text,"Old delay = %u unit(s) ", _CR40 + 1 );
-
- if ( param[ 0 ] != NULL )
- new_CR40 = (uchar)atoi( param[ 0 ] ) & 0x03;
-
- switch ( cmd ) {
- case _SET: _CR40 = read_CR( 0x40 ) & 0x3F;
- write_CR( 0x40, ( ( new_CR40 >> 6 ) & 0xC0 ) | _CR40 );
- sprintf( msg.temp,"\nNew delay = %u unit(s)", new_CR40 + 1 );
- strcat ( msg.text, msg.temp );
- break;
- case _HELP: case _GET:
- sprintf( msg.temp, "\nVL-bus gap between ABEN' & DBEN'%s%s",
- "\n\t1 unit = 00\n\t2 units = 01\n\t3 units = 02",
- "\n\t4 units = 03");
- strcat( msg.text, msg.temp );
- break;
- default:
- sprintf( msg.text, "_864::_fxn3(cmd) UNRECOGNIZED cmd.");
- status = EXIT_FAILURE;
- }
- }
-
-
-
- void
- _864::_fxn4( int cmd ) // RAS precharge timing select
- { // bits 7-6 of _CR68
- if ( cmd == _QUERY ) {
- strcpy( msg.text, "4 S3-864/964 RAS' precharge timing delay\n" );
- return;
- }
-
-
- uchar _CR68 = ( read_CR( 0x68 ) >> 6 ) & 0x03; // 7654 3210 -> 0000 0076
- uchar new_CR68= 0x01; // maximum delay default, 4.5 MCLKs
-
- if ( param[ 0 ] != NULL )
- new_CR68 = ( (uchar)atoi( param[ 0 ] ) ) & 0x03;
-
- sprintf(msg.text,"Old RAS' precharge value = %02X (see table) ", _CR68 );
-
- switch ( cmd ) {
- case _SET: _CR68 = read_CR( 0x68 ) & 0x3F; // 00XX XXXX
- write_CR( 0x68, _CR68 | ( ( new_CR68 << 6 ) & 0xC0 ) );
- sprintf( msg.temp,"\nNew RAS' value = %02X ", new_CR68 );
- strcat ( msg.text, msg.temp );
- break;
- case _HELP: case _GET:
- sprintf( msg.temp, "\nDRAM RAS' precharge delays%s",
- "\n\t0 = RESERVED\n\t1 = 4.5MCLKs\n\t2 = 3.5\n\t3 = 2.5");
- strcat( msg.text, msg.temp );
- break;
- default:
- sprintf( msg.text, "_864::_fxn4(cmd) UNRECOGNIZED cmd.");
- status = EXIT_FAILURE;
- }
- }
-
-
- void
- _864::_fxn5( int cmd ) // RAS precharge timing select
- { // bits 5-4 of _CR68
- if ( cmd == _QUERY ) {
- strcpy( msg.text, "5 S3-864/964 RAS' low timing select\n" );
- return;
- }
-
-
- uchar _CR68 = ( read_CR( 0x68 ) >> 4 ) & 0x03; // 7654 3210 -> 0000 0054
- uchar new_CR68= 0x00; // maximum delay default, 6.5 MCLKs
-
- if ( param[ 0 ] != NULL )
- new_CR68 = ( (uchar)atoi( param[ 0 ] ) ) & 0x03;
-
- sprintf(msg.text,"Old RAS' low timing value = %02X (see table) ", _CR68 );
-
- switch ( cmd ) {
- case _SET: _CR68 = read_CR( 0x68 ) & 0xCF; // XX00 XXXX
- write_CR( 0x68, _CR68 | ( ( new_CR68 << 4 ) & 0x30 ) );
- sprintf( msg.temp,"\nNew RAS' value = %02X", new_CR68 );
- strcat ( msg.text, msg.temp );
- break;
- case _HELP: case _GET:
- sprintf( msg.temp, "\nDRAM RAS' low timing select%s",
- "\n\t0 = 6.5MCLKs\n\t1 = 5.5\n\t2 = 4.5\n\t3 = 3.5");
- strcat( msg.text, msg.temp );
- break;
- default:
- sprintf( msg.text, "_864::_fxn5(cmd) UNRECOGNIZED cmd.");
- status = EXIT_FAILURE;
- }
- }
-
-
- message
- _868::_info( void )
- {
- return _ramtype( 0x0F ) ;
- // Call _ramtype, allowing all cases 0, 1, 2 & 3
- }
-
-
- void // Read "M, N, R" values from S3 registers _SR10 & _SR11
- _Trio::read_PLL( uchar *M, uchar *N, uchar *R )
- {
- uchar _SR10= read_SR( 0x10 ); // Read _SR10, contains N & R
-
- *M = read_SR( 0x11 ) & 0x7F; // _SR11 -> 0XXX XXXX = M value
- *N = _SR10 & 0x1F; // _N = _SR11 -> 000X XXXX
- *R = ( _SR10 >> 5 ) & 0x03; // _R ( 7654 3210 -> 0000 0065 )
- }
-
-
- message
- _Triov::_info( void )
- {
- return _ramtype( 0x0D ) ;
- // Call _ramtype, allowing case0, 2 & 3
- }
-
-
- void
- _Trio::_mclk( int cmd ) // MCLK reprogramming
- { // _SR10, _SR11
- if ( cmd == _QUERY ) {
- strcpy( msg.text, "0 S3 Trio/Virge MCLK programming\n");
- return;
- }
-
- uchar _M, _N, _R, _SR10, _SR11;
- read_PLL( &_M, &_N, &_R ); // Load _M, _N, _R with PLL values
- sprintf( msg.text,"Old MCLK = %.2fMHz ( M=%u, N=%u, R=%u ) ",
- _PLL( _M, _N, _R ), _M, _N, _R );
-
- if ( num_param < 3 && cmd == _SET ) {
- strcat( msg.text, "\n...not enough parameters, need total of 3." );
- cmd = _HELP; } // Not enough parameters. }
- else {
- _M = (uchar)atoi( param[ 0 ] );
- _N = (uchar)atoi( param[ 1 ] );
- _R = (uchar)atoi( param[ 2 ] );
-
- _M = ( _M & 0x7F );
- _SR11 = ( read_SR( 0x11 ) & 0x80 ) | _M;
- _N = ( _N & 0x1F );
- _R = ( _R << 5 ) & 0X60 ;
- _SR10 = ( read_SR( 0x10 ) & 0x80 ) | _N | _R;
- }
-
- switch ( cmd ) {
- case _SET: write_bit( _SRindex, 0x15, 0, 0 ); // Prep MCLK load
- write_SR( 0x11, _SR11 );
- write_SR( 0x10, _SR10 );
- write_bit( _SRindex, 0x15, 0, 1 ); // Load MCLK values
- delay(1000); // Wait for new values to take effect
- write_bit( _SRindex, 0x15, 0, 0 ); // Clear MCLK load
- read_PLL( &_M, &_N, &_R); // Reread new values
- sprintf(msg.temp,"\nNew MCLK = %.2fMHz ( M=%u, N=%u, R=%u ) ",
- _PLL( _M, _N, _R ), _M, _N, _R );
- strcat ( msg.text, msg.temp );
- break;
- case _HELP: case _GET:
- strcat( msg.text, "\nS3 Trio/Virge MCLK programming" );
- mclk_help(); // Get Trio mclk help, put in msg.temp
- strcat( msg.text, msg.temp );
- break;
- default:
- sprintf( msg.text, "_Trio::_mclk(cmd) UNRECOGNIZED cmd.");
- status = EXIT_FAILURE;
- }
- }
-
- void
- _Trio::_fxn3( int cmd ) // RAS' timing control
- { // bit2 = RAS' Low, bit3 = RAS' precharge _CR68
- if ( cmd == _QUERY ) {
- strcpy(msg.text,"3 S3Trio RAS' timing control (2 parameters)\n");
- return;
- }
-
- uchar _bit2 = read_bit( _CRindex, 0x68, 2 ),
- _bit3 = read_bit( _CRindex, 0x68, 3 );
-
- sprintf( msg.text, "Old RAS-LOW = %.1fMCLKs, Old RAS-Pre = %.1fMCLKs",
- 4.5 - _bit2, 3.5 - _bit3 );
-
- if ( num_param < 2 && cmd == _SET ) {
- strcat( msg.text, "\nError! Need TWO parameters for input!");
- cmd = _HELP; }
- else if ( num_param >= 2 ) {
- _bit2 = ( (uchar)atoi( param[ 0 ] ) ) & 0x01;
- _bit3 = ( (uchar)atoi( param[ 1 ] ) ) & 0x01;
- }
-
- switch ( cmd ) {
- case _SET: write_bit( _CRindex, 0x68, 2, _bit2 );
- write_bit( _CRindex, 0x68, 3, _bit3 );
- sprintf(msg.temp,"\nNew LOW = %.1fMCLKs, New PRE = %.1fMCLKs",
- 4.5 - _bit2, 3.5 - _bit3 );
- strcat ( msg.text, msg.temp );
- break;
- case _HELP: case _GET:
- sprintf( msg.temp, "\nDRAM RAS delays/stretches%s%s",
- "\n\tRAS'LOW RAS'PRE (1st-param 2nd-param )",
- "\n\t0 = 4.5 0 = 3.5\n\t1 = 3.5 1 = 2.5" );
- strcat( msg.text, msg.temp );
- break;
- default:
- sprintf( msg.text, "_Trio::_fxn3(cmd) UNRECOGNIZED cmd.");
- status = EXIT_FAILURE;
- }
- }
-
-
- void
- _Trio::_fxn4( int cmd ) // Memory write timing, 2MCLK/3MCLK, SR08/SR15
- {
- if ( cmd == _QUERY ) {
- sprintf( msg.text,"4 S3Trio 2MCLK/3MCLK timing controls\n" );
- return;
- }
-
- uchar _SR0A = read_bit( _SRindex, 0x0A, 7 ), // SR0A/b7 = CPU-write
- _SR15 = read_bit( _SRindex, 0x15, 7 ); // SR15/b7 = mem-write
-
- sprintf(msg.text,"Old CPU-write = %uMCLKs, mem-write = %uMCLKS",
- 3 - _SR0A, 3 - _SR15 );
-
- if ( num_param < 2 && cmd == _SET ) {
- strcat( msg.text, "\nError! TWO parameters required!");
- cmd = _HELP; }
- else if ( num_param >= 2 ) {
- _SR0A = ( (uchar)atoi( param[ 0 ] ) ) & 0x01;
- _SR15 = ( (uchar)atoi( param[ 1 ] ) ) & 0x01;
- }
-
- switch ( cmd ) {
- case _SET:
- write_bit( _SRindex, 0x0A, 7, _SR0A );
- write_bit( _SRindex, 0x15, 7, _SR15 );
- sprintf( msg.temp,"\nNew CPU = %uMCLKs, mem = %uMCLKs",
- 3 - _SR0A, 3 - _SR15 );
- strcat ( msg.text, msg.temp );
- break;
- case _HELP: case _GET:
- sprintf( msg.temp, "\nCPU-write and MEM-write control\n%s%s%s",
- "For each item, enter: \n\t0 (3MCLKs)\n\t1 (2MCLKs, faster,",
- " but MCLK freq must be < 57MHz.)\n\tAdditional constraint ",
- "for 2MCLK MEM-write: 55MHz < MCLK < 57MHz" );
- strcat( msg.text, msg.temp );
- break;
- default:
- sprintf( msg.text, "_Trio::_fxn4(cmd) UNRECOGNIZED cmd.");
- status = EXIT_FAILURE;
- }
- }
-
-
- void
- _Triov::_fxn1( int cmd ) // Memory page mode control )
- { // bits3-2 of _CR36
- if ( cmd == _QUERY ) {
- strcpy( msg.text,
- "1 Trio64V+/Virge memory page-mode control\n");
- return;
- }
-
- uchar _CR36 = read_CR( 0x36 ) & 0xF3; // XXXX 00XX
- uchar new_CR36 = _CR36 & 0x03;
-
- if ( param[ 0 ] != NULL )
- new_CR36 = ( (uchar)atoi( param[ 0 ] ) ) & 0x03;
-
- switch ( cmd ) {
- case _SET:
- write_CR( 0x36, ( new_CR36 << 2 ) | _CR36 );
- sprintf( msg.temp,"\nSelected RAM access-mode %u", new_CR36 );
- strcat ( msg.text, msg.temp );
- break;
- case _HELP: case _GET:
- sprintf( msg.temp, "S3 Trio64V+/Virge memory access-mode%s%s",
- " control\n\t0 = 1-cycle EDO\n\t2 = 2-cycle EDO \n\t",
- "3 = fast-page mode timing");
- strcat( msg.text, msg.temp );
- break;
- default:
- sprintf( msg.text, "_Triov::_fxn1(cmd) UNRECOGNIZED cmd.");
- status = EXIT_FAILURE;
- }
- }
-
-
- message
- _964::_info( void )
- {
- return ( _ramtype( 0x0C ) );
- // Call _ramtype, allowing only case2 & 3
- }
-
-
- /* PLL - TIVP3025
- *
- * Calculates MCLK frequency from M, N, _FREF, and P values
- * returns double value MHz, works for TIVP3025 RAMDAC
- */
- double
- _964::_PLL( uchar M, uchar N, uchar P )
- {
- double Pval;
-
- switch ( P ) {
- case 0: case 1: case 2: case 3:
- Pval = pow( 2.0, P ); // Pval = 2 ^ P;
-
- break; // <- how'd I forget to put this here...
- default:
- Pval=0; // Error!
- }
- return ( 8.0 * ( M + 2.0 ) * _OSC ) / ( ( N + 2.0 ) * Pval );
- /* ( M + 2 )
- * FVCO = --------- * 8 * _FREF ... _FREF = 14.31818 MHz
- * ( N + 2 )
- *
- * FPLL (MHz) = FVCO / ( 2^P ) FPLL = final MCLK frequency
- *
- * constraint: 110MHz < FVCO < 220MHz
- * and... FREF/(N+2) > 0.5MHz
- * and... N >= 1 , M >= 1
- */
- }
-
-
-
- void
- _964::_mclk( int cmd ) // MCLK programming for TI VP3025 RAMDAC
- {
- if ( cmd == _QUERY && tivpdac == TRUE ) {
- sprintf( msg.text, "0 TIVP3025/3026 RAMDAC MCLK programming\n" );
- return; }
- else if ( tivpdac == FALSE ) {
- sprintf( msg.text,"0 MCLK function NOT available\n" );
- return;
- }
-
- uchar _CR33 = read_bit( _CRindex, 0x33, 4 ); // Remember LOCK DACW v0.84
-
- uchar _M, _N, _P, byte1, byte2, byte3;
-
- write_bit( _CRindex, 0x55, 0, 1 ); // Enable DAC extension RS2
- write_bit( _CRindex, 0x55, 1, 0 ); // Disable DAC extension RS3
- // TIVP3025's indirect registers are accessed via "INDEX" and "DATA"
- // where RS[2:0]=110 "INDEX" , RS[2:0]=111 "DATA"
- // MCLK PLL Control register is at 0x2E
- //
-
- outportb( _DACmask, 0x2E ); // set "INDEX" (RS[110]) to MCLK PLL-con
- // To access first MCLK PLL register, must write 00 -> PLLcontrol[1:0]
- write_bit( _DACindexR, 0, 0 ); // 0 -> bit0 of PLLcontrol
- write_bit( _DACindexR, 1, 0 ); // 0 -> bit1 of PLLcontrol
- // PLL control register is autoincremented
-
- byte1 = inportb( _DACmask ); // Read data from MCLK PLL data register
- byte2 = inportb( _DACmask ); // ...
- byte3 = inportb( _DACmask ); // ...
- _N = byte1 & 0x7F;
- _M = byte2 & 0x7F;
- _P = byte3 & 0x03;
- sprintf( msg.text,"Old MCLK = %.2fMHz ( M=%u, N=%u, P=%u ) ",
- _PLL( _M, _N, _P ), _M, _N, _P );
-
- if ( num_param < 3 && cmd == _SET ) {
- strcat( msg.text, "\n...not enough parameters, need total of 3." );
- cmd = _HELP; } // Not enough parameters. }
- else {
- _M = (uchar)atoi( param[ 0 ] ) & 0x7F;
- _N = (uchar)atoi( param[ 1 ] ) & 0x7F;
- _P = (uchar)atoi( param[ 2 ] ) & 0x03;
- byte1 = ( byte1 & 0x80 ) | _M;
- byte2 = ( byte2 & 0x80 ) | _N;
- byte3 = ( byte3 & 0xFC ) | _P;
- }
-
- switch ( cmd ) {
- case _SET: write_bit( _CRindex, 0x33, 4, 0 );
- // enable RAMDAC writes
- write_bit( _CRindex, 0x55, 0, 1 ); // set RS2 to 1
- write_bit( _CRindex, 0x55, 1, 0 ); // clear RS3 to 0
- outportb( _DACmask, 0x2E ); // set "INDEX" to 0x2E
- write_bit( _DACindexR, 0, 0 ); // 0 -> bit0 of PLLcontrol
- write_bit( _DACindexR, 1, 0 ); // 0 -> bit1 of PLLcontrol
-
- outportb( _DACmask, byte1 ); // Write 1st byte
- outportb( _DACmask, byte2 ); // Write 2nd byte
- outportb( _DACmask, byte3 ); // Write 3rd byte
-
- // Now, read-back the new values!
-
- outportb( _DACmask, 0x2E ); // set "INDEX" to 0x2E
- write_bit( _DACindexR, 0, 0 ); // 0 -> bit0 of PLLcontrol
- write_bit( _DACindexR, 1, 0 ); // 0 -> bit1 of PLLcontrol
- byte1 = inportb( _DACmask ); // Read data from MCLK PLL
- byte2 = inportb( _DACmask ); // ...
- byte3 = inportb( _DACmask ); // ...
- _N = byte1 & 0x7F;
- _M = byte2 & 0x7F;
- _P = byte3 & 0x03;
-
- sprintf(msg.temp,"\nNew MCLK = %.2fMHz ( M=%u, N=%u, P=%u ) ",
- _PLL( _M, _N, _P ), _M, _N, _P );
- strcat( msg.text, msg.temp );
- write_bit( _CRindex, 0x33, 4, _CR33 ); // Restore bit4
- break;
- case _GET: case _HELP:
- strcat( msg.text, "\nTIVP3025 RAMDAC MCLK programming" );
- mclk_help(); // Get mclk help, put in msg.temp
- strcat( msg.text, msg.temp );
- break;
- default:
- sprintf( msg.text, "_964::_mclk(cmd) UNRECOGNIZED cmd.");
- status = EXIT_FAILURE;
- }
- }
-
- void
- _964::mclk_help( void ) // Display help for TIVP3025 MCLK programming
- {
- sprintf( msg.temp, "\nFormula for TI VP3025 MCLK driver... %s%s%s",
- "(3 parameters, M, N, P)\n\t( M + 2 ) * 8\n\t--------- * 14.31818MHz",
- "\n\t(N+2)*2^P\n\n\tConstraint: 110MHz < MCLK * (2^P) < 220MHz",
- "\n\t and... 1<=M<=127 1<=N<=127 0<=P<=3" );
- }
-
-
- void
- _964::_fxn1( int cmd ) // Ready Control delay (VL-BUS only ) & SAM
- { // bit4 of _CR40 and bit6 of CR58
- if ( cmd == _QUERY ) {
- strcpy( msg.text,
- "1 S3-964 RDY CTL (VL-bus only), VRAM SAM control (2 items)\n");
- return;
- }
-
- uchar _CR40 = read_bit( _CRindex, 0x40, 4 ),
- _CR58 = read_bit( _CRindex, 0x58, 6 );
- uchar new_CR40=0, new_CR58=0;
-
- if ( num_param < 2 && cmd == _SET ) {
- strcat( msg.text, "\nError! TWO parameters required!");
- cmd = _HELP; }
- else if ( num_param >= 2 ) {
- new_CR40 = ( (uchar)atoi( param[ 0 ] ) ) & 0x01;
- new_CR58 = ( (uchar)atoi( param[ 1 ] ) ) & 0x01;
- }
-
- sprintf(msg.text,"Old RDY-CTL = %uT wait state(s), SAM = %d", _CR40,
- 512 - ( 256 * _CR58 ) );
-
- switch ( cmd ) {
- case _SET:
- write_bit( _CRindex, 0x40, 4, new_CR40 );
- write_bit( _CRindex, 0x58, 6, new_CR58 );
- sprintf( msg.temp,"\nNew RDY-CTL = %uT, SAM = %d", new_CR40,
- 512 - ( 256 * new_CR58 ) );
- strcat ( msg.text, msg.temp );
- break;
- case _HELP: case _GET:
- sprintf( msg.temp, "\nVL-bus RDY Control delay\n\t%s%s",
- "0 = no-wait\n\t1 = one wait-state\n\n\tSAM control",
- "\n\t0 = 512 words ( faster )\n\t1 = 256 words");
- strcat( msg.text, msg.temp );
- break;
- default:
- sprintf( msg.text, "_964::_fxn1(cmd) UNRECOGNIZED cmd.");
- status = EXIT_FAILURE;
- }
- }
-
-
- message
- _968::_info( void )
- {
- return _ramtype( 0x0D );
- // Call _ramtype, allowing cases 0, 2 & 3
-
- }
-
-
- //----S3 Virge
-
- message
- _Virge::_info( void )
- {
- return _ramtype( 0x05 ) ;
- // Call _ramtype, allowing case0 & 2
- return msg;
- }
-
-
- void
- _VirgeVX::mclk_help( void ) // Display help for VirgeVX MCLK programming
- {
- sprintf( msg.temp, "\nFormula for S3 Virge/VX MCLK driver... %s%s%s",
- "(3 parameters, M, N, R)\n\t( M + 2 )\n\t--------- * 14.31818MHz",
- "\n\t(N+2)*2^R\n\n\tConstraint: 220MHz < 2^R * 14.31818MHz < 440MHz",
- "\n\t and... 1<=M<=127 1<=N<=31 0<=R<=3" );
- }
-