/*************************************************************************** ioctrl.c - description ------------------- begin : Sun Nov 16 2003 copyright : (C) 2003 by Pete Bernert email : BlackDove@addcom.de ***************************************************************************/ /*************************************************************************** * * * 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. See also the license.txt file for * * additional informations. * * * ***************************************************************************/ //*************************************************************************// // History of changes: // // 2003/11/16 - Pete // - generic cleanup for the Peops release // //*************************************************************************// ///////////////////////////////////////////////////////// #include "stdafx.h" #define _IN_IOCTL #include "externals.h" ///////////////////////////////////////////////////////// HANDLE hIOCTL=NULL; // global drive file handle DWORD dwIOCTLAttr=0; // open attribute OVERLAPPED ovcIOCTL; // global overlapped struct SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER sptIOCTL; // global read bufs RAW_READ_INFO rawIOCTL; ///////////////////////////////////////////////////////// // open drive void OpenIOCTLHandle(int iA,int iT,int iL) { char cLetter; if(hIOCTL) return; cLetter=MapIOCTLDriveLetter(iA,iT,iL); // get drive if(!cLetter) return; hIOCTL=OpenIOCTLFile(cLetter, // open drive (iUseCaching==2)?TRUE:FALSE); // (caching:2 -> overlapped) } ///////////////////////////////////////////////////////// // close drive void CloseIOCTLHandle(void) { if(hIOCTL) CloseHandle(hIOCTL); hIOCTL=NULL; } ///////////////////////////////////////////////////////// // get drive letter by a,t,l char MapIOCTLDriveLetter(int iA,int iT,int iL) { char cLetter[4];int iDA,iDT,iDL;HANDLE hF; strcpy(cLetter,"C:\\"); for(cLetter[0]='C';cLetter[0]<='Z';cLetter[0]++) { if(GetDriveType(cLetter)==DRIVE_CDROM) { hF=OpenIOCTLFile(cLetter[0],FALSE); GetIOCTLAdapter(hF,&iDA,&iDT,&iDL); CloseHandle(hF); if(iA==iDA && iT==iDT && iL==iDL) return cLetter[0]; } } return 0; } ///////////////////////////////////////////////////////// // get cd drive list, using ioctl, not aspi int GetIOCTLCDDrives(char * pDList) { char cLetter[4];int iDA,iDT,iDL;HANDLE hF; int iCnt=0;char * p=pDList; strcpy(cLetter,"C:\\"); for(cLetter[0]='C';cLetter[0]<='Z';cLetter[0]++) { if(GetDriveType(cLetter)==DRIVE_CDROM) { hF=OpenIOCTLFile(cLetter[0],FALSE); GetIOCTLAdapter(hF,&iDA,&iDT,&iDL); CloseHandle(hF); if(iDA!=-1 && iDT!=-1 && iDL!=-1) { wsprintf(p,"[%d:%d:%d] Drive %c:", iDA,iDT,iDL,cLetter[0]); p+=strlen(p)+1; iCnt++; } } } return iCnt; } ///////////////////////////////////////////////////////// // open drive in sync/async mode HANDLE OpenIOCTLFile(char cLetter,BOOL bAsync) { HANDLE hF;char szFName[16]; OSVERSIONINFO ov;DWORD dwFlags; 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) // mmm... no success? { dwFlags^=GENERIC_WRITE; // -> try write toggle hF=CreateFile(szFName,dwFlags,FILE_SHARE_READ, // -> open drive again NULL,OPEN_EXISTING,dwIOCTLAttr,NULL); if(hF==INVALID_HANDLE_VALUE) return NULL; } return hF; } ///////////////////////////////////////////////////////// // get a,t,l void 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; } ///////////////////////////////////////////////////////// // we fake the aspi call in ioctl scsi mode DWORD IOCTLSendASPI32Command(LPSRB pSRB) { LPSRB_ExecSCSICmd pSC;DWORD dwRet;BOOL bStat; if(!pSRB) return SS_ERR; if(hIOCTL==NULL || pSRB->SRB_Cmd!=SC_EXEC_SCSI_CMD) // we only fake exec aspi scsi commands { pSRB->SRB_Status=SS_ERR; return SS_ERR; } pSC=(LPSRB_ExecSCSICmd)pSRB; memset(&sptIOCTL,0,sizeof(sptIOCTL)); sptIOCTL.spt.Length = sizeof(SCSI_PASS_THROUGH_DIRECT); sptIOCTL.spt.CdbLength = pSC->SRB_CDBLen; sptIOCTL.spt.DataTransferLength = pSC->SRB_BufLen; sptIOCTL.spt.TimeOutValue = 60; sptIOCTL.spt.DataBuffer = pSC->SRB_BufPointer; sptIOCTL.spt.SenseInfoLength = 14; sptIOCTL.spt.TargetId = pSC->SRB_Target; sptIOCTL.spt.Lun = pSC->SRB_Lun; sptIOCTL.spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, ucSenseBuf); if(pSC->SRB_Flags&SRB_DIR_IN) sptIOCTL.spt.DataIn = SCSI_IOCTL_DATA_IN; else if(pSC->SRB_Flags&SRB_DIR_OUT) sptIOCTL.spt.DataIn = SCSI_IOCTL_DATA_OUT; else sptIOCTL.spt.DataIn = SCSI_IOCTL_DATA_UNSPECIFIED; memcpy(sptIOCTL.spt.Cdb,pSC->CDBByte,pSC->SRB_CDBLen); if(dwIOCTLAttr==FILE_FLAG_OVERLAPPED) // async? { ovcIOCTL.Internal=0; ovcIOCTL.InternalHigh=0; ovcIOCTL.Offset=0; ovcIOCTL.OffsetHigh=0; ovcIOCTL.hEvent=hEvent; bStat = DeviceIoControl(hIOCTL, IOCTL_SCSI_PASS_THROUGH_DIRECT, &sptIOCTL, sizeof(sptIOCTL), &sptIOCTL, sizeof(sptIOCTL), &dwRet, &ovcIOCTL); } else // sync? { bStat = DeviceIoControl(hIOCTL, IOCTL_SCSI_PASS_THROUGH_DIRECT, &sptIOCTL, sizeof(sptIOCTL), &sptIOCTL, sizeof(sptIOCTL), &dwRet, NULL); } if(!bStat) // some err? { DWORD dwErrCode; dwErrCode=GetLastError(); if(dwErrCode==ERROR_IO_PENDING) // -> pending? { pSC->SRB_Status=SS_COMP; // --> ok return SS_PENDING; } pSC->SRB_Status=SS_ERR; // -> else error return SS_ERR; } pSC->SRB_Status=SS_COMP; return SS_COMP; } ///////////////////////////////////////////////////////// // special raw mode... works on TEAC532S, for example DWORD ReadIOCTL_Raw(BOOL bWait,FRAMEBUF * f) { DWORD dwRet;BOOL bStat; if(hIOCTL==NULL) return SS_ERR; rawIOCTL.DiskOffset.QuadPart = f->dwFrame*2048; // 2048 is needed here rawIOCTL.SectorCount = f->dwFrameCnt; rawIOCTL.TrackMode = XAForm2;//CDDA;//YellowMode2;//XAForm2; if(dwIOCTLAttr==FILE_FLAG_OVERLAPPED) // async? { ovcIOCTL.Internal=0; ovcIOCTL.InternalHigh=0; ovcIOCTL.Offset=0; ovcIOCTL.OffsetHigh=0; ovcIOCTL.hEvent=hEvent; ResetEvent(hEvent); bStat = DeviceIoControl(hIOCTL, IOCTL_CDROM_RAW_READ, &rawIOCTL,sizeof(RAW_READ_INFO), &(f->BufData[0]),f->dwBufLen,//2048, &dwRet, &ovcIOCTL); } else // sync? { bStat = DeviceIoControl(hIOCTL, IOCTL_CDROM_RAW_READ, &rawIOCTL,sizeof(RAW_READ_INFO), &(f->BufData[0]),f->dwBufLen,//2048, &dwRet,NULL); } if(!bStat) { DWORD dwErrCode; dwErrCode=GetLastError(); #ifdef DBGOUT auxprintf("errorcode %d\n", dwErrCode); #endif if(dwErrCode==ERROR_IO_PENDING) { // we do a wait here, not later... no real async mode anyway // bDoWaiting=TRUE; WaitGenEvent(0xFFFFFFFF); } else { sx.SRB_Status=SS_ERR; return SS_ERR; } } sx.SRB_Status=SS_COMP; return SS_COMP; } ///////////////////////////////////////////////////////// // special raw + special sub... dunno if this really // works on any drive (teac is working, but giving unprecise // subdata) DWORD ReadIOCTL_Raw_Sub(BOOL bWait,FRAMEBUF * f) { DWORD dwRet;BOOL bStat; SUB_Q_CHANNEL_DATA qd;unsigned char * p; CDROM_SUB_Q_DATA_FORMAT qf; if(hIOCTL==NULL) return SS_ERR; rawIOCTL.DiskOffset.QuadPart = f->dwFrame*2048; rawIOCTL.SectorCount = f->dwFrameCnt; rawIOCTL.TrackMode = XAForm2; bStat = DeviceIoControl(hIOCTL, IOCTL_CDROM_RAW_READ, &rawIOCTL,sizeof(RAW_READ_INFO), &(f->BufData[0]),f->dwBufLen, &dwRet,NULL); if(!bStat) {sx.SRB_Status=SS_ERR;return SS_ERR;} qf.Format=IOCTL_CDROM_CURRENT_POSITION; qf.Track=1; bStat = DeviceIoControl(hIOCTL, IOCTL_CDROM_READ_Q_CHANNEL, &qf,sizeof(CDROM_SUB_Q_DATA_FORMAT), &qd,sizeof(SUB_Q_CHANNEL_DATA), &dwRet,NULL); p=(unsigned char*)&qd; SubCData[12]=(p[5]<<4)|(p[5]>>4); SubCData[13]=p[6]; SubCData[14]=p[7]; SubCData[15]=p[13]; SubCData[16]=p[14]; SubCData[17]=p[15]; SubCData[18]=0; SubCData[19]=p[9]; SubCData[20]=p[10]; SubCData[21]=p[11]; SubCData[15]=itob(SubCData[15]); SubCData[16]=itob(SubCData[16]); SubCData[17]=itob(SubCData[17]); SubCData[19]=itob(SubCData[19]); SubCData[20]=itob(SubCData[20]); SubCData[21]=itob(SubCData[21]); if(!bStat) {sx.SRB_Status=SS_ERR;return SS_ERR;} sx.SRB_Status=SS_COMP; return SS_COMP; } /////////////////////////////////////////////////////////