home *** CD-ROM | disk | FTP | other *** search
- /* tseng.cpp
- *
- * Tseng ET6000 class declarations
- */
- // v0.93a Added Tseng Labs ET-6000 MCLK programming
- // doesn't work with some brands of ET-6000 adapters
- // v0.93b modified _et6000() class to set MEEN/IOEN controls
- //
- //
- //
- //
-
-
- #include "tseng.h"
-
- #include<dos.h>
- #include<string.h>
- #include<stdio.h>
- #include<stdlib.h>
- #include<math.h>
-
- _w32p::_w32p( vga_info info ) : vga( info )
- {
- outportb( 0x3BF, 0x03 ); // Unlock W32P "key"
- outportb( 0x3D8, 0xA0 ); // Unlock W32P "key"
- }
-
-
- void
- _w32p::_fxn1( int cmd ) // PCI burst mode enable
- { // bit4 of _CR34
- if ( cmd == _QUERY ) {
- strcpy( msg.text, "1 W32P PCI burst mode (PCI only)\n");
- return;
- }
-
- uchar _CR34 = read_bit( _CRindex, 0x34, 4 );
- uchar new_CR34= 0x0;
-
- if ( param[ 0 ] != NULL )
- new_CR34 = (uchar)atoi( param[ 0 ] );
-
- sprintf( msg.text, "PCI Burst mode = %sd", bitstat( _CR34 ) );
-
- switch ( cmd ) {
- case _SET:
- write_bit( _CRindex, 0x34, 4, new_CR34 );
- sprintf( msg.temp,"\n...now %sd",
- bitstat( read_bit( _CRindex, 0x34, 4 ) ) );
- strcat( msg.text, msg.temp );
- break;
- case _HELP: case _GET:
- sprintf( msg.temp, "\nPCI Burst mode (PCI only) \n\t%s",
- "DISable = 0d\n\tENable = 1d");
- strcat( msg.text, msg.temp );
- break;
- default:
- sprintf( msg.text, "_w32p::_fxn1(cmd) UNRECOGNIZED cmd.");
- status = EXIT_FAILURE;
- }
- }
-
-
- void
- _w32p::_fxn2( int cmd ) // memory interleaving
- { // bit7 of _CR32
- if ( cmd == _QUERY ) {
- strcpy( msg.text, "2 W32P memory interleaving (2mb only)\n");
- return;
- }
-
- uchar _CR32 = read_bit( _CRindex, 0x32, 7 );
- uchar new_CR32= 0x0;
-
- if ( param[ 0 ] != NULL )
- new_CR32 = (uchar)atoi( param[ 0 ] );
-
- sprintf(msg.text,"DRAM memory interleaving = %sd", bitstat( _CR32 ) );
-
- switch ( cmd ) {
- case _SET:
- write_bit( _CRindex, 0x32, 7, new_CR32 );
- sprintf( msg.temp,"\n...now %sd", bitstat( new_CR32 ) );
- strcat( msg.text, msg.temp );
- break;
- case _HELP: case _GET: sprintf( msg.temp,
- "\nDRAM Memory interleaving ( requires 2mb DRAM )%s",
- "\n\tDISable = 0d\n\tENable = 1d");
- strcat( msg.text, msg.temp );
- break;
- default:
- sprintf( msg.text, "_w32p::_fxn2(cmd) UNRECOGNIZED cmd.");
- status = EXIT_FAILURE;
- }
- }
-
-
- void
- _w32p::_fxn3( int cmd ) // FIFO threshold control
- { // bit7,bit5 of _CR37
- if ( cmd == _QUERY ) {
- strcpy( msg.text, "3 W32P FIFO threshold control (2 items)\n");
- return;
- }
-
- uchar low = read_bit( _CRindex, 0x37, 7 ),
- high = read_bit( _CRindex, 0x37, 5 );
-
- sprintf( msg.text, "FIFO low threshold = %u, FIFO high threshold = %u",
- low, high );
-
- if ( num_param < 2 && cmd == _SET ) {
- strcat( msg.text, "\nError! TWO parameters required!");
- cmd = _HELP; }
- else if ( num_param >= 2 ) {
- low = ( (uchar)atoi( param[ 0 ] ) ) & 0x01;
- high = ( (uchar)atoi( param[ 1 ] ) ) & 0x01;
- }
-
- switch ( cmd ) {
- case _SET: write_bit( _CRindex, 0x37, 7, low );
- write_bit( _CRindex, 0x37, 5, high );
- sprintf( msg.temp, "\n...low = %u, high = %u ", low, high );
- strcat( msg.text, msg.temp );
- break;
- case _HELP: case _GET: sprintf( msg.temp,
- "\nLow threshold ... 0=normal, 1=increased%s%s%s",
- "\nHigh threshold ... higher priority for ",
- "\n\t0 = W32p (accelerator uses more bandwidth)",
- "\n\t1 = CPU (host accesses get higher priority)");
- strcat( msg.text, msg.temp );
- break;
- default:
- sprintf( msg.text, "_w32p::_fxn3(cmd) UNRECOGNIZED cmd.");
- status = EXIT_FAILURE;
- }
- }
-
-
- void
- _w32pb::_fxn4( int cmd ) // Fast read/write control
- { // bits5-4 of TS Register6
- if ( cmd == _QUERY ) {
- strcpy( msg.text,
- "4 W32P fast read/write control (2 items, W32p RevB +)\n");
- return;
- }
-
- uchar read = read_bit( _SRindex, 0x6, 5 ),
- write = read_bit( _SRindex, 0x6, 4 );
-
- sprintf( msg.text, "Fast read control = %sd, Fast write control = %sd",
- bitstat( read ), bitstat( write ) );
-
- if ( num_param < 2 && cmd == _SET ) {
- strcat( msg.text, "\nError! TWO parameters required!");
- cmd = _HELP; }
- else if ( num_param >= 2 ) {
- read = ( (uchar)atoi( param[ 0 ] ) ) & 0x01;
- write = ( (uchar)atoi( param[ 1 ] ) ) & 0x01;
- }
-
- switch ( cmd ) {
- case _SET: write_bit( _SRindex, 0x6, 5, read );
- write_bit( _SRindex, 0x6, 4, write );
- sprintf( msg.temp, "\n...fast read = %s, fast write = %s ",
- bitstat( read ), bitstat( write ) );
- strcat( msg.text, msg.temp );
- break;
- case _HELP: case _GET: sprintf( msg.temp,
- "\nRequires W32p RevB or better\n2 parameters %s",
- " ... 1=ENABLE, 0=DISABLE" );
- strcat( msg.text, msg.temp );
- break;
- default:
- sprintf( msg.text, "_w32pb::_fxn4(cmd) UNRECOGNIZED cmd.");
- status = EXIT_FAILURE;
- }
- }
-
-
- void
- _w32pb::_fxn5( int cmd ) // PCI burst mode enable
- { // bit6 of _SR06
- if ( cmd == _QUERY ) {
- strcpy( msg.text, "5 W32P 0 wait-state control (W32p RevB + )\n");
- return;
- }
-
- uchar _SR06 = read_bit( _SRindex, 0x06, 6 );
- sprintf( msg.text, "Zero read/write wait-state = %sd",
- bitstat( !_SR06 ) );
-
- if ( param[ 0 ] != NULL )
- _SR06 = ( (uchar)atoi( param[ 0 ] ) ) & 0x01 ;
-
- switch ( cmd ) {
- case _SET:
- write_bit( _SRindex, 0x06, 6, _SR06 );
- sprintf( msg.temp,"\n...now %sd", bitstat( !_SR06 ) );
- strcat( msg.text, msg.temp );
- break;
- case _HELP: case _GET:
- sprintf( msg.temp, "\nZero wait-state (W32p RevB + )\n\t%s",
- "DISable = 1d\n\tENable = 0d");
- strcat( msg.text, msg.temp );
- break;
- default:
- sprintf( msg.text, "_w32pb::_fxn5(cmd) UNRECOGNIZED cmd.");
- status = EXIT_FAILURE;
- }
- }
-
-
- // v0.93 Tseng Labs ET-6000 class definition
- // Constructor
- _et6000::_et6000( vga_info info ) : vga( info )
- {
- // pci_bios_type *pci_bios;
- // pci_device_handle_type pci_vga;
-
- int i;
- dword creg; // Configuration test variable to test for VL-bus ET6000
-
- pci_bios=new pci_bios_type; // Open PCI-bios routines, INT 0x1A
- pci_bus = FALSE;
-
- // Note, the absence of BIOS-support for PCI does not automatically
- // mean the host-bus isn't PCI. It could mean an older system BIOS.
- // Currently, MCLK requires BIOS-support for PCI-devices.
-
- if ( pci_bios->installation_check() != NULL )
- { // Good, PCI_BIOS present
- pci_vga.vendor=0x100C; // Tseng Labs, Inc.
- pci_vga.device=0x3208; // ET-6000
- pci_vga.index = 0; // Only look for 1st installed ET6000
-
- // Look for PCI ET6000, if found, find_device() will store
- // the host/bus# and dev/func# into our *pci_vga object
- if ( pci_bios->find_device( &pci_vga ) == TRUE )
- {
- pci_bus = TRUE;
- strcat( id.chipset, " (PCI config)" );
- }
- }
-
- if ( pci_bus == FALSE ) // No ET6000 found yet, so check VL-bus
- {
- for (i = 0; i < 4; ++ i ) // VL-IO can be at F100, x1, x2, or x3
- outportb( 0xF100 + i, 0 ); // Enable VL-IO on ET6000
-
- // Assume ET6000 VL-BUS installed, check for vendor/device ID
- creg.b.b0 = read_cbyte( 0 ); // read ET6000 config-register
- creg.b.b1 = read_cbyte( 1 ); // index 0, 1, 2, & 3
- creg.b.b2 = read_cbyte( 2 ); //
- creg.b.b3 = read_cbyte( 3 ); //
-
- // Test for Tseng Labs ET6000, vendor 0x100C, Device 0x3208
- if ( creg.w.w0 == 0x100C && creg.w.w1 == 0x3208 ) ;
- //strcat( id.chipset, " VL-bus" );
- else
- strcat( id.chipset, " not found, assume VL-bus config" );
-
- // 0x3CA is Feature Control Read Register
- // Bit 5 specifies host-bus config, bit5=1 VL-BUS, bit5=0 PCI
- // if ( read_bit( 0x3CA, 5 ) == 1 )
- // {
- // }
- }
-
- // Set Memory-space enable bit and IO space enable bit
-
- pci_cfg04= read_cbyte( 4 ); // Preserve original value
- write_cbyte( 4, pci_cfg04 | 0x03 ); // Set bits 0 and 1
- }
-
-
- // v0.93b Destructor
- _et6000::~_et6000()
- {
- write_cbyte( 4, pci_cfg04 ); // Restore PCI CFG04 register
- }
-
- uchar
- _et6000::read_cbyte( const uchar index )
- {
- uchar value, status = TRUE;
- if ( pci_bus == TRUE )
- {
- status = pci_bios->read_cbyte( pci_vga, index, &value );
- return value;
- } else
- return inportb( 0xF100 + index );
- // ET6000 in VL-bus configuration has config registers fixed at
- // port-io space F100h
- }
-
-
- uchar
- _et6000::write_cbyte( const uchar index, const uchar value )
- {
- uchar status= TRUE;
-
- if ( pci_bus == TRUE )
- {
- if ( pci_bios->write_cbyte( pci_vga, index, value ) != 0 )
- status = FALSE;
- } else
- outportb( 0xF100 + index, value );
- // ET6000 in VL-bus configuration has config registers fixed at
- // port-io space F10Fh
- return status;
- }
-
-
- message
- _et6000::_info( void )
- {
- INITMSG( msg.text );
-
- dword baseio;
-
- baseio.b.b0 = 0x01; // ET6000 Hardware default
- baseio.b.b1 = read_CR( 0x21 ); // bits 15-8 of base address 1
- baseio.b.b2 = read_CR( 0x22 ); // bits 23-16 of base address 1
- baseio.b.b3 = read_CR( 0x23 ); // bits 31-24 of base address 1
-
- msgout << "IO config address = 0x" ;
- hexout( msgout, baseio.b.b3 ); // print reg.h.bl in "XX" format
- hexout( msgout, baseio.b.b2 );
- msgout << " ";
- hexout( msgout, baseio.b.b1 );
- msgout << "00 ";
-
- msgout << ends ;
- return msg;
- }
-
-
- void
- _et6000::mclk_help( void ) // Display help for ET6000 MCLK programming
- {
- INITMSG( msg.temp ); // initialize msgout function for TEMP
- msgout << "\nFormula for ET-6000 MCLK driver... " <<
- "(3 parameters, M, N, R)\n\t( M + 2 )\n\t--------- * 14.31818MHz" <<
- "\n\t(N+2)*2^R\n\n\tConstraint: MCLK < 135MHz (default = 90MHz)" <<
- "\n\t and... 1<=M<=127 1<=N<=31 0<=R<=3" ;
-
- msgout << ends; // Terminate msgout iostream with NULL
- }
-
-
- void // Read CLOCK1 ET6000 registers CFG 0x67/0x68
- _et6000::read_clock1( uchar *byte1, uchar *byte0 )
- {
- uchar temp; // temp Data registers
-
- // CLKDAC registers are 0x67/68, and 0x69, where 0x67/68 is "index"
- // and 0x69 is "data", Clock1 is index 0xA
-
- // Register layout for 0x67/0x68
- // bit[7:0] RRRR 3210 -> "R" = reserved, "3210" = index
-
- temp = read_cbyte( 0x67 ) & 0xF0; // Read/modify/write
- write_cbyte( 0x67, temp | 0xA ); // Select CLKDAC register 0xA
- temp = read_cbyte( 0x68 ) & 0xF0; // read/modify/write
- write_cbyte( 0x68, temp | 0xA ); // Select CLKDAC register 0xA
- *byte0 = read_cbyte( 0x69 ); // Read Clock1 register byte0
- *byte1 = read_cbyte( 0x69 ); // Read Clock1 register byte1
- }
-
-
- void
- _et6000::_mclk( int cmd ) // MCLK reprogramming for ET6000
- {
- INITMSG( msg.text ); // initialize msgout function
-
- if ( cmd == _QUERY ) {
- msgout << "0 ET-6000 MCLK programming\n" << ends;
- return;
- }
-
- union {
- struct {
- uchar b0; // Byte 0
- uchar b1; // Byte 1
- } b;
-
- struct {
- unsigned _M : 7; // "M" = bits6:0 of first byte
- unsigned reserved1 : 1;
- unsigned _N : 5; // "N1" = bits4:0 of second byte
- unsigned _R : 2; // "N2" = bits 5:6 of second byte
- unsigned reserved2 : 1;
- double freq( void ) // Returns calculated PLL frequency
- {
- return ( ( _M + 2.0 ) * _OSC ) /
- ( ( _N + 2.0 ) * pow(2.0, _R) );
- /* Calculates MCLK frequency from M, N1, N2 values
- * returns double value MHz, works for ET6000
- * Note, I renamed N1 -> N and N2 -> R, for code readability
- * ( M + 2 )
- * --------- * _FREF ... _FREF = 14.31818 MHz
- * (N+2)*2^R
- *
- * constraint: 0 < M < 127, 0 < N < 31, 0 < R < 3
- * and... N >= 1
- */
- };
- } name; // Named registers
- } clock1; // Clock1 data structure, 16-bits total (2 bytes)
-
- uchar _M, _N, _R; // parameters of CLKDAC
- uchar byte0, byte1, temp;
-
- read_clock1( &clock1.b.b1, &clock1.b.b0 );
- // Read clock1 registers into struct clock1
- // Load byte1 and byte0 with raw CLKDAC register values
-
- msgout.precision( 2 );
- msgout << "Old MCLK = " << clock1.name.freq() << " MHz ( M=" << (int)
- clock1.name._M << ", N=" << (int)clock1.name._N << ", R=" << (int)
- clock1.name._R << " ) ";
-
- // 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 ) {
- msgout << "\n...not enough parameters, need total of 3.";
- cmd = _HELP; } // Not enough parameters.
- else {
- clock1.name._M = (uchar)atoi( param[ 0 ] ) & 0x7F;
- clock1.name._N = (uchar)atoi( param[ 1 ] ) & 0x1F;
- clock1.name._R = (uchar)atoi( param[ 2 ] ) & 0x03;
- }
-
- switch ( cmd ) {
- case _SET:
- temp = read_cbyte( 0x67 ) & 0xF0; // Read/modify/write
- write_cbyte( 0x67, temp | 0xA ); // Select CLKDAC register 0xA
- temp = read_cbyte( 0x68 ) & 0xF0; // read/modify/write
- write_cbyte( 0x68, temp | 0xA ); // Select CLKDAC register 0xA
-
- write_cbyte( 0x69, clock1.b.b0 ); // "M byte" goes first
- write_cbyte( 0x69, clock1.b.b1 ); // then N1/N2 byte
-
- read_clock1( &clock1.b.b1, &clock1.b.b0 );// Reread new values
- msgout << "\nNew MCLK = " << clock1.name.freq() << " MHz ( M="
- << (int)clock1.name._M << ", N=" << (int)clock1.name._N <<
- ", R=" << (int)clock1.name._R << " ) ";
- break;
- case _HELP: case _GET:
- msgout << "\nTseng Labs ET-6000 MCLK programming";
- mclk_help(); // Get ET6000 mclk help, put in msg.temp
- msgout << msg.temp;
- break;
- default:
- msgout << "_et6000::_mclk(cmd) UNRECOGNIZED cmd.";
- status = EXIT_FAILURE;
- }
- msgout << ends; // Terminate msgout iostream with NULL
- }
-
-
- void
- _et6000::_fxn1( int cmd ) // RAS/CAS configuration register (PCICFG 0x44)
- {
- INITMSG( msg.text ); // initialize msgout function
-
- union {
- uchar byte;
- struct {
- unsigned csw : 2; // bits 0-1
- unsigned rsp : 2; // bits 2-3
- unsigned rcd : 2; // bits 4-5
- unsigned unused : 2;// bits 6-7
- } x;
- } creg; // Configuration register structure
-
- if ( cmd == _QUERY ) {
- msgout<<"1 ET-6000 RAS/CAS configuration (3 parameters)\n"<<ends;
- return;
- }
-
-
- creg.byte = read_cbyte( 0x44 ); // PCICFG 0x44 = RAS/CAS config
-
- msgout << "Old RAS/CAS configuration : RCD=" << (int)( creg.x.rcd ) <<
- " RSP=" << (int)( creg.x.rsp ) << " CSW=" << (int)( creg.x.csw );
-
- if ( num_param < 3 && cmd == _SET ) {
- msgout << "\nError! Need THREE parameters for input!" ;
- cmd = _HELP;
- } else if ( num_param >= 3 ) {
- creg.byte = creg.byte & 0xC0 ; // XX00 0000 clear bits 5-0
- creg.x.rcd = ( (uchar)atoi( param[ 0 ] ) ) & 0x03;
- creg.x.rsp = ( (uchar)atoi( param[ 1 ] ) ) & 0x03;
- creg.x.csw = ( (uchar)atoi( param[ 2 ] ) ) & 0x03;
- }
-
-
- switch ( cmd ) {
- case _SET:
- write_cbyte( 0x44, creg.byte );
- creg.byte = read_cbyte( 0x44 ); // Re-read RAS/CAS config
- msgout << "\nNew RAS/CAS configuration : RCD=" <<
- (int)( creg.x.rcd ) << " RSP=" << (int)( creg.x.rsp ) <<
- " CSW=" << (int)( creg.x.csw );
- break;
- case _GET: case _HELP:
- msgout << "\n\nET6000 RAS/CAS configuration register\n\t" <<
- "RCD = DRAM/MDRAM RAS to CAS delay memory timing\n\t" <<
- "RSP = DRAM/MDRAM RAS to RAS precharge time \n\t" <<
- "CAS = DRAM read cycle pulse width, or MDRAM CAS to read "
- "data latency\n\n\tValid input range (RCD/RSP/CAS) is 0-3.";
- break;
- default: msgout << "_et6000::_fxn1(cmd) UNRECOGNIZED cmd.";
- status = EXIT_FAILURE;
- }
- msgout << ends; // Terminate msgout iostream with NULL
- }
-