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