1 /*
2 * Copyright (C) 2002-2010 The DOSBox Team
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19 /* $Id: cdrom_aspi_win32.cpp,v 1.21 2009-05-27 09:15:41 qbix79 Exp $ */
20
21 #if defined (WIN32)
22
23 #include <ctype.h>
24
25 #include "dosbox.h"
26 #include "cdrom.h"
27 #include "support.h"
28
29 //Are actually system includes but leave for now
30 #include "wnaspi32.h"
31
32 #if defined (_MSC_VER)
33 #include <ntddcdrm.h> // Ioctl stuff
34 #include <ntddscsi.h>
35 #include <winioctl.h> // Ioctl stuff
36 #elif (defined __MINGW64_VERSION_MAJOR)
37 #include <winioctl.h> // Ioctl stuff
38 #include <ntddcdrm.h> // Ioctl stuff
39 #include <ntddscsi.h>
40 #else
41 #include "ddk/ntddcdrm.h" // Ioctl stuff
42 #include "ddk/ntddscsi.h"
43 #endif
44
45 #include "scsidefs.h"
46
47 // always use a buffer of the maximum struct size (like the union of all 'SRB_*' struct types)
48 // Thanx SaPu
49 typedef union {
50 SRB_HAInquiry hainquiry;
51 SRB_GDEVBlock gdevblock;
52 SRB_ExecSCSICmd execscsicmd;
53 SRB_Abort abort;
54 SRB_BusDeviceReset busdevicereset;
55 SRB_GetDiskInfo getdiskinfo;
56 SRB_RescanPort rescanport;
57 SRB_GetSetTimeouts getsettimeouts;
58 } ASPI_SRB;
59
60 // *****************************************************************
61 // Windows ASPI functions (should work for all WIN with ASPI layer)
62 // *****************************************************************
63
CDROM_Interface_Aspi(void)64 CDROM_Interface_Aspi::CDROM_Interface_Aspi(void)
65 {
66 hASPI = NULL;
67 hEvent = NULL;
68 pGetASPI32SupportInfo = NULL;
69 pSendASPI32Command = NULL;
70 memset(&oldLeadOut,0,sizeof(oldLeadOut));
71 };
72
~CDROM_Interface_Aspi(void)73 CDROM_Interface_Aspi::~CDROM_Interface_Aspi(void)
74 {
75 // Stop Audio
76 StopAudio();
77
78 pGetASPI32SupportInfo = NULL; // clear funcs
79 pSendASPI32Command = NULL;
80
81 if (hASPI) { // free aspi
82 FreeLibrary(hASPI);
83 hASPI=NULL;
84 }
85 };
86
GetRegistryValue(HKEY & hKey,char * valueName,char * buffer,ULONG bufferSize)87 bool GetRegistryValue(HKEY& hKey,char* valueName, char* buffer, ULONG bufferSize)
88 // hKey has to be open
89 {
90 // Read subkey
91 ULONG valType;
92 ULONG result;
93 result = RegQueryValueEx(hKey,valueName,NULL,&valType,(unsigned char*)&buffer[0],&bufferSize);
94 return (result == ERROR_SUCCESS);
95 };
96
GetHostAdapter(char * hardwareID)97 BYTE CDROM_Interface_Aspi::GetHostAdapter(char* hardwareID)
98 {
99 ASPI_SRB sh;
100 ASPI_SRB sd;
101 DWORD d = pGetASPI32SupportInfo();
102 int cnt = LOBYTE(LOWORD(d));
103 int i,j,k,max;
104
105 for(i=0; i<cnt; i++) {
106 memset(&sh, 0, sizeof(sh));
107 sh.hainquiry.SRB_Cmd = SC_HA_INQUIRY;
108 sh.hainquiry.SRB_HaId = i;
109 pSendASPI32Command((LPSRB)&sh);
110 if (sh.hainquiry.SRB_Status!=SS_COMP) continue;
111
112 // Indicates the maximum number of targets the adapter supports
113 // If the value is not 8 or 16, then it should be assumed max target is 8
114 max = (int)sh.hainquiry.HA_Unique[3];
115 if ((max!=8) && (max!=16)) max = 8;
116
117 for(j=0; j<max; j++) {
118 for(k=0; k<8; k++) {
119 memset(&sd, 0, sizeof(sd));
120 sd.gdevblock.SRB_Cmd = SC_GET_DEV_TYPE;
121 sd.gdevblock.SRB_HaId = i;
122 sd.gdevblock.SRB_Target = j;
123 sd.gdevblock.SRB_Lun = k;
124 pSendASPI32Command((LPSRB)&sd);
125 if (sd.gdevblock.SRB_Status == SS_COMP) {
126 if (sd.gdevblock.SRB_DeviceType == DTYPE_CDROM) {
127 if ((target==j) && (lun==k)) {
128 LOG(LOG_MISC,LOG_NORMAL)("SCSI: Getting Hardware vendor.");
129 // "Hardware ID = vendor" match ?
130 char vendor[64];
131 if (GetVendor(i,target,lun,vendor)) {
132 LOG(LOG_MISC,LOG_NORMAL)("SCSI: Vendor : %s",vendor);
133 if (strstr(strupr(hardwareID),strupr(vendor))) {
134 LOG(LOG_MISC,LOG_NORMAL)("SCSI: Host Adapter found: %d",i);
135 return i;
136 }
137 };
138 }
139 }
140 }
141 }
142 }
143 }
144 LOG(LOG_MISC,LOG_ERROR)("SCSI: Host Adapter not found: %d",i);
145 return 0;
146 };
147
ScanRegistryFindKey(HKEY & hKeyBase)148 bool CDROM_Interface_Aspi::ScanRegistryFindKey(HKEY& hKeyBase)
149 // hKey has to be open
150 {
151 FILETIME time;
152 ULONG result,newKeyResult;
153 char subKey[256];
154 char buffer[256];
155 ULONG subKeySize = 256;
156 HKEY hNewKey;
157
158 ULONG index = 0;
159 do {
160 result = RegEnumKeyEx (hKeyBase,index,&subKey[0],&subKeySize,NULL,NULL,0,&time);
161 if (result==ERROR_SUCCESS) {
162 // Open Key...
163 newKeyResult = RegOpenKeyEx (hKeyBase,subKey,0,KEY_READ,&hNewKey);
164 if (newKeyResult==ERROR_SUCCESS) {
165 static const char drive_letter_assignment[] = "CurrentDriveLetterAssignment";
166 if (GetRegistryValue(hNewKey,(char*)&drive_letter_assignment,buffer,256)) {
167 LOG(LOG_MISC,LOG_NORMAL)("SCSI: Drive Letter found: %s",buffer);
168 // aha, something suspicious...
169 if (buffer[0]==letter) {
170 char hardwareID[256];
171 // found it... lets see if we can get the scsi values
172 static const char SCSI_LUN[] = "SCSILUN";
173 bool v1 = GetRegistryValue(hNewKey,(char*)SCSI_LUN,buffer,256);
174 LOG(LOG_MISC,LOG_NORMAL)("SCSI: SCSILUN found: %s",buffer);
175 lun = buffer[0]-'0';
176 static const char SCSI_TargetID[] = "SCSITargetID";
177 bool v2 = GetRegistryValue(hNewKey,(char*)SCSI_TargetID,buffer,256);
178 LOG(LOG_MISC,LOG_NORMAL)("SCSI: SCSITargetID found: %s",buffer);
179 target = buffer[0]-'0';
180 static const char Hardware_ID[] = "HardwareID";
181 bool v3 = GetRegistryValue(hNewKey,(char*)Hardware_ID,hardwareID,256);
182 RegCloseKey(hNewKey);
183 if (v1 && v2 && v3) {
184 haId = GetHostAdapter(hardwareID);
185 return true;
186 };
187 }
188 };
189 };
190 RegCloseKey(hNewKey);
191 };
192 index++;
193 } while ((result==ERROR_SUCCESS) || (result==ERROR_MORE_DATA));
194 return false;
195 };
196
GetVendor(BYTE HA_num,BYTE SCSI_Id,BYTE SCSI_Lun,char * szBuffer)197 bool CDROM_Interface_Aspi::GetVendor(BYTE HA_num, BYTE SCSI_Id, BYTE SCSI_Lun, char* szBuffer)
198 {
199 ASPI_SRB srbExec;
200 // SRB_ExecSCSICmd srbExec;
201 memset ( &srbExec, 0, sizeof ( SRB_ExecSCSICmd ) );
202
203 hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
204
205 srbExec.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD ;
206 srbExec.execscsicmd.SRB_HaId = HA_num;
207 srbExec.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
208 srbExec.execscsicmd.SRB_Target = SCSI_Id;
209 srbExec.execscsicmd.SRB_Lun = SCSI_Lun;
210 srbExec.execscsicmd.SRB_BufLen = 36;
211 srbExec.execscsicmd.SRB_BufPointer = (unsigned char*)szBuffer;
212 srbExec.execscsicmd.SRB_SenseLen = SENSE_LEN;
213 srbExec.execscsicmd.SRB_CDBLen = 6;
214 srbExec.execscsicmd.SRB_PostProc = (LPVOID)hEvent;
215 srbExec.execscsicmd.CDBByte [ 0 ] = SCSI_INQUIRY;
216 srbExec.execscsicmd.CDBByte [ 4 ] = 36; // allocation length per szBuffer [ ]
217
218 ResetEvent(hEvent);
219 int dwStatus = pSendASPI32Command ((LPSRB)&srbExec);
220 // LOG(LOG_MISC|LOG_ERROR,"SCSI: Get vendor command send");
221
222 if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,30000);
223 // LOG(LOG_MISC|LOG_ERROR,"SCSI: Pending done.");
224
225 CloseHandle(hEvent);
226 if (srbExec.execscsicmd.SRB_Status != SS_COMP) {
227 strcpy (szBuffer, "error" );
228 return false;
229 } else {
230 safe_strncpy(szBuffer,szBuffer+8,26);
231 size_t len = strlen(szBuffer);
232 for (size_t i=0; i<len; i++) if (szBuffer[i]<=32) szBuffer[i]='_';
233 }
234 return true;
235 }
236
ScanRegistry(HKEY & hKeyBase)237 bool CDROM_Interface_Aspi::ScanRegistry(HKEY& hKeyBase)
238 // hKey has to be open
239 {
240 FILETIME time;
241 ULONG result,newKeyResult;
242 char subKey[256];
243 ULONG subKeySize= 256;
244 HKEY hNewKey;
245
246 ULONG index = 0;
247 do {
248 result = RegEnumKeyEx (hKeyBase,index,&subKey[0],&subKeySize,NULL,NULL,0,&time);
249 if ((result==ERROR_SUCCESS) || (result==ERROR_MORE_DATA)) {
250 // Open Key...
251 newKeyResult = RegOpenKeyEx (hKeyBase,subKey,0,KEY_READ,&hNewKey);
252 if (newKeyResult==ERROR_SUCCESS) {
253 bool found = ScanRegistryFindKey(hNewKey);
254 RegCloseKey(hNewKey);
255 if (found) return true;
256 };
257 RegCloseKey(hNewKey);
258 };
259 index++;
260 } while ((result==ERROR_SUCCESS) || (result==ERROR_MORE_DATA));
261 return false;
262 };
263
SetDevice(char * path,int forceCD)264 bool CDROM_Interface_Aspi::SetDevice(char* path, int forceCD)
265 {
266 // load WNASPI32.DLL
267 hASPI = LoadLibrary ( "WNASPI32.DLL" );
268 if (!hASPI) return false;
269 // Get Pointer to ASPI funcs
270 pGetASPI32SupportInfo = (DWORD(*)(void))GetProcAddress(hASPI,"GetASPI32SupportInfo");
271 pSendASPI32Command = (DWORD(*)(LPSRB))GetProcAddress(hASPI,"SendASPI32Command");
272 if (!pGetASPI32SupportInfo || !pSendASPI32Command) return false;
273 // Letter
274 letter = toupper(path[0]);
275
276 // Check OS
277 OSVERSIONINFO osi;
278 osi.dwOSVersionInfoSize = sizeof(osi);
279 GetVersionEx(&osi);
280 if ((osi.dwPlatformId==VER_PLATFORM_WIN32_NT) && (osi.dwMajorVersion>4)) {
281 if (GetDriveType(path)==DRIVE_CDROM) {
282 // WIN XP/NT/2000
283 int iDA,iDT,iDL;
284 letter = path[0];
285 HANDLE hF = OpenIOCTLFile(letter,FALSE);
286 GetIOCTLAdapter(hF,&iDA,&iDT,&iDL);
287 CloseHandle(hF);
288 // Set SCSI IDs
289 haId = iDA;
290 target = iDT;
291 lun = iDL;
292 return true;
293 }
294 } else {
295 // win 95/98/ME have to scan the registry...
296 // lets hope the layout is always the same... i dunno...
297 char key[2048];
298 HKEY hKeyBase;
299 bool found = false;
300 strcpy(key,"ENUM\\SCSI");
301 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,key,0,KEY_READ,&hKeyBase)==ERROR_SUCCESS) {
302 found = ScanRegistry(hKeyBase);
303 };
304 RegCloseKey(hKeyBase);
305 return found;
306 }
307 return false;
308 };
309
GetAudioTracks(int & stTrack,int & endTrack,TMSF & leadOut)310 bool CDROM_Interface_Aspi::GetAudioTracks(int& stTrack, int& endTrack, TMSF& leadOut)
311 {
312 TOC toc;
313 if (GetTOC((LPTOC)&toc) == SS_COMP) {
314 stTrack = toc.cFirstTrack;
315 endTrack = toc.cLastTrack;
316 leadOut.min = (unsigned char)(toc.tracks[endTrack].lAddr >> 8) &0xFF;
317 leadOut.sec = (unsigned char)(toc.tracks[endTrack].lAddr >> 16) &0xFF;
318 leadOut.fr = (unsigned char)(toc.tracks[endTrack].lAddr >> 24) &0xFF;
319 return true;
320 }
321 return false;
322 };
323
GetAudioTrackInfo(int track,TMSF & start,unsigned char & attr)324 bool CDROM_Interface_Aspi::GetAudioTrackInfo (int track, TMSF& start, unsigned char& attr)
325 {
326 TOC toc;
327 if (GetTOC((LPTOC)&toc) == SS_COMP) {
328 start.min = (unsigned char)(toc.tracks[track-1].lAddr >> 8) &0xFF;
329 start.sec = (unsigned char)(toc.tracks[track-1].lAddr >> 16) &0xFF;
330 start.fr = (unsigned char)(toc.tracks[track-1].lAddr >> 24) &0xFF;
331 attr = (toc.tracks[track-1].cAdrCtrl << 4) & 0xEF;
332 return true;
333 };
334 return false;
335 };
336
OpenIOCTLFile(char cLetter,BOOL bAsync)337 HANDLE CDROM_Interface_Aspi::OpenIOCTLFile(char cLetter,BOOL bAsync)
338 {
339 HANDLE hF;
340 char szFName[16];
341 OSVERSIONINFO ov;
342 DWORD dwFlags;
343 DWORD dwIOCTLAttr;
344 // if(bAsync) dwIOCTLAttr=FILE_FLAG_OVERLAPPED;
345 // else
346 dwIOCTLAttr=0;
347
348 memset(&ov,0,sizeof(OSVERSIONINFO));
349 ov.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
350 GetVersionEx(&ov);
351
352 if ((ov.dwPlatformId==VER_PLATFORM_WIN32_NT) && (ov.dwMajorVersion>4))
353 dwFlags = GENERIC_READ|GENERIC_WRITE; // add gen write on W2k/XP
354 else
355 dwFlags = GENERIC_READ;
356
357 wsprintf(szFName, "\\\\.\\%c:",cLetter);
358
359 hF=CreateFile(szFName,dwFlags,FILE_SHARE_READ, // open drive
360 NULL,OPEN_EXISTING,dwIOCTLAttr,NULL);
361
362 if (hF==INVALID_HANDLE_VALUE) {
363 dwFlags^=GENERIC_WRITE; // mmm... no success
364 hF=CreateFile(szFName,dwFlags,FILE_SHARE_READ, // -> open drive again
365 NULL,OPEN_EXISTING,dwIOCTLAttr,NULL);
366 if (hF==INVALID_HANDLE_VALUE) return NULL;
367 }
368 return hF;
369 }
370
GetIOCTLAdapter(HANDLE hF,int * iDA,int * iDT,int * iDL)371 void CDROM_Interface_Aspi::GetIOCTLAdapter(HANDLE hF,int * iDA,int * iDT,int * iDL)
372 {
373 char szBuf[1024];
374 PSCSI_ADDRESS pSA;
375 DWORD dwRet;
376
377 *iDA=*iDT=*iDL=-1;
378 if(hF==NULL) return;
379
380 memset(szBuf,0,1024);
381
382 pSA=(PSCSI_ADDRESS)szBuf;
383 pSA->Length=sizeof(SCSI_ADDRESS);
384
385 if(!DeviceIoControl(hF,IOCTL_SCSI_GET_ADDRESS,NULL,
386 0,pSA,sizeof(SCSI_ADDRESS),
387 &dwRet,NULL))
388 return;
389
390 *iDA = pSA->PortNumber;
391 *iDT = pSA->TargetId;
392 *iDL = pSA->Lun;
393 }
394
GetTOC(LPTOC toc)395 DWORD CDROM_Interface_Aspi::GetTOC(LPTOC toc)
396 {
397 // SRB_ExecSCSICmd s;
398 ASPI_SRB s;
399 DWORD dwStatus;
400
401 hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
402
403 memset(&s,0,sizeof(s));
404
405 s.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD;
406 s.execscsicmd.SRB_HaId = haId;
407 s.execscsicmd.SRB_Target = target;
408 s.execscsicmd.SRB_Lun = lun;
409 s.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
410 s.execscsicmd.SRB_BufLen = sizeof(*toc);
411 s.execscsicmd.SRB_BufPointer = (BYTE FAR *)toc;
412 s.execscsicmd.SRB_SenseLen = SENSE_LEN;
413 s.execscsicmd.SRB_CDBLen = 0x0A;
414 s.execscsicmd.SRB_PostProc = (LPVOID)hEvent;
415 s.execscsicmd.CDBByte[0] = SCSI_READ_TOC;
416 s.execscsicmd.CDBByte[1] = 0x02; // 0x02 for MSF
417 s.execscsicmd.CDBByte[7] = 0x03;
418 s.execscsicmd.CDBByte[8] = 0x24;
419
420 ResetEvent(hEvent);
421 dwStatus=pSendASPI32Command((LPSRB)&s);
422
423 if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,30000);
424
425 CloseHandle(hEvent);
426
427 return (s.execscsicmd.SRB_Status==SS_COMP);
428 }
429
PlayAudioSector(unsigned long start,unsigned long len)430 bool CDROM_Interface_Aspi::PlayAudioSector(unsigned long start,unsigned long len)
431 {
432 // SRB_ExecSCSICmd s;
433 ASPI_SRB s;
434 DWORD dwStatus;
435
436 hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
437
438 memset(&s,0,sizeof(s));
439 s.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD;
440 s.execscsicmd.SRB_HaId = haId;
441 s.execscsicmd.SRB_Target = target;
442 s.execscsicmd.SRB_Lun = lun;
443 s.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
444 s.execscsicmd.SRB_BufLen = 0;
445 s.execscsicmd.SRB_BufPointer = 0;
446 s.execscsicmd.SRB_SenseLen = SENSE_LEN;
447 s.execscsicmd.SRB_CDBLen = 12;
448 s.execscsicmd.SRB_PostProc = (LPVOID)hEvent;
449
450 s.execscsicmd.CDBByte[0] = SCSI_PLAYAUD_12;
451 s.execscsicmd.CDBByte[1] = lun << 5;
452 s.execscsicmd.CDBByte[2] = (unsigned char)((start >> 24) & 0xFF);
453 s.execscsicmd.CDBByte[3] = (unsigned char)((start >> 16) & 0xFF);
454 s.execscsicmd.CDBByte[4] = (unsigned char)((start >> 8) & 0xFF);
455 s.execscsicmd.CDBByte[5] = (unsigned char)((start & 0xFF));
456 s.execscsicmd.CDBByte[6] = (unsigned char)((len >> 24) & 0xFF);
457 s.execscsicmd.CDBByte[7] = (unsigned char)((len >> 16) & 0xFF);
458 s.execscsicmd.CDBByte[8] = (unsigned char)((len >> 8) & 0xFF);
459 s.execscsicmd.CDBByte[9] = (unsigned char)(len & 0xFF);
460
461 ResetEvent(hEvent);
462
463 dwStatus = pSendASPI32Command((LPSRB)&s);
464
465 if(dwStatus==SS_PENDING) WaitForSingleObject(hEvent,10000);
466
467 CloseHandle(hEvent);
468
469 return s.execscsicmd.SRB_Status==SS_COMP;
470 }
471
StopAudio(void)472 bool CDROM_Interface_Aspi::StopAudio(void)
473 {
474 return PauseAudio(false);
475 };
476
PauseAudio(bool resume)477 bool CDROM_Interface_Aspi::PauseAudio(bool resume)
478 {
479 //SRB_ExecSCSICmd s;
480 ASPI_SRB s;
481 DWORD dwStatus;
482
483 hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
484
485 memset(&s,0,sizeof(s));
486
487 s.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD;
488 s.execscsicmd.SRB_HaId = haId;
489 s.execscsicmd.SRB_Target = target;
490 s.execscsicmd.SRB_Lun = lun;
491 s.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
492 s.execscsicmd.SRB_BufLen = 0x00;
493 s.execscsicmd.SRB_SenseLen = SENSE_LEN;
494 s.execscsicmd.SRB_CDBLen = 0x0A;
495 s.execscsicmd.SRB_PostProc = (LPVOID)hEvent;
496 s.execscsicmd.CDBByte[0] = 0x4B;
497 s.execscsicmd.CDBByte[8] = (unsigned char)resume; // Pause
498
499 ResetEvent(hEvent);
500 dwStatus=pSendASPI32Command((LPSRB)&s);
501
502 if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,30000);
503
504 CloseHandle(hEvent);
505
506 return (s.execscsicmd.SRB_Status==SS_COMP);
507 };
508
GetAudioSub(unsigned char & attr,unsigned char & track,unsigned char & index,TMSF & relPos,TMSF & absPos)509 bool CDROM_Interface_Aspi::GetAudioSub(unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos)
510 {
511 SUB_Q_CURRENT_POSITION pos;
512 // SRB_ExecSCSICmd s;
513 ASPI_SRB s;
514 DWORD dwStatus;
515
516 hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
517
518 memset(&s,0,sizeof(s));
519
520 s.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD;
521 s.execscsicmd.SRB_HaId = haId;
522 s.execscsicmd.SRB_Target = target;
523 s.execscsicmd.SRB_Lun = lun;
524 s.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
525 s.execscsicmd.SRB_SenseLen = SENSE_LEN;
526
527 s.execscsicmd.SRB_BufLen = sizeof(pos);
528 s.execscsicmd.SRB_BufPointer = (BYTE FAR *)&pos;
529 s.execscsicmd.SRB_CDBLen = 10;
530 s.execscsicmd.SRB_PostProc = (LPVOID)hEvent;
531
532 s.execscsicmd.CDBByte[0] = SCSI_SUBCHANNEL;
533 s.execscsicmd.CDBByte[1] = (lun<<5)|2; // lun & msf
534 s.execscsicmd.CDBByte[2] = 0x40; // subq
535 s.execscsicmd.CDBByte[3] = 0x01; // curr pos info
536 s.execscsicmd.CDBByte[6] = 0; // track number (only in isrc mode, ignored)
537 s.execscsicmd.CDBByte[7] = 0; // alloc len
538 s.execscsicmd.CDBByte[8] = sizeof(pos);
539
540 ResetEvent(hEvent);
541
542 dwStatus = pSendASPI32Command((LPSRB)&s);
543
544 if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,0xFFFFFFFF);
545
546 CloseHandle(hEvent);
547
548 if (s.execscsicmd.SRB_Status!=SS_COMP) return false;
549
550 attr = (pos.Control<<4) &0xEF;
551 track = pos.TrackNumber;
552 index = pos.IndexNumber;
553 absPos.min = pos.AbsoluteAddress[1];
554 absPos.sec = pos.AbsoluteAddress[2];
555 absPos.fr = pos.AbsoluteAddress[3];
556 relPos.min = pos.TrackRelativeAddress[1];
557 relPos.sec = pos.TrackRelativeAddress[2];
558 relPos.fr = pos.TrackRelativeAddress[3];
559
560 return true;
561 };
562
GetUPC(unsigned char & attr,char * upcdata)563 bool CDROM_Interface_Aspi::GetUPC(unsigned char& attr, char* upcdata)
564 {
565 SUB_Q_MEDIA_CATALOG_NUMBER upc;
566 ASPI_SRB s;
567 //SRB_ExecSCSICmd s;
568 DWORD dwStatus;
569
570 hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
571
572 memset(&s,0,sizeof(s));
573
574 s.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD;
575 s.execscsicmd.SRB_HaId = haId;
576 s.execscsicmd.SRB_Target = target;
577 s.execscsicmd.SRB_Lun = lun;
578 s.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
579 s.execscsicmd.SRB_SenseLen = SENSE_LEN;
580
581 s.execscsicmd.SRB_BufLen = sizeof(upc);
582 s.execscsicmd.SRB_BufPointer = (BYTE FAR *)&upc;
583 s.execscsicmd.SRB_CDBLen = 10;
584 s.execscsicmd.SRB_PostProc = (LPVOID)hEvent;
585
586 s.execscsicmd.CDBByte[0] = SCSI_SUBCHANNEL;
587 s.execscsicmd.CDBByte[1] = (lun<<5)|2; // lun & msf
588 s.execscsicmd.CDBByte[2] = 0x40; // subq
589 s.execscsicmd.CDBByte[3] = 0x02; // get upc
590 s.execscsicmd.CDBByte[6] = 0; // track number (only in isrc mode, ignored)
591 s.execscsicmd.CDBByte[7] = 0; // alloc len
592 s.execscsicmd.CDBByte[8] = sizeof(upc);
593
594 ResetEvent(hEvent);
595
596 dwStatus = pSendASPI32Command((LPSRB)&s);
597
598 if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,0xFFFFFFFF);
599
600 CloseHandle(hEvent);
601
602 if (s.execscsicmd.SRB_Status!=SS_COMP) return false;
603
604 // attr = (upc.ADR<<4) | upc.Control;
605 attr = 0;
606 // Convert to mscdex format
607 for (int i=0; i<7; i++) upcdata[i] = upc.MediaCatalog[i];
608 for (int i=0; i<7; i++) upcdata[i] = (upc.MediaCatalog[i*2] << 4) | (upc.MediaCatalog[i*2+1] & 0x0F);
609
610 return true;
611 };
612
GetAudioStatus(bool & playing,bool & pause)613 bool CDROM_Interface_Aspi::GetAudioStatus(bool& playing, bool& pause)
614 {
615 playing = pause = false;
616
617 SUB_Q_HEADER sub;
618 // SRB_ExecSCSICmd s;
619 ASPI_SRB s;
620 DWORD dwStatus;
621
622 hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
623
624 memset(&s,0,sizeof(s));
625
626 s.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD;
627 s.execscsicmd.SRB_HaId = haId;
628 s.execscsicmd.SRB_Target = target;
629 s.execscsicmd.SRB_Lun = lun;
630 s.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
631 s.execscsicmd.SRB_SenseLen = SENSE_LEN;
632
633 s.execscsicmd.SRB_BufLen = sizeof(sub);
634 s.execscsicmd.SRB_BufPointer = (BYTE FAR *)⊂
635 s.execscsicmd.SRB_CDBLen = 10;
636 s.execscsicmd.SRB_PostProc = (LPVOID)hEvent;
637
638 s.execscsicmd.CDBByte[0] = SCSI_SUBCHANNEL;
639 s.execscsicmd.CDBByte[1] = (lun<<5)|2; // lun & msf
640 s.execscsicmd.CDBByte[2] = 0x00; // no subq
641 s.execscsicmd.CDBByte[3] = 0x00; // dont care
642 s.execscsicmd.CDBByte[6] = 0; // track number (only in isrc mode, ignored)
643 s.execscsicmd.CDBByte[7] = 0; // alloc len
644 s.execscsicmd.CDBByte[8] = sizeof(sub);
645
646 ResetEvent(hEvent);
647
648 dwStatus = pSendASPI32Command((LPSRB)&s);
649
650 if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,0xFFFFFFFF);
651
652 CloseHandle(hEvent);
653
654 if (s.execscsicmd.SRB_Status!=SS_COMP) return false;
655
656 playing = (sub.AudioStatus==0x11);
657 pause = (sub.AudioStatus==0x12);
658
659 return true;
660 };
661
LoadUnloadMedia(bool unload)662 bool CDROM_Interface_Aspi::LoadUnloadMedia(bool unload)
663 {
664 //SRB_ExecSCSICmd s;
665 ASPI_SRB s;
666 DWORD dwStatus;
667
668 hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
669
670 memset(&s,0,sizeof(s));
671
672 s.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD;
673 s.execscsicmd.SRB_HaId = haId;
674 s.execscsicmd.SRB_Target = target;
675 s.execscsicmd.SRB_Lun = lun;
676 s.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
677 s.execscsicmd.SRB_SenseLen = SENSE_LEN;
678
679 s.execscsicmd.SRB_BufLen = 0;
680 s.execscsicmd.SRB_BufPointer = 0;
681 s.execscsicmd.SRB_CDBLen = 6; // 14;
682 s.execscsicmd.SRB_PostProc = (LPVOID)hEvent;
683
684 s.execscsicmd.CDBByte[0] = SCSI_LOAD_UN;
685 s.execscsicmd.CDBByte[1] = (lun<<5)|1; // lun & immediate
686 s.execscsicmd.CDBByte[4] = (unload ? 0x02:0x03); // unload/load media
687
688 ResetEvent(hEvent);
689
690 dwStatus = pSendASPI32Command((LPSRB)&s);
691
692 if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,0xFFFFFFFF);
693
694 CloseHandle(hEvent);
695
696 if (s.execscsicmd.SRB_Status!=SS_COMP) return false;
697
698 return true;
699 };
700
GetMediaTrayStatus(bool & mediaPresent,bool & mediaChanged,bool & trayOpen)701 bool CDROM_Interface_Aspi::GetMediaTrayStatus(bool& mediaPresent, bool& mediaChanged, bool& trayOpen)
702 {
703 // Seems not possible to get this values using ioctl...
704 int track1,track2;
705 TMSF leadOut;
706 // If we can read, there's a media
707 mediaPresent = GetAudioTracks(track1, track2, leadOut),
708 trayOpen = !mediaPresent;
709 mediaChanged = (oldLeadOut.min!=leadOut.min) || (oldLeadOut.sec!=leadOut.sec) || (oldLeadOut.fr!=leadOut.fr);
710 // Save old values
711 oldLeadOut.min = leadOut.min;
712 oldLeadOut.sec = leadOut.sec;
713 oldLeadOut.fr = leadOut.fr;
714 // always success
715 return true;
716 };
717
ReadSectors(PhysPt buffer,bool raw,unsigned long sector,unsigned long num)718 bool CDROM_Interface_Aspi::ReadSectors(PhysPt buffer, bool raw, unsigned long sector, unsigned long num)
719 {
720 //SRB_ExecSCSICmd s;
721 ASPI_SRB s;
722 DWORD dwStatus;
723
724 hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
725
726 memset(&s,0,sizeof(s));
727
728 Bitu buflen = raw?2352*num:2048*num;
729 Bit8u* bufdata = new Bit8u[buflen];
730
731 s.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD;
732 s.execscsicmd.SRB_HaId = haId;
733 s.execscsicmd.SRB_Target = target;
734 s.execscsicmd.SRB_Lun = lun;
735 s.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
736 s.execscsicmd.SRB_SenseLen = SENSE_LEN;
737
738 s.execscsicmd.SRB_BufLen = buflen;
739 s.execscsicmd.SRB_BufPointer = (BYTE FAR*)bufdata;
740 s.execscsicmd.SRB_CDBLen = 12;
741 s.execscsicmd.SRB_PostProc = (LPVOID)hEvent;
742
743 s.execscsicmd.CDBByte[0] = 0xBE;
744 s.execscsicmd.CDBByte[2] = (unsigned char)((sector >> 24) & 0xFF);
745 s.execscsicmd.CDBByte[3] = (unsigned char)((sector >> 16) & 0xFF);
746 s.execscsicmd.CDBByte[4] = (unsigned char)((sector >> 8) & 0xFF);
747 s.execscsicmd.CDBByte[5] = (unsigned char)((sector & 0xFF));
748 s.execscsicmd.CDBByte[6] = (unsigned char)((num >> 16) & 0xFF);
749 s.execscsicmd.CDBByte[7] = (unsigned char)((num >> 8) & 0xFF);
750 s.execscsicmd.CDBByte[8] = (unsigned char) (num & 0xFF);
751 s.execscsicmd.CDBByte[9] = (raw?0xF0:0x10);
752
753 ResetEvent(hEvent);
754
755 dwStatus = pSendASPI32Command((LPSRB)&s);
756
757 if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,0xFFFFFFFF);
758
759 CloseHandle(hEvent);
760
761 // Copy to PhysPt
762 MEM_BlockWrite(buffer,bufdata,buflen);
763
764 delete[] bufdata;
765
766 return (s.execscsicmd.SRB_Status==SS_COMP);
767 };
768
769 #endif
770