// ---------------------------------------------- // - ASPIFUNC implementation file - // - Written 1996-1998 by Christoph Schmelnik - // ---------------------------------------------- // Version 1.40 : 24.02.1998 // Changes: // Set correct direction flags, to work with NT device IO interface and ATAPI drives // Added Immediate paremeter for WaitSCSIRequest to allow detection of buffer underruns #include #include "aspifunc.h" HMODULE hDLL=0; VOIDPROC GetASPI32SupportInfo; SRBPROC SendASPI32Command; int ASPIInstalled; int RunningNT; int NumberOfHostAdapters; //Implementation of base ASPI Functions BOOL HAInquiry(int HostAdapterNumber,char *ManagerID, char *HAID,THAUnique &HAUnique) { SRB_HAInquiry MySRB; DWORD ASPI_Status; memset(&MySRB,0,sizeof(SRB_HAInquiry)); MySRB.SRB_Cmd = SC_HA_INQUIRY; MySRB.SRB_HaId = HostAdapterNumber; MySRB.SRB_Flags = 0; MySRB.SRB_Hdr_Rsvd = 0; ASPI_Status = SendASPI32Command ( (LPSRB) &MySRB ); if (ASPI_Status!=SS_COMP) return FALSE; HAUnique=MySRB.HA_Unique; for (int i=0; i<16; i++) { ManagerID[i]=MySRB.HA_ManagerId[i]; HAID[i]=MySRB.HA_Identifier[i]; } ManagerID[16]=0; HAID[16]=0; return TRUE; } int GetDeviceType(int HostAdapterNumber,int TargetId,int LUN) { SRB_GDEVBlock MySRB; DWORD ASPI_Status; memset(&MySRB,0,sizeof(SRB_GDEVBlock)); MySRB.SRB_Cmd = SC_GET_DEV_TYPE; MySRB.SRB_HaId = HostAdapterNumber; MySRB.SRB_Flags = 0; MySRB.SRB_Hdr_Rsvd = 0; MySRB.SRB_Target = TargetId; MySRB.SRB_Lun = LUN; ASPI_Status = SendASPI32Command ((LPSRB)&MySRB); /***************************************************/ /* If ASPI_Status == SS_COMP, MySRB.SRB_DeviceType */ /* will contain the peripheral device type. */ /***************************************************/ if (ASPI_Status==SS_COMP) return MySRB.SRB_DeviceType; return DTYPE_UNKNOWN; } BOOL ExecuteSCSIRequest(int HostAdapterNumber,int TargetId,int LUN,int RequestFlags, TOpcode OpC, BYTE OpCLen,void *DataPtr, int DataLen, HANDLE hDriveEvent) { if ((HostAdapterNumber>=NumberOfHostAdapters) && RunningNT) { DWORD il, ol; SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER sb; ZeroMemory(&sb, sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER)); sb.sptd.Length = sizeof(SCSI_PASS_THROUGH_DIRECT); sb.sptd.CdbLength = OpCLen; sb.sptd.DataIn = ((SRB_DIR_IN & RequestFlags) ? 1/*SCSI_IOCTL_DATA_IN*/ : 0/*SCSI_IOCTL_DATA_OUT*/); sb.sptd.SenseInfoLength = 32; sb.sptd.DataTransferLength = DataLen; sb.sptd.TimeOutValue = 2; sb.sptd.DataBuffer = (unsigned char*) DataPtr; sb.sptd.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, ucSenseBuf); for (int i=0; i=NumberOfHostAdapters) && RunningNT) { MySRB.SRB_Flags = RequestFlags; } else { MySRB.SRB_Flags = RequestFlags|SRB_EVENT_NOTIFY; MySRB.SRB_Hdr_Rsvd = 0; MySRB.SRB_PostProc = (void(__cdecl *)(void))hDriveEvent; } MySRB.SRB_Target = TargetId; MySRB.SRB_Lun = LUN; MySRB.SRB_BufPointer = (unsigned char*) DataPtr; MySRB.SRB_BufLen = DataLen; MySRB.SRB_CDBLen = OpCLen; MySRB.SRB_SenseLen = SENSE_LEN; for (int i=0; i=NumberOfHostAdapters) && RunningNT) { DWORD il, ol; SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER sb; ZeroMemory(&sb, sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER)); sb.sptd.Length = sizeof(SCSI_PASS_THROUGH_DIRECT); sb.sptd.PathId = 0; sb.sptd.TargetId = 1; sb.sptd.Lun = 0; sb.sptd.CdbLength = MySRB.SRB_CDBLen; sb.sptd.DataIn = MySRB.SRB_Flags; sb.sptd.SenseInfoLength = 32; sb.sptd.DataTransferLength = MySRB.SRB_BufLen; sb.sptd.TimeOutValue = TIMEOUT; sb.sptd.DataBuffer = MySRB.SRB_BufPointer; sb.sptd.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, ucSenseBuf); for (int i=0; i=NumberOfHostAdapters) && RunningNT) return MySRB.SRB_Status; if ((MySRB.SRB_Status == SS_PENDING) && !bImmediate) { DWORD ASPIEventStatus = WaitForSingleObject(hDriveEvent, 100); if (ASPIEventStatus == WAIT_OBJECT_0) { ResetEvent(hDriveEvent); } } return MySRB.SRB_Status; } BOOL AbortSCSIRequest(SRB_ExecSCSICmd &StuckSRB) { SRB_Abort AbortSRB; DWORD ASPIStatus; AbortSRB.SRB_Cmd = SC_ABORT_SRB; AbortSRB.SRB_HaId = StuckSRB.SRB_HaId; AbortSRB.SRB_Flags = 0; AbortSRB.SRB_Hdr_Rsvd = 0; AbortSRB.SRB_ToAbort = (LPSRB)&StuckSRB; ASPIStatus = SendASPI32Command ( (LPSRB)&AbortSRB ); return (ASPIStatus==SS_COMP); } int GetDeviceInfo(int HostAdapterNumber,int TargetId,int LUN,BYTE &SCSIType,char *VendorID, char *ProductID,char *ProductRevision,HANDLE hDriveEvent) { struct InquireFormat { BYTE ConfigPara[8]; char VendorID[8]; char ProductID[16]; char ProductRevision[4]; } DeviceInfo; TOpcode OpC; OpC[0]=0x12; OpC[1]=0; OpC[2]=0; OpC[3]=0; OpC[4]=sizeof(DeviceInfo); OpC[5]=0; memset(&DeviceInfo,0,sizeof(DeviceInfo)); BOOL r=ExecuteSCSIRequest(HostAdapterNumber,TargetId,LUN,SRB_DIR_IN,OpC,6,(void*)&DeviceInfo,sizeof(DeviceInfo),hDriveEvent); if (r) { for (int i=0; i<16; i++) { if (i<8) VendorID[i]=DeviceInfo.VendorID[i]; ProductID[i]=DeviceInfo.ProductID[i]; if (i<4) ProductRevision[i]=DeviceInfo.ProductRevision[i]; } VendorID[8]=0; ProductID[16]=0; ProductRevision[4]=0; SCSIType=DeviceInfo.ConfigPara[2] & 0x0f; return DeviceInfo.ConfigPara[0]; } return DTYPE_UNKNOWN; } BOOL TestUnitReady(int HostAdapterNumber,int TargetId,int LUN,HANDLE hDriveEvent) { TOpcode OpC; OpC[0]=0; OpC[1]=0; OpC[2]=0; OpC[3]=0; OpC[4]=0; OpC[5]=0; return ExecuteSCSIRequest(HostAdapterNumber,TargetId,LUN,SRB_DIR_IN,OpC,6,NULL,0,hDriveEvent); } BOOL ModeSense(int HostAdapterNumber,int TargetId,int LUN,TDriveMode &ModeData,int Size,int PageCode,HANDLE hDriveEvent) { // while (!TestUnitReady(HostAdapterNumber,TargetId,LUN)); TOpcode OpC; OpC[0]=0x1a; OpC[1]=0x00; OpC[2]=PageCode; OpC[3]=0x00; OpC[4]=Size; OpC[5]=0x00; return ExecuteSCSIRequest(HostAdapterNumber,TargetId,LUN,SRB_DIR_IN,OpC,6,(void *)&ModeData,Size,hDriveEvent); } BOOL ATAPIModeSense(int HostAdapterNumber,int TargetId,int LUN,TDriveMode &ModeData,int Size,int PageCode,HANDLE hDriveEvent) { // while (!TestUnitReady(HostAdapterNumber,TargetId,LUN)); TOpcode OpC; OpC[0]=0x5a; OpC[1]=0x00; OpC[2]=PageCode; OpC[3]=0x00; OpC[4]=0x00; OpC[5]=0x00; OpC[6]=0x00; OpC[7]=0x00; OpC[8]=Size; OpC[9]=0x00; OpC[10]=0x00; OpC[11]=0x00; return ExecuteSCSIRequest(HostAdapterNumber,TargetId,LUN,SRB_DIR_IN,OpC,12,(void *)&ModeData,Size,hDriveEvent); } BOOL addModeSense(int HostAdapterNumber,int TargetId,int LUN,TDriveMode &ModeData,int Size,HANDLE hDriveEvent) { // while (!TestUnitReady(HostAdapterNumber,TargetId,LUN)); TOpcode OpC; OpC[0]=0xca; OpC[1]=0x08; OpC[2]=0x0f; OpC[3]=0x00; OpC[4]=0x00; OpC[5]=0x00; OpC[6]=0x00; OpC[7]=0x00; OpC[8]=Size; OpC[9]=0x00; return ExecuteSCSIRequest(HostAdapterNumber,TargetId,LUN,SRB_DIR_IN,OpC,10,(void *)&ModeData,Size,hDriveEvent); } BOOL ModeSelect(int HostAdapterNumber,int TargetId,int LUN,TDriveMode &ModeData,int Size,HANDLE hDriveEvent) { // while (!TestUnitReady(HostAdapterNumber,TargetId,LUN)); TOpcode OpC; OpC[0]=0x15; if (Size==12) OpC[1]=0x00; else OpC[1]=0x10; OpC[2]=0x00; OpC[3]=0x00; OpC[4]=Size; OpC[5]=0x00; return ExecuteSCSIRequest(HostAdapterNumber,TargetId,LUN,SRB_DIR_OUT,OpC,6,(void *)&ModeData,Size,hDriveEvent); } BOOL addModeSelect(int HostAdapterNumber,int TargetId,int LUN,TDriveMode &ModeData,int Size,HANDLE hDriveEvent) { // while (!TestUnitReady(HostAdapterNumber,TargetId,LUN)); TOpcode OpC; OpC[0]=0xc5; OpC[1]=0x10; OpC[2]=0x00; OpC[3]=0x00; OpC[4]=0x00; OpC[5]=0x00; OpC[6]=0x00; OpC[7]=0x00; OpC[8]=Size; OpC[9]=0x00; return ExecuteSCSIRequest(HostAdapterNumber,TargetId,LUN,SRB_DIR_OUT,OpC,10,(void *)&ModeData,Size,hDriveEvent); } BOOL SCSIMaxBlocks(HANDLE fh, int *mb) { DWORD ol; IO_SCSI_CAPABILITIES ca; if (DeviceIoControl(fh,IOCTL_SCSI_GET_CAPABILITIES,NULL,0, &ca,sizeof(IO_SCSI_CAPABILITIES),&ol,NULL)) { *mb=(int)ca.MaximumTransferLength; return TRUE; } return FALSE; }