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

  1. /*    tseng.cpp
  2.  *
  3.  *    Tseng ET6000 class declarations
  4.  */
  5. //    v0.93a Added Tseng Labs ET-6000 MCLK programming
  6. //         doesn't work with some brands of ET-6000 adapters
  7. //    v0.93b modified _et6000() class to set MEEN/IOEN controls
  8. //
  9. //
  10. //
  11. //
  12.  
  13.  
  14. #include "tseng.h"
  15.  
  16. #include<dos.h>
  17. #include<string.h>
  18. #include<stdio.h>
  19. #include<stdlib.h>
  20. #include<math.h>
  21.  
  22. _w32p::_w32p( vga_info info ) : vga( info )
  23. {
  24.     outportb( 0x3BF, 0x03 );    //    Unlock W32P "key"
  25.     outportb( 0x3D8, 0xA0 );    //    Unlock W32P "key"
  26. }
  27.  
  28.  
  29. void
  30. _w32p::_fxn1( int cmd )    //    PCI burst mode enable
  31. {    //    bit4 of _CR34
  32.     if ( cmd == _QUERY )    {
  33.         strcpy( msg.text, "1  W32P PCI burst mode (PCI only)\n");
  34.         return;
  35.     }
  36.  
  37.     uchar _CR34 = read_bit( _CRindex, 0x34, 4 );
  38.     uchar new_CR34= 0x0;
  39.  
  40.     if ( param[ 0 ] != NULL )
  41.         new_CR34 = (uchar)atoi( param[ 0 ] );
  42.  
  43.     sprintf( msg.text, "PCI Burst mode = %sd", bitstat( _CR34 ) );
  44.  
  45.     switch ( cmd )    {
  46.         case _SET:
  47.             write_bit( _CRindex, 0x34, 4, new_CR34 );
  48.             sprintf( msg.temp,"\n...now %sd",
  49.                 bitstat( read_bit( _CRindex, 0x34, 4 ) ) );
  50.             strcat( msg.text, msg.temp );
  51.             break;
  52.         case _HELP:    case _GET:
  53.             sprintf( msg.temp, "\nPCI Burst mode (PCI only) \n\t%s",
  54.                 "DISable = 0d\n\tENable  = 1d");
  55.             strcat( msg.text, msg.temp );
  56.             break;
  57.         default:
  58.             sprintf( msg.text, "_w32p::_fxn1(cmd)  UNRECOGNIZED cmd.");
  59.             status = EXIT_FAILURE;
  60.     }
  61. }
  62.  
  63.  
  64. void
  65. _w32p::_fxn2( int cmd )    //    memory interleaving
  66. {    //    bit7 of _CR32
  67.     if ( cmd == _QUERY )    {
  68.         strcpy( msg.text, "2  W32P memory interleaving (2mb only)\n");
  69.         return;
  70.     }
  71.  
  72.     uchar _CR32 = read_bit( _CRindex, 0x32, 7 );
  73.     uchar new_CR32= 0x0;
  74.  
  75.     if ( param[ 0 ] != NULL )
  76.         new_CR32 = (uchar)atoi( param[ 0 ] );
  77.  
  78.     sprintf(msg.text,"DRAM memory interleaving = %sd", bitstat( _CR32 ) );
  79.  
  80.     switch ( cmd )    {
  81.         case _SET:
  82.             write_bit( _CRindex, 0x32, 7, new_CR32 );
  83.             sprintf( msg.temp,"\n...now %sd", bitstat( new_CR32 ) );
  84.             strcat( msg.text, msg.temp );
  85.             break;
  86.         case _HELP:    case _GET:    sprintf( msg.temp,
  87.             "\nDRAM Memory interleaving ( requires 2mb DRAM )%s",
  88.                 "\n\tDISable = 0d\n\tENable  = 1d");
  89.             strcat( msg.text, msg.temp );
  90.             break;
  91.         default:
  92.             sprintf( msg.text, "_w32p::_fxn2(cmd)  UNRECOGNIZED cmd.");
  93.             status = EXIT_FAILURE;
  94.     }
  95. }
  96.  
  97.  
  98. void
  99. _w32p::_fxn3( int cmd )    //    FIFO threshold control
  100. {    //    bit7,bit5 of _CR37
  101.     if ( cmd == _QUERY )    {
  102.         strcpy( msg.text, "3  W32P FIFO threshold control (2 items)\n");
  103.         return;
  104.     }
  105.  
  106.     uchar low = read_bit( _CRindex, 0x37, 7 ),
  107.         high = read_bit( _CRindex, 0x37, 5 );
  108.  
  109.     sprintf( msg.text, "FIFO low threshold = %u,  FIFO high threshold = %u",
  110.         low, high );
  111.  
  112.     if ( num_param < 2 && cmd == _SET )    {
  113.         strcat( msg.text, "\nError!  TWO parameters required!");
  114.         cmd = _HELP; }
  115.     else    if ( num_param >= 2 ) {
  116.         low = ( (uchar)atoi( param[ 0 ] ) ) & 0x01;
  117.         high = ( (uchar)atoi( param[ 1 ] ) ) & 0x01;
  118.     }
  119.  
  120.     switch ( cmd )    {
  121.         case _SET:    write_bit( _CRindex, 0x37, 7, low );
  122.             write_bit( _CRindex, 0x37, 5, high );
  123.             sprintf( msg.temp, "\n...low = %u,  high = %u ", low, high );
  124.             strcat( msg.text, msg.temp );
  125.             break;
  126.         case _HELP:    case _GET:    sprintf( msg.temp,
  127.             "\nLow threshold ... 0=normal,  1=increased%s%s%s",
  128.                 "\nHigh threshold ... higher priority for ",
  129.                 "\n\t0 = W32p (accelerator uses more bandwidth)",
  130.                 "\n\t1 = CPU  (host accesses get higher priority)");
  131.             strcat( msg.text, msg.temp );
  132.             break;
  133.         default:
  134.             sprintf( msg.text, "_w32p::_fxn3(cmd)  UNRECOGNIZED cmd.");
  135.             status = EXIT_FAILURE;
  136.     }
  137. }
  138.  
  139.  
  140. void
  141. _w32pb::_fxn4( int cmd )    //    Fast read/write control
  142. {    //    bits5-4 of TS Register6
  143.     if ( cmd == _QUERY )    {
  144.         strcpy( msg.text,
  145.          "4  W32P fast read/write control (2 items, W32p RevB +)\n");
  146.         return;
  147.     }
  148.  
  149.     uchar read = read_bit( _SRindex, 0x6, 5 ),
  150.         write = read_bit( _SRindex, 0x6, 4 );
  151.  
  152.     sprintf( msg.text, "Fast read control = %sd,  Fast write control = %sd",
  153.         bitstat( read ), bitstat( write ) );
  154.  
  155.     if ( num_param < 2 && cmd == _SET )    {
  156.         strcat( msg.text, "\nError!  TWO parameters required!");
  157.         cmd = _HELP; }
  158.     else    if ( num_param >= 2 ) {
  159.         read = ( (uchar)atoi( param[ 0 ] ) ) & 0x01;
  160.         write = ( (uchar)atoi( param[ 1 ] ) ) & 0x01;
  161.     }
  162.  
  163.     switch ( cmd )    {
  164.         case _SET:    write_bit( _SRindex, 0x6, 5, read );
  165.             write_bit( _SRindex, 0x6, 4, write );
  166.             sprintf( msg.temp, "\n...fast read = %s,  fast write = %s ",
  167.                 bitstat( read ), bitstat( write ) );
  168.             strcat( msg.text, msg.temp );
  169.             break;
  170.         case _HELP:    case _GET:    sprintf( msg.temp,
  171.             "\nRequires W32p RevB or better\n2 parameters %s",
  172.             " ... 1=ENABLE,  0=DISABLE" );
  173.             strcat( msg.text, msg.temp );
  174.             break;
  175.         default:
  176.             sprintf( msg.text, "_w32pb::_fxn4(cmd)  UNRECOGNIZED cmd.");
  177.             status = EXIT_FAILURE;
  178.     }
  179. }
  180.  
  181.  
  182. void
  183. _w32pb::_fxn5( int cmd )    //    PCI burst mode enable
  184. {    //    bit6 of _SR06
  185.     if ( cmd == _QUERY )    {
  186.         strcpy( msg.text, "5  W32P 0 wait-state control (W32p RevB + )\n");
  187.         return;
  188.     }
  189.  
  190.     uchar _SR06 = read_bit( _SRindex, 0x06, 6 );
  191.     sprintf( msg.text, "Zero read/write wait-state = %sd",
  192.         bitstat( !_SR06 ) );
  193.  
  194.     if ( param[ 0 ] != NULL )
  195.         _SR06 = ( (uchar)atoi( param[ 0 ] ) ) & 0x01 ;
  196.  
  197.     switch ( cmd )    {
  198.         case _SET:
  199.             write_bit( _SRindex, 0x06, 6, _SR06 );
  200.             sprintf( msg.temp,"\n...now %sd", bitstat( !_SR06 ) );
  201.             strcat( msg.text, msg.temp );
  202.             break;
  203.         case _HELP:    case _GET:
  204.             sprintf( msg.temp, "\nZero wait-state (W32p RevB + )\n\t%s",
  205.                 "DISable = 1d\n\tENable  = 0d");
  206.             strcat( msg.text, msg.temp );
  207.             break;
  208.         default:
  209.             sprintf( msg.text, "_w32pb::_fxn5(cmd)  UNRECOGNIZED cmd.");
  210.             status = EXIT_FAILURE;
  211.     }
  212. }
  213.  
  214.  
  215. //    v0.93 Tseng Labs ET-6000 class definition
  216. //    Constructor
  217. _et6000::_et6000( vga_info info ) : vga( info )
  218. {
  219. //   pci_bios_type *pci_bios;
  220. //   pci_device_handle_type pci_vga;
  221.  
  222.     int i;
  223.     dword creg;    // Configuration test variable to test for VL-bus ET6000
  224.  
  225.     pci_bios=new pci_bios_type;    // Open PCI-bios routines, INT 0x1A
  226.      pci_bus = FALSE;
  227.  
  228.      // Note, the absence of BIOS-support for PCI does not automatically
  229.      // mean the host-bus isn't PCI.  It could mean an older system BIOS.
  230.      // Currently, MCLK requires BIOS-support for PCI-devices.
  231.  
  232.      if ( pci_bios->installation_check() != NULL )
  233.     {    // Good, PCI_BIOS present
  234.          pci_vga.vendor=0x100C;    // Tseng Labs, Inc.
  235.          pci_vga.device=0x3208;    // ET-6000
  236.             pci_vga.index = 0;    // Only look for 1st installed ET6000
  237.  
  238.           // Look for PCI ET6000, if found, find_device() will store
  239.           // the host/bus# and dev/func# into our *pci_vga object
  240.           if ( pci_bios->find_device( &pci_vga ) == TRUE )
  241.           {
  242.             pci_bus = TRUE;
  243.               strcat( id.chipset, " (PCI config)" );
  244.           }
  245.     }
  246.  
  247.      if ( pci_bus == FALSE )    // No ET6000 found yet, so check VL-bus
  248.      {
  249.           for (i = 0; i < 4; ++ i )    // VL-IO can be at F100, x1, x2, or x3
  250.               outportb( 0xF100 + i, 0 );    // Enable VL-IO on ET6000
  251.  
  252.          // Assume ET6000 VL-BUS installed, check for vendor/device ID
  253.         creg.b.b0 = read_cbyte( 0 );    // read ET6000 config-register
  254.           creg.b.b1 = read_cbyte( 1 );    // index 0, 1, 2, & 3
  255.           creg.b.b2 = read_cbyte( 2 );    //
  256.           creg.b.b3 = read_cbyte( 3 );    //
  257.  
  258.           // Test for Tseng Labs ET6000, vendor 0x100C, Device 0x3208
  259.           if ( creg.w.w0 == 0x100C && creg.w.w1 == 0x3208 ) ;
  260.               //strcat( id.chipset, " VL-bus" );
  261.           else
  262.               strcat( id.chipset, " not found, assume VL-bus config" );
  263.  
  264.         //    0x3CA is Feature Control Read Register
  265.          //    Bit 5 specifies host-bus config, bit5=1 VL-BUS, bit5=0 PCI
  266. //         if ( read_bit( 0x3CA, 5 ) == 1 )
  267. //        {
  268. //         }
  269.     }
  270.  
  271.      // Set Memory-space enable bit and IO space enable bit
  272.  
  273.      pci_cfg04= read_cbyte( 4 );    // Preserve original value
  274.      write_cbyte( 4, pci_cfg04 | 0x03 );    // Set bits 0 and 1
  275. }
  276.  
  277.  
  278. //    v0.93b Destructor
  279. _et6000::~_et6000()
  280. {
  281.      write_cbyte( 4, pci_cfg04 );        // Restore PCI CFG04 register
  282. }
  283.  
  284. uchar
  285. _et6000::read_cbyte( const uchar index )
  286. {
  287.     uchar value, status = TRUE;
  288.     if ( pci_bus == TRUE )
  289.     {
  290.          status = pci_bios->read_cbyte( pci_vga, index, &value );
  291.          return value;
  292.      } else
  293.          return inportb( 0xF100 + index );
  294.           // ET6000 in VL-bus configuration has config registers fixed at
  295.           // port-io space F100h
  296. }
  297.  
  298.  
  299. uchar
  300. _et6000::write_cbyte( const uchar index, const uchar value )
  301. {
  302.      uchar status= TRUE;
  303.  
  304.     if ( pci_bus == TRUE )
  305.     {
  306.          if ( pci_bios->write_cbyte( pci_vga, index, value ) != 0 )
  307.               status = FALSE;
  308.      } else
  309.          outportb( 0xF100 + index, value );
  310.           // ET6000 in VL-bus configuration has config registers fixed at
  311.           // port-io space F10Fh
  312.     return status;
  313. }
  314.  
  315.  
  316. message
  317. _et6000::_info( void )
  318. {
  319.     INITMSG( msg.text );
  320.  
  321.      dword baseio;
  322.  
  323.      baseio.b.b0 = 0x01;            // ET6000 Hardware default
  324.     baseio.b.b1 = read_CR( 0x21 ); // bits 15-8 of base address 1
  325.      baseio.b.b2 = read_CR( 0x22 ); // bits 23-16 of base address 1
  326.      baseio.b.b3 = read_CR( 0x23 ); // bits 31-24 of base address 1
  327.  
  328.     msgout <<    "IO config address = 0x" ;
  329.     hexout( msgout, baseio.b.b3 );    // print reg.h.bl in "XX" format
  330.      hexout( msgout, baseio.b.b2 );
  331.      msgout << " ";
  332.      hexout( msgout, baseio.b.b1 );
  333.      msgout << "00 ";
  334.  
  335.     msgout << ends ;
  336.     return msg;
  337. }
  338.  
  339.  
  340. void
  341. _et6000::mclk_help( void )    //    Display help for ET6000 MCLK programming
  342. {
  343.     INITMSG( msg.temp );    // initialize msgout function for TEMP
  344.     msgout << "\nFormula for ET-6000 MCLK driver... " <<
  345.      "(3 parameters, M, N, R)\n\t( M + 2 )\n\t--------- * 14.31818MHz" <<
  346.      "\n\t(N+2)*2^R\n\n\tConstraint: MCLK < 135MHz (default = 90MHz)" <<
  347.      "\n\t     and...   1<=M<=127    1<=N<=31    0<=R<=3" ;
  348.  
  349.     msgout << ends;    // Terminate msgout iostream with NULL
  350. }
  351.  
  352.  
  353. void        //    Read CLOCK1 ET6000 registers CFG 0x67/0x68
  354. _et6000::read_clock1( uchar *byte1, uchar *byte0 )
  355. {
  356.     uchar temp;        // temp Data registers
  357.  
  358.      // CLKDAC registers are 0x67/68, and 0x69, where 0x67/68 is "index"
  359.      // and 0x69 is "data", Clock1 is index 0xA
  360.  
  361.      // Register layout for 0x67/0x68
  362.     // bit[7:0] RRRR 3210 -> "R" = reserved, "3210" = index
  363.  
  364.      temp = read_cbyte( 0x67 ) & 0xF0;    // Read/modify/write
  365.      write_cbyte( 0x67, temp | 0xA );    // Select CLKDAC register 0xA
  366.      temp = read_cbyte( 0x68 ) & 0xF0;    // read/modify/write
  367.      write_cbyte( 0x68, temp | 0xA );    // Select CLKDAC register 0xA
  368.      *byte0 = read_cbyte( 0x69 );    // Read Clock1 register byte0
  369.      *byte1 = read_cbyte( 0x69 );    // Read Clock1 register byte1
  370. }
  371.  
  372.  
  373. void
  374. _et6000::_mclk( int cmd )    //    MCLK reprogramming for ET6000
  375. {
  376.     INITMSG( msg.text );    // initialize msgout function
  377.  
  378.     if ( cmd == _QUERY )    {
  379.         msgout << "0  ET-6000 MCLK programming\n" << ends;
  380.         return;
  381.     }
  382.  
  383.      union {
  384.          struct {
  385.               uchar b0;    //    Byte 0
  386.                uchar b1;    //    Byte 1
  387.           } b;
  388.  
  389.           struct {
  390.                unsigned _M : 7;    // "M" = bits6:0 of first byte
  391.               unsigned reserved1 : 1;
  392.                unsigned _N : 5;    // "N1" = bits4:0 of second byte
  393.                unsigned _R : 2;    // "N2" = bits 5:6 of second byte
  394.                unsigned reserved2 : 1;
  395.             double freq( void )    // Returns calculated PLL frequency
  396.                {
  397.                    return ( ( _M + 2.0 ) * _OSC ) /
  398.                     ( ( _N + 2.0 ) * pow(2.0, _R) );
  399.     /*    Calculates MCLK frequency from M, N1, N2 values
  400.      *    returns double value MHz, works for ET6000
  401.      *   Note, I renamed N1 -> N and N2 -> R, for code readability
  402.      *    ( M + 2 )
  403.      *   --------- * _FREF ... _FREF = 14.31818 MHz
  404.      *   (N+2)*2^R
  405.      *
  406.      *    constraint:    0 < M < 127, 0 < N < 31, 0 < R < 3
  407.      *        and...    N >= 1
  408.      */
  409.                };
  410.           } name;    // Named registers
  411.      } clock1;    // Clock1 data structure, 16-bits total (2 bytes)
  412.  
  413.      uchar _M, _N, _R;    // parameters of CLKDAC
  414.      uchar byte0, byte1, temp;
  415.  
  416.      read_clock1( &clock1.b.b1, &clock1.b.b0 );
  417.          // Read clock1 registers into struct clock1
  418.           //    Load byte1 and byte0 with raw CLKDAC register values
  419.  
  420.     msgout.precision( 2 );
  421.     msgout << "Old MCLK = " << clock1.name.freq() << " MHz ( M=" << (int)
  422.         clock1.name._M << ", N=" << (int)clock1.name._N << ", R=" << (int)
  423.         clock1.name._R << " ) ";
  424.  
  425. //    sprintf( msg.text,"Old MCLK = %.2fMHz ( M=%u, N=%u, R=%u ) ",
  426. //        _PLL( _M, _N, _R ), _M, _N, _R );
  427.  
  428.     if ( num_param < 3 && cmd == _SET )    {
  429.         msgout << "\n...not enough parameters, need total of 3.";
  430.         cmd = _HELP;    }    //    Not enough parameters.
  431.     else    {
  432.         clock1.name._M = (uchar)atoi( param[ 0 ] ) & 0x7F;
  433.         clock1.name._N = (uchar)atoi( param[ 1 ] ) & 0x1F;
  434.         clock1.name._R = (uchar)atoi( param[ 2 ] ) & 0x03;
  435.     }
  436.  
  437.     switch ( cmd )    {
  438.         case _SET:
  439.              temp = read_cbyte( 0x67 ) & 0xF0;    // Read/modify/write
  440.              write_cbyte( 0x67, temp | 0xA );    // Select CLKDAC register 0xA
  441.              temp = read_cbyte( 0x68 ) & 0xF0;    // read/modify/write
  442.              write_cbyte( 0x68, temp | 0xA );    // Select CLKDAC register 0xA
  443.  
  444.                write_cbyte( 0x69, clock1.b.b0 );    // "M byte" goes first
  445.                write_cbyte( 0x69, clock1.b.b1 );    // then N1/N2 byte
  446.  
  447.              read_clock1( &clock1.b.b1, &clock1.b.b0 );// Reread new values
  448.                msgout << "\nNew MCLK = " << clock1.name.freq() << " MHz ( M="
  449.                 << (int)clock1.name._M << ", N=" << (int)clock1.name._N <<
  450.                 ", R=" << (int)clock1.name._R << " ) ";
  451.             break;
  452.         case _HELP:    case _GET:
  453.             msgout << "\nTseng Labs ET-6000 MCLK programming";
  454.             mclk_help();    //    Get ET6000 mclk help, put in msg.temp
  455.             msgout << msg.temp;
  456.             break;
  457.         default:
  458.             msgout << "_et6000::_mclk(cmd)  UNRECOGNIZED cmd.";
  459.             status = EXIT_FAILURE;
  460.     }
  461.     msgout << ends;    // Terminate msgout iostream with NULL
  462. }
  463.  
  464.  
  465. void
  466. _et6000::_fxn1( int cmd )    // RAS/CAS configuration register (PCICFG 0x44)
  467. {
  468.     INITMSG( msg.text );    // initialize msgout function
  469.  
  470.      union {
  471.          uchar byte;
  472.           struct {
  473.                unsigned csw : 2;    // bits 0-1
  474.                unsigned rsp : 2;    // bits 2-3
  475.                unsigned rcd : 2;    // bits 4-5
  476.               unsigned unused : 2;// bits 6-7
  477.           } x;
  478.      } creg;    // Configuration register structure
  479.  
  480.     if ( cmd == _QUERY )    {
  481.         msgout<<"1  ET-6000 RAS/CAS configuration (3 parameters)\n"<<ends;
  482.         return;
  483.     }
  484.  
  485.  
  486.      creg.byte = read_cbyte( 0x44 );    // PCICFG 0x44 = RAS/CAS config
  487.  
  488.     msgout << "Old RAS/CAS configuration :  RCD=" << (int)( creg.x.rcd ) <<
  489.          " RSP=" << (int)( creg.x.rsp ) << " CSW=" << (int)( creg.x.csw );
  490.  
  491.     if ( num_param < 3 && cmd == _SET )     {
  492.         msgout << "\nError!  Need THREE parameters for input!" ;
  493.         cmd = _HELP;
  494.     } else if ( num_param >= 3 ) {
  495.          creg.byte = creg.byte & 0xC0 ; // XX00 0000 clear bits 5-0
  496.         creg.x.rcd = ( (uchar)atoi( param[ 0 ] ) ) & 0x03;
  497.         creg.x.rsp = ( (uchar)atoi( param[ 1 ] ) ) & 0x03;
  498.         creg.x.csw = ( (uchar)atoi( param[ 2 ] ) ) & 0x03;
  499.     }
  500.  
  501.  
  502.     switch ( cmd )    {
  503.         case _SET:
  504.             write_cbyte( 0x44, creg.byte );
  505.              creg.byte = read_cbyte( 0x44 );    // Re-read RAS/CAS config
  506.                msgout << "\nNew RAS/CAS configuration :  RCD=" <<
  507.                 (int)( creg.x.rcd ) << " RSP=" << (int)( creg.x.rsp ) <<
  508.                 " CSW=" << (int)( creg.x.csw );
  509.             break;
  510.         case _GET:    case _HELP:
  511.             msgout << "\n\nET6000 RAS/CAS configuration register\n\t" <<
  512.             "RCD = DRAM/MDRAM RAS to CAS delay memory timing\n\t" <<
  513.             "RSP = DRAM/MDRAM RAS to RAS precharge time \n\t" <<
  514.             "CAS = DRAM read cycle pulse width, or MDRAM CAS to read "
  515.             "data latency\n\n\tValid input range (RCD/RSP/CAS) is 0-3.";
  516.             break;
  517.         default:    msgout << "_et6000::_fxn1(cmd)  UNRECOGNIZED cmd.";
  518.             status = EXIT_FAILURE;
  519.     }
  520.     msgout << ends;    // Terminate msgout iostream with NULL
  521. }
  522.