📄 aspilib.c
字号:
if ( !cdHandles[idx].used )
{
alErrCode = ALERR_INVHANDLE;
ReleaseMutex( cdMutexes[idx] );
return SS_ERR;
}
heventSRB = CreateEvent( NULL, TRUE, FALSE, NULL );
memset( &s, 0, sizeof( s ) );
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.SRB_HaID = cdHandles[idx].ha;
s.SRB_Target = cdHandles[idx].tgt;
s.SRB_Lun = cdHandles[idx].lun;
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
s.SRB_BufLen = 0x324;
s.SRB_BufPointer = (BYTE FAR *)toc;
s.SRB_SenseLen = 0x0E;
s.SRB_CDBLen = 0x0A;
s.SRB_PostProc = (LPVOID)heventSRB;
s.CDBByte[0] = 0x43;
s.CDBByte[1] = cdHandles[idx].bMSF?0x02:0x00;
// s.CDBByte[1] = 0x02; /* 0x02 == MSF format, 0x00 == LBA */
s.CDBByte[7] = 0x03; /* length of buffer to hold TOC */
s.CDBByte[8] = 0x24; /* == 0x324 */
ResetEvent( heventSRB );
dwStatus = pfnSendASPI32Command( (LPSRB)&s );
if ( dwStatus == SS_PENDING )
{
WaitForSingleObject( heventSRB, 4000 );
}
CloseHandle( heventSRB );
if ( s.SRB_Status != SS_COMP )
{
alErrCode = ALERR_ASPI;
alAspiErr = s.SRB_Status;
retVal = SS_ERR;
}
#ifdef _DEBUG
{
FILE *fp = fopen( "toc.dat", "wb" );
fwrite( toc, 1, sizeof(TOC), fp );
fclose( fp );
}
#endif
ReleaseMutex( cdMutexes[idx] );
return retVal;
}
/***************************************************************************
* resetSCSIBus
*
* According to Adaptec, this command can cause problems in Win95
*
***************************************************************************/
void resetSCSIBus( void )
{
DWORD dwStatus;
HANDLE heventSRB;
SRB_BusDeviceReset s;
dbprintf( "akrip32: reset bus!" );
heventSRB = CreateEvent( NULL, TRUE, FALSE, NULL );
memset( &s, 0, sizeof( s ) );
s.SRB_Cmd = SC_RESET_DEV;
s.SRB_PostProc = (LPVOID)heventSRB;
ResetEvent( heventSRB );
dwStatus = pfnSendASPI32Command( (LPSRB)&s );
if ( dwStatus == SS_PENDING )
{
WaitForSingleObject( heventSRB, DEFWAITLEN );
}
CloseHandle( heventSRB );
#ifdef _DEBUG
if ( s.SRB_Status != SS_COMP )
{
dbprintf( "akrip32: RESET BUS aspi status: 0x%08X\n", s.SRB_Status );
}
#endif
}
/******************************************************************
* GetCDList
*
* Scans all host adapters for CD-ROM units, and stores information
* for all units located
******************************************************************/
int GetCDList( LPCDLIST cd )
{
SRB_HAInquiry sh;
SRB_GDEVBlock sd;
int numAdapters, i, j, k;
int maxTgt;
/* initialize cd list */
maxTgt = cd->max;
memset( cd, 0, sizeof(*cd) );
cd->max = maxTgt;
numAdapters = GetNumAdapters();
#ifdef _DEBUG
dbprintf( "AKRip32: GetCDList(): numAdapters == %d", numAdapters );
#endif
//return 0;
for( i = 0; i < numAdapters; i++ )
{
memset( &sh, 0, sizeof( sh ) );
sh.SRB_Cmd = SC_HA_INQUIRY;
sh.SRB_HaID = i;
pfnSendASPI32Command( (LPSRB)&sh );
/* on error skip to next adapter */
if ( sh.SRB_Status != SS_COMP )
continue;
maxTgt = (int)sh.HA_Unique[3];
if ( maxTgt == 0 )
maxTgt = 8;
for( j = 0; j < maxTgt; j++ )
{
for( k = 0; k < 8; k++ )
{
memset( &sd, 0, sizeof( sd ) );
sd.SRB_Cmd = SC_GET_DEV_TYPE;
sd.SRB_HaID = i;
sd.SRB_Target = j;
sd.SRB_Lun = k;
pfnSendASPI32Command( (LPSRB)&sd );
if ( sd.SRB_Status == SS_COMP )
{
if ( sd.SRB_DeviceType == DTYPE_CDROM )
{
cd->cd[cd->num].ha = i;
cd->cd[cd->num].tgt = j;
cd->cd[cd->num].lun = k;
memset( cd->cd[cd->num].id, 0, MAXIDLEN+1 );
GetDriveInfo( i, j, k, &(cd->cd[cd->num]) );
// getDriveInfo( i, j, k, cd->cd[cd->num].id, MAXIDLEN+1 );
cd->num++;
}
#ifdef _DEBUG
else
{
dbprintf( " : sd.SRB_DeviceType == %d", sd.SRB_DeviceType );
GetDriveInfo( i, j, k, NULL );
}
#endif
}
}
}
}
return 1;
}
DWORD ReadCDAudioLBA( HCDROM hCD, LPTRACKBUF t )
{
int idx = (int)hCD - 1;
DWORD retVal;
if ( (idx<0) || (idx>=MAXCDHAND) )
{
alErrCode = ALERR_INVHANDLE;
return SS_ERR;
}
retVal = WaitForSingleObject( cdMutexes[idx], TIMEOUT );
if ( retVal != WAIT_OBJECT_0 )
{
alErrCode = ALERR_LOCK;
return SS_ERR;
}
if ( !cdHandles[idx].used )
{
alErrCode = ALERR_INVHANDLE;
ReleaseMutex( cdMutexes[idx] );
return SS_ERR;
}
retVal = cdHandles[idx].pfnRead( hCD, t );
ReleaseMutex( cdMutexes[idx] );
return retVal;
}
/*
* Test the currently set read function. Fills the buffer with 0xAA
* prior to reading, and then checks the read area for a series of 0xAA
* bytes. This is because some read commands do not return an error, but
* also don't read correct data or a full buffer.
*/
DWORD testReadCDAudio( HCDROM hCD, LPTRACKBUF t )
{
DWORD i;
DWORD dwStatus;
BYTE *p;
int idx = (int)hCD - 1;
int count;
// fill buffer with dummy data
memset( t->buf, 0xAA, t->len );
dwStatus = cdHandles[idx].pfnRead( hCD, t );
if ( dwStatus != SS_COMP )
{
return dwStatus;
}
p = &(t->buf[t->startOffset]);
for( i = 0, count = 0; i < t->len; i += 4 )
{
if ( *((DWORD *)p) == 0xAAAAAAAA )
count += 1;
else
count = 0;
if ( count == 8 )
{
return SS_ERR;
}
p += 4;
}
return dwStatus;
}
/***************************************************************************
* readCDAudioLBA_ANY
*
* Attempts to autodetect the proper read function for the CD. It tries
* ATAPI2, ATAPI1, and then finally READ10
*
***************************************************************************/
DWORD readCDAudioLBA_ANY( HCDROM hCD, LPTRACKBUF t )
{
DWORD dwStatus;
int idx = (int)hCD - 1;
int i, j;
int ord[7] = { 2, 1, 8, 4, 5, 6, 7 };
if ( (idx<0) || (idx>=MAXCDHAND) || !cdHandles[idx].used )
{
alErrCode = ALERR_INVHANDLE;
return SS_ERR;
}
if ( t->numFrames * 2352 > t->maxLen )
{
alErrCode = ALERR_BUFTOOSMALL;
return SS_ERR;
}
for( i = 0; i < 7; i++ )
{
#ifdef _DEBUG
dbprintf( "akrip32: testing read fn %d", ord[i] );
#endif
cdHandles[idx].readType = ord[i];
cdHandles[idx].pfnRead = aReadFn[ord[i]];
cdHandles[idx].pfnDeinit = NULL;
cdHandles[idx].bInit = FALSE;
for( j = 0; j < 3; j++ )
{
dwStatus = testReadCDAudio( hCD, t );
if ( dwStatus == SS_COMP )
{
return dwStatus;
}
}
}
// Failed to find compatible read mode, so we reset to the default
// and return the error
cdHandles[idx].readType = CDR_ANY;
cdHandles[idx].pfnRead = readCDAudioLBA_ANY;
return dwStatus;
}
DWORD GetASPI32SupportInfo( void )
{
return pfnGetASPI32SupportInfo();
}
DWORD SendASPI32Command( LPSRB s )
{
return pfnSendASPI32Command( s );
}
#define _GEN_CDPARMS 0
DWORD readCDParameters( HCDROM hCD, BOOL bChangeMask )
{
HANDLE h;
SRB_ExecSCSICmd s;
DWORD d;
BYTE b[256];
int lenData;
BYTE *p;
BYTE *pMax = b + 256;
LPSENSEMASK psm;
int idx = (int)hCD - 1;
#if _GEN_CDPARMS
FILE *fp;
#endif
if ( (idx<0) || (idx>=MAXCDHAND) || !cdHandles[idx].used )
{
alErrCode = ALERR_INVHANDLE;
return SS_ERR;
}
cdHandles[idx].smRead = FALSE;
psm = &cdHandles[idx].sm;
memset( psm, 0, sizeof( SENSEMASK ) );
h = CreateEvent( NULL, TRUE, FALSE, NULL );
memset( &s, 0, sizeof( s ) );
memset( b, 0xFF, 256 );
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.SRB_HaID = cdHandles[idx].ha;
s.SRB_Target = cdHandles[idx].tgt;
s.SRB_Lun = cdHandles[idx].lun;
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
s.SRB_BufLen = 256;
s.SRB_BufPointer = b;
s.SRB_CDBLen = 12;
s.SRB_PostProc = (LPVOID)h;
s.CDBByte[0] = 0x5A;
s.CDBByte[2] = 0x3F;
s.CDBByte[7] = 0x01;
s.CDBByte[8] = 0x00;
/* do we want just a mask of changable items? */
if ( bChangeMask )
s.CDBByte[2] |= 0x40;
ResetEvent( h );
d = pfnSendASPI32Command( (LPSRB)&s );
if ( d == SS_PENDING )
{
WaitForSingleObject( h, 500 );
}
CloseHandle( h );
if ( s.SRB_Status != SS_COMP )
{
alErrCode = ALERR_ASPI;
alAspiErr = s.SRB_Status;
ReleaseMutex( cdMutexes[idx] );
return SS_ERR;
}
#if _GEN_CDPARMS
fp = fopen( "cdparms.dat", "wb" );
if ( fp )
{
fwrite( b, 1, 256, fp );
fclose( fp );
}
#endif
lenData = ((unsigned int)b[0] << 8) + b[1];
/* set to first sense mask, and then walk through the masks */
p = b + 8;
while( (p < &(b[2+lenData])) && (p < pMax) )
{
BYTE which;
which = p[0] & 0x3F;
switch( which )
{
case READERRREC:
psm->rerAvail = TRUE;
memcpy( psm->rer, p, p[1]+2 );
break;
case CDRPARMS:
psm->cpmAvail = TRUE;
memcpy( psm->cpm, p, p[1]+2 );
break;
case CDRAUDIOCTL:
psm->cacmAvail = TRUE;
memcpy( psm->cacm, p, p[1]+2 );
break;
case CDRCAPS:
psm->ccsmAvail = TRUE;
memcpy( psm->ccsm, p, p[1]+2 );
break;
}
p += (p[1] + 2);
}
cdHandles[idx].smRead = TRUE;
return s.SRB_Status;
}
/****************************************************************
* Generic function to query CD unit capabilities and parameters
*
* which: specifies the parm we wish to query
* pNum: pointer to DWORD to return data
*
* returns: If the parm is not available, returns FALSE. Otherwise
* returns TRUE.
*
* The data requested will either be returned as a BOOL, or copied
* to pNum, depending on the parameter requested.
****************************************************************/
BOOL QueryCDParms( HCDROM hCD, int which, DWORD *pNum )
{
BOOL retVal = FALSE;
DWORD dwTmp;
int idx = (int)hCD - 1;
if ( (idx<0) || (idx>=MAXCDHAND) || !cdHandles[idx].used )
{
alErrCode = ALERR_INVHANDLE;
return FALSE;
}
if ( WaitForSingleObject( cdMutexes[idx], TIMEOUT ) != WAIT_OBJECT_0 )
{
alErrCode = ALERR_LOCK;
return SS_ERR;
}
if ( pNum )
*pNum = 0;
else
pNum = &dwTmp;
if ( !cdHandles[idx].smRead )
{
if ( readCDParameters( hCD, FALSE ) != SS_COMP )
{
ReleaseMutex( cdMutexes[idx] );
return FALSE;
}
}
switch( which )
{
case CDP_READCDR:
retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[2] & 0x01);
break;
case CDP_READCDE:
retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[2] & 0x02);
break;
case CDP_METHOD2:
retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[2] & 0x04);
break;
case CDP_WRITECDR:
retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[3] & 0x01);
break;
case CDP_WRITECDE:
retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[3] & 0x02);
break;
case CDP_AUDIOPLAY:
retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[4] & 0x01);
break;
case CDP_COMPOSITE:
retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[4] & 0x02);
break;
case CDP_DIGITAL1:
retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[4] & 0x04);
break;
case CDP_DIGITAL2:
retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[4] & 0x08);
break;
case CDP_M2FORM1:
retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[4] & 0x10);
break;
case CDP_M2FORM2:
retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[4] & 0x20);
break;
case CDP_MULTISES:
retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[4] & 0x40);
break;
case CDP_CDDA:
retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[5] & 0x01);
break;
case CDP_RW:
retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[5] & 0x04);
break;
case CDP_RWCORR:
retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[5] & 0x08);
break;
case CDP_C2SUPP:
retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[5] & 0x10);
break;
case CDP_ISRC:
retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[5] & 0x20);
break;
case CDP_UPC:
retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[5] & 0x40);
break;
case CDP_CANLOCK:
retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[6] & 0x01);
break;
case CDP_LOCKED:
retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[6] & 0x02);
break;
case CDP_PREVJUMP:
retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[6] & 0x04);
break;
case CDP_CANEJECT:
retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[6] & 0x08);
break;
case CDP_SEPVOL:
retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[7] & 0x01);
break;
case CDP_SEPMUTE:
retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[7] & 0x02);
break;
case CDP_SDP:
retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[7] & 0x04);
break;
case CDP_SSS:
retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[7] & 0x08);
break;
case CDP_MECHTYPE:
if ( cdHandles[idx].sm.ccsmAvail )
{
retVal = TRUE;
*pNum = (DWORD)(cdHandles[idx].sm.ccsm[6] >> 5);
}
break;
case CDP_STREAMACC:
return cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[5] & 0x02);
break;
case CDP_MAXSPEED:
if ( cdHandles[idx].sm.ccsmAvail )
{
retVal = TRUE;
*pNum = ((DWORD)cdHandles[idx].sm.ccsm[8] << 8) + (DWORD)cdHandles[idx].sm.ccsm[9];
}
break;
case CDP_NUMVOL:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -