DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator
src/dos/cdrom_aspi_win32.cpp
00001 /*
00002  *  Copyright (C) 2002-2015  The DOSBox Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  */
00018 
00019 
00020 #if defined (WIN32) && 0
00021 
00022 #include <ctype.h>
00023 
00024 #include "dosbox.h"
00025 #include "cdrom.h"
00026 #include "support.h"
00027 
00028 //Are actually system includes but leave for now
00029 #include "wnaspi32.h"
00030 
00031 #if defined (_MSC_VER)
00032 #include <ntddcdrm.h>                   // Ioctl stuff
00033 #include <ntddscsi.h>
00034 #include <winioctl.h>                   // Ioctl stuff
00035 #else 
00036 #ifdef __MINGW64_VERSION_MAJOR
00037 #include <winioctl.h>
00038 #endif
00039 #include "ddk/ntddcdrm.h"               // Ioctl stuff
00040 #include "ddk/ntddscsi.h"
00041 #endif
00042 
00043 #include "scsidefs.h"
00044 
00045 // always use a buffer of the maximum struct size (like the union of all 'SRB_*' struct types)
00046 // Thanx SaPu
00047 typedef union {
00048         SRB_HAInquiry       hainquiry;
00049         SRB_GDEVBlock       gdevblock;
00050         SRB_ExecSCSICmd     execscsicmd;
00051         SRB_Abort           abort;
00052         SRB_BusDeviceReset  busdevicereset;
00053         SRB_GetDiskInfo     getdiskinfo;
00054         SRB_RescanPort      rescanport;
00055         SRB_GetSetTimeouts  getsettimeouts;
00056 } ASPI_SRB;
00057 
00058 // *****************************************************************
00059 // Windows ASPI functions (should work for all WIN with ASPI layer)
00060 // *****************************************************************
00061 
00062 CDROM_Interface_Aspi::CDROM_Interface_Aspi(void)
00063 {
00064         hASPI                                   = NULL;
00065         hEvent                                  = NULL;
00066         pGetASPI32SupportInfo   = NULL;
00067         pSendASPI32Command              = NULL;
00068         memset(&oldLeadOut,0,sizeof(oldLeadOut));
00069 };
00070 
00071 CDROM_Interface_Aspi::~CDROM_Interface_Aspi(void)
00072 {
00073         // Stop Audio
00074         StopAudio();
00075 
00076         pGetASPI32SupportInfo   = NULL; // clear funcs
00077         pSendASPI32Command              = NULL;
00078 
00079         if (hASPI) {                                    // free aspi
00080                 FreeLibrary(hASPI);
00081                 hASPI=NULL;
00082         }
00083 };
00084 
00085 bool GetRegistryValue(HKEY& hKey,char* valueName, char* buffer, ULONG bufferSize)
00086 // hKey has to be open
00087 {       
00088         // Read subkey
00089         ULONG valType;
00090         ULONG result;
00091         result = RegQueryValueEx(hKey,valueName,NULL,&valType,(unsigned char*)&buffer[0],&bufferSize);
00092         return (result == ERROR_SUCCESS);
00093 };
00094 
00095 BYTE CDROM_Interface_Aspi::GetHostAdapter(char* hardwareID)
00096 {
00097         ASPI_SRB sh;
00098         ASPI_SRB sd;
00099         DWORD d         = pGetASPI32SupportInfo();
00100         int cnt         = LOBYTE(LOWORD(d));
00101         int i,j,k,max;
00102 
00103         for(i=0; i<cnt; i++) {
00104                 memset(&sh, 0, sizeof(sh));
00105                 sh.hainquiry.SRB_Cmd  = SC_HA_INQUIRY;
00106                 sh.hainquiry.SRB_HaId = i;
00107                 pSendASPI32Command((LPSRB)&sh);
00108                 if (sh.hainquiry.SRB_Status!=SS_COMP) continue;
00109                 
00110                 // Indicates the maximum number of targets the adapter supports
00111                 // If the value is not 8 or 16, then it should be assumed max target is 8
00112                 max = (int)sh.hainquiry.HA_Unique[3];
00113                 if ((max!=8) && (max!=16)) max = 8;
00114                 
00115                 for(j=0; j<max; j++) {
00116                         for(k=0; k<8; k++) {
00117                                 memset(&sd, 0, sizeof(sd));
00118                                 sd.gdevblock.SRB_Cmd    = SC_GET_DEV_TYPE;
00119                                 sd.gdevblock.SRB_HaId   = i;
00120                                 sd.gdevblock.SRB_Target = j;
00121                                 sd.gdevblock.SRB_Lun    = k;
00122                                 pSendASPI32Command((LPSRB)&sd);
00123                                 if (sd.gdevblock.SRB_Status == SS_COMP) {
00124                                         if (sd.gdevblock.SRB_DeviceType == DTYPE_CDROM) {                                               
00125                                                 if ((target==j) && (lun==k)) {
00126                                                         LOG(LOG_MISC,LOG_NORMAL)("SCSI: Getting Hardware vendor.");                                                             
00127                                                         // "Hardware ID = vendor" match ?
00128                                                         char vendor[64];
00129                                                         if (GetVendor(i,target,lun,vendor)) {
00130                                                                 LOG(LOG_MISC,LOG_NORMAL)("SCSI: Vendor : %s",vendor);   
00131                                                                 if (strstr(strupr(hardwareID),strupr(vendor))) {
00132                                                                         LOG(LOG_MISC,LOG_NORMAL)("SCSI: Host Adapter found: %d",i);                                                             
00133                                                                         return i;                                                               
00134                                                                 }
00135                                                         };
00136                                                 }
00137                                         }
00138                                 }
00139                         }
00140                 }
00141         }
00142         LOG(LOG_MISC,LOG_ERROR)("SCSI: Host Adapter not found: %d",i);                                                                  
00143         return 0;
00144 };
00145 
00146 bool CDROM_Interface_Aspi::ScanRegistryFindKey(HKEY& hKeyBase)
00147 // hKey has to be open
00148 {
00149         FILETIME        time;
00150         ULONG           result,newKeyResult;
00151         char            subKey[256];
00152         char            buffer[256];
00153         ULONG           subKeySize = 256;
00154         HKEY            hNewKey;
00155         
00156         ULONG index = 0;
00157         do {
00158                 result = RegEnumKeyEx (hKeyBase,index,&subKey[0],&subKeySize,NULL,NULL,0,&time);
00159                 if (result==ERROR_SUCCESS) {
00160                         // Open Key...
00161                         newKeyResult = RegOpenKeyEx (hKeyBase,subKey,0,KEY_READ,&hNewKey);
00162                         if (newKeyResult==ERROR_SUCCESS) {
00163                                 static const char drive_letter_assignment[] = "CurrentDriveLetterAssignment";
00164                                 if (GetRegistryValue(hNewKey,(char*)&drive_letter_assignment,buffer,256)) {
00165                                         LOG(LOG_MISC,LOG_NORMAL)("SCSI: Drive Letter found: %s",buffer);                                        
00166                                         // aha, something suspicious...
00167                                         if (buffer[0]==letter) {
00168                                                 char hardwareID[256];
00169                                                 // found it... lets see if we can get the scsi values                           
00170                                                 static const char SCSI_LUN[] = "SCSILUN";
00171                                                 bool v1 = GetRegistryValue(hNewKey,(char*)SCSI_LUN,buffer,256);
00172                                                 LOG(LOG_MISC,LOG_NORMAL)("SCSI: SCSILUN found: %s",buffer);                                     
00173                                                 lun             = buffer[0]-'0';
00174                                                 static const char SCSI_TargetID[] = "SCSITargetID";
00175                                                 bool v2 = GetRegistryValue(hNewKey,(char*)SCSI_TargetID,buffer,256);
00176                                                 LOG(LOG_MISC,LOG_NORMAL)("SCSI: SCSITargetID found: %s",buffer);                                        
00177                                                 target  = buffer[0]-'0';
00178                                                 static const char Hardware_ID[] = "HardwareID";
00179                                                 bool v3 = GetRegistryValue(hNewKey,(char*)Hardware_ID,hardwareID,256);
00180                                                 RegCloseKey(hNewKey);
00181                                                 if (v1 && v2 && v3) {   
00182                                                         haId = GetHostAdapter(hardwareID);
00183                                                         return true;
00184                                                 };
00185                                         }
00186                                 };
00187                         };
00188                         RegCloseKey(hNewKey);
00189                 };
00190                 index++;
00191         } while ((result==ERROR_SUCCESS) || (result==ERROR_MORE_DATA));
00192         return false;
00193 };
00194 
00195 bool CDROM_Interface_Aspi::GetVendor(BYTE HA_num, BYTE SCSI_Id, BYTE SCSI_Lun, char* szBuffer) 
00196 {
00197         ASPI_SRB srbExec;
00198         //      SRB_ExecSCSICmd srbExec;
00199         memset ( &srbExec, 0, sizeof ( SRB_ExecSCSICmd ) );
00200 
00201         hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
00202 
00203         srbExec.execscsicmd.SRB_Cmd                     = SC_EXEC_SCSI_CMD ;
00204         srbExec.execscsicmd.SRB_HaId            = HA_num;
00205         srbExec.execscsicmd.SRB_Flags           = SRB_DIR_IN | SRB_EVENT_NOTIFY;
00206         srbExec.execscsicmd.SRB_Target          = SCSI_Id;
00207         srbExec.execscsicmd.SRB_Lun                     = SCSI_Lun;
00208         srbExec.execscsicmd.SRB_BufLen          = 36;
00209         srbExec.execscsicmd.SRB_BufPointer      = (unsigned char*)szBuffer;
00210         srbExec.execscsicmd.SRB_SenseLen        = SENSE_LEN;
00211         srbExec.execscsicmd.SRB_CDBLen          = 6;
00212         srbExec.execscsicmd.SRB_PostProc        = (LPVOID)hEvent;
00213         srbExec.execscsicmd.CDBByte [ 0 ]       = SCSI_INQUIRY;
00214         srbExec.execscsicmd.CDBByte [ 4 ]       = 36;  // allocation length per szBuffer [ ]
00215 
00216         ResetEvent(hEvent);
00217         int dwStatus = pSendASPI32Command ((LPSRB)&srbExec);
00218 //      LOG(LOG_MISC|LOG_ERROR,"SCSI: Get vendor command send");                                        
00219         
00220         if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,30000);
00221 //      LOG(LOG_MISC|LOG_ERROR,"SCSI: Pending done.");                                  
00222 
00223         CloseHandle(hEvent);
00224         if (srbExec.execscsicmd.SRB_Status != SS_COMP) {
00225                 strcpy (szBuffer, "error" );
00226                 return false;
00227         } else {
00228                 safe_strncpy(szBuffer,szBuffer+8,26);
00229                 size_t len = strlen(szBuffer);
00230                 for (size_t i=0; i<len; i++) if (szBuffer[i]<=32) szBuffer[i]='_';
00231         }
00232         return true;
00233 }
00234 
00235 bool CDROM_Interface_Aspi::ScanRegistry(HKEY& hKeyBase)
00236 // hKey has to be open
00237 {
00238         FILETIME        time;
00239         ULONG           result,newKeyResult;
00240         char            subKey[256];
00241         ULONG           subKeySize= 256;
00242         HKEY            hNewKey;
00243         
00244         ULONG index = 0;
00245         do {
00246                 result = RegEnumKeyEx (hKeyBase,index,&subKey[0],&subKeySize,NULL,NULL,0,&time);
00247                 if ((result==ERROR_SUCCESS) || (result==ERROR_MORE_DATA)) {
00248                         // Open Key...
00249                         newKeyResult = RegOpenKeyEx (hKeyBase,subKey,0,KEY_READ,&hNewKey);
00250                         if (newKeyResult==ERROR_SUCCESS) {
00251                                 bool found = ScanRegistryFindKey(hNewKey);
00252                                 RegCloseKey(hNewKey);
00253                                 if (found) return true;
00254                         };
00255                         RegCloseKey(hNewKey);
00256                 };
00257                 index++;
00258         } while ((result==ERROR_SUCCESS) || (result==ERROR_MORE_DATA));
00259         return false;
00260 };
00261 
00262 bool CDROM_Interface_Aspi::SetDevice(char* path, int forceCD)
00263 {
00264         // load WNASPI32.DLL
00265         hASPI = LoadLibrary ( "WNASPI32.DLL" );
00266         if (!hASPI) return false;
00267         // Get Pointer to ASPI funcs
00268     pGetASPI32SupportInfo       = (DWORD(*)(void))GetProcAddress(hASPI,"GetASPI32SupportInfo");
00269     pSendASPI32Command          = (DWORD(*)(LPSRB))GetProcAddress(hASPI,"SendASPI32Command");
00270         if (!pGetASPI32SupportInfo || !pSendASPI32Command) return false;
00271         // Letter
00272         letter = toupper(path[0]);
00273 
00274         // Check OS
00275         OSVERSIONINFO osi;
00276         osi.dwOSVersionInfoSize = sizeof(osi);
00277         GetVersionEx(&osi);
00278         if ((osi.dwPlatformId==VER_PLATFORM_WIN32_NT) && (osi.dwMajorVersion>4)) {
00279                 if (GetDriveType(path)==DRIVE_CDROM) {  
00280                         // WIN XP/NT/2000
00281                         int iDA,iDT,iDL;
00282                         letter = path[0];
00283                         HANDLE hF = OpenIOCTLFile(letter,FALSE);
00284                         GetIOCTLAdapter(hF,&iDA,&iDT,&iDL);
00285                         CloseHandle(hF);
00286                         // Set SCSI IDs
00287                         haId    = iDA;
00288                         target  = iDT;
00289                         lun             = iDL;
00290                         return true;
00291                 }
00292         } else {
00293                 // win 95/98/ME have to scan the registry...
00294                 // lets hope the layout is always the same... i dunno...
00295                 char key[2048];
00296                 HKEY hKeyBase;
00297                 bool found = false;
00298                 strcpy(key,"ENUM\\SCSI");
00299                 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,key,0,KEY_READ,&hKeyBase)==ERROR_SUCCESS) {
00300                         found = ScanRegistry(hKeyBase);
00301                 };      
00302                 RegCloseKey(hKeyBase);
00303                 return found;
00304         } 
00305         return false;
00306 };
00307 
00308 bool CDROM_Interface_Aspi::GetAudioTracks(int& stTrack, int& endTrack, TMSF& leadOut) 
00309 {
00310         TOC toc;
00311         if (GetTOC((LPTOC)&toc) == SS_COMP) {
00312                 stTrack         = toc.cFirstTrack;
00313                 endTrack        = toc.cLastTrack;
00314                 leadOut.min     = (unsigned char)(toc.tracks[endTrack].lAddr >>  8) &0xFF;
00315                 leadOut.sec     = (unsigned char)(toc.tracks[endTrack].lAddr >> 16) &0xFF;
00316                 leadOut.fr      = (unsigned char)(toc.tracks[endTrack].lAddr >> 24) &0xFF;
00317                 return true;
00318         }
00319         return false;
00320 };
00321 
00322 bool CDROM_Interface_Aspi::GetAudioTrackInfo    (int track, TMSF& start, unsigned char& attr)
00323 {
00324         TOC toc;
00325         if (GetTOC((LPTOC)&toc) == SS_COMP) {
00326                 start.min       = (unsigned char)(toc.tracks[track-1].lAddr >>  8) &0xFF;
00327                 start.sec       = (unsigned char)(toc.tracks[track-1].lAddr >> 16) &0xFF;
00328                 start.fr        = (unsigned char)(toc.tracks[track-1].lAddr >> 24) &0xFF;
00329                 attr            = (toc.tracks[track-1].cAdrCtrl << 4) & 0xEF;
00330                 return true;
00331         };              
00332         return false;
00333 };
00334 
00335 HANDLE CDROM_Interface_Aspi::OpenIOCTLFile(char cLetter,BOOL bAsync)
00336 {
00337         HANDLE hF;
00338         char szFName[16];
00339         OSVERSIONINFO ov;
00340         DWORD dwFlags;
00341         DWORD dwIOCTLAttr;
00342 //      if(bAsync) dwIOCTLAttr=FILE_FLAG_OVERLAPPED;
00343 //      else       
00344         dwIOCTLAttr=0;
00345 
00346         memset(&ov,0,sizeof(OSVERSIONINFO));
00347         ov.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
00348         GetVersionEx(&ov);
00349 
00350         if ((ov.dwPlatformId==VER_PLATFORM_WIN32_NT) && (ov.dwMajorVersion>4))
00351                 dwFlags = GENERIC_READ|GENERIC_WRITE;            // add gen write on W2k/XP
00352         else
00353                 dwFlags = GENERIC_READ;
00354 
00355         wsprintf(szFName, "\\\\.\\%c:",cLetter);
00356 
00357         hF=CreateFile(szFName,dwFlags,FILE_SHARE_READ,        // open drive
00358                                 NULL,OPEN_EXISTING,dwIOCTLAttr,NULL);
00359 
00360         if (hF==INVALID_HANDLE_VALUE) {
00361                 dwFlags^=GENERIC_WRITE;                         // mmm... no success
00362                 hF=CreateFile(szFName,dwFlags,FILE_SHARE_READ,      // -> open drive again
00363                                         NULL,OPEN_EXISTING,dwIOCTLAttr,NULL);
00364                 if (hF==INVALID_HANDLE_VALUE) return NULL;
00365         }
00366         return hF;                                          
00367 }
00368 
00369 void CDROM_Interface_Aspi::GetIOCTLAdapter(HANDLE hF,int * iDA,int * iDT,int * iDL)
00370 {
00371         char szBuf[1024];
00372         PSCSI_ADDRESS pSA;
00373         DWORD dwRet;
00374 
00375         *iDA=*iDT=*iDL=-1;
00376         if(hF==NULL) return;
00377 
00378         memset(szBuf,0,1024);
00379 
00380         pSA=(PSCSI_ADDRESS)szBuf;
00381         pSA->Length=sizeof(SCSI_ADDRESS);
00382                                                
00383         if(!DeviceIoControl(hF,IOCTL_SCSI_GET_ADDRESS,NULL,
00384                                          0,pSA,sizeof(SCSI_ADDRESS),
00385                                          &dwRet,NULL))
00386         return;
00387 
00388         *iDA = pSA->PortNumber;
00389         *iDT = pSA->TargetId;
00390         *iDL = pSA->Lun;
00391 }
00392 
00393 DWORD CDROM_Interface_Aspi::GetTOC(LPTOC toc)
00394 {
00395 //      SRB_ExecSCSICmd s;
00396         ASPI_SRB s;
00397         DWORD dwStatus;
00398 
00399         hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
00400 
00401         memset(&s,0,sizeof(s));
00402 
00403         s.execscsicmd.SRB_Cmd        = SC_EXEC_SCSI_CMD;
00404         s.execscsicmd.SRB_HaId       = haId;
00405         s.execscsicmd.SRB_Target     = target;
00406         s.execscsicmd.SRB_Lun        = lun;
00407         s.execscsicmd.SRB_Flags      = SRB_DIR_IN | SRB_EVENT_NOTIFY;
00408         s.execscsicmd.SRB_BufLen     = sizeof(*toc);
00409         s.execscsicmd.SRB_BufPointer = (BYTE FAR *)toc;
00410         s.execscsicmd.SRB_SenseLen   = SENSE_LEN;
00411         s.execscsicmd.SRB_CDBLen     = 0x0A;
00412         s.execscsicmd.SRB_PostProc   = (LPVOID)hEvent;
00413         s.execscsicmd.CDBByte[0]     = SCSI_READ_TOC;
00414         s.execscsicmd.CDBByte[1]     = 0x02; // 0x02 for MSF
00415         s.execscsicmd.CDBByte[7]     = 0x03;
00416         s.execscsicmd.CDBByte[8]     = 0x24;
00417 
00418         ResetEvent(hEvent);
00419         dwStatus=pSendASPI32Command((LPSRB)&s);
00420 
00421         if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,30000);
00422 
00423         CloseHandle(hEvent);
00424 
00425         return (s.execscsicmd.SRB_Status==SS_COMP);
00426 }
00427 
00428 bool CDROM_Interface_Aspi::PlayAudioSector(unsigned long start,unsigned long len)
00429 {
00430 //      SRB_ExecSCSICmd s;
00431         ASPI_SRB s;
00432         DWORD dwStatus;
00433 
00434         hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
00435 
00436         memset(&s,0,sizeof(s));
00437         s.execscsicmd.SRB_Cmd        = SC_EXEC_SCSI_CMD;
00438         s.execscsicmd.SRB_HaId       = haId;
00439         s.execscsicmd.SRB_Target     = target;
00440         s.execscsicmd.SRB_Lun        = lun;
00441         s.execscsicmd.SRB_Flags      = SRB_DIR_IN | SRB_EVENT_NOTIFY;
00442         s.execscsicmd.SRB_BufLen     = 0;
00443         s.execscsicmd.SRB_BufPointer = 0;
00444         s.execscsicmd.SRB_SenseLen   = SENSE_LEN;
00445         s.execscsicmd.SRB_CDBLen     = 12;
00446         s.execscsicmd.SRB_PostProc   = (LPVOID)hEvent;
00447 
00448         s.execscsicmd.CDBByte[0]     = SCSI_PLAYAUD_12;
00449         s.execscsicmd.CDBByte[1]     = lun << 5;
00450         s.execscsicmd.CDBByte[2]     = (unsigned char)((start >> 24) & 0xFF);
00451         s.execscsicmd.CDBByte[3]     = (unsigned char)((start >> 16) & 0xFF);
00452         s.execscsicmd.CDBByte[4]     = (unsigned char)((start >> 8) & 0xFF);
00453         s.execscsicmd.CDBByte[5]     = (unsigned char)((start & 0xFF));
00454         s.execscsicmd.CDBByte[6]     = (unsigned char)((len >> 24) & 0xFF);
00455         s.execscsicmd.CDBByte[7]     = (unsigned char)((len >> 16) & 0xFF);
00456         s.execscsicmd.CDBByte[8]     = (unsigned char)((len >> 8) & 0xFF);
00457         s.execscsicmd.CDBByte[9]     = (unsigned char)(len & 0xFF);
00458 
00459         ResetEvent(hEvent);
00460 
00461         dwStatus = pSendASPI32Command((LPSRB)&s);
00462 
00463         if(dwStatus==SS_PENDING) WaitForSingleObject(hEvent,10000);
00464 
00465         CloseHandle(hEvent);
00466 
00467         return s.execscsicmd.SRB_Status==SS_COMP;
00468 }
00469 
00470 bool CDROM_Interface_Aspi::StopAudio(void)
00471 {
00472         return PauseAudio(false);
00473 };
00474 
00475 bool CDROM_Interface_Aspi::PauseAudio(bool resume)
00476 {
00477         //SRB_ExecSCSICmd s;
00478         ASPI_SRB s;
00479         DWORD dwStatus;
00480 
00481         hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
00482 
00483         memset(&s,0,sizeof(s));
00484 
00485         s.execscsicmd.SRB_Cmd        = SC_EXEC_SCSI_CMD;
00486         s.execscsicmd.SRB_HaId       = haId;
00487         s.execscsicmd.SRB_Target     = target;
00488         s.execscsicmd.SRB_Lun        = lun;
00489         s.execscsicmd.SRB_Flags      = SRB_DIR_IN | SRB_EVENT_NOTIFY;
00490         s.execscsicmd.SRB_BufLen     = 0x00;
00491         s.execscsicmd.SRB_SenseLen   = SENSE_LEN;
00492         s.execscsicmd.SRB_CDBLen     = 0x0A;
00493         s.execscsicmd.SRB_PostProc   = (LPVOID)hEvent;
00494         s.execscsicmd.CDBByte[0]     = 0x4B;
00495         s.execscsicmd.CDBByte[8]     = (unsigned char)resume;                           // Pause
00496 
00497         ResetEvent(hEvent);
00498         dwStatus=pSendASPI32Command((LPSRB)&s);
00499 
00500         if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,30000);
00501 
00502         CloseHandle(hEvent);
00503 
00504         return (s.execscsicmd.SRB_Status==SS_COMP);
00505 };
00506 
00507 bool CDROM_Interface_Aspi::GetAudioSub(unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos)
00508 {
00509         SUB_Q_CURRENT_POSITION pos;
00510 //      SRB_ExecSCSICmd s;
00511         ASPI_SRB s;
00512         DWORD dwStatus;
00513         
00514         hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
00515 
00516         memset(&s,0,sizeof(s));
00517 
00518         s.execscsicmd.SRB_Cmd        = SC_EXEC_SCSI_CMD;
00519         s.execscsicmd.SRB_HaId       = haId;
00520         s.execscsicmd.SRB_Target     = target;
00521         s.execscsicmd.SRB_Lun        = lun;
00522         s.execscsicmd.SRB_Flags      = SRB_DIR_IN | SRB_EVENT_NOTIFY;
00523         s.execscsicmd.SRB_SenseLen   = SENSE_LEN;
00524 
00525         s.execscsicmd.SRB_BufLen     = sizeof(pos);
00526         s.execscsicmd.SRB_BufPointer = (BYTE FAR *)&pos;
00527         s.execscsicmd.SRB_CDBLen     = 10;
00528         s.execscsicmd.SRB_PostProc   = (LPVOID)hEvent;
00529 
00530         s.execscsicmd.CDBByte[0]     = SCSI_SUBCHANNEL;
00531         s.execscsicmd.CDBByte[1]     = (lun<<5)|2;   // lun & msf
00532         s.execscsicmd.CDBByte[2]     = 0x40;            // subq
00533         s.execscsicmd.CDBByte[3]     = 0x01;            // curr pos info
00534         s.execscsicmd.CDBByte[6]     = 0;               // track number (only in isrc mode, ignored)
00535         s.execscsicmd.CDBByte[7]     = 0;               // alloc len
00536         s.execscsicmd.CDBByte[8]     = sizeof(pos);             
00537 
00538         ResetEvent(hEvent);
00539 
00540         dwStatus = pSendASPI32Command((LPSRB)&s);
00541 
00542         if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,0xFFFFFFFF);
00543 
00544         CloseHandle(hEvent);
00545         
00546         if (s.execscsicmd.SRB_Status!=SS_COMP) return false;
00547 
00548         attr            = (pos.Control<<4) &0xEF;
00549         track           = pos.TrackNumber;
00550         index           = pos.IndexNumber;
00551         absPos.min      = pos.AbsoluteAddress[1];
00552         absPos.sec      = pos.AbsoluteAddress[2];
00553         absPos.fr       = pos.AbsoluteAddress[3];
00554         relPos.min      = pos.TrackRelativeAddress[1];
00555         relPos.sec      = pos.TrackRelativeAddress[2];
00556         relPos.fr       = pos.TrackRelativeAddress[3];
00557         
00558         return true;
00559 };
00560 
00561 bool CDROM_Interface_Aspi::GetUPC(unsigned char& attr, char* upcdata)
00562 {
00563         SUB_Q_MEDIA_CATALOG_NUMBER upc;
00564         ASPI_SRB s;
00565         //SRB_ExecSCSICmd s;
00566         DWORD dwStatus;
00567 
00568         hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
00569 
00570         memset(&s,0,sizeof(s));
00571         
00572         s.execscsicmd.SRB_Cmd        = SC_EXEC_SCSI_CMD;
00573         s.execscsicmd.SRB_HaId       = haId;
00574         s.execscsicmd.SRB_Target     = target;
00575         s.execscsicmd.SRB_Lun        = lun;
00576         s.execscsicmd.SRB_Flags      = SRB_DIR_IN | SRB_EVENT_NOTIFY;
00577         s.execscsicmd.SRB_SenseLen   = SENSE_LEN;
00578 
00579         s.execscsicmd.SRB_BufLen     = sizeof(upc);
00580         s.execscsicmd.SRB_BufPointer = (BYTE FAR *)&upc;
00581         s.execscsicmd.SRB_CDBLen     = 10;
00582         s.execscsicmd.SRB_PostProc   = (LPVOID)hEvent;
00583 
00584         s.execscsicmd.CDBByte[0]     = SCSI_SUBCHANNEL;
00585         s.execscsicmd.CDBByte[1]     = (lun<<5)|2;   // lun & msf
00586         s.execscsicmd.CDBByte[2]     = 0x40;            // subq
00587         s.execscsicmd.CDBByte[3]     = 0x02;            // get upc
00588         s.execscsicmd.CDBByte[6]     = 0;               // track number (only in isrc mode, ignored)
00589         s.execscsicmd.CDBByte[7]     = 0;               // alloc len
00590         s.execscsicmd.CDBByte[8]     = sizeof(upc);             
00591 
00592         ResetEvent(hEvent);
00593 
00594         dwStatus = pSendASPI32Command((LPSRB)&s);
00595 
00596         if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,0xFFFFFFFF);
00597 
00598         CloseHandle(hEvent);
00599 
00600         if (s.execscsicmd.SRB_Status!=SS_COMP) return false;
00601 
00602 //      attr = (upc.ADR<<4) | upc.Control;
00603         attr    = 0;
00604         // Convert to mscdex format
00605         for (int i=0; i<7; i++) upcdata[i] = upc.MediaCatalog[i];
00606     for (int i=0; i<7; i++) upcdata[i] = (upc.MediaCatalog[i*2] << 4) | (upc.MediaCatalog[i*2+1] & 0x0F);
00607 
00608         return true;
00609 };
00610 
00611 bool CDROM_Interface_Aspi::GetAudioStatus(bool& playing, bool& pause)
00612 {
00613         playing = pause = false;
00614         
00615         SUB_Q_HEADER sub;
00616 //      SRB_ExecSCSICmd s;
00617         ASPI_SRB s;
00618         DWORD dwStatus;
00619 
00620         hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
00621 
00622         memset(&s,0,sizeof(s));
00623         
00624         s.execscsicmd.SRB_Cmd        = SC_EXEC_SCSI_CMD;
00625         s.execscsicmd.SRB_HaId       = haId;
00626         s.execscsicmd.SRB_Target     = target;
00627         s.execscsicmd.SRB_Lun        = lun;
00628         s.execscsicmd.SRB_Flags      = SRB_DIR_IN | SRB_EVENT_NOTIFY;
00629         s.execscsicmd.SRB_SenseLen   = SENSE_LEN;
00630 
00631         s.execscsicmd.SRB_BufLen     = sizeof(sub);
00632         s.execscsicmd.SRB_BufPointer = (BYTE FAR *)&sub;
00633         s.execscsicmd.SRB_CDBLen     = 10;
00634         s.execscsicmd.SRB_PostProc   = (LPVOID)hEvent;
00635 
00636         s.execscsicmd.CDBByte[0]     = SCSI_SUBCHANNEL;
00637         s.execscsicmd.CDBByte[1]     = (lun<<5)|2;   // lun & msf
00638         s.execscsicmd.CDBByte[2]     = 0x00;            // no subq
00639         s.execscsicmd.CDBByte[3]     = 0x00;            // dont care
00640         s.execscsicmd.CDBByte[6]     = 0;               // track number (only in isrc mode, ignored)
00641         s.execscsicmd.CDBByte[7]     = 0;               // alloc len
00642         s.execscsicmd.CDBByte[8]     = sizeof(sub);             
00643 
00644         ResetEvent(hEvent);
00645 
00646         dwStatus = pSendASPI32Command((LPSRB)&s);
00647 
00648         if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,0xFFFFFFFF);
00649 
00650         CloseHandle(hEvent);
00651 
00652         if (s.execscsicmd.SRB_Status!=SS_COMP) return false;
00653 
00654         playing                 = (sub.AudioStatus==0x11);
00655         pause                   = (sub.AudioStatus==0x12);
00656 
00657         return true;
00658 };
00659 
00660 bool CDROM_Interface_Aspi::LoadUnloadMedia(bool unload)
00661 {
00662         //SRB_ExecSCSICmd s;
00663         ASPI_SRB s;
00664         DWORD dwStatus;
00665 
00666         hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
00667 
00668         memset(&s,0,sizeof(s));
00669         
00670         s.execscsicmd.SRB_Cmd        = SC_EXEC_SCSI_CMD;
00671         s.execscsicmd.SRB_HaId       = haId;
00672         s.execscsicmd.SRB_Target     = target;
00673         s.execscsicmd.SRB_Lun        = lun;
00674         s.execscsicmd.SRB_Flags      = SRB_DIR_IN | SRB_EVENT_NOTIFY;
00675         s.execscsicmd.SRB_SenseLen   = SENSE_LEN;
00676 
00677         s.execscsicmd.SRB_BufLen     = 0;
00678         s.execscsicmd.SRB_BufPointer = 0;
00679         s.execscsicmd.SRB_CDBLen     = 6; // 14;
00680         s.execscsicmd.SRB_PostProc   = (LPVOID)hEvent;
00681 
00682         s.execscsicmd.CDBByte[0]     = SCSI_LOAD_UN;
00683         s.execscsicmd.CDBByte[1]     = (lun<<5)|1; // lun & immediate
00684         s.execscsicmd.CDBByte[4]     = (unload ? 0x02:0x03);            // unload/load media
00685         
00686         ResetEvent(hEvent);
00687 
00688         dwStatus = pSendASPI32Command((LPSRB)&s);
00689 
00690         if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,0xFFFFFFFF);
00691 
00692         CloseHandle(hEvent);
00693 
00694         if (s.execscsicmd.SRB_Status!=SS_COMP) return false;
00695 
00696         return true;
00697 };
00698 
00699 bool CDROM_Interface_Aspi::GetMediaTrayStatus(bool& mediaPresent, bool& mediaChanged, bool& trayOpen)
00700 {
00701         // Seems not possible to get this values using ioctl...
00702         int             track1,track2;
00703         TMSF    leadOut;
00704         // If we can read, there's a media
00705         mediaPresent = GetAudioTracks(track1, track2, leadOut),
00706         trayOpen         = !mediaPresent;
00707         mediaChanged = (oldLeadOut.min!=leadOut.min) || (oldLeadOut.sec!=leadOut.sec) || (oldLeadOut.fr!=leadOut.fr);
00708         // Save old values
00709         oldLeadOut.min = leadOut.min;
00710         oldLeadOut.sec = leadOut.sec;
00711         oldLeadOut.fr  = leadOut.fr;
00712         // always success
00713         return true;
00714 };
00715 
00716 bool CDROM_Interface_Aspi::ReadSectors(PhysPt buffer, bool raw, unsigned long sector, unsigned long num)
00717 {
00718         //SRB_ExecSCSICmd s;
00719         ASPI_SRB s;
00720         DWORD dwStatus;
00721 
00722         hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
00723 
00724         memset(&s,0,sizeof(s));
00725 
00726         Bitu   buflen   = raw?2352*num:2048*num;
00727         Bit8u* bufdata  = new Bit8u[buflen];
00728 
00729         s.execscsicmd.SRB_Cmd        = SC_EXEC_SCSI_CMD;
00730         s.execscsicmd.SRB_HaId       = haId;
00731         s.execscsicmd.SRB_Target     = target;
00732         s.execscsicmd.SRB_Lun        = lun;
00733         s.execscsicmd.SRB_Flags      = SRB_DIR_IN | SRB_EVENT_NOTIFY;
00734         s.execscsicmd.SRB_SenseLen   = SENSE_LEN;
00735 
00736         s.execscsicmd.SRB_BufLen     = buflen;
00737         s.execscsicmd.SRB_BufPointer = (BYTE FAR*)bufdata;
00738         s.execscsicmd.SRB_CDBLen     = 12;
00739         s.execscsicmd.SRB_PostProc   = (LPVOID)hEvent;
00740 
00741         s.execscsicmd.CDBByte[0]     = 0xBE;
00742         s.execscsicmd.CDBByte[2]     = (unsigned char)((sector >> 24) & 0xFF);
00743         s.execscsicmd.CDBByte[3]     = (unsigned char)((sector >> 16) & 0xFF);
00744         s.execscsicmd.CDBByte[4]     = (unsigned char)((sector >> 8) & 0xFF);
00745         s.execscsicmd.CDBByte[5]     = (unsigned char)((sector & 0xFF));
00746         s.execscsicmd.CDBByte[6]     = (unsigned char)((num >> 16) & 0xFF);
00747         s.execscsicmd.CDBByte[7]     = (unsigned char)((num >>  8) & 0xFF);
00748         s.execscsicmd.CDBByte[8]     = (unsigned char) (num & 0xFF);
00749         s.execscsicmd.CDBByte[9]         = (raw?0xF0:0x10);
00750 
00751         ResetEvent(hEvent);
00752 
00753         dwStatus = pSendASPI32Command((LPSRB)&s);
00754 
00755         if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,0xFFFFFFFF);
00756 
00757         CloseHandle(hEvent);
00758 
00759         // Copy to PhysPt
00760         MEM_BlockWrite(buffer,bufdata,buflen);
00761 
00762         delete[] bufdata;
00763 
00764         return (s.execscsicmd.SRB_Status==SS_COMP);
00765 };
00766 
00767 bool CDROM_Interface_Aspi::ReadSectorsHost(void *buffer, bool raw, unsigned long sector, unsigned long num)
00768 {
00769         return false;/*TODO*/
00770 };
00771 
00772 #endif