Logo Search packages:      
Sourcecode: dosbox version File versions  Download package

cdrom_aspi_win32.cpp

/*
 *  Copyright (C) 2002-2004  The DOSBox Team
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

/* $Id: cdrom_aspi_win32.cpp,v 1.12 2004/08/04 09:12:53 qbix79 Exp $ */

#if defined (WIN32)

#include <ctype.h>

#include "dosbox.h"
#include "cdrom.h"

//Are actually system includes but leave for now
#include "wnaspi32.h"

#if defined (_MSC_VER)
#include <ntddcdrm.h>               // Ioctl stuff
#include <ntddscsi.h>
#include <winioctl.h>               // Ioctl stuff
#else 
#include "ddk/ntddcdrm.h"           // Ioctl stuff
#include "ddk/ntddscsi.h"
#endif

#include "scsidefs.h"

// always use a buffer of the maximum struct size (like the union of all 'SRB_*' struct types)
// Thanx SaPu
typedef union {
      SRB_HAInquiry       hainquiry;
      SRB_GDEVBlock       gdevblock;
      SRB_ExecSCSICmd     execscsicmd;
      SRB_Abort           abort;
      SRB_BusDeviceReset  busdevicereset;
      SRB_GetDiskInfo     getdiskinfo;
      SRB_RescanPort      rescanport;
      SRB_GetSetTimeouts  getsettimeouts;
} ASPI_SRB;

// *****************************************************************
// Windows ASPI functions (should work for all WIN with ASPI layer)
// *****************************************************************

CDROM_Interface_Aspi::CDROM_Interface_Aspi(void)
{
      hASPI                         = NULL;
      hEvent                              = NULL;
      pGetASPI32SupportInfo   = NULL;
      pSendASPI32Command            = NULL;
      memset(&oldLeadOut,0,sizeof(oldLeadOut));
};

CDROM_Interface_Aspi::~CDROM_Interface_Aspi(void)
{
      // Stop Audio
      StopAudio();

      pGetASPI32SupportInfo   = NULL;     // clear funcs
      pSendASPI32Command            = NULL;

      if (hASPI) {                              // free aspi
            FreeLibrary(hASPI);
            hASPI=NULL;
      }
};

bool GetRegistryValue(HKEY& hKey,char* valueName, char* buffer, ULONG bufferSize)
// hKey has to be open
{     
      // Read subkey
      ULONG valType;
      ULONG result;
      result = RegQueryValueEx(hKey,valueName,NULL,&valType,(unsigned char*)&buffer[0],&bufferSize);
      return (result == ERROR_SUCCESS);
};

BYTE CDROM_Interface_Aspi::GetHostAdapter(char* hardwareID)
{
      ASPI_SRB sh;
      ASPI_SRB sd;
      DWORD d           = pGetASPI32SupportInfo();
      int cnt           = LOBYTE(LOWORD(d));
      int i,j,k,max;

      for(i=0; i<cnt; i++) {
            memset(&sh, 0, sizeof(sh));
            sh.hainquiry.SRB_Cmd  = SC_HA_INQUIRY;
            sh.hainquiry.SRB_HaId = i;
            pSendASPI32Command((LPSRB)&sh);
            if (sh.hainquiry.SRB_Status!=SS_COMP) continue;
            
            // Indicates the maximum number of targets the adapter supports
            // If the value is not 8 or 16, then it should be assumed max target is 8
            max = (int)sh.hainquiry.HA_Unique[3];
            if ((max!=8) && (max!=16)) max = 8;
            
            for(j=0; j<max; j++) {
                  for(k=0; k<8; k++) {
                        memset(&sd, 0, sizeof(sd));
                        sd.gdevblock.SRB_Cmd    = SC_GET_DEV_TYPE;
                        sd.gdevblock.SRB_HaId   = i;
                        sd.gdevblock.SRB_Target = j;
                        sd.gdevblock.SRB_Lun    = k;
                        pSendASPI32Command((LPSRB)&sd);
                        if (sd.gdevblock.SRB_Status == SS_COMP) {
                              if (sd.gdevblock.SRB_DeviceType == DTYPE_CDROM) {                                   
                                    if ((target==j) && (lun==k)) {
                                          LOG(LOG_MISC,LOG_NORMAL)("SCSI: Getting Hardware vendor.");                                           
                                          // "Hardware ID = vendor" match ?
                                          char vendor[64];
                                          if (GetVendor(i,target,lun,vendor)) {
                                                LOG(LOG_MISC,LOG_NORMAL)("SCSI: Vendor : %s",vendor); 
                                                if (strstr(strupr(hardwareID),strupr(vendor))) {
                                                      LOG(LOG_MISC,LOG_NORMAL)("SCSI: Host Adapter found: %d",i);                                           
                                                      return i;                                             
                                                }
                                          };
                                    }
                              }
                        }
                  }
            }
      }
      LOG(LOG_MISC,LOG_ERROR)("SCSI: Host Adapter not found: %d",i);                                                    
      return 0;
};

bool CDROM_Interface_Aspi::ScanRegistryFindKey(HKEY& hKeyBase)
// hKey has to be open
{
      FILETIME    time;
      ULONG       result,newKeyResult;
      char        subKey[256];
      char        buffer[256];
      ULONG       bufferSize = 256;
      ULONG       subKeySize = 256;
      HKEY        hNewKey;
      
      ULONG index = 0;
      do {
            result = RegEnumKeyEx (hKeyBase,index,&subKey[0],&subKeySize,NULL,NULL,0,&time);
            if (result==ERROR_SUCCESS) {
                  // Open Key...
                  newKeyResult = RegOpenKeyEx (hKeyBase,subKey,0,KEY_READ,&hNewKey);
                  if (newKeyResult==ERROR_SUCCESS) {
                        if (GetRegistryValue(hNewKey,"CurrentDriveLetterAssignment",buffer,256)) {
                              LOG(LOG_MISC,LOG_NORMAL)("SCSI: Drive Letter found: %s",buffer);                          
                              // aha, something suspicious...
                              if (buffer[0]==letter) {
                                    char hardwareID[256];
                                    // found it... lets see if we can get the scsi values                   
                                    bool v1 = GetRegistryValue(hNewKey,"SCSILUN",buffer,256);
                                    LOG(LOG_MISC,LOG_NORMAL)("SCSI: SCSILUN found: %s",buffer);                         
                                    lun         = buffer[0]-'0';
                                    bool v2 = GetRegistryValue(hNewKey,"SCSITargetID",buffer,256);
                                    LOG(LOG_MISC,LOG_NORMAL)("SCSI: SCSITargetID found: %s",buffer);                          
                                    target  = buffer[0]-'0';
                                    bool v3 = GetRegistryValue(hNewKey,"HardwareID",hardwareID,256);
                                    RegCloseKey(hNewKey);
                                    if (v1 && v2 && v3) {   
                                          haId = GetHostAdapter(hardwareID);
                                          return true;
                                    };
                              }
                        };
                  };
                  RegCloseKey(hNewKey);
            };
            index++;
      } while ((result==ERROR_SUCCESS) || (result==ERROR_MORE_DATA));
      return false;
};

bool CDROM_Interface_Aspi::GetVendor(BYTE HA_num, BYTE SCSI_Id, BYTE SCSI_Lun, char* szBuffer) 
{
      ASPI_SRB srbExec;
      //    SRB_ExecSCSICmd srbExec;
      memset ( &srbExec, 0, sizeof ( SRB_ExecSCSICmd ) );

      hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);

      srbExec.execscsicmd.SRB_Cmd               = SC_EXEC_SCSI_CMD ;
      srbExec.execscsicmd.SRB_HaId        = HA_num;
      srbExec.execscsicmd.SRB_Flags       = SRB_DIR_IN | SRB_EVENT_NOTIFY;
      srbExec.execscsicmd.SRB_Target            = SCSI_Id;
      srbExec.execscsicmd.SRB_Lun               = SCSI_Lun;
      srbExec.execscsicmd.SRB_BufLen            = 36;
      srbExec.execscsicmd.SRB_BufPointer  = (unsigned char*)szBuffer;
      srbExec.execscsicmd.SRB_SenseLen    = SENSE_LEN;
      srbExec.execscsicmd.SRB_CDBLen            = 6;
      srbExec.execscsicmd.SRB_PostProc    = (LPVOID)hEvent;
      srbExec.execscsicmd.CDBByte [ 0 ]   = SCSI_INQUIRY;
      srbExec.execscsicmd.CDBByte [ 4 ]   = 36;  // allocation length per szBuffer [ ]

      ResetEvent(hEvent);
      int dwStatus = pSendASPI32Command ((LPSRB)&srbExec);
//    LOG(LOG_MISC|LOG_ERROR,"SCSI: Get vendor command send");                            
      
      if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,30000);
//    LOG(LOG_MISC|LOG_ERROR,"SCSI: Pending done.");                          

      CloseHandle(hEvent);
      if (srbExec.execscsicmd.SRB_Status != SS_COMP) {
            strcpy (szBuffer, "error" );
            return false;
      } else {
            strncpy(szBuffer,szBuffer+8,25);
            szBuffer[25] = 0;
            int len = strlen(szBuffer);
            for (int i=0; i<len; i++) if (szBuffer[i]<=32) szBuffer[i]='_';
      };
      return true;
}

bool CDROM_Interface_Aspi::ScanRegistry(HKEY& hKeyBase)
// hKey has to be open
{
      FILETIME    time;
      ULONG       result,newKeyResult;
      char        subKey[256];
      ULONG       subKeySize= 256;
      HKEY        hNewKey;
      
      ULONG index = 0;
      do {
            result = RegEnumKeyEx (hKeyBase,index,&subKey[0],&subKeySize,NULL,NULL,0,&time);
            if ((result==ERROR_SUCCESS) || (result==ERROR_MORE_DATA)) {
                  // Open Key...
                  newKeyResult = RegOpenKeyEx (hKeyBase,subKey,0,KEY_READ,&hNewKey);
                  if (newKeyResult==ERROR_SUCCESS) {
                        bool found = ScanRegistryFindKey(hNewKey);
                        RegCloseKey(hNewKey);
                        if (found) return true;
                  };
                  RegCloseKey(hNewKey);
            };
            index++;
      } while ((result==ERROR_SUCCESS) || (result==ERROR_MORE_DATA));
      return false;
};

bool CDROM_Interface_Aspi::SetDevice(char* path, int forceCD)
{
      // load WNASPI32.DLL
      hASPI = LoadLibrary ( "WNASPI32.DLL" );
      if (!hASPI) return false;
      // Get Pointer to ASPI funcs
    pGetASPI32SupportInfo     = (DWORD(*)(void))GetProcAddress(hASPI,"GetASPI32SupportInfo");
    pSendASPI32Command        = (DWORD(*)(LPSRB))GetProcAddress(hASPI,"SendASPI32Command");
      if (!pGetASPI32SupportInfo || !pSendASPI32Command) return false;
      // Letter
      letter = toupper(path[0]);

      // Check OS
      OSVERSIONINFO osi;
      osi.dwOSVersionInfoSize = sizeof(osi);
      GetVersionEx(&osi);
      if ((osi.dwPlatformId==VER_PLATFORM_WIN32_NT) && (osi.dwMajorVersion>4)) {
            if (GetDriveType(path)==DRIVE_CDROM) {    
                  // WIN XP/NT/2000
                  int iDA,iDT,iDL;
                  letter = path[0];
                  HANDLE hF = OpenIOCTLFile(letter,FALSE);
                  GetIOCTLAdapter(hF,&iDA,&iDT,&iDL);
                  CloseHandle(hF);
                  // Set SCSI IDs
                  haId  = iDA;
                  target      = iDT;
                  lun         = iDL;
                  return true;
            }
      } else {
            // win 95/98/ME have to scan the registry...
            // lets hope the layout is always the same... i dunno...
            char key[2048];
            HKEY hKeyBase;
            bool found = false;
            strcpy(key,"ENUM\\SCSI");
            if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,key,0,KEY_READ,&hKeyBase)==ERROR_SUCCESS) {
                  found = ScanRegistry(hKeyBase);
            };    
            RegCloseKey(hKeyBase);
            return found;
      } 
      return false;
};

bool CDROM_Interface_Aspi::GetAudioTracks(int& stTrack, int& endTrack, TMSF& leadOut) 
{
      TOC toc;
      if (GetTOC((LPTOC)&toc) == SS_COMP) {
            stTrack           = toc.cFirstTrack;
            endTrack    = toc.cLastTrack;
            leadOut.min = (unsigned char)(toc.tracks[endTrack].lAddr >>  8) &0xFF;
            leadOut.sec = (unsigned char)(toc.tracks[endTrack].lAddr >> 16) &0xFF;
            leadOut.fr  = (unsigned char)(toc.tracks[endTrack].lAddr >> 24) &0xFF;
            return true;
      }
      return false;
};

bool CDROM_Interface_Aspi::GetAudioTrackInfo    (int track, TMSF& start, unsigned char& attr)
{
      TOC toc;
      if (GetTOC((LPTOC)&toc) == SS_COMP) {
            start.min   = (unsigned char)(toc.tracks[track-1].lAddr >>  8) &0xFF;
            start.sec   = (unsigned char)(toc.tracks[track-1].lAddr >> 16) &0xFF;
            start.fr    = (unsigned char)(toc.tracks[track-1].lAddr >> 24) &0xFF;
            attr        = (toc.tracks[track-1].cAdrCtrl << 4) & 0xEF;
            return true;
      };          
      return false;
};

HANDLE CDROM_Interface_Aspi::OpenIOCTLFile(char cLetter,BOOL bAsync)
{
      HANDLE hF;
      char szFName[16];
      OSVERSIONINFO ov;
      DWORD dwFlags;
      DWORD dwIOCTLAttr;
//    if(bAsync) dwIOCTLAttr=FILE_FLAG_OVERLAPPED;
//    else       
      dwIOCTLAttr=0;

      memset(&ov,0,sizeof(OSVERSIONINFO));
      ov.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
      GetVersionEx(&ov);

      if ((ov.dwPlatformId==VER_PLATFORM_WIN32_NT) && (ov.dwMajorVersion>4))
            dwFlags = GENERIC_READ|GENERIC_WRITE;            // add gen write on W2k/XP
      else
            dwFlags = GENERIC_READ;

      wsprintf(szFName, "\\\\.\\%c:",cLetter);

      hF=CreateFile(szFName,dwFlags,FILE_SHARE_READ,        // open drive
                        NULL,OPEN_EXISTING,dwIOCTLAttr,NULL);

      if (hF==INVALID_HANDLE_VALUE) {
            dwFlags^=GENERIC_WRITE;                         // mmm... no success
            hF=CreateFile(szFName,dwFlags,FILE_SHARE_READ,      // -> open drive again
                              NULL,OPEN_EXISTING,dwIOCTLAttr,NULL);
            if (hF==INVALID_HANDLE_VALUE) return NULL;
      }
      return hF;                                          
}

void CDROM_Interface_Aspi::GetIOCTLAdapter(HANDLE hF,int * iDA,int * iDT,int * iDL)
{
      char szBuf[1024];
      PSCSI_ADDRESS pSA;
      DWORD dwRet;

      *iDA=*iDT=*iDL=-1;
      if(hF==NULL) return;

      memset(szBuf,0,1024);

      pSA=(PSCSI_ADDRESS)szBuf;
      pSA->Length=sizeof(SCSI_ADDRESS);
                                               
      if(!DeviceIoControl(hF,IOCTL_SCSI_GET_ADDRESS,NULL,
                               0,pSA,sizeof(SCSI_ADDRESS),
                               &dwRet,NULL))
      return;

      *iDA = pSA->PortNumber;
      *iDT = pSA->TargetId;
      *iDL = pSA->Lun;
}

DWORD CDROM_Interface_Aspi::GetTOC(LPTOC toc)
{
//    SRB_ExecSCSICmd s;
      ASPI_SRB s;
      DWORD dwStatus;

      hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);

      memset(&s,0,sizeof(s));

      s.execscsicmd.SRB_Cmd        = SC_EXEC_SCSI_CMD;
      s.execscsicmd.SRB_HaId       = haId;
      s.execscsicmd.SRB_Target     = target;
      s.execscsicmd.SRB_Lun        = lun;
      s.execscsicmd.SRB_Flags      = SRB_DIR_IN | SRB_EVENT_NOTIFY;
      s.execscsicmd.SRB_BufLen     = sizeof(*toc);
      s.execscsicmd.SRB_BufPointer = (BYTE FAR *)toc;
      s.execscsicmd.SRB_SenseLen   = SENSE_LEN;
      s.execscsicmd.SRB_CDBLen     = 0x0A;
      s.execscsicmd.SRB_PostProc   = (LPVOID)hEvent;
      s.execscsicmd.CDBByte[0]     = SCSI_READ_TOC;
      s.execscsicmd.CDBByte[1]     = 0x02; // 0x02 for MSF
      s.execscsicmd.CDBByte[7]     = 0x03;
      s.execscsicmd.CDBByte[8]     = 0x24;

      ResetEvent(hEvent);
      dwStatus=pSendASPI32Command((LPSRB)&s);

      if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,30000);

      CloseHandle(hEvent);

      return (s.execscsicmd.SRB_Status==SS_COMP);
}

bool CDROM_Interface_Aspi::PlayAudioSector(unsigned long start,unsigned long len)
{
//    SRB_ExecSCSICmd s;
      ASPI_SRB s;
      DWORD dwStatus;

      hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);

      memset(&s,0,sizeof(s));
      s.execscsicmd.SRB_Cmd        = SC_EXEC_SCSI_CMD;
      s.execscsicmd.SRB_HaId       = haId;
      s.execscsicmd.SRB_Target     = target;
      s.execscsicmd.SRB_Lun        = lun;
      s.execscsicmd.SRB_Flags      = SRB_DIR_IN | SRB_EVENT_NOTIFY;
      s.execscsicmd.SRB_BufLen     = 0;
      s.execscsicmd.SRB_BufPointer = 0;
      s.execscsicmd.SRB_SenseLen   = SENSE_LEN;
      s.execscsicmd.SRB_CDBLen     = 12;
      s.execscsicmd.SRB_PostProc   = (LPVOID)hEvent;

      s.execscsicmd.CDBByte[0]     = SCSI_PLAYAUD_12;
      s.execscsicmd.CDBByte[1]     = lun << 5;
      s.execscsicmd.CDBByte[2]     = (unsigned char)((start >> 24) & 0xFF);
      s.execscsicmd.CDBByte[3]     = (unsigned char)((start >> 16) & 0xFF);
      s.execscsicmd.CDBByte[4]     = (unsigned char)((start >> 8) & 0xFF);
      s.execscsicmd.CDBByte[5]     = (unsigned char)((start & 0xFF));
      s.execscsicmd.CDBByte[6]     = (unsigned char)((len >> 24) & 0xFF);
      s.execscsicmd.CDBByte[7]     = (unsigned char)((len >> 16) & 0xFF);
      s.execscsicmd.CDBByte[8]     = (unsigned char)((len >> 8) & 0xFF);
      s.execscsicmd.CDBByte[9]     = (unsigned char)(len & 0xFF);

      ResetEvent(hEvent);

      dwStatus = pSendASPI32Command((LPSRB)&s);

      if(dwStatus==SS_PENDING) WaitForSingleObject(hEvent,10000);

      CloseHandle(hEvent);

      return s.execscsicmd.SRB_Status==SS_COMP;
}

bool CDROM_Interface_Aspi::StopAudio(void)
{
      return PauseAudio(false);
};

bool CDROM_Interface_Aspi::PauseAudio(bool resume)
{
      //SRB_ExecSCSICmd s;
      ASPI_SRB s;
      DWORD dwStatus;

      hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);

      memset(&s,0,sizeof(s));

      s.execscsicmd.SRB_Cmd        = SC_EXEC_SCSI_CMD;
      s.execscsicmd.SRB_HaId       = haId;
      s.execscsicmd.SRB_Target     = target;
      s.execscsicmd.SRB_Lun        = lun;
      s.execscsicmd.SRB_Flags      = SRB_DIR_IN | SRB_EVENT_NOTIFY;
      s.execscsicmd.SRB_BufLen     = 0x00;
      s.execscsicmd.SRB_SenseLen   = SENSE_LEN;
      s.execscsicmd.SRB_CDBLen     = 0x0A;
      s.execscsicmd.SRB_PostProc   = (LPVOID)hEvent;
      s.execscsicmd.CDBByte[0]     = 0x4B;
      s.execscsicmd.CDBByte[8]     = (unsigned char)resume;                   // Pause

      ResetEvent(hEvent);
      dwStatus=pSendASPI32Command((LPSRB)&s);

      if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,30000);

      CloseHandle(hEvent);

      return (s.execscsicmd.SRB_Status==SS_COMP);
};

bool CDROM_Interface_Aspi::GetAudioSub(unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos)
{
      SUB_Q_CURRENT_POSITION pos;
//    SRB_ExecSCSICmd s;
      ASPI_SRB s;
      DWORD dwStatus;
      
      hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);

      memset(&s,0,sizeof(s));

      s.execscsicmd.SRB_Cmd        = SC_EXEC_SCSI_CMD;
      s.execscsicmd.SRB_HaId       = haId;
      s.execscsicmd.SRB_Target     = target;
      s.execscsicmd.SRB_Lun        = lun;
      s.execscsicmd.SRB_Flags      = SRB_DIR_IN | SRB_EVENT_NOTIFY;
      s.execscsicmd.SRB_SenseLen   = SENSE_LEN;

      s.execscsicmd.SRB_BufLen     = sizeof(pos);
      s.execscsicmd.SRB_BufPointer = (BYTE FAR *)&pos;
      s.execscsicmd.SRB_CDBLen     = 10;
      s.execscsicmd.SRB_PostProc   = (LPVOID)hEvent;

      s.execscsicmd.CDBByte[0]     = SCSI_SUBCHANNEL;
      s.execscsicmd.CDBByte[1]     = (lun<<5)|2;   // lun & msf
      s.execscsicmd.CDBByte[2]     = 0x40;            // subq
      s.execscsicmd.CDBByte[3]     = 0x01;            // curr pos info
      s.execscsicmd.CDBByte[6]     = 0;               // track number (only in isrc mode, ignored)
      s.execscsicmd.CDBByte[7]     = 0;               // alloc len
      s.execscsicmd.CDBByte[8]     = sizeof(pos);           

      ResetEvent(hEvent);

      dwStatus = pSendASPI32Command((LPSRB)&s);

      if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,0xFFFFFFFF);

      CloseHandle(hEvent);
      
      if (s.execscsicmd.SRB_Status!=SS_COMP) return false;

      attr        = (pos.Control<<4) &0xEF;
      track       = pos.TrackNumber;
      index       = pos.IndexNumber;
      absPos.min  = pos.AbsoluteAddress[1];
      absPos.sec  = pos.AbsoluteAddress[2];
      absPos.fr   = pos.AbsoluteAddress[3];
      relPos.min  = pos.TrackRelativeAddress[1];
      relPos.sec  = pos.TrackRelativeAddress[2];
      relPos.fr   = pos.TrackRelativeAddress[3];
      
      return true;
};

bool CDROM_Interface_Aspi::GetUPC(unsigned char& attr, char* upcdata)
{
      SUB_Q_MEDIA_CATALOG_NUMBER upc;
      ASPI_SRB s;
      //SRB_ExecSCSICmd s;
      DWORD dwStatus;

      hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);

      memset(&s,0,sizeof(s));
      
      s.execscsicmd.SRB_Cmd        = SC_EXEC_SCSI_CMD;
      s.execscsicmd.SRB_HaId       = haId;
      s.execscsicmd.SRB_Target     = target;
      s.execscsicmd.SRB_Lun        = lun;
      s.execscsicmd.SRB_Flags      = SRB_DIR_IN | SRB_EVENT_NOTIFY;
      s.execscsicmd.SRB_SenseLen   = SENSE_LEN;

      s.execscsicmd.SRB_BufLen     = sizeof(upc);
      s.execscsicmd.SRB_BufPointer = (BYTE FAR *)&upc;
      s.execscsicmd.SRB_CDBLen     = 10;
      s.execscsicmd.SRB_PostProc   = (LPVOID)hEvent;

      s.execscsicmd.CDBByte[0]     = SCSI_SUBCHANNEL;
      s.execscsicmd.CDBByte[1]     = (lun<<5)|2;   // lun & msf
      s.execscsicmd.CDBByte[2]     = 0x40;            // subq
      s.execscsicmd.CDBByte[3]     = 0x02;            // get upc
      s.execscsicmd.CDBByte[6]     = 0;               // track number (only in isrc mode, ignored)
      s.execscsicmd.CDBByte[7]     = 0;               // alloc len
      s.execscsicmd.CDBByte[8]     = sizeof(upc);           

      ResetEvent(hEvent);

      dwStatus = pSendASPI32Command((LPSRB)&s);

      if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,0xFFFFFFFF);

      CloseHandle(hEvent);

      if (s.execscsicmd.SRB_Status!=SS_COMP) return false;

//    attr = (upc.ADR<<4) | upc.Control;
      attr  = 0;
      int pos     = 0;
      // Convert to mscdex format
      for (int i=0; i<7; i++) upcdata[i] = upc.MediaCatalog[i];
    for (int i=0; i<7; i++) upcdata[i] = (upc.MediaCatalog[i*2] << 4) | (upc.MediaCatalog[i*2+1] & 0x0F);

      return true;
};

bool CDROM_Interface_Aspi::GetAudioStatus(bool& playing, bool& pause)
{
      playing = pause = false;
      
      SUB_Q_HEADER sub;
//    SRB_ExecSCSICmd s;
      ASPI_SRB s;
      DWORD dwStatus;

      hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);

      memset(&s,0,sizeof(s));
      
      s.execscsicmd.SRB_Cmd        = SC_EXEC_SCSI_CMD;
      s.execscsicmd.SRB_HaId       = haId;
      s.execscsicmd.SRB_Target     = target;
      s.execscsicmd.SRB_Lun        = lun;
      s.execscsicmd.SRB_Flags      = SRB_DIR_IN | SRB_EVENT_NOTIFY;
      s.execscsicmd.SRB_SenseLen   = SENSE_LEN;

      s.execscsicmd.SRB_BufLen     = sizeof(sub);
      s.execscsicmd.SRB_BufPointer = (BYTE FAR *)&sub;
      s.execscsicmd.SRB_CDBLen     = 10;
      s.execscsicmd.SRB_PostProc   = (LPVOID)hEvent;

      s.execscsicmd.CDBByte[0]     = SCSI_SUBCHANNEL;
      s.execscsicmd.CDBByte[1]     = (lun<<5)|2;   // lun & msf
      s.execscsicmd.CDBByte[2]     = 0x00;            // no subq
      s.execscsicmd.CDBByte[3]     = 0x00;            // dont care
      s.execscsicmd.CDBByte[6]     = 0;               // track number (only in isrc mode, ignored)
      s.execscsicmd.CDBByte[7]     = 0;               // alloc len
      s.execscsicmd.CDBByte[8]     = sizeof(sub);           

      ResetEvent(hEvent);

      dwStatus = pSendASPI32Command((LPSRB)&s);

      if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,0xFFFFFFFF);

      CloseHandle(hEvent);

      if (s.execscsicmd.SRB_Status!=SS_COMP) return false;

      playing                 = (sub.AudioStatus==0x11);
      pause             = (sub.AudioStatus==0x12);

      return true;
};

bool CDROM_Interface_Aspi::LoadUnloadMedia(bool unload)
{
      //SRB_ExecSCSICmd s;
      ASPI_SRB s;
      DWORD dwStatus;

      hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);

      memset(&s,0,sizeof(s));
      
      s.execscsicmd.SRB_Cmd        = SC_EXEC_SCSI_CMD;
      s.execscsicmd.SRB_HaId       = haId;
      s.execscsicmd.SRB_Target     = target;
      s.execscsicmd.SRB_Lun        = lun;
      s.execscsicmd.SRB_Flags      = SRB_DIR_IN | SRB_EVENT_NOTIFY;
      s.execscsicmd.SRB_SenseLen   = SENSE_LEN;

      s.execscsicmd.SRB_BufLen     = 0;
      s.execscsicmd.SRB_BufPointer = 0;
      s.execscsicmd.SRB_CDBLen     = 6; // 14;
      s.execscsicmd.SRB_PostProc   = (LPVOID)hEvent;

      s.execscsicmd.CDBByte[0]     = SCSI_LOAD_UN;
      s.execscsicmd.CDBByte[1]     = (lun<<5)|1; // lun & immediate
      s.execscsicmd.CDBByte[4]     = (unload ? 0x02:0x03);        // unload/load media
      
      ResetEvent(hEvent);

      dwStatus = pSendASPI32Command((LPSRB)&s);

      if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,0xFFFFFFFF);

      CloseHandle(hEvent);

      if (s.execscsicmd.SRB_Status!=SS_COMP) return false;

      return true;
};

bool CDROM_Interface_Aspi::GetMediaTrayStatus(bool& mediaPresent, bool& mediaChanged, bool& trayOpen)
{
      // Seems not possible to get this values using ioctl...
      int         track1,track2;
      TMSF  leadOut;
      // If we can read, there's a media
      mediaPresent = GetAudioTracks(track1, track2, leadOut),
      trayOpen     = !mediaPresent;
      mediaChanged = (oldLeadOut.min!=leadOut.min) || (oldLeadOut.sec!=leadOut.sec) || (oldLeadOut.fr!=leadOut.fr);
      // Save old values
      oldLeadOut.min = leadOut.min;
      oldLeadOut.sec = leadOut.sec;
      oldLeadOut.fr  = leadOut.fr;
      // always success
      return true;
};

bool CDROM_Interface_Aspi::ReadSectors(PhysPt buffer, bool raw, unsigned long sector, unsigned long num)
{
      //SRB_ExecSCSICmd s;
      ASPI_SRB s;
      DWORD dwStatus;

      hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);

      memset(&s,0,sizeof(s));

      Bitu   buflen     = raw?2352*num:2048*num;
      Bit8u* bufdata    = new Bit8u[buflen];

      s.execscsicmd.SRB_Cmd        = SC_EXEC_SCSI_CMD;
      s.execscsicmd.SRB_HaId       = haId;
      s.execscsicmd.SRB_Target     = target;
      s.execscsicmd.SRB_Lun        = lun;
      s.execscsicmd.SRB_Flags      = SRB_DIR_IN | SRB_EVENT_NOTIFY;
      s.execscsicmd.SRB_SenseLen   = SENSE_LEN;

      s.execscsicmd.SRB_BufLen     = buflen;
      s.execscsicmd.SRB_BufPointer = (BYTE FAR*)bufdata;
      s.execscsicmd.SRB_CDBLen     = 12;
      s.execscsicmd.SRB_PostProc   = (LPVOID)hEvent;

      s.execscsicmd.CDBByte[0]     = 0xBE;
      s.execscsicmd.CDBByte[2]     = (unsigned char)((sector >> 24) & 0xFF);
      s.execscsicmd.CDBByte[3]     = (unsigned char)((sector >> 16) & 0xFF);
      s.execscsicmd.CDBByte[4]     = (unsigned char)((sector >> 8) & 0xFF);
      s.execscsicmd.CDBByte[5]     = (unsigned char)((sector & 0xFF));
      s.execscsicmd.CDBByte[6]     = (unsigned char)((num >> 16) & 0xFF);
      s.execscsicmd.CDBByte[7]     = (unsigned char)((num >>  8) & 0xFF);
      s.execscsicmd.CDBByte[8]     = (unsigned char) (num & 0xFF);
      s.execscsicmd.CDBByte[9]       = (raw?0xF0:0x10);

      ResetEvent(hEvent);

      dwStatus = pSendASPI32Command((LPSRB)&s);

      if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,0xFFFFFFFF);

      CloseHandle(hEvent);

      // Copy to PhysPt
      MEM_BlockWrite(buffer,bufdata,buflen);

      delete[] bufdata;

      return (s.execscsicmd.SRB_Status==SS_COMP);
};

#endif

Generated by  Doxygen 1.6.0   Back to index