DOSBox-X
|
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 *)⊂ 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