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

  1. /*    cirrus.cpp        03/21/97    0.93α
  2.  *
  3.  *    Includes class definitions for Cirrus Logic
  4.  *    GD-5420/22 (_cirrus) 1 setting, tested
  5.  *    GD-5424 and up ( 3 settings, tested...4th setting is read-back only)
  6.  *    GD-543x ( 3 settings, only the 1st one is tested )
  7.  *
  8.  *    v0.83B, GD-5434 MCLK will warn user about GD-5434 BIOS
  9.  *    v0.83B, tries to get Cirrus Silicon revision (through BIOS 0x10)
  10.  *    v0.84B, Cirrus Logic GD-5436 specific code
  11.  *            (GD5430/5440 grouped together)
  12.  *    v0.85B, converted sprintf calls to ostrstream << method
  13.  *    v0.89B, modified 5436 functions to read "5436/46"
  14.  *   v0.92B, cosmetic changes (no new code)
  15.  *    v0.93α, added Cirrus Logic GD-546X code (untested), more cosmetic changes
  16.  */
  17.  
  18.  
  19. #include "cirrus.h"
  20.  
  21. #include<dos.h>
  22. #include<string.h>
  23. #include<stdio.h>
  24. #include<stdlib.h>
  25. #include<iostreams.h>
  26.  
  27. /*
  28.  *    cirrus.h
  29.  *    cirrus class function definitions
  30.  */
  31.  
  32.  
  33. message
  34. _cirrus::_info( void )
  35. {
  36.     INITMSG( msg.text );
  37.     union REGS reg;
  38.     reg.h.ah = 0x12 ;
  39.     reg.h.bl = 0x80 ;
  40.     int86( 0x10, ®, ® );
  41.  
  42.     if ( reg.h.bl != 0x80 )    {
  43.         msgout <<    "Chip revision = " ;
  44.         hexout( msgout, reg.h.bl );    // print reg.h.bl in "XX" format
  45.     } else
  46.         msgout << "Chip revision NOT available.";
  47.  
  48.     msgout << "  RAS timing mode = ";
  49.     if ( read_bit( _SRindex, 0x0F, 2 ) )
  50.         msgout << "standard (faster) ";
  51.     else
  52.         msgout << "extended (slower) ";
  53.  
  54.     msgout << ends ;
  55.     return msg;
  56. }
  57.  
  58.  
  59. void
  60. _cirrus::_mclk( int cmd )
  61. {
  62.     uchar _SR1F = read_SR ( 0x1F ) & 0x3F;        // Read _SR1F register
  63.     uchar new_MCLK = _SR1F;    // New MCLK byte
  64.     INITMSG( msg.text );
  65.  
  66.     if ( cmd == _QUERY )    {
  67.         msgout << "0  GD-54xx MCLK memory clock setting\n" << ends;
  68.         return;
  69.     }
  70.  
  71. //    sprintf( msg.text, "Current MCLK = %.2fMHz (%02dd)", get_mclkfreq(),
  72. //        _SR1F );
  73.     msgout.precision( 2 );
  74.     msgout << "Old MCLK = " << get_mclkfreq() << "MHz (" << (int)(_SR1F)
  75.         << "d)";
  76.  
  77.     if ( param[ 0 ] != NULL ) // Only the 1st parameter is used
  78.         new_MCLK = ( (uchar) atoi( param[ 0 ] ) ) & 0x3F;
  79.  
  80.     switch ( cmd )    {
  81.         case _SET    : _SR1F = read_SR( 0x1F) & 0xC0;    // XX00 0000
  82.                 //    Now perform a READ/MODIFY/WRITE to _SR1F
  83.             write_SR( 0x1F, _SR1F | new_MCLK );
  84.             msgout << "\nNew MCLK = " << get_mclkfreq() << "MHz ("
  85.                 << (int)( new_MCLK ) << "d)";
  86. //            sprintf( msg.temp, "\nNew MCLK = %.2fMHz (%02dd) ",
  87. //                get_mclkfreq(), new_MCLK );
  88. //            strcat( msg.text, msg.temp );
  89.             break;
  90.         case _GET :    case _HELP:    msgout
  91.              << "\nNote:  GD-5429 max = 60MHz, all other GD=542x = 50MHz"
  92.              << "\n       GD-5430/5440 max = 60MHz, GD-5436 = 80MHz"
  93.              << "\n\tInput = 0-63dec, example values : "
  94.              << "\n\t23d = 41.17MHz\n\t25d = 44.74MHz"
  95.              << "\n\t28d = 50.11MHz\n\tOther values ok.";
  96.             break;
  97.         default:
  98.             msgout << "cirrus::_mclk(cmd)  UNRECOGNIZED cmd.";
  99.             status = EXIT_FAILURE;
  100.     }
  101.     msgout << ends;
  102. }
  103.  
  104.  
  105. void
  106. _GD5424::_fxn2( int cmd )    //    RDY delay for I/O (local bus only)
  107. {
  108.     INITMSG( msg.text );
  109.     if ( cmd == _QUERY )    {
  110.         msgout << "2  GD-5424/6/8/9 RDY delay for I/O (local-bus only)\n"
  111.             << ends;
  112.         return;
  113.     }
  114.  
  115.  
  116.     uchar _SR16 = ( read_SR( 0x16 ) >> 6 ) & 0x03; // Read _SR16 register
  117.     uchar new_RDY= 0x03;    //    Default to 2T delay
  118.  
  119.     if ( param[ 0 ] != NULL )
  120.         new_RDY = (uchar)atoi( param[ 0 ] );
  121.  
  122. //    sprintf( msg.text, "Old I/O RDY delay = %uT (%ud) ", _SR16 / 2, _SR16 );
  123.     msgout << "Old I/O RDY delay = " << (int) (_SR16 / 2) << "T ("
  124.         << (int)_SR16 << ") ";
  125.  
  126.     switch ( cmd )    {
  127.         case _SET:    _SR16 = read_SR( 0x16 ) & 0x3F;    //    DD00 0000
  128.             write_SR( 0x16, ( ( new_RDY << 6 ) & 0xC0 ) | _SR16 );
  129. //            sprintf( msg.temp, "\nNew delay = %uT (%ud) ",
  130. //                new_RDY /2 , new_RDY );
  131. //            strcat ( msg.text, msg.temp );
  132.             msgout << "\nNew delay = " << (int) (new_RDY / 2) << "T ("
  133.                 << (int)new_RDY << ") ";
  134.             break;
  135.         case _GET:    case _HELP:
  136.             msgout <<    "\n(local-bus only)\nActual clock delays (T) / XXd"
  137.                 << " (where XXd is INPUT value in decimal.)"
  138.                 << "\n\t0T/00\n\t0T/01\n\t1T/02\n\t1T/03";
  139.             break;
  140.         default:
  141.             msgout << "_GD5424::_fxn2(cmd)  UNRECOGNIZED cmd.";
  142.             status = EXIT_FAILURE;
  143.     }
  144.     msgout << ends;
  145. }
  146.  
  147. /*    REMOVED, BECAUSE CIRRUS BIOS RE-PROGRAMS FIFO THRESHOLD FOR EVERY mode!
  148. void
  149. _GD5424::_fxn4( int cmd )    //    FIFO refilling threshold (_SR16 bits 3-0)
  150. {
  151.     if ( cmd == _QUERY )    {
  152.         strcpy(msg.text, "4  GD-5424+ FIFO Demand Threshold\n" );
  153.         return;
  154.     }
  155.  
  156.  
  157.     uchar _SR16 = read_SR( 0x16 ) & 0x0F;    // 0000 XXXX
  158.     uchar new_SR16= 0x0F;    //    Default to 15 FIFO slots
  159.  
  160.     if ( param[ 0 ] != NULL )
  161.         new_SR16 = (uchar)atoi( param[ 0 ] );
  162.  
  163.     sprintf( msg.text, "Old FIFO threshold = %u ", _SR16 );
  164.  
  165.     switch ( cmd )    {
  166.         case _SET:    _SR16 = read_SR( 0x16 ) & 0xF0;    //    DD00 0000
  167.             write_SR( 0x16, ( new_SR16 & 0x0F ) | _SR16 );
  168.             sprintf( msg.temp, "\nNew FIFO = %u ", new_SR16 );
  169.             strcat ( msg.text, msg.temp );
  170.             break;
  171.         case _GET:    case _HELP:
  172.             sprintf( msg.temp, "\nFIFO threshold (GD-5424 and up) %s%s%s",
  173.                 "\nTriggering level for CRT to re-fill CRT FIFO (0-15d)",
  174.                 "\n\t( lower value = more frequent re-fills )",
  175.                 "\n\tAllowable input:  0-15 (decimal)");
  176.             strcat ( msg.text, msg.temp );
  177.             break;
  178.         default:
  179.             sprintf( msg.text, "_GD5424::_fxn4(cmd)  UNRECOGNIZED cmd.");
  180.             status = EXIT_FAILURE;
  181.     }
  182. } */
  183.  
  184.  
  185.  
  186. void
  187. _GD5424::_fxn3( int cmd )    //    RDY Delay for Memory Write
  188. {
  189.     INITMSG( msg.text );
  190.  
  191.     if ( cmd == _QUERY )    {
  192.         msgout << "3  GD-5424/6/8/9 RDY Delay for mem-write "
  193.             << "(local-bus only)\n" << ends;
  194.         return;
  195.     }
  196.  
  197.  
  198.     uchar _SR16 = ( read_SR( 0x16 ) >> 4 ) & 0x03; // Read _SR16 register
  199.     uchar new_RDY= 0x03;    //    Default to 2T delay
  200.     uchar _is5429 = ( strcmpi( id.chipset, "GD-5429" ) == 0 );
  201.         // _is5429 is a status-variable, 0 = not 5429
  202.  
  203.     if ( param[ 0 ] != NULL )
  204.         new_RDY = (uchar)atoi( param[ 0 ] );
  205.  
  206.     msgout << "Old RDY write-mem delay = " << (int)( 2 - _is5429 + _SR16 )
  207.         << "T (" << (int)( _SR16 ) << ") ";
  208. //    sprintf( msg.text, "Old RDY write-mem delay = %uT (%ud) ", ( 2 -
  209. //        _is5429 + _SR16 ), _SR16 ) ;
  210.  
  211.     switch ( cmd )    {
  212.         case _SET:    _SR16 = read_SR( 0x16 ) & 0xCF;    //    00DD 0000
  213.             write_SR( 0x16, ( ( new_RDY << 4 ) & 0x30 ) | _SR16 );
  214.             msgout << "\nNew delay = " << (int)( 2 - _is5429 + new_RDY )
  215.                 << "T (" << (int)( new_RDY ) << ") ";
  216. //            sprintf( msg.temp, "\nNew delay = %uT (%ud) ", 2 - _is5429 +
  217. //                new_RDY, new_RDY );
  218. //            strcat ( msg.text, msg.temp );
  219.             break;
  220.         case _GET:    case _HELP:    msgout << "\n(local-bus only)"
  221.                 << " Actual LRDY I/O clock delays (T) / XXd"
  222.                 << "\n(where XXd is INPUT value in decimal.)";
  223.             if ( _is5429 )
  224.              msgout << "\n\t1T/00\n\t2T/01\n\t3T/02\n\t4T/03";
  225.             else
  226.              msgout << "\n\t2T/00\n\t3T/01\n\t4T/02\n\t5T/03";
  227.             break;
  228.         default:    msgout << "_GD5424::_fxn3(cmd)  UNRECOGNIZED cmd.";
  229.             status = EXIT_FAILURE;
  230.     }
  231.     msgout << ends;
  232. }
  233.  
  234.  
  235. //-------------------- Cirrus GD-543x functions --------------------------
  236. void
  237. _GD543x::_fxn2( int cmd )    //    LRDY delay for VL-bus only
  238. {    //    0600 0000 bit6 of _SR16 = LRDY delay
  239.     INITMSG( msg.text );
  240.  
  241.     if ( cmd == _QUERY )    {
  242.         msgout << "2  GD-543x RDY delay for I/O (local-bus only)\n"
  243.             << ends;
  244.      return;
  245.     }
  246.  
  247.     uchar _SR16 = read_bit( _SRindex, 0x16, 6 ); // Read bit6 _SR16 register
  248.     uchar new_RDY= 0x01;    //    Default to 2T READ/ 1T WRITE delay
  249.  
  250.     if ( param[ 0 ] != NULL )
  251.         new_RDY = (uchar)atoi( param[ 0 ] ) ;
  252.  
  253.     sprintf( msg.text, "Old vl-bus LRDY R/W delay = %uT/%uT (%ud) ", 1 +
  254.         _SR16, _SR16, _SR16 );
  255.  
  256.     switch ( cmd )    {
  257.         case _SET:
  258.             write_bit( _SRindex, 0x16, 6, new_RDY );
  259.             sprintf( msg.temp, "\nNew R/W delay = %uT/%uT (%ud) ", 1 +
  260.                 new_RDY, new_RDY, new_RDY );
  261.             strcat ( msg.text, msg.temp );
  262.             break;
  263.         case _GET:    case _HELP:
  264.             sprintf( msg.temp,"\n(only applicable in VL-bus setup.)%s",
  265.                 "\n\t1T read/0T write - 00\n\t2T read/1T write - 01");
  266.             strcat ( msg.text, msg.temp );
  267.             break;
  268.         default:
  269.             sprintf( msg.text, "_GD543x::_fxn2(cmd)  UNRECOGNIZED cmd.");
  270.             status = EXIT_FAILURE;
  271.     }
  272. }
  273.  
  274.  
  275. void
  276. _GD543x::_fxn3( int cmd )    //    LRDY Delay for Memory Cycles
  277. {    // LRDY Delay = bit4 of _SR16
  278.     INITMSG( msg.text );
  279.  
  280.     if ( cmd == _QUERY )    {
  281.         msgout << "3  GD-543x RDY Delay for mem-write (local-bus only)\n"
  282.             << ends;
  283.         return;
  284.     }
  285.  
  286.     uchar _SR16 = read_bit( _SRindex, 0x16, 4 ); // Read bit4 _SR16 register
  287.     uchar new_RDY= 0x01;    //    Default to 2T-1T R/W delay
  288.  
  289.     if ( param[ 0 ] != NULL )
  290.         new_RDY = (uchar)atoi( param[ 0 ] );
  291.  
  292.     sprintf( msg.text, "Old LRDY R/W mem delay = %uT/%uT (%ud) ", 1 +
  293.          _SR16, _SR16, _SR16 ) ;
  294.  
  295.     switch ( cmd )    {
  296.         case _SET:
  297.             write_bit( _SRindex, 0x16, 4, new_RDY );
  298.             sprintf( msg.temp, "\nNew R/W delay = %uT/%uT (%ud) ", 1 +
  299.                 new_RDY, new_RDY, new_RDY ) ;
  300.             strcat ( msg.text, msg.temp );
  301.             break;
  302.         case _GET:    case _HELP:
  303.             sprintf( msg.temp, "\n(local-bus only)%s",
  304.              "\nRead delay / Write delay\n\t1T/0T - 00\n\t2T/1T - 01" );
  305.             strcat( msg.text, msg.temp );
  306.             break;
  307.         default:
  308.             sprintf( msg.text, "_GD543x::_fxn3(cmd)  UNRECOGNIZED cmd.");
  309.             status = EXIT_FAILURE;
  310.     }
  311. }
  312.  
  313.  
  314. void
  315. _GD5434::_mclk( int cmd )
  316. {
  317.     uchar _SR1F = read_SR ( 0x1F ) & 0x3F;        // Read _SR1F register
  318.     uchar new_MCLK = _SR1F;    // New MCLK byte
  319.     union REGS reg;
  320.     INITMSG( msg.text );
  321.  
  322.     if ( cmd == _QUERY )    {
  323.         msgout <<    "0  GD-5434 MCLK memory clock setting\n" << ends;
  324.         return;
  325.     }
  326. //    sprintf( msg.text, "Current MCLK = %.2fMHz (%02dd)", get_mclkfreq(),
  327. //        _SR1F );
  328.     msgout.precision( 2 );
  329.     msgout << "Old MCLK = " << get_mclkfreq() << "MHz (" << (int)(_SR1F)
  330.         << "d)";
  331.  
  332.     if ( param[ 0 ] != NULL ) // Only the 1st parameter is used
  333.         new_MCLK = ( (uchar) atoi( param[ 0 ] ) ) & 0x3F;
  334.  
  335.     switch ( cmd )    {
  336.         case _SET    :    _SR1F = read_SR( 0x1F) & 0xC0;    // XX00 0000
  337.                 //    Now perform a READ/MODIFY/WRITE to _SR1F
  338.             write_SR( 0x1F, _SR1F | new_MCLK );
  339.             msgout << "\nNew MCLK = " << get_mclkfreq() << "MHz ("
  340.                 << (int)( new_MCLK ) << "d)";
  341. //            sprintf( msg.temp, "\nNew MCLK = %.2fMHz (%02dd) ",
  342. //                get_mclkfreq(), new_MCLK );
  343. //            strcat( msg.text, msg.temp );
  344.             break;
  345.         case _GET :    case _HELP:    msgout << "\nGD-5434 max = 50MHz, "
  346.             << "GD-5434revE max = 60MHz\nInput = 0-63dec, example values "
  347.             << ": \n\t23d = 41.17MHz\n\t25d = 44.74MHz"
  348.             << "\n\t28d = 50.11MHz\n\tOther values ok.\n\t**WARNING** "
  349.             << "GD-5434's video BIOS resets MCLK on every mode change!";
  350. //            strcat( msg.text, msg.temp );
  351.             break;
  352.         default:
  353.             msgout << "_GD5434::_mclk(cmd)  UNRECOGNIZED cmd.";
  354.             status = EXIT_FAILURE;
  355.     }
  356.     msgout << ends;
  357. }
  358.  
  359.  
  360. void
  361. _GD5436::_fxn1( int cmd )    //    Enable 8-MCLK EDO Timing
  362. {    //    bit2 of _GR18, 0 = no, 1 = 8-MCLK EDO timing
  363.     INITMSG( msg.text );
  364.  
  365.     if ( cmd == _QUERY )    {
  366.         msgout << "1  GD-5436/46 8-MCLK EDO DRAM timing\n" << ends;
  367.         return;
  368.     }
  369.     uchar new_EDO = read_bit( _GRindex, 0x18, 2 );    // Default to old val
  370.  
  371.     sprintf( msg.text, "Old 8-MCLK EDO timing = %s", bitstat( new_EDO ) );
  372.  
  373.     if ( param[ 0 ] != NULL )
  374.         new_EDO = (uchar)atoi( param[ 0 ] );
  375.  
  376.     switch ( cmd )    {
  377.         case _SET:    write_bit( _GRindex, 0x18, 2, new_EDO );
  378.             sprintf( msg.temp, "\n8-MCLK EDO timing is now %s ",
  379.                 bitstat( new_EDO ) );
  380.             strcat ( msg.text, msg.temp );
  381.             break;
  382.         case _GET:    case _HELP:
  383.             sprintf( msg.temp, "\n8-MCLK EDO Timing\n\t1 = enable%s%s",
  384.                 "\n\t0 = disable\nDisable for FPM-DRAM, activate for EDO-DRAM timing",
  385.                 "\n(Increased delay may permit higher MCLK-frequencies" );
  386.             strcat ( msg.text, msg.temp );
  387.             break;
  388.         default:
  389.             sprintf( msg.text, "_GD5436::_fxn1(cmd)  UNRECOGNIZED cmd.");
  390.             status = EXIT_FAILURE;
  391.     }
  392. }
  393.  
  394.  
  395. void
  396. _GD5436::_fxn2( int cmd )    //    Single Refresh Cycle
  397. {    //    bit3 of _GR18, 0 = standard timing, 1 = single-refresh cycle
  398.     INITMSG( msg.text );
  399.  
  400.     if ( cmd == _QUERY )    {
  401.         msgout << "2  GD-5436/46 RAM refresh-cycle timing\n" << ends;
  402.         return;
  403.     }
  404.     uchar new_CYC = read_bit( _GRindex, 0x18, 3 );    // Default to old val
  405.  
  406.     sprintf( msg.text, "Single-refresh cycle timing = %s",
  407.         bitstat( new_CYC ) );
  408.  
  409.     if ( param[ 0 ] != NULL )
  410.         new_CYC = (uchar)atoi( param[ 0 ] );
  411.  
  412.     switch ( cmd )    {
  413.         case _SET:    write_bit( _GRindex, 0x18, 3, new_CYC );
  414.             sprintf( msg.temp, "\nSingle-cycle refresh timing is now %s.",
  415.                 bitstat( new_CYC ) );
  416.             strcat ( msg.text, msg.temp );
  417.             break;
  418.         case _GET:    case _HELP:
  419.             sprintf( msg.temp, "\nSingle-cycle refresh\n\t1 = enable%s%s",
  420.                 "\n\t0 = disable\n\nEnabling single-cycle refresh ",
  421.                 "increases available memory-bandwidth." );
  422.             strcat ( msg.text, msg.temp );
  423.             break;
  424.         default:
  425.             sprintf( msg.text, "_GD5436::_fxn2(cmd)  UNRECOGNIZED cmd.");
  426.             status = EXIT_FAILURE;
  427.     }
  428. }
  429.  
  430.  
  431. _GD5462::_GD5462( vga_info info ) : vga( info )
  432. {
  433.      // First, get and store original MMIO0 base-address
  434.     // We need to keep it, because it'll be changed later
  435.      baseio.b.b0 = read_cbyte( 0x10 +0 );    // Read PCICFG$10, bits 7:0
  436.      baseio.b.b1 = read_cbyte( 0x10 +1 );    // Read PCICFG$11, bits 15:8
  437.     baseio.b.b2 = read_cbyte( 0x10 +2 );    // Read PCICFG$12, bits 23:16
  438.     baseio.b.b3 = read_cbyte( 0x10 +3 );    // Read PCICFG$13, bits 31:24
  439.      // Byte3 = most-significant byte, Byte0= least-significant)
  440.  
  441.          // Actually, the Cirrus Logic mmio0 spans bits 31:15 at PCICFG$10
  442.           // We don't need to store b0.  We only need to store bit7 of b1
  443.           // MMIO aperature = 32KB (mmio0 address = 32kB granularity)
  444.           // For aperature at A000:0000 (absolute offset 6556360 decimal)
  445.           // Must set MMIO[31:15] = $14 (hex)
  446.         // --> translates into b3 = 0x0A, b2 = 0, b1[bit 7] = 0
  447.  
  448.  
  449.      // Now we have to enable I/O access to MMIO registers
  450.      pci_command.b.b0 = read_cbyte( 0x04 );    // Preserve original value
  451.      pci_command.b.b1 = read_cbyte( 0x05 );    // Preserve original value
  452.  
  453.      write_cbyte( 0x04, pci_command.b.b0 | 0x01 ); // Write out XXXX XXX1
  454.  
  455.      framebuffer = (uchar*)MK_FP( 0xA000, 0x0000 );
  456.          // Set framebuffer to point to VGA framebuffer address 0xA0000
  457.  
  458. }
  459.  
  460.  
  461. _GD5462::~_GD5462()
  462. {
  463.      // Restore original MMIO aperature location
  464.     write_cbyte( 0x10, baseio.b.b0 );
  465.     write_cbyte( 0x11, baseio.b.b1 );
  466.     write_cbyte( 0x12, baseio.b.b2 );
  467.     write_cbyte( 0x13, baseio.b.b3 );
  468.  
  469.      // Now restore pci_command register
  470.     write_cbyte( 0x04, pci_command.b.b0 );
  471.      write_cbyte( 0x05, pci_command.b.b1 );
  472. }
  473.  
  474.  
  475. message
  476. _GD5462::_info( void )
  477. {
  478.     INITMSG( msg.text );
  479.  
  480.     msgout <<    "IO config address = 0x" ;    // 32-bit absolute byte address
  481.     hexout( msgout, baseio.b.b3 );    // print reg.h.bl in "XX" format
  482.      hexout( msgout, baseio.b.b2 );
  483.      msgout << " ";
  484.      if ( baseio.b.b1 & 0x80 )    // Is bet7 of b1 set?
  485.          msgout << "8000";        // Yup!  +32Kbyte offset
  486.      else
  487.          msgout << "0000";        // Nope!  No such offset
  488.  
  489.     msgout << ends ;
  490.     return msg;
  491. }
  492.  
  493.  
  494. uchar
  495. _GD5462::read_cbyte( const uchar index )
  496. {
  497.     uchar value, status = TRUE;
  498.  
  499.         status = pci_bios->read_cbyte( pci_vga, index, &value );
  500.      return value;
  501. }
  502.  
  503.  
  504. uchar
  505. _GD5462::write_cbyte( const uchar index, const uchar value )
  506. {
  507.      uchar status= TRUE;
  508.  
  509.     if ( pci_bios->write_cbyte( pci_vga, index, value ) != 0 )
  510.          status = FALSE;
  511.  
  512.     return status;
  513. }
  514.  
  515. uchar
  516. _GD5462::get_mclkbyte( void )
  517. {
  518.      uchar mclk_byte;
  519.      // Set MMIO0 aperature to A0000, so it's readable by real-mode apps
  520.      // Actually, the Cirrus Logic mmio0 spans bits 31:15 at PCICFG$10
  521.     // We don't need to store b0.  We only need to store bit7 of b1
  522.      // MMIO aperature = 32KB (mmio0 address = 32kB granularity)
  523.      // For aperature at A000:0000 (absolute offset 6556360 decimal)
  524.      // Must set MMIO[31:15] = $14 (hex)
  525.      // --> translates into b3 = 0x0A, b2 = 0, b1[bit 7] = 0
  526.  
  527.     write_cbyte( 0x12, 0x0A );    // base-address[8:1] = 0x0A
  528.     write_cbyte( 0x13, 0x00 );    // base-address[16:9] = 0x00
  529.      write_cbyte( 0x11, read_cbyte( 0x11 ) & 0x7F );
  530.         // bit7=0, or base-address[0] = 0
  531.  
  532.      mclk_byte = *( framebuffer + 0x8C );    // read MMIO0 offset 0x8C
  533.  
  534.     // Restore MMIO0 aperature to original value
  535.      write_cbyte( 0x11, baseio.b.b1 );
  536.     write_cbyte( 0x12, baseio.b.b2 );
  537.     write_cbyte( 0x13, baseio.b.b3 );
  538.  
  539.      return mclk_byte;
  540. }
  541.  
  542.  
  543. void
  544. _GD5462::_mclk( int cmd )
  545. {
  546.     union    {
  547.          uchar byte;    // MCLK register byte
  548.           struct {
  549.               unsigned mult : 5;    // RAMBUS multiplier, 5-bits
  550.                unsigned other : 3;
  551.           } x;
  552.      } mclk;
  553.  
  554.     INITMSG( msg.text );
  555.  
  556.     if ( cmd == _QUERY )    {
  557.         msgout << "0  GD-546X RAMBUS clock setting\n" << ends;
  558.         return;
  559.     }
  560.  
  561.     mclk.byte = get_mclkbyte();    // Get mclk_byte
  562.  
  563.     msgout.precision( 2 );
  564.     msgout << "Old RAMBUS clock = " << ( _OSC * mclk.x.mult ) << " MHz ("
  565.         << (int)( mclk.x.mult ) << "d)";
  566.  
  567.     if ( param[ 0 ] != NULL ) // Only the 1st parameter is used
  568.         mclk.x.mult = (unsigned) atoi( param[ 0 ] ) & 0x1F;
  569.  
  570.     switch ( cmd )    {
  571.         case _SET    :    // First, set MMIO address to A000:0000
  572.             write_cbyte( 0x12, 0x0A );    // base-address[15:0] = 0x000A
  573.             write_cbyte( 0x13, 0x00 );
  574.             write_cbyte( 0x11, read_cbyte( 0x11 ) & 0x7F );
  575.                 // bit7=0, or base-address[0] = 0
  576.  
  577.              *( framebuffer + 0x8C ) = mclk.byte;
  578.                 // Write mclk_byte -> MMIO0 offset 0x8C
  579.  
  580.             // Restore MMIO0 aperature to original value
  581.                write_cbyte( 0x11, baseio.b.b1 );
  582.             write_cbyte( 0x12, baseio.b.b2 );
  583.             write_cbyte( 0x13, baseio.b.b3 );
  584.  
  585.             mclk.byte = get_mclkbyte();    // Re-read mclk_byte
  586.             msgout << "\nNew RAMBUS clock = " << ( _OSC * mclk.x.mult ) <<
  587.                 " MHz (" << (int)( mclk.x.mult ) << "d)";
  588.             break;
  589.         case _GET :    case _HELP:    msgout
  590.              << "\nNote:  GD-546X maximum RAMBUS clock (BCLK) = "
  591.              << "258MHz (18d),\n\tInput = 7-22dec, example values :"
  592.              << "\n\t18 = 257.73MHz\n\t20 = 286.36MHz\n\tOther values ok."
  593.              << "\n\nWARNING!  Win95 drivers reset RAMBUS clock!  See "
  594.              << "546X.TXT for details!";
  595.  
  596.             break;
  597.         default:
  598.             msgout << "_GD5462::_mclk(cmd)  UNRECOGNIZED cmd.";
  599.             status = EXIT_FAILURE;
  600.     }
  601.     msgout << ends;
  602. }
  603.  
  604.  
  605. void
  606. _GD5464::_fxn2( int cmd )    // PCI Master Latency Timer Register
  607. {    // PCI Config $0D[7:3]
  608.     union    {
  609.          uchar byte;    // PCI Master latency timer register byte
  610.           struct {
  611.                unsigned other : 3;
  612.               unsigned timer : 5;    // PCI latency timer, 5-bits
  613.           } x;
  614.      } pcfg;
  615.  
  616.     INITMSG( msg.text );
  617.  
  618.     if ( cmd == _QUERY )    {
  619.         msgout << "2  GD-5464 PCI Master Latency Timer\n" << ends;
  620.         return;
  621.     }
  622.  
  623.     pcfg.byte = read_cbyte( 0x0D);    // Get pcfg_byte
  624.  
  625.     msgout << "Old Latency Timer=" << (int)( pcfg.x.timer ) << " cycle(s)";
  626.  
  627.     if ( param[ 0 ] != NULL ) // Only the 1st parameter is used
  628.         pcfg.x.timer = (unsigned) atoi( param[ 0 ] ) & 0x1F;
  629.  
  630.     switch ( cmd )    {
  631.         case _SET    :    write_cbyte( 0x0D, pcfg.byte );
  632.  
  633.             pcfg.byte = read_cbyte( 0x0D );    // Re-read pcfg_byte
  634.             msgout << "\nNew Latency Timer=" << (int)( pcfg.x.timer ) <<
  635.                 " cycle(s)";
  636.             break;
  637.         case _GET :    case _HELP:    msgout
  638.              << "\nGD-5464 PCI Latency Timer\n Controls latency when "
  639.              << "GD-5464 acts as a PCI-bus master.\n\tInput = 0-31 "
  640.              << "(number of PCI clock cycles)";
  641.             break;
  642.         default:
  643.             msgout << "_GD5464::_fxn2(cmd)  UNRECOGNIZED cmd.";
  644.             status = EXIT_FAILURE;
  645.     }
  646.     msgout << ends;
  647. }
  648.