// ---------------------------------------------- // - DAC32.DLL Implementations Datei - // - Written 1996-1998 by Christoph Schmelnik - // ---------------------------------------------- // Version 1.33 : 18.01.1998 // Changes: // Added speed selection support for all current Plextor drives // // Version 1.40 : 24.02.1998 // Changes: // Set correct direction flags, to work with NT device IO interface and ATAPI drives // Changed main CD detection to TestUnitReady // Removed CD detection from Audio Status Info // Added hopefully correct read command for Matsushita/Panasonic drives // Added Parameters to CDAC class to allow the disabling of the audio test and to spin up the drive for a specified time // in seconds to avoid spin up problems on some drives. Both parameters have default values so it behaves like the old version // without the additional parameters // Added Parameter to the constructor of CWaveSave to disable writing any Headers. Also this parameter has a default to work like // before. // Added virtual function in CDAC to report buffer underruns in Burst Copy Mode // For the last feature an immediate parameter in WaitCDDA is added // GetLastSense function added to return the sense information for the last read audio command // Configuration in CMapDrive extended by new features // Added function to CD Class to read Media Cataloge Number // // Version 1.41 : 02.05.1998 // Changes: // New GetInfoEx() function in CMapDrive, to allow a better result checking. // Bugfixed error handling in CWaveSave and CDAC regarding write errors // // Version 1.42 : 02.08.1998 // Changes: // Added GetLastReadableAddress function to get the last readable Sektor of a session. // Added a flag in the drive properties for the function. // Added this function to the CDAC object. // // Version 1.43 : 23.12.1998 // Changes: // Added Wave and DAC classes are now available in a MT version, the old versions will not longer be updated. // // Version 1.44 : 10.03.1999 // Changes: // Added Support for current Plextor CDROM drives and CD-Writers. // Added Support for Jukeboxes // Changed Handling of the Ringbuffer // // Version 1.45 : 15.08.1999 // Changes: // Added Enhanced error detection for Plextor drives. // Several Bugfixes (initialising under NT and Ringbuffer specific) // // Version 1.45-Build 11 : 11.11.1999 // Changes: // Added a check for the MaxSektor parameter in CBaseWaveMT to avoid Program failures even if the applications provides an invalid value. // Changed source to comile with Borland compiler // Added MMC-2 Type which will be default for Sony CD-Writers 140 and 928 // Skip Virtual CD devices in Bus scan // Fixed Array out of bound bug in drive detection. //limit the read to 64k, because of a bug in the Adaptec drivers #define Bug64 //limit the number of retries at error to 5 #define MAXTRIES 5 #include "dac32.h" #include #include #include #ifdef __BORLANDC__ // pgo (to make it compatible with Bormand compiler) #define _stricmp _stricmp #define _strlwr strlwr #endif // ---------------------------------------------------------------------------------------- // - Implementation of the private copy operators - // - - // - Author: Christoph Schmelnik - // - Purpose: Check the syntax of program - // ---------------------------------------------------------------------------------------- CBaseCD& CBaseCD::operator = (const CBaseCD &other) { assert(!&other); return (*this); } CSCSICD& CSCSICD::operator = (const CSCSICD &other) { assert(!&other); return (*this); } // ---------------------------------------------------------------------------------------- // - Implementation of the class members of CCDAdress - // - - // - Author: Christoph Schmelnik - // - Purpose: Eliminate the errors at compile time - // ---------------------------------------------------------------------------------------- void CCDAdress::SetRedbook(long Value) { Adresse=Value >> 24; Adresse+=((Value >> 16) & 255)*75; Adresse+=((Value >> 8) & 255)*4500; }; // ---------------------------------------------------------------------------------------- // - Implementation of the class members of CMapInfo - // - - // - Author: Christoph Schmelnik - // - Purpose: Implement the information of the TypeMappings - // ---------------------------------------------------------------------------------------- CMapInfo::CMapInfo() { strncpy(TypNamen[0],"TOSHIBA ", 9); strncpy(TypNamen[1],"SONY ", 9); strncpy(TypNamen[2],"NEC ", 9); strncpy(TypNamen[3],"HITACHI ", 9); strncpy(TypNamen[4],"YAMAHA ", 9); strncpy(TypNamen[5],"PIONEER ", 9); strncpy(TypNamen[6],"IBM ", 9); strncpy(TypNamen[7],"PLEXTOR ", 9); strncpy(TypNamen[8],"PHILIPS ", 9); strncpy(TypNamen[9],"GRUNDIG ", 9); strncpy(TypNamen[10],"HP ", 9); strncpy(TypNamen[11],"IMS ", 9); strncpy(TypNamen[12],"MITSUMI ", 9); strncpy(TypNamen[13],"ATAPI ", 9); strncpy(TypNamen[14],"TOSHNEW ", 9); strncpy(TypNamen[15],"RICOH ", 9); strncpy(TypNamen[16],"MATSHITA", 9); strncpy(TypNamen[17],"PLASMON ", 9); strncpy(TypNamen[18],"KODAK ", 9); strncpy(TypNamen[19],"TEAC ", 9); strncpy(TypNamen[20],"CyberDrv", 9); strncpy(TypNamen[21],"MMC-2 ", 9); // pgo int const t[]={CDTYPE_TOSHIBA,CDTYPE_SONY,CDTYPE_NEC,CDTYPE_SONY,CDTYPE_SONY,CDTYPE_SONY, CDTYPE_SONY,CDTYPE_PLEXTOR,CDTYPE_PHILIPS,CDTYPE_PHILIPS,CDTYPE_PHILIPS,CDTYPE_PHILIPS, CDTYPE_PHILIPS,CDTYPE_ATAPI,CDTYPE_TOSHNEW,CDTYPE_RICOH,CDTYPE_MATSHITA,CDTYPE_PHILIPS, CDTYPE_PHILIPS,CDTYPE_SONY,CDTYPE_CYBERDRV, CDTYPE_CYBERDRV}; // pgo for (int i=0; iNext; delete Akt; } }; void CMapDrive::Reset() { TDriveInfoMem *Akt,*Last; DeleteAll(); BYTE SCSIType; TDriveInfo Info = {0}; int DType = DTYPE_UNKNOWN; char Revision[5] = {0}; char ManagerID[17] = {0}; char HAID[17] = {0}; THAUnique HAUnique; MEMORYSTATUS MemStat; MemStat.dwLength=sizeof(MEMORYSTATUS); GlobalMemoryStatus((LPMEMORYSTATUS)&MemStat); CMapInfo MapInfo; int HostNum; for (HostNum=0; HostNum=MaxMappings) i=1; //pgo: avoid array out of bound Info.Type=i; } else Info.Type=MapInfo.GetTypMappingRev(CDTYPE_ATAPI); if (MapInfo.GetTypMapping(Info.Type)==CDTYPE_TOSHIBA) { char szNumbers[17] = {0}; for (size_t i=0; i3800) && (nProductID<4000)) || ((nProductID>5700) && (nProductID<10000))) Info.Type=MapInfo.GetTypMappingRev(CDTYPE_TOSHNEW); } // pgo else if (MapInfo.GetTypMapping(Info.Type)==CDTYPE_SONY) { if (SCSIType) { char szNumbers[17] = {0}; for (size_t i=0; i(HostAdapterMemory[HostNum]/2352)) Info.MaxSektors=HostAdapterMemory[HostNum]/2352; #ifdef Bug64 if (Info.MaxSektors>27) Info.MaxSektors=27; #else if (Info.MaxSektors>446) Info.MaxSektors=446; #endif if (!Info.MaxSektors) Info.MaxSektors=26; Info.SynchSektors=3; Info.Speed=0; Info.PerformDATest=DATEST_FIRSTTRACK; Info.SpinUpMode=SPINUP_NEVER; Info.dwSpinUpTime=5; Info.bUseLastReadableAddress=FALSE; Info.bUseC2ErrorInfo=FALSE; Info.bSpinDown=FALSE; Akt=new TDriveInfoMem; Akt->Info=Info; Akt->Next=0; if (!First) First=Akt; else Last->Next=Akt; //Last must be set to Akt Last=Akt; } } } } if (RunningNT) { //check all drives for direct access int Index, Length; wchar_t DriveList[128] = {0}, *pDrives = 0; Length=GetLogicalDriveStrings(128,DriveList); if (Length) { pDrives=DriveList; Index=0; while (pDrives && *pDrives && (Index 4) ) dwOpenFlags |= GENERIC_WRITE; hDrive=CreateFile(CDDevice,dwOpenFlags,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL); if (hDrive!=INVALID_HANDLE_VALUE) { //CT> added correct host/id/lun guessing extern int getSCSIIDFromDrive(char driveletter, int *host, int *id, int *lun); int m_lun; getSCSIIDFromDrive((char)pDrives[0],&HostNum,&IDNum,&m_lun); DType=GetDeviceInfo(HostNum,IDNum,m_lun,SCSIType,Info.VendorID,Info.ProductID,Revision,hDrive); if ((DType==DTYPE_CROM)|| (DType==DTYPE_WORM)) { SCSIMaxBlocks(hDrive,&HostAdapterMemory[HostNum]); if (SCSIType) { int i; for (i=0; (i=MaxMappings) i=1; //pgo: avoid array out of bound Info.Type=i; } else Info.Type=MapInfo.GetTypMappingRev(CDTYPE_ATAPI); if (MapInfo.GetTypMapping(Info.Type)==CDTYPE_TOSHIBA) { char szNumbers[17]; szNumbers[0]=0; for (size_t i=0; i3800) && (nProductID<4000)) || ((nProductID>5700) && (nProductID<10000))) Info.Type=MapInfo.GetTypMappingRev(CDTYPE_TOSHNEW); } // pgo else if (MapInfo.GetTypMapping(Info.Type)==CDTYPE_SONY) { if (SCSIType) { char szNumbers[17] = {0}; for (size_t i=0; i(HostAdapterMemory[HostNum]/2352)) Info.MaxSektors=HostAdapterMemory[HostNum]/2352; #ifdef Bug64 if (Info.MaxSektors>27) Info.MaxSektors=27; #else if (Info.MaxSektors>446) Info.MaxSektors=446; #endif if (!Info.MaxSektors || (MapInfo.GetTypMapping(Info.Type)==CDTYPE_ATAPI)) Info.MaxSektors=26; Info.SynchSektors=3; Info.Speed=0; Info.PerformDATest=DATEST_FIRSTTRACK; Info.SpinUpMode=SPINUP_NEVER; Info.dwSpinUpTime=5; Info.bUseLastReadableAddress=FALSE; Info.bUseC2ErrorInfo=FALSE; Info.bSpinDown=FALSE; Akt=new TDriveInfoMem; Akt->Info=Info; Akt->Next=0; if (!First) First=Akt; else Last->Next=Akt; //Last must be set to Akt Last=Akt; HostNum++; } CloseHandle(hDrive); } } pDrives+=4; Index+=4; } } } }; int CMapDrive::GetMaxDrives() { int i=0; TDriveInfoMem *Akt; Akt=First; while (Akt) { i++; Akt=Akt->Next; } return i; }; TDriveInfo &CMapDrive::GetInfo(int index) { int i=0; TDriveInfoMem *Akt; Akt=First; while ((Akt) && (iNext; } return Akt->Info; }; BOOL CMapDrive::GetInfoEx(int index, TDriveInfo *&pInfo) { int i=0; TDriveInfoMem *Akt; Akt=First; while ((Akt) && (iNext; } if (!Akt) return FALSE; pInfo=&Akt->Info; return TRUE; }; void CMapDrive::DeleteInfo(int index) { int i=0; TDriveInfoMem *Akt,*Prev; Akt=First; Prev=0; while ((Akt) && (iNext; } if (!Akt) return; if (Prev) Prev->Next=Akt->Next; else First=Akt->Next; delete Akt; }; int CMapDrive::GetMaxHostAdapters() { return NumberOfHostAdapters; }; int CMapDrive::GetSupportedHostAdapterMemory(int index) { if ((index=0)) return HostAdapterMemory[index]; else return -1; }; void CMapDrive::SetSupportedHostAdapterMemory(int index,int Memory) { if ((index=0)) HostAdapterMemory[index]=Memory; } int CMapDrive::GetMaxSektors(int HostAdapterNumber) { #ifdef Bug64 int Result=HostAdapterMemory[HostAdapterNumber]/2352; if (Result>27) Result=27; return Result; #else return HostAdapterMemory[HostAdapterNumber]/2352; #endif }; // ---------------------------------------------------------------------------------------- // - Implementation of the class members of CMapInfoJuke - // - - // - Author: Christoph Schmelnik - // - Purpose: Implement the information of the TypeMappings - // ---------------------------------------------------------------------------------------- CMapInfoJuke::CMapInfoJuke() { strncpy(TypNamen[0],"SONY ", 9); strncpy(TypNamen[1],"PIONEER ", 9); int const t[]={JUKETYPE_SONY,JUKETYPE_PIONEER}; for (int i=0; iNext; if (Akt->Info.pConnectedDrives) delete Akt->Info.pConnectedDrives; delete Akt; } }; void CMapJuke::Reset() { TJukeInfoMem *Akt,*Last; DeleteAll(); BYTE SCSIType = 0; TJukeInfo Info = {0}; int DType = DTYPE_UNKNOWN; char Revision[5] = {0}; char ManagerID[17] = {0}; char HAID[17] = {0}; THAUnique HAUnique; CMapInfoJuke MapInfo; for (int HostNum=0; HostNumInfo=Info; Akt->bIsWorking=FALSE; Akt->Next=0; if (!First) First=Akt; else Last->Next=Akt; //Last must be set to Akt Last=Akt; } } } } } }; int CMapJuke::GetMaxJukes() { int i=0; TJukeInfoMem *Akt; Akt=First; while (Akt) { i++; Akt=Akt->Next; } return i; }; TJukeInfo &CMapJuke::GetInfo(int index) { int i=0; TJukeInfoMem *Akt; Akt=First; while ((Akt) && (iNext; } return Akt->Info; }; BOOL CMapJuke::IsWorking(int index) { int i=0; TJukeInfoMem *Akt; Akt=First; while ((Akt) && (iNext; } return Akt->bIsWorking; }; void CMapJuke::SetWorking(int index,BOOL bIsWorking) { int i=0; TJukeInfoMem *Akt; Akt=First; while ((Akt) && (iNext; } Akt->bIsWorking=bIsWorking; }; void CMapJuke::DeleteInfo(int index) { int i=0; TJukeInfoMem *Akt,*Prev; Akt=First; Prev=0; while ((Akt) && (iNext; } if (!Akt) return; if (Prev) Prev->Next=Akt->Next; else First=Akt->Next; if (Akt->Info.pConnectedDrives) delete Akt->Info.pConnectedDrives; delete Akt; }; // ---------------------------------------------------------------------------------------- // - Implementation of the class members of CJukeBox - // - - // - Author: Christoph Schmelnik - // - Purpose: Control the basic JukeBox functions over ASPI - // ---------------------------------------------------------------------------------------- CJukeBox::CJukeBox (TJukeInfo &xInfo):Config(xInfo) { m_hJukeEvent=INVALID_HANDLE_VALUE; wchar_t szEventName[32] = {0}; wsprintf(szEventName,L"%X",this); m_hJukeEvent=CreateEvent(NULL,TRUE,FALSE,szEventName); assert(m_hJukeEvent); } CJukeBox::~CJukeBox() { if (m_hJukeEvent!=INVALID_HANDLE_VALUE) CloseHandle(m_hJukeEvent); } BOOL CJukeBox::MoveMedium(int Source,int Destination) { switch (MapInfo.GetTypMapping(Config.Type)) { case JUKETYPE_PIONEER : if ((Source<1) || (Source>Config.MaxDiscs)) if ((Source<0x4000) || (Source>=(0x4000+Config.MaxDrives))) return FALSE; if ((Destination<1) || (Destination>Config.MaxDiscs)) if ((Destination<0x4000) || (Destination>=(0x4000+Config.MaxDrives))) return FALSE; break; case JUKETYPE_SONY : default: if ((Source<1) || (Source>Config.MaxDiscs)) { if ((Source<0x4000) || (Source>=(0x4000+Config.MaxDrives))) return FALSE; else Source-=0x3fff; } else Source+=10; if ((Destination<1) || (Destination>Config.MaxDiscs)) { if ((Destination<0x4000) || (Destination>=(0x4000+Config.MaxDrives))) return FALSE; else Destination-=0x3fff; } else Destination+=10; break; } while (!TestUnitReady(Config.HostAdapterNumber,Config.ID,Config.LUN,m_hJukeEvent)); TOpcode OpC; OpC[0]=0xa5; OpC[1]=Config.LUN>>5; OpC[2]=0x00; OpC[3]=0x00; OpC[4]=Source/256; OpC[5]=Source%256; OpC[6]=Destination/256; OpC[7]=Destination%256; OpC[8]=0x00; OpC[9]=0x00; OpC[10]=0x00; OpC[11]=0x00; return ExecuteSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,0,OpC,12,NULL,0,m_hJukeEvent); } // ---------------------------------------------------------------------------------------- // - Implementation of the class members of CBaseCD - // - - // - Author: Christoph Schmelnik - // - Purpose: The drive independent functions to access the CD-ROM drives - // ---------------------------------------------------------------------------------------- int CBaseCD::Lasterror() { int h; h=Error; Error=CDOK; return h; } int CBaseCD::ReadFirstTrackInfo(TTrackList &Infos) { if (!FirstTrack) return 0; AktTrack=FirstTrack; Infos=AktTrack->Info; return 1; } int CBaseCD::ReadNextTrackInfo(TTrackList &Infos) { if ((!FirstTrack) || (!AktTrack->Next)) return 0; AktTrack=AktTrack->Next; Infos=AktTrack->Info; return 1; } int CBaseCD::ReadPrevTrackInfo(TTrackList &Infos) { if ((!FirstTrack) || (!AktTrack->Prev)) return 0; AktTrack=AktTrack->Prev; Infos=AktTrack->Info; return 1; } int CBaseCD::ReadTrackInfo(TTrackList &Infos) { if ((!FirstTrack) || (Infos.TrackNummer<1)) return 0; if (!AktTrack) AktTrack=FirstTrack; if (AktTrack->Info.TrackNummer==Infos.TrackNummer) { Infos=AktTrack->Info; return 1; } while ((AktTrack->Info.TrackNummer>Infos.TrackNummer) && (AktTrack->Prev)) AktTrack=AktTrack->Prev; while ((AktTrack->Info.TrackNummerNext)) AktTrack=AktTrack->Next; if (AktTrack->Info.TrackNummer!=Infos.TrackNummer) return 0; Infos=AktTrack->Info; return 1; } int CBaseCD::ReadMaxTracks() { TTrackListeMem *Laeufer; if (!FirstTrack) return 0; Laeufer=AktTrack; while (Laeufer->Next) Laeufer=Laeufer->Next; return Laeufer->Info.TrackNummer; } void CBaseCD::DeleteTrackList() { while (FirstTrack) { AktTrack=FirstTrack->Next; delete FirstTrack; FirstTrack=AktTrack; } } // ---------------------------------------------------------------------------------------- // - Implementation of the class members of CSCSICD - // - - // - Author: Christoph Schmelnik - // - Purpose: Control the basic CDROM functions over ASPI - // ---------------------------------------------------------------------------------------- CSCSICD::CSCSICD (char drive, TDriveInfo &xInfo):Config(xInfo) { m_bSpeedTableInitialized=FALSE; FirstTrack=0; NECRotationSpeed = 0; // pgo Changed=FALSE; CDPresentLast=TRUE; Error=CDOK; m_hDriveEvent=INVALID_HANDLE_VALUE; memset(&m_SenseInfo,0,sizeof(TSenseInfo)); if ((Config.HostAdapterNumber>=NumberOfHostAdapters) && RunningNT) { DWORD dwFlags; OSVERSIONINFO osver; wchar_t CDDevice[10]=L"\\\\.\\x:"; CDDevice[4]=(wchar_t)drive;//(Config.HostAdapterNumber + 'A'/* + 1*/); //For Windows NT 5 use other file flags memset( &osver, 0x00, sizeof(osver) ); osver.dwOSVersionInfoSize = sizeof(osver); GetVersionEx( &osver ); // if Win2K or greater, add GENERIC_WRITE dwFlags = GENERIC_READ; if ( (osver.dwPlatformId == VER_PLATFORM_WIN32_NT) && (osver.dwMajorVersion > 4) ) dwFlags |= GENERIC_WRITE; m_hDriveEvent = CreateFile( CDDevice, dwFlags, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); } else { wchar_t szEventName[32] = {0}; wsprintf(szEventName,L"%X",this); m_hDriveEvent=CreateEvent(NULL,TRUE,FALSE,szEventName); assert(m_hDriveEvent); } TDriveStatus DInfo=Get_DriveStatus(); if (DInfo.CDPresent) ReRead(); } CSCSICD::~CSCSICD() { DeleteTrackList(); if (m_hDriveEvent!=INVALID_HANDLE_VALUE) CloseHandle(m_hDriveEvent); } void CSCSICD::PrepareCDDA() { switch (MapInfo.GetTypMapping(Config.Type)) { case CDTYPE_TOSHIBA : { memset(&ModeData,0,sizeof(ModeData)); if (!ModeSense(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeData,12,0,m_hDriveEvent)) { Error=CDASPIError; return; } ModeData[0]=0; TDriveMode ModeSelectData; ModeSelectData[0]=0x00; ModeSelectData[1]=0x00; ModeSelectData[2]=0x00; ModeSelectData[3]=0x08; ModeSelectData[4]=0x82; ModeSelectData[5]=0x00; ModeSelectData[6]=0x00; ModeSelectData[7]=0x00; ModeSelectData[8]=0x00; ModeSelectData[9]=0x00; ModeSelectData[10]=0x09; ModeSelectData[11]=0x30; if (!ModeSelect(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeSelectData,12,m_hDriveEvent)) { Error=CDASPIError; return; } break; } case CDTYPE_TOSHNEW : { memset(&ModeData,0,sizeof(ModeData)); if (!ModeSense(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeData,15,0x20,m_hDriveEvent)) { Error=CDASPIError; return; } ModeData[0]=0; TDriveMode ModeSelectData; ModeSelectData[0]=0x00; ModeSelectData[1]=0x00; ModeSelectData[2]=0x00; ModeSelectData[3]=0x08; ModeSelectData[4]=0x82; ModeSelectData[5]=0x00; ModeSelectData[6]=0x00; ModeSelectData[7]=0x00; ModeSelectData[8]=0x00; ModeSelectData[9]=0x00; ModeSelectData[10]=0x09; ModeSelectData[11]=0x30; ModeSelectData[12]=0x20; ModeSelectData[13]=0x01; ModeSelectData[14]=(ModeData[14] & 0xcf)|0x10; if (!ModeSelect(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeSelectData,15,m_hDriveEvent)) { Error=CDASPIError; return; } break; } case CDTYPE_NEC : { memset(&ModeData,0,sizeof(ModeData)); if (!addModeSense(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeData,12,m_hDriveEvent)) { Error=CDASPIError; return; } NECRotationSpeed=ModeData[6] & 0x20; ModeData[6]=ModeData[6]|0x20; if (!addModeSelect(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeData,12,m_hDriveEvent)) { Error=CDASPIError; return; } break; } case CDTYPE_PHILIPS : case CDTYPE_MATSHITA : { memset(&ModeData,0,sizeof(ModeData)); if (!ModeSense(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeData,12,0,m_hDriveEvent)) { Error=CDASPIError; return; } ModeData[0]=0; TDriveMode ModeSelectData; ModeSelectData[0]=0x00; ModeSelectData[1]=0x00; ModeSelectData[2]=0x00; ModeSelectData[3]=0x08; ModeSelectData[4]=0x00; ModeSelectData[5]=0x00; ModeSelectData[6]=0x00; ModeSelectData[7]=0x00; ModeSelectData[8]=0x00; ModeSelectData[9]=0x00; ModeSelectData[10]=0x09; ModeSelectData[11]=0x30; if (!ModeSelect(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeSelectData,12,m_hDriveEvent)) { Error=CDASPIError; return; } break; } } } void CSCSICD::ReadCDDA(CCDAdress StartSektor,long Sektoranzahl,void *Buffer,BOOL bUseC2ErrorInfo) { TOpcode OpC; OpC[1]=0x00; OpC[2]=0x00; OpC[3]=LOBYTE(HIWORD(StartSektor.GetHSG())); OpC[4]=HIBYTE(LOWORD(StartSektor.GetHSG())); OpC[5]=LOBYTE(LOWORD(StartSektor.GetHSG())); OpC[6]=0x00; switch (MapInfo.GetTypMapping(Config.Type)) { case CDTYPE_TOSHIBA : case CDTYPE_TOSHNEW : { OpC[0]=0x28; OpC[7]=HIBYTE(LOWORD(Sektoranzahl)); OpC[8]=LOBYTE(LOWORD(Sektoranzahl)); OpC[9]=0x00; FillSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,SRB_DIR_IN,OpC,10,Buffer,Sektoranzahl*2352,ReadSRB,m_hDriveEvent); break; } case CDTYPE_SONY : case CDTYPE_RICOH : case CDTYPE_PLEXTOR : { OpC[0]=0xD8; OpC[7]=0x00; OpC[8]=HIBYTE(LOWORD(Sektoranzahl)); OpC[9]=LOBYTE(LOWORD(Sektoranzahl)); // benski if (bUseC2ErrorInfo) OpC[10]=0x04; else OpC[10]=0x00; OpC[11]=0x00; FillSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,SRB_DIR_IN,OpC,12,Buffer,(bUseC2ErrorInfo)?(Sektoranzahl*2646):(Sektoranzahl*2352),ReadSRB,m_hDriveEvent); break; } case CDTYPE_NEC : { OpC[0]=0xD4; OpC[7]=HIBYTE(LOWORD(Sektoranzahl)); OpC[8]=LOBYTE(LOWORD(Sektoranzahl)); OpC[9]=0x00; FillSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,SRB_DIR_IN,OpC,10,Buffer,Sektoranzahl*2352,ReadSRB,m_hDriveEvent); break; } case CDTYPE_MATSHITA : { OpC[0]=0xD4; OpC[7]=0x00; OpC[8]=HIBYTE(LOWORD(Sektoranzahl)); OpC[9]=LOBYTE(LOWORD(Sektoranzahl)); OpC[10]=0x00; OpC[11]=0x00; FillSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,SRB_DIR_IN,OpC,12,Buffer,Sektoranzahl*2352,ReadSRB,m_hDriveEvent); break; } case CDTYPE_PHILIPS : { OpC[0]=0x28; OpC[7]=HIBYTE(LOWORD(Sektoranzahl)); OpC[8]=LOBYTE(LOWORD(Sektoranzahl)); OpC[9]=0x00; FillSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,SRB_DIR_IN,OpC,10,Buffer,Sektoranzahl*2352,ReadSRB,m_hDriveEvent); break; } case CDTYPE_ATAPI : case CDTYPE_CYBERDRV : { OpC[0]=0xBE; OpC[1]=0x04; OpC[7]=HIBYTE(LOWORD(Sektoranzahl)); OpC[8]=LOBYTE(LOWORD(Sektoranzahl)); OpC[9]=0xF0; // benski if (bUseC2ErrorInfo) OpC[9]|=2; // flag 2 is supposed to mean check for C2 error info OpC[10]=0x00; OpC[11]=0x00; // with C2 error info, our sector size is now 2646 bytes FillSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,SRB_DIR_IN,OpC,12,Buffer,bUseC2ErrorInfo?(Sektoranzahl*2646):(Sektoranzahl*2352),ReadSRB,m_hDriveEvent); break; } } ExecuteSCSIRequest(ReadSRB,m_hDriveEvent); StartReadTime=GetTickCount(); } BOOL CSCSICD::WaitCDDA(BOOL bImmediate) { BYTE Status=WaitSCSIRequest(ReadSRB,m_hDriveEvent,bImmediate); if ((Status!=SS_PENDING) && (Status!=SS_COMP)) { memcpy(&m_SenseInfo,&ReadSRB.SenseArea,SENSE_LEN); Error=CDASPIError; } if ((Status==SS_PENDING) && !bImmediate) { DWORD AktReadTime=GetTickCount(); if (abs((long long)AktReadTime-StartReadTime)>12000) { AbortSCSIRequest(ReadSRB); Error=CDTimeOut; Status=SS_COMP; } } return (Status!=SS_PENDING); } void CSCSICD::FinishCDDA() { switch (MapInfo.GetTypMapping(Config.Type)) { case CDTYPE_TOSHIBA : { if (!ModeSelect(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeData,12,m_hDriveEvent)) { Error=CDASPIError; return; } break; } case CDTYPE_TOSHNEW : { if (!ModeSelect(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeData,15,m_hDriveEvent)) { Error=CDASPIError; return; } break; } case CDTYPE_NEC : { ModeData[6]=ModeData[6]|NECRotationSpeed; if (!addModeSelect(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeData,12,m_hDriveEvent)) { Error=CDASPIError; return; } break; } case CDTYPE_PHILIPS : case CDTYPE_MATSHITA : { if (!ModeSelect(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeData,12,m_hDriveEvent)) { Error=CDASPIError; return; } break; } } } void CSCSICD::SortWaveData(DWORD *Data,int Samples) { switch (MapInfo.GetTypMapping(Config.Type)) { case CDTYPE_PHILIPS : // RICOH Drives doesn't seem to swap the bytes // This has been evaluated with the CD-RW drives // So they are even just handled like SONY drives, but i don't remove this type // case CDTYPE_RICOH : { for (int i=0; i>8)| ((Data[i]&0x00ff00ff)<<8); break; } } } CCDAdress CSCSICD::GetErrorAdress() { CCDAdress h; h.SetHSG(0); if ((Error!=CDOK)&& (ReadSRB.SRB_TargStat==STATUS_CHKCOND)) h.SetHSG((ReadSRB.SenseArea[3]<<24)+ (ReadSRB.SenseArea[4]<<16)+ (ReadSRB.SenseArea[5]<<8)+ ReadSRB.SenseArea[6]); return h; } void CSCSICD::Play_Audio(CCDAdress StartSektor,long Sektoranzahl) { while (!TestUnitReady(Config.HostAdapterNumber,Config.ID,Config.LUN,m_hDriveEvent)); TOpcode OpC; OpC[0]=0x45; OpC[1]=0x00; OpC[2]=HIBYTE(HIWORD(StartSektor.GetHSG())); OpC[3]=LOBYTE(HIWORD(StartSektor.GetHSG())); OpC[4]=HIBYTE(LOWORD(StartSektor.GetHSG())); OpC[5]=LOBYTE(LOWORD(StartSektor.GetHSG())); OpC[6]=0x00; OpC[7]=HIBYTE(LOWORD(Sektoranzahl)); OpC[8]=LOBYTE(LOWORD(Sektoranzahl)); OpC[9]=0x00; if (!ExecuteSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,0,OpC,10,NULL,0,m_hDriveEvent)) Error=CDDriveNotReady; } void CSCSICD::Stop_Audio() { while (!TestUnitReady(Config.HostAdapterNumber,Config.ID,Config.LUN,m_hDriveEvent)); TOpcode OpC; /* OpC[0]=0x1b; OpC[1]=0x00; OpC[2]=0x00; OpC[3]=0x00; OpC[4]=0x00; OpC[5]=0x00; */ OpC[0]=0x2b; OpC[1]=0x00; OpC[2]=0x00; OpC[3]=0x00; OpC[4]=0x00; OpC[5]=0x00; OpC[6]=0x00; OpC[7]=0x00; OpC[8]=0x00; OpC[9]=0x00; if (!ExecuteSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,0,OpC,10,NULL,0,m_hDriveEvent)) Error=CDDriveNotReady; } void CSCSICD::Pause_Audio() { while (!TestUnitReady(Config.HostAdapterNumber,Config.ID,Config.LUN,m_hDriveEvent)); TOpcode OpC; OpC[0]=0x4b; OpC[1]=0x00; OpC[2]=0x00; OpC[3]=0x00; OpC[4]=0x00; OpC[5]=0x00; OpC[6]=0x00; OpC[7]=0x00; OpC[8]=0x00; OpC[9]=0x00; if (!ExecuteSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,0,OpC,10,NULL,0,m_hDriveEvent)) Error=CDDriveNotReady; } void CSCSICD::Resume_Audio() { while (!TestUnitReady(Config.HostAdapterNumber,Config.ID,Config.LUN,m_hDriveEvent)); TOpcode OpC; OpC[0]=0x4b; OpC[1]=0x00; OpC[2]=0x00; OpC[3]=0x00; OpC[4]=0x00; OpC[5]=0x00; OpC[6]=0x00; OpC[7]=0x00; OpC[8]=0x01; OpC[9]=0x00; if (!ExecuteSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,0,OpC,10,NULL,0,m_hDriveEvent)) Error=CDDriveNotReady; } TDriveStatus CSCSICD::Get_DriveStatus() { TDriveStatus h = {0}; /* TOpcode OpC; TQChannelInfo ChannelInfo; BOOL b; memset(&ChannelInfo,0,sizeof(ChannelInfo)); OpC[0]=0x42; OpC[1]=0x02; OpC[2]=0x40; OpC[3]=0x01; OpC[4]=0x00; OpC[5]=0x00; OpC[6]=0x00; OpC[7]=0x00; OpC[8]=sizeof(ChannelInfo); OpC[9]=0x00; if (MapInfo.GetTypMapping(Config.Type)==CDTYPE_ATAPI) { OpC[10]=0; OpC[11]=0; b=ExecuteSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,0,OpC,12,(void *)&ChannelInfo,sizeof(ChannelInfo),m_hDriveEvent); } else b=ExecuteSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,0,OpC,10,(void *)&ChannelInfo,sizeof(ChannelInfo),m_hDriveEvent); if (b && ChannelInfo.DataLen) */ if (TestUnitReady(Config.HostAdapterNumber,Config.ID,Config.LUN,m_hDriveEvent)) h.CDPresent=TRUE; else h.CDPresent=FALSE; if (h.CDPresent!=CDPresentLast) Changed=TRUE; CDPresentLast=h.CDPresent; return h; } BOOL CSCSICD::MediaChanged() { BOOL h; h=Changed; //if (CDPresentLast) Changed=FALSE; return h; } TAudioStatus CSCSICD::Get_AudioStatus_Info() { TAudioStatus h; TOpcode OpC; TQChannelInfo ChannelInfo; BOOL b; memset(&ChannelInfo,0,sizeof(ChannelInfo)); OpC[0]=0x42; OpC[1]=0x02; OpC[2]=0x40; OpC[3]=0x01; OpC[4]=0x00; OpC[5]=0x00; OpC[6]=0x00; OpC[7]=0x00; OpC[8]=0x10; OpC[9]=0x00; h.Pause=FALSE; h.IsPlaying=FALSE; h.IsDone=FALSE; h.PlayError=FALSE; if (MapInfo.GetTypMapping(Config.Type)==CDTYPE_ATAPI) { OpC[10]=0; OpC[11]=0; b=ExecuteSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,SRB_DIR_IN,OpC,12,(void *)&ChannelInfo,16,m_hDriveEvent); } else b=ExecuteSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,SRB_DIR_IN,OpC,10,(void *)&ChannelInfo,16,m_hDriveEvent); if (b && ChannelInfo.DataLen) { // if (!CDPresentLast) Changed=TRUE; // CDPresentLast=TRUE; switch (ChannelInfo.AudioStatus) { case 0x11 : h.IsPlaying=TRUE; break; case 0x12 : h.Pause=TRUE; break; case 0x13 : h.IsDone=TRUE; break; case 0x14 : h.PlayError=TRUE; break; } h.AbsSektor.SetRedbook(ChannelInfo.AbsCDAdress); h.RelSektor.SetRedbook(ChannelInfo.RelTrackAdress); h.TrackNummer=ChannelInfo.TrackNumber; } else { // if (CDPresentLast) Changed=TRUE; // CDPresentLast=FALSE; h.PlayError=TRUE; Error=CDNoCD; } return h; } void CSCSICD::Get_MediaCatalogNumber(char szUPC[16]) { TOpcode OpC; BYTE Info[24] = {0}; BOOL b; szUPC[0]=0; OpC[0]=0x42; OpC[1]=0x02; OpC[2]=0x40; OpC[3]=0x02; OpC[4]=0x00; OpC[5]=0x00; OpC[6]=0x00; OpC[7]=0x00; OpC[8]=sizeof(Info); OpC[9]=0x00; if (MapInfo.GetTypMapping(Config.Type)==CDTYPE_ATAPI) { OpC[10]=0; OpC[11]=0; b=ExecuteSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,SRB_DIR_IN,OpC,12,(void *)&Info,sizeof(Info),m_hDriveEvent); } else b=ExecuteSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,SRB_DIR_IN,OpC,10,(void *)&Info,sizeof(Info),m_hDriveEvent); if (b && (Info[8]&0x80)) { BOOL bIsEmpty=TRUE; for (int i=0; i<15; i++) { BYTE Value=Info[i+9]; if (Value) bIsEmpty=FALSE; if (Value<10) Value+=0x30; szUPC[i]=Value; } szUPC[15]=0; if (bIsEmpty) szUPC[0]=0; } } void CSCSICD::EjectDisk() { TOpcode OpC; OpC[0]=0x1b; OpC[1]=0x00; OpC[2]=0x00; OpC[3]=0x00; OpC[4]=0x02; OpC[5]=0x00; if (!ExecuteSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,0,OpC,6,NULL,0,m_hDriveEvent)) Error=CDDriveNotReady; } void CSCSICD::LockDoor(int Lock) { TOpcode OpC; OpC[0]=0x1e; OpC[1]=0x00; OpC[2]=0x00; OpC[3]=0x00; OpC[4]=((BYTE) Lock) & 1; OpC[5]=0x00; if (!ExecuteSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,0,OpC,6,NULL,0,m_hDriveEvent)) Error=CDDriveNotReady; } void CSCSICD::CloseTray() { TOpcode OpC; OpC[0]=0x1b; OpC[1]=0x00; OpC[2]=0x00; OpC[3]=0x00; OpC[4]=0x03; OpC[5]=0x00; if (!ExecuteSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,0,OpC,6,NULL,0,m_hDriveEvent)) Error=CDDriveNotReady; } int Swap(int value) { int result=(value & 0xff000000)>>24; result|=(value & 0x00ff0000)>>8; result|=(value & 0x0000ff00)<<8; result|=(value & 0x000000ff)<<24; return result; } void CSCSICD::ReRead() { DeleteTrackList(); m_bSpeedTableInitialized=FALSE; TTOCHeader TOCHeader; memset(&TOCHeader,0,sizeof(TOCHeader)); TOpcode OpC; OpC[0]=0x43; OpC[1]=0; OpC[2]=0; OpC[3]=0; OpC[4]=0; OpC[5]=0; OpC[6]=0; OpC[7]=HIBYTE(sizeof(TTOCHeader)); OpC[8]=LOBYTE(sizeof(TTOCHeader)); OpC[9]=0; BOOL r=ExecuteSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,SRB_DIR_IN,OpC,10,(void*)&TOCHeader,sizeof(TOCHeader),m_hDriveEvent); if (r && TOCHeader.FirstTrack && TOCHeader.LastTrack) { TTrackListeMem *Last; CCDAdress Ende; Last=FirstTrack; for (int i=TOCHeader.FirstTrack; i<=TOCHeader.LastTrack; i++) { AktTrack=new TTrackListeMem; //AbsCDAdress //AdrCtrl AktTrack->Info.TrackNummer=TOCHeader.Info[i-1].TrackNummer; AktTrack->Info.StartSektor.SetHSG(Swap(TOCHeader.Info[i-1].AbsCDAdress)+150); Ende.SetHSG(Swap(TOCHeader.Info[i].AbsCDAdress)+150); AktTrack->Info.Laenge=Ende.GetHSG()-AktTrack->Info.StartSektor.GetHSG(); AktTrack->Info.StartSektor.SetHSG(AktTrack->Info.StartSektor.GetHSG()-150); if (TOCHeader.Info[i-1].AdrCtrl & 8) AktTrack->Info.Flags.AudioChannels=4; else AktTrack->Info.Flags.AudioChannels=2; AktTrack->Info.Flags.PreEmphasis=(TOCHeader.Info[i-1].AdrCtrl & 1); AktTrack->Info.Flags.DataTrack=(TOCHeader.Info[i-1].AdrCtrl & 4); AktTrack->Info.Flags.CopyProhibeted=!(TOCHeader.Info[i-1].AdrCtrl & 2); AktTrack->Prev=Last; AktTrack->Next=0; if (FirstTrack) Last->Next=AktTrack; else FirstTrack=AktTrack; Last=AktTrack; } // check for CD-Extra if (AktTrack) { if (AktTrack->Info.Flags.DataTrack) { Last=AktTrack->Prev; if (Last && !Last->Info.Flags.DataTrack) { if (Last->Info.Laenge>11400) Last->Info.Laenge-=11400; } } } } else { if (CDPresentLast) Changed=TRUE; CDPresentLast=FALSE; Error=CDDriveNotReady; } } CCDAdress CSCSICD::GetLastReadableAddress(CCDAdress StartSektor) { CCDAdress LastSektor; BYTE RetVal[8] = {0}; TOpcode OpC; OpC[0]=0x25; OpC[1]=0; OpC[2]=HIBYTE(HIWORD(StartSektor.GetHSG())); OpC[3]=LOBYTE(HIWORD(StartSektor.GetHSG())); OpC[4]=HIBYTE(LOWORD(StartSektor.GetHSG())); OpC[5]=LOBYTE(LOWORD(StartSektor.GetHSG())); OpC[6]=0; OpC[7]=0; OpC[8]=1; //Set PMI Bit OpC[9]=0; BOOL r=ExecuteSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,SRB_DIR_IN,OpC,10,(void*)&RetVal,sizeof(RetVal),m_hDriveEvent); if (!r) return StartSektor; LastSektor.SetHSG((RetVal[0]<<24)+(RetVal[1]<<16)+(RetVal[2]<<8)+RetVal[3]); return LastSektor; } int CSCSICD::GetMaxSektors() { return Config.MaxSektors; }; int CSCSICD::GetSynchSektors() { return Config.SynchSektors; }; int CSCSICD::GetMode() { return Config.Mode; }; int CSCSICD::GetSpeed() { return Config.Speed; }; TSenseInfo CSCSICD::GetSense() { TSenseInfo SenseInfo; memset(&SenseInfo,0,sizeof(SenseInfo)); TOpcode OpC; OpC[0]=0x03; OpC[1]=0; OpC[2]=0; OpC[3]=0; OpC[4]=sizeof(SenseInfo); OpC[5]=0; BOOL r=ExecuteSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,SRB_DIR_IN,OpC,6,(void*)&SenseInfo,sizeof(SenseInfo),m_hDriveEvent); if (!r) memset(&SenseInfo,0,sizeof(SenseInfo)); return SenseInfo; } TSenseInfo CSCSICD::GetLastSenseInfo() { TSenseInfo Info=m_SenseInfo; memset(&m_SenseInfo,0,sizeof(TSenseInfo)); return Info; } void CSCSICD::InitSpeedTable() { if (m_bSpeedTableInitialized) return; SupportedSpeeds=0; switch (MapInfo.GetTypMapping(Config.Type)) { case CDTYPE_TOSHIBA : break; case CDTYPE_TOSHNEW : { SpeedTable[0]=2352*75; SpeedTable[1]=2352*75*4; SpeedTable[2]=2352*75*4; SpeedTable[3]=-2; SupportedSpeeds=4; break; } case CDTYPE_SONY : case CDTYPE_RICOH : case CDTYPE_ATAPI : case CDTYPE_CYBERDRV : { int LastSpeed=GetCurrentSpeed(); int Speed=65532000; BOOL bFound=FALSE; while (!bFound && (Speed>0)) { SetCurrentSpeed(Speed); if (Lasterror()==CDOK) { int ResultingSpeed=GetCurrentSpeed(); if (Lasterror()==CDOK) { bFound=FALSE; for (int i=0; i1) { //Swap entries for (int i=0; i<(SupportedSpeeds/2); i++) { int Help=SpeedTable[i]; SpeedTable[i]=SpeedTable[SupportedSpeeds-1-i]; SpeedTable[SupportedSpeeds-1-i]=Help; } } SetCurrentSpeed(LastSpeed); break; } case CDTYPE_PLEXTOR : { int LastSpeed=GetCurrentSpeed(); for (int index=1; index<=20; index++) { SetCurrentSpeed(index*2352*75); if (Lasterror()==CDOK) { int Speed=GetCurrentSpeed(); if (Lasterror()==CDOK) { BOOL found=FALSE; for (int i=0; iProductID,"2000")) bResult=TRUE; if (strstr(pConfig->ProductID,"4020")) bResult=TRUE; return bResult; } //return the identifictaion number for the plextor models //defined values: #define PX4X 0 #define PX6X 1 #define PX8X 2 #define PX12X 3 #define PX20X 4 #define PX32X 5 #define PXR412 6 #define PX40X 7 DWORD GetPlextorModel(TDriveInfo *pConfig) { DWORD dwResult=PX40X; char szId[7] = {0}; strncpy(szId,&pConfig->ProductID[10],6); szId[6]=0; if (!_stricmp(szId,"W4220T")) { dwResult=PXR412; } else { if (!_stricmp(szId,"W8220T")) { dwResult=PXR412; } else { szId[5]=0; if (!_stricmp(szId,"R412C")) { dwResult=PXR412; } else { if (!_stricmp(szId,"R820T")) { dwResult=PXR412; } else { szId[2]=0; if (!strcmp(szId,"40")) dwResult=PX40X; else { if (!strcmp(szId,"32")) dwResult=PX32X; else { if (!strcmp(szId,"20")) dwResult=PX20X; else { if (!strcmp(szId,"12")) dwResult=PX12X; else { if (!isdigit(szId[1])) szId[1]=0; if (!strcmp(szId,"8")) dwResult=PX8X; else { if (!strcmp(szId,"6")) dwResult=PX6X; else { if (!strcmp(szId,"4")) dwResult=PX4X; } } } } } } } } } } return dwResult; } int CSCSICD::GetCurrentSpeed() { TDriveMode ModeSenseData; int Speed=0; switch (MapInfo.GetTypMapping(Config.Type)) { case CDTYPE_TOSHIBA : { Speed=0; break; } case CDTYPE_TOSHNEW : { if (!ModeSense(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeSenseData,15,0x20,m_hDriveEvent)) { Error=CDASPIError; return 0; } int Index=(ModeSenseData[14] & 0x30)>>4; switch (Index) { case 0 : Speed=2352*75; break; case 1 : Speed=2352*75*4; break; case 2 : Speed=2352*75*4; break; case 3 : Speed=-2; break; } break; } case CDTYPE_SONY : case CDTYPE_RICOH : case CDTYPE_CYBERDRV : { if (!ModeSense(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeSenseData,34,0x2A,m_hDriveEvent)) { Error=CDASPIError; return 0; } Speed=(ModeSenseData[26]*256+ModeSenseData[27])*1000; break; } case CDTYPE_ATAPI : { if (!ATAPIModeSense(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeSenseData,34,0x2A,m_hDriveEvent)) { Error=CDASPIError; return 0; } if ((ModeSenseData[8]&0x3F)==0x2A) Speed=(ModeSenseData[22]*256+ModeSenseData[23])*1000; else if ((ModeSenseData[4]&0x3F)==0x2A) Speed=(ModeSenseData[18]*256+ModeSenseData[19])*1000; else Speed=-1; break; } case CDTYPE_PLEXTOR : { DWORD dwModel=GetPlextorModel(&Config); if (dwModel!=PXR412) { if (!ModeSense(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeSenseData,16,0x31,m_hDriveEvent)) { Error=CDASPIError; return 0; } int Index=ModeSenseData[14]; switch (dwModel) { case PX4X : { switch (Index) { case 0 : Speed=2352*75; break; case 1 : Speed=2352*75*2; break; case 2 : Speed=2352*75*4; break; default : Speed=-1; break; } break; } case PX6X : { switch (Index) { case 0 : Speed=2352*75; break; case 1 : Speed=2352*75*4; break; case 2 : Speed=2352*75*6; break; default : Speed=-1; break; } break; } case PX8X : { switch (Index) { case 0 : Speed=2352*75; break; case 1 : Speed=2352*75*2; break; case 2 : Speed=2352*75*4; break; case 3 : Speed=2352*75*8; break; default : Speed=-1; break; } break; } case PX12X : { switch (Index) { case 0 : Speed=2352*75; break; case 1 : Speed=2352*75*2; break; case 2 : Speed=2352*75*4; break; case 3 : Speed=2352*75*8; break; case 4 : Speed=2352*75*8; break; case 5 : Speed=2352*75*12; break; default : Speed=-1; break; } break; } case PX20X : { switch (Index) { case 0 : Speed=2352*75; break; case 1 : Speed=2352*75*2; break; case 2 : Speed=2352*75*4; break; case 3 : Speed=2352*75*8; break; case 4 : Speed=2352*75*8; break; case 5 : Speed=-2; break; case 6 : Speed=2352*75*12; break; default : Speed=-1; break; } break; } case PX32X : { switch (Index) { case 0 : Speed=2352*75; break; case 1 : Speed=2352*75*2; break; case 2 : Speed=2352*75*4; break; case 3 : Speed=2352*75*8; break; case 4 : Speed=2352*75*8; break; case 5 : Speed=2352*75*8; break; case 6 : Speed=2352*75*14; break; default : Speed=-1; break; } break; } case PX40X : { switch (Index) { case 0 : Speed=2352*75; break; case 1 : Speed=2352*75*2; break; case 2 : Speed=2352*75*4; break; case 3 : Speed=2352*75*8; break; case 4 : Speed=2352*75*8; break; case 5 : Speed=2352*75*10; break; case 6 : Speed=2352*75*17; break; default : Speed=-1; break; } break; } } } else { if (!ModeSense(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeSenseData,32,0x2A,m_hDriveEvent)) { Error=CDASPIError; return 0; } Speed=(ModeSenseData[26]*256+ModeSenseData[27])*1000; } break; } case CDTYPE_NEC : { if (!addModeSense(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeSenseData,12,m_hDriveEvent)) { Error=CDASPIError; return 0; } // Speed=ModeSenseData[6] & 0x20; break; } case CDTYPE_PHILIPS : case CDTYPE_MATSHITA : { if (!ModeSense(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeSenseData,20,0x23,m_hDriveEvent)) { Error=CDASPIError; return 0; } int Index; if (IsOldPhilips(&Config)) Index=ModeSenseData[14]; else Index=ModeSenseData[16]; switch (Index) { case 0 : Speed=-1; break; case 1 : Speed=2352*75; break; case 2 : Speed=2352*75*2; break; case 4 : Speed=2352*75*4; break; case 6 : Speed=2352*75*6; break; case 8 : Speed=2352*75*8; break; default : Speed=-2; } break; } default : Speed=0; } return Speed; } void CSCSICD::SetCurrentSpeed(int Speed) { TDriveMode ModeSenseData; if (Speed==0) return; switch (MapInfo.GetTypMapping(Config.Type)) { case CDTYPE_TOSHIBA : break; case CDTYPE_TOSHNEW : { if (!ModeSense(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeSenseData,15,0x20,m_hDriveEvent)) { Error=CDASPIError; return; } ModeSenseData[0]=0; int Index; switch (Speed) { case -2 : Index=3; break; case 2352*75 : Index=0; break; case 2352*75*4 : Index=1; break; default : Index=2; } ModeSenseData[14]=(ModeSenseData[14] & 0xcf)|(Index<<4); if (!ModeSelect(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeSenseData,15,m_hDriveEvent)) Error=CDASPIError; break; } case CDTYPE_SONY : case CDTYPE_RICOH : case CDTYPE_CYBERDRV : case CDTYPE_ATAPI : { TOpcode OpC; OpC[0]=0xbb; OpC[1]=0x00; OpC[4]=0x00; OpC[5]=0x00; OpC[6]=0x00; OpC[7]=0x00; OpC[8]=0x00; OpC[9]=0x00; OpC[10]=0x00; OpC[11]=0x00; int NewSpeed=Speed/1000; int ModSpeed=NewSpeed*1000; int Direction=0; int AktSpeed=0; int Counter=0; do { Error=CDOK; Counter++; NewSpeed+=Direction; OpC[2]=NewSpeed/256; OpC[3]=NewSpeed%256; if (!ExecuteSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,SRB_DIR_OUT,OpC,12,NULL,0,m_hDriveEvent)) Error=CDASPIError; // Is the speed really the one we have selected? AktSpeed=GetCurrentSpeed(); if (!Direction) { if (AktSpeedSpeed) Direction=-1; } } while ((AktSpeed!=ModSpeed) && NewSpeed && (Counter<3)); break; } case CDTYPE_PLEXTOR : { DWORD dwModel=GetPlextorModel(&Config); if (dwModel!=PXR412) { if (!ModeSense(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeSenseData,16,0x31,m_hDriveEvent)) { Error=CDASPIError; return; } int Index; switch (dwModel) { case PX4X : { switch (Speed) { case 2352*75 : Index=0; break; case 2352*75*2 : Index=1; break; case -1 : case 2352*75*4 : Index=2; break; default : Index=-1; break; } break; } case PX6X : { switch (Speed) { case 2352*75 : Index=0; break; case 2352*75*4 : Index=1; break; case -1 : case 2352*75*6 : Index=2; break; default : Index=-1; break; } break; } case PX8X : { switch (Speed) { case 2352*75 : Index=0; break; case 2352*75*2 : Index=1; break; case 2352*75*4 : Index=2; break; case -1 : case 2352*75*8 : Index=3; break; default : Index=-1; break; } break; } case PX12X : { switch (Speed) { case 2352*75 : Index=0; break; case 2352*75*2 : Index=1; break; case 2352*75*4 : Index=2; break; case 2352*75*8 : Index=3; break; case -1 : case 2352*75*12 : Index=5; break; default : Index=-1; break; } break; } case PX20X : { switch (Speed) { case 2352*75 : Index=0; break; case 2352*75*2 : Index=1; break; case 2352*75*4 : Index=2; break; case 2352*75*8 : Index=3; break; case -1 : case 2352*75*12 : Index=6; break; default : Index=-1; break; } break; } case PX32X : { switch (Speed) { case 2352*75 : Index=0; break; case 2352*75*2 : Index=1; break; case 2352*75*4 : Index=2; break; case 2352*75*8 : Index=3; break; case -1 : case 2352*75*14 : Index=6; break; default : Index=-1; break; } break; } case PX40X : { switch (Speed) { case 2352*75 : Index=0; break; case 2352*75*2 : Index=1; break; case 2352*75*4 : Index=2; break; case 2352*75*8 : Index=3; break; case 2352*75*10 : Index=5; break; case -1 : case 2352*75*17 : Index=6; break; default : Index=-1; break; } break; } } if (Index>=0) { ModeSenseData[14]=Index; if (!ModeSelect(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeSenseData,16,m_hDriveEvent)) Error=CDASPIError; } else Error=CDASPIError; } else { TOpcode OpC; OpC[0]=0xbb; OpC[1]=0x00; OpC[4]=0xff; OpC[5]=0xff; OpC[6]=0x00; OpC[7]=0x00; OpC[8]=0x00; OpC[9]=0x00; OpC[10]=0x00; OpC[11]=0x00; int NewSpeed=Speed/1000; int ModSpeed=NewSpeed*1000; int Direction=0; int AktSpeed=0; int Counter=0; do { Error=CDOK; Counter++; NewSpeed+=Direction; OpC[2]=NewSpeed/256; OpC[3]=NewSpeed%256; if (!ExecuteSCSIRequest(Config.HostAdapterNumber,Config.ID,Config.LUN,SRB_DIR_OUT,OpC,12,NULL,0,m_hDriveEvent)) Error=CDASPIError; // Is the speed really the one we have selected? AktSpeed=GetCurrentSpeed(); if (!Direction) { if (AktSpeedSpeed) Direction=-1; } } while ((AktSpeed!=ModSpeed) && NewSpeed && (Counter<3)); } break; } case CDTYPE_NEC : { if (!addModeSense(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeSenseData,12,m_hDriveEvent)) { Error=CDASPIError; return; } // Speed=ModeSenseData[6] & 0x20; if (!addModeSelect(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeSenseData,12,m_hDriveEvent)) Error=CDASPIError; break; } case CDTYPE_PHILIPS : case CDTYPE_MATSHITA : { if (!ModeSense(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeSenseData,20,0x23,m_hDriveEvent)) { Error=CDASPIError; return; } ModeSenseData[0]=0; int Index; switch (Speed) { case -2 : case -1 : Index=0; break; case 2352*75 : Index=1; break; case 2352*75*2 : Index=2; break; case 2352*75*4 : Index=4; break; case 2352*75*6 : Index=6; break; case 2352*75*8 : Index=8; break; default : Index=0; } if (IsOldPhilips(&Config)) ModeSenseData[14]=Index; else ModeSenseData[16]=Index; if (!ModeSelect(Config.HostAdapterNumber,Config.ID,Config.LUN,ModeSenseData,20,m_hDriveEvent)) Error=CDASPIError; break; } } } int CSCSICD::GetSpeed(BYTE Index) { if (Index