home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1999 January / pcwk_01_1999.iso / Tajnepp / MCLK093 / TRIDENT.CPP < prev    next >
C/C++ Source or Header  |  1997-05-04  |  5KB  |  175 lines

  1. /*    trident.cpp        12/30/96    0.92ß
  2.  *
  3.  *    Includes class definitions for Trident Microsystems
  4.  *    v0.85b First public release, completely non-functional
  5.  *    v0.91b working MCLK code for 96XX (haven't tested 9440)
  6.  *    v0.92b noticed bug under Win95-OSR2 where screen-corruption can happen
  7.  *          can't seem to fix it
  8.  *    source-code based on information compiled in VGADOC4B.ZIP
  9.  */
  10.  
  11. #include "trident.h"
  12.  
  13. #include<dos.h>
  14. #include<string.h>
  15. #include<stdio.h>
  16. #include<stdlib.h>
  17. #include<iostreams.h>
  18.  
  19.  
  20. message
  21. _TR9440::_info( void )
  22. {
  23.     sprintf( msg.text, "" );
  24.     return msg;
  25. }
  26.  
  27. /*
  28. void
  29. _TR9440::setmode(uchar mode)
  30. {
  31.     switch ( mode )    {
  32.         case _NEW:    // Set Trident _SR registers to "NEW" mode
  33.             outportb( _SRindex, 0x0B );    // Reading forces NEW mode
  34.             inportb( _SRIO );
  35.             inportb( _SRIO );        // Two 8-bit reads = 16-bit read
  36.             break;
  37.         case _OLD:    // Set Trident _SR registers to "OLD" mode
  38.             outportb( _SRindex, 0x0B );    // Writing forces OLD mode
  39.             outportb( _SRIO, 0 );    // Two 8-bit writes = 16-bit write
  40.             outportb( _SRIO, 0 );
  41.             break;
  42.         default:
  43.             fprintf( stderr, "\n_TR9440::setmode( mode ) error!" );
  44.             exit( EXIT_FAILURE );
  45.     }
  46. }
  47. */
  48.  
  49. int
  50. _TR9440::read_mclk( void )    // Reads MCLK bytes into one int
  51. {
  52.     // Trident MCLK-word is at port 0x43C6 and 0x43C7 (16-bits total)
  53.     int _43C6 = inportb( 0x43C6 );
  54.     int _43C7 = inportb( 0x43C7 );
  55.     // No, you can't just do int mclk = inport( 0x43C6 )... doesn't work!
  56.  
  57.     return ( _43C7 << 8 ) | _43C6 ;
  58. }
  59.  
  60.  
  61. double
  62. _TR9440::get_mclkfreq()
  63. {
  64.     double freq;
  65.     int mclk = read_mclk();  // Read MCLK word
  66.     uchar mult2 = (mclk & 0x0200) ? 0 : 1;    // Multiply by 2?
  67.     uchar divisor = mclk & 0x0007 ; //  lowest three bits 0000 0000 0000 0XXX
  68.     uchar scale = ( mclk & 0x01F8 ) >> 3; // 0000 000X XXXX X000
  69.  
  70.     freq = _OSC * (scale + 4.0 ) / ( divisor + 2.0 );
  71.     //
  72.     // v0.91b
  73.     // I don't know if this is 100% accurate--I reverse-engineered the
  74.     // dram-clock formula
  75.     //
  76.     //  _OSC = 14.31818 MHz (reference frequency)
  77.     //                      ( B + 4 ) * ( _A )
  78.     //  DCLK (MHz) = _OSC * ------------------
  79.     //                           ( C + 2 )
  80.     //
  81.     //
  82.     // port 0x43C6 and 0x43C7 form 16-bit binary MCLK "word" (Intel-style)
  83.     // MCLK( 15:0 ) = ???? ??AB  BBBB BCCC <- 16-bit word
  84.     //                5432 1098  7654 3210 <- bit#
  85.     //
  86.     // "A" single-bit flag ( 0 = scale up by 2, 1 = no effect )
  87.     // "B" 6-bit "scale" factor
  88.     // "C" 3-bit "divisor" factor
  89.     // "?" don't really know
  90.  
  91.     if ( mult2 )
  92.         freq *= 2.0 ; // if mult2 is set, double freq
  93.  
  94.     return freq;
  95. }
  96.  
  97.  
  98. void        //    MCLK programming for Trident 9440/96xx
  99. _TR9440::_mclk( int cmd )
  100. {
  101.     int mclk;
  102.      uchar _SR0E;    //    Register _SR0E, temp-holding place
  103.  
  104.     if ( cmd == _QUERY )    {
  105.         strcpy( msg.text, "0  9440/96xx MCLK programming\n" );
  106.         return;
  107.     }
  108.  
  109.      mclk = read_mclk();    // New MCLK 16-bit value
  110.     uchar mult2 = (mclk & 0x0200) ? 0 : 1;    // Multiply by 2?
  111.     uchar divisor = mclk & 0x0007 ; // lowest three bits 0000 0000 0000 0XXX
  112.     uchar scale = ( mclk & 0x01F8 ) >> 3; // 0000 000X XXXX X000
  113.      sprintf( msg.text, "Old MCLK = %.2fMHz (%04X)", get_mclkfreq(),
  114.         read_mclk() );
  115.     sprintf( msg.temp, "\nscale = %d (dec), divisor = %X, mult2 = %d (dec)",
  116.         scale, divisor, mult2 );
  117.     strcat( msg.text, msg.temp );
  118.  
  119.     if ( num_param < 3 && cmd == _SET )    {
  120.         strcat( msg.text, "\nError!  THREE parameters required!");
  121.         cmd = _HELP; }
  122.     else    if ( num_param >= 3 ) {
  123.         mult2 = ( (uchar)atoi( param[ 2 ] ) ) & 0x01;
  124.         divisor = ( (uchar)atoi( param[ 1 ] ) ) & 0x07;
  125.         scale = ( (uchar)atoi( param[ 0 ] ) ) & 0x3F;
  126.     }
  127.  
  128.     if ( param[ 0 ] != NULL ) // Only the 1st parameter is used
  129.         if ( sscanf( param[ 0 ], " %x", &mclk ) == 0 )
  130.             cmd = _HELP;    //    Error, no value scanned
  131.  
  132.     switch ( cmd )    {
  133.         case _SET    :
  134.             uchar mhigh = inportb( 0x43C7 ) & 0xFC;    // preserve top 6 bits
  135.             uchar mlow = ( scale << 3 ) | divisor;
  136.             mhigh = mhigh | ( mult2 ? 0 : 0x02 ) | ( scale >> 5 ) ;
  137.             _SR0E = read_SR( 0x0E );    // XX00 0000
  138.             write_SR( 0x0E, _SR0E | 0x82 );    // 1XXX XX1X
  139.                 // To update MCLK, bits 1 & 7 must be SET
  140.             outportb( 0x43C6,  mlow );
  141.             outportb( 0x43C7, mhigh );
  142.             write_SR( 0x0E, _SR0E );    // Restore _SR0E to original value!
  143.  
  144.             mclk = read_mclk();
  145.             sprintf( msg.temp, "\n\nNew MCLK = %.2fMHz (%04X) ",
  146.                 get_mclkfreq(), mclk );
  147.             mult2 = (mclk & 0x0200) ? 0 : 1;
  148.             divisor = mclk & 0x0007 ;
  149.             scale = ( mclk & 0x01F8 ) >> 3;
  150.             strcat( msg.text, msg.temp );
  151.             sprintf( msg.temp,
  152.                 "\nscale = %d (dec), divisor = %X, mult2 = %d (dec)",
  153.                 scale, divisor, mult2 );
  154.             strcat( msg.text, msg.temp );
  155.             break;
  156.         case _GET :    case _HELP:    sprintf( msg.temp, "%s%s%s%s%s",
  157.              "\n  Note:  Trident 9440/96xx MCLK max = 80MHz",
  158.              "\n\t mclk = 14.31818MHz * ( scale+4 ) / ( divisor+2 )",
  159.              ", (if mult2=1, * 2 )",
  160.              "\n\t Input: mclk /0 SCALE DIVISOR MULT2 (3 parameters)",
  161.              "\n\t        scale = 0-63, divisor = 0-7, mult2 = 0 or 1" );
  162.             strcat( msg.text, msg.temp );
  163.             break;
  164. /*    --CODE TAKEN FROM VGADOC4B.ZIP
  165. 43C6h W(R/W):  Memory Clock                                             (9440)
  166. bit 0-15  Selects the memory clock. 2C6h = 50MHz, 307h = 58MHz, 87h = 64MHz
  167.           8Eh = 75MHz
  168. Note: 3C4h index Eh (new) bits 1 & 7 must be set to update this register
  169. */
  170.  
  171.         default:
  172.             sprintf( msg.text, "_TR9440::_mclk(cmd)  UNRECOGNIZED cmd.");
  173.             status = EXIT_FAILURE;
  174.     }
  175. }