📄 main.cpp
字号:
(AnsiString)ASC +
(AnsiString)" ASCQ " +
(AnsiString)ASCQ).c_str() );
}
//speed is stored in bytes 22 & 23 of mode page 0x2A
return (int)((b[22] << 8) + b[23]);
}
int __fastcall TMainWindow::getMAXCDSpeed()
{
SRB_ExecSCSICmd s;
unsigned char b[256];
memset( &s, 0, sizeof( s ) );
memset( b, 0xFF, 256 );
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.SRB_HaId = gbyCurrentHostAdapter;
s.SRB_Target = gbyCurrentTarget;
s.SRB_Lun = 0;
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
s.SRB_BufLen = 256;
s.SRB_BufPointer = b;
s.SRB_CDBLen = 12;
s.CDBByte[0] = SCSI_MODESENSE;
s.CDBByte[2] = 0x2A; //mode page 0x2A contains the max speed
s.CDBByte[7] = 0x01;
s.CDBByte[8] = 0x00;
BYTE byStatus = ExecSCSICommand(&s);
if( byStatus != SS_COMP )
log( ((AnsiString)"getMAXCDSpeed returned status " +
LookupASPIStatus(byStatus) +
(AnsiString)" with HaStat " +
(AnsiString)s.SRB_HaStat +
(AnsiString)" TargStat " +
(AnsiString)s.SRB_TargStat).c_str() );
if( byStatus == SS_ERR && s.SRB_TargStat == STATUS_CHKCOND )
{
BYTE SenseKey = s.SenseArea[2] & (BYTE)15;
BYTE ASC = s.SenseArea[12];
BYTE ASCQ = s.SenseArea[13];
log( ((AnsiString)" Check Condition: Sense Key " +
(AnsiString)SenseKey +
(AnsiString)" ASC " +
(AnsiString)ASC +
(AnsiString)" ASCQ " +
(AnsiString)ASCQ).c_str() );
}
//bytes 16 & 17 in mode page 0x2A represent the max speed
return (int)((b[16] << 8) + b[17]);
}
//----------------------------------
//Rounds a float to the closest int
//----------------------------------
int __fastcall TMainWindow::round( float num )
{
int roundnum = (int)num;
if( (num - roundnum) >= .5 )
return roundnum+1;
else
return roundnum;
}
//----------------------------------------------------
//Given a read speed in kilobytes, this function
// returns an integer saying how fast this is in
// the common CD-ROM convention of [Speed]x
//----------------------------------------------------
int __fastcall TMainWindow::LookupX( int KB )
{
return round((float)KB/(float)176);
}
//----------------------------------------------------
//Given an integer representing "Speed" in the [Speed]x
// CD-ROM transfer rate notation, this function finds
// and returns the read speed of the currently selected
// CD-ROM drive corresponding to that X value
//----------------------------------------------------
int __fastcall TMainWindow::LookupKB( int X )
{
//Here's the thing -- different drives report different
// speeds for the same X rating. My ASUS34x reports
// 4x speeds to be exactly 176*4 = 704 kb/s, but my Creative
// 4224 reports 4x to be 706 kb/s. Instead of simply looking
// up the kb/s using multiple of 176, I must scan the "area"
// around the multiple a few kb/s in either direction until
// I hit on one that the drive accepts. That is the speed
// corresponding to that x for this particular drive.
// Pretty screwy, huh?
//TOLERANCE is the number of kb/s this function scans on either
// side of the multiple of 176
const int TOLERANCE = ToleranceEdit->Text.ToInt();
//since I'll be issuing read speed set commands in order
// to determine which transfer rate the drive accepts, I
// save the speed at which the drive is currently set
int rememberspeed = getCDSpeed();
//test all speeds +/- [TOLERANCE] kb/s from [X rating]*176:
//1) attempt the set the drive's speed
//2) get the drive's speed
//3) if the gotten speed equals the set speed, that's
// the tranfer rate corresponding to the X rating
// for this drive
for( int j = 0; j < TOLERANCE*2; j++ )
{
setCDSpeed( X1*X - TOLERANCE + j );
if( getCDSpeed() == X1*X - TOLERANCE+j )
{
log( ((AnsiString)"Found speed " +
(AnsiString)(X1*X - TOLERANCE + j)).c_str() );
//restore the drive's original speed
setCDSpeed( rememberspeed );
return X1*X - TOLERANCE + j;
}
}
//restore the drive's original speed
setCDSpeed( rememberspeed );
//if it gets this far, then no corresponding kb/s value was found
// for this drive, and the function returns 0
return 0;
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//CD Spindown Commands
//---------------------------------------------------------------------------
#define SPINDOWN_VENDOR_SPECIFIC 0x00
#define SPINDOWN_125MS 0x01
#define SPINDOWN_250MS 0x02
#define SPINDOWN_500MS 0x03
#define SPINDOWN_1S 0x04
#define SPINDOWN_2S 0x05
#define SPINDOWN_4S 0x06
#define SPINDOWN_8S 0x07
#define SPINDOWN_16S 0x08
#define SPINDOWN_32S 0x09
#define SPINDOWN_1MIN 0x0A
#define SPINDOWN_2MIN 0x0B
#define SPINDOWN_4MIN 0x0C
#define SPINDOWN_8MIN 0x0D
#define SPINDOWN_16MIN 0x0E
#define SPINDOWN_32MIN 0x0F
//----------------------------------------------------
//Given one of the above codes, this function returns
// a string indicating what the corresponding spindown
// time is
//----------------------------------------------------
AnsiString LookupSpindownText( BYTE code )
{
AnsiString returnstring;
switch( code )
{
case SPINDOWN_VENDOR_SPECIFIC: returnstring = "VS"; break;
case SPINDOWN_125MS : returnstring = "125 ms"; break;
case SPINDOWN_250MS : returnstring = "250 ms"; break;
case SPINDOWN_500MS : returnstring = "500 ms"; break;
case SPINDOWN_1S : returnstring = "1 s"; break;
case SPINDOWN_2S : returnstring = "2 s"; break;
case SPINDOWN_4S : returnstring = "4 s"; break;
case SPINDOWN_8S : returnstring = "8 s"; break;
case SPINDOWN_16S : returnstring = "16 s"; break;
case SPINDOWN_32S : returnstring = "32 s"; break;
case SPINDOWN_1MIN : returnstring = "1 min"; break;
case SPINDOWN_2MIN : returnstring = "2 min"; break;
case SPINDOWN_4MIN : returnstring = "4 min"; break;
case SPINDOWN_8MIN : returnstring = "8 min"; break;
case SPINDOWN_16MIN : returnstring = "16 min"; break;
case SPINDOWN_32MIN : returnstring = "32 min"; break;
}
return returnstring;
}
//----------------------------------------------------
//Give one of the strings that the above function
// returns, this returns the above code that
// corresponds to this string
//----------------------------------------------------
BYTE LookupSpindownCode( AnsiString Text )
{
if( Text == "125 ms" ) return SPINDOWN_125MS;
if( Text == "250 ms" ) return SPINDOWN_250MS;
if( Text == "500 ms" ) return SPINDOWN_500MS;
if( Text == "1 s" ) return SPINDOWN_1S;
if( Text == "2 s" ) return SPINDOWN_2S;
if( Text == "4 s" ) return SPINDOWN_4S;
if( Text == "8 s" ) return SPINDOWN_8S;
if( Text == "16 s" ) return SPINDOWN_16S;
if( Text == "32 s" ) return SPINDOWN_32S;
if( Text == "1 min" ) return SPINDOWN_1MIN;
if( Text == "2 min" ) return SPINDOWN_2MIN;
if( Text == "4 min" ) return SPINDOWN_4MIN;
if( Text == "8 min" ) return SPINDOWN_8MIN;
if( Text == "16 min" ) return SPINDOWN_16MIN;
if( Text == "32 min" ) return SPINDOWN_32MIN;
else return 0;
}
//----------------------------------------------------
//Issues a mode sense command to obtain the current
// spindown time of the current drive
//----------------------------------------------------
BYTE __fastcall TMainWindow::getCDSpindown()
{
SRB_ExecSCSICmd s;
unsigned char b[256];
memset( &s, 0, sizeof( s ) );
memset( b, 0xFF, 256 );
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.SRB_HaId = gbyCurrentHostAdapter;
s.SRB_Target = gbyCurrentTarget;
s.SRB_Lun = 0;
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
s.SRB_BufLen = 256;
s.SRB_BufPointer = b;
s.SRB_CDBLen = 12;
s.CDBByte[0] = SCSI_MODESENSE;
s.CDBByte[2] = 0x0D; //spindown timer is on the 0x0D mode page
s.CDBByte[7] = 0x01;
s.CDBByte[8] = 0x00;
BYTE byStatus = ExecSCSICommand(&s);
if( byStatus != SS_COMP )
log( ((AnsiString)"getCDSpindown returned status " +
LookupASPIStatus(byStatus) +
(AnsiString)" with HaStat " +
(AnsiString)s.SRB_HaStat +
(AnsiString)" TargStat " +
(AnsiString)s.SRB_TargStat).c_str() );
if( byStatus == SS_ERR && s.SRB_TargStat == STATUS_CHKCOND )
{
BYTE SenseKey = s.SenseArea[2] & (BYTE)15;
BYTE ASC = s.SenseArea[12];
BYTE ASCQ = s.SenseArea[13];
log( ((AnsiString)" Check Condition: Sense Key " +
(AnsiString)SenseKey +
(AnsiString)" ASC " +
(AnsiString)ASC +
(AnsiString)" ASCQ " +
(AnsiString)ASCQ).c_str() );
}
//the byte corresponding to spindown time is 11
return b[11];
}
//----------------------------------------------------
//Issues a mode select command to set the current
// spindown time of the current drive
//----------------------------------------------------
BYTE __fastcall TMainWindow::setCDSpindown( BYTE code )
{
SRB_ExecSCSICmd s;
memset( &s, 0, sizeof( s ) );
unsigned char b[16];
memset( &b, 0, 16 );
b[8] = 0x0D; //I'm doing a mode select on page 0x0D
b[9] = 0x06; //The length of this page is 0x06
b[11]= code; //The code representing spindown time goes here
b[13]= 0x3C; //other defaults that have nothing
b[15]= 0x4B; // to do with the spindown time
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.SRB_HaId = gbyCurrentHostAdapter;
s.SRB_Target = gbyCurrentTarget;
s.SRB_Lun = 0;
s.SRB_Flags = SRB_DIR_OUT | SRB_EVENT_NOTIFY;
s.SRB_SenseLen = SENSE_LEN;
s.SRB_BufPointer = b;
s.SRB_BufLen = 16;
s.SRB_CDBLen = 12;
s.CDBByte[0] = SCSI_MODESELECT;
s.CDBByte[1] = 0x10; //a default from the ATAPI specs
s.CDBByte[8] = (BYTE)16;
BYTE byStatus = ExecSCSICommand(&s);
if( byStatus != SS_COMP )
log( ((AnsiString)"setCDSpindown returned status " +
LookupASPIStatus(byStatus) +
(AnsiString)" with HaStat " +
(AnsiString)s.SRB_HaStat +
(AnsiString)" TargStat " +
(AnsiString)s.SRB_TargStat).c_str() );
if( byStatus == SS_ERR && s.SRB_TargStat == STATUS_CHKCOND )
{
BYTE SenseKey = s.SenseArea[2] & (BYTE)15;
BYTE ASC = s.SenseArea[12];
BYTE ASCQ = s.SenseArea[13];
log( ((AnsiString)" Check Condition: Sense Key " +
(AnsiString)SenseKey +
(AnsiString)" ASC " +
(AnsiString)ASC +
(AnsiString)" ASCQ " +
(AnsiString)ASCQ).c_str() );
}
return byStatus;
}
//---------------------------------------------------------------------------
//Translates ASPI status codes into meaningful text
//---------------------------------------------------------------------------
AnsiString __fastcall TMainWindow::LookupASPIStatus( BYTE code )
{
switch( code )
{
case SS_ILLEGAL_MODE:
return (AnsiString)"SS_ILLEGAL_MODE";
case SS_NO_ASPI:
return (AnsiString)"SS_NO_ASPI";
case SS_MISMATCHED_COMPONENTS:
return (AnsiString)"SS_MISMATCHED_COMPONENTS";
case SS_INSUFFICIENT_RESOURCES:
return (AnsiString)"SS_INSUFFICIENT_RESOURCES";
case SS_FAILED_INIT:
return (AnsiString)"SS_FAILED_INIT";
case SS_NO_ADAPTERS:
return (AnsiString)"SS_NO_ADAPTERS";
case SS_COMP:
return (AnsiString)"SS_COMP";
case SS_INVALID_HA:
return (AnsiString)"SS_INVALID_HA";
case SS_NO_DEVICE:
return (AnsiString)"SS_NO_DEVICE";
case SS_ERR:
return (AnsiString)"SS_ERR";
default:
char buffer[50];
sprintf( buffer, "Unknown Status Code: 0x%X", code );
return (AnsiString)buffer;
}
}
//---------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -