public UnitSerialNumberVPDPage(byte[] buffer, int offset) { PeripheralQualifier = (byte)(buffer[offset + 0] >> 5); PeripheralDeviceType = (PeripheralDeviceType)(buffer[offset + 0] & 0x1F); PageCode = (VitalProductDataPageName)buffer[offset + 1]; PageLength = buffer[offset + 3]; ProductSerialNumber = ASCIIEncoding.ASCII.GetString(buffer, offset + 4, PageLength); }
public BlockDeviceCharacteristicsVPDPage(byte[] buffer, int offset) { PeripheralQualifier = (byte)(buffer[offset + 0] >> 5); PeripheralDeviceType = (PeripheralDeviceType)(buffer[offset + 0] & 0x1F); PageCode = (VitalProductDataPageName)buffer[offset + 1]; PageLength = buffer[offset + 3]; MediumRotationRate = BigEndianConverter.ToUInt16(buffer, offset + 4); Reserved = BigEndianConverter.ToUInt16(buffer, offset + 6); }
private SCSIStatusCodeName ReportLUNs(out byte[] response) { uint bytesReturned; uint outBufferLength = 4096; IntPtr outBuffer = Marshal.AllocHGlobal((int)outBufferLength); SCSIStatusCodeName status; if (!DeviceIoControl(m_handle, IOCTL_SCSI_GET_INQUIRY_DATA, IntPtr.Zero, 0, outBuffer, outBufferLength, out bytesReturned, IntPtr.Zero)) { Win32Error lastError = (Win32Error)Marshal.GetLastWin32Error(); Log(Severity.Error, "DeviceIoControl/IOCTL_SCSI_GET_INQUIRY_DATA error: {0}, Device path: {1}", lastError, m_path); response = VirtualSCSITarget.FormatSenseData(SenseDataParameter.GetIllegalRequestUnsupportedCommandCodeSenseData()); status = SCSIStatusCodeName.CheckCondition; } else { List <SCSI_INQUIRY_DATA> devices = SCSI_ADAPTER_BUS_INFO.GetInquiryDataForAllDevices(outBuffer); ReportLUNsParameter parameter = new ReportLUNsParameter(); foreach (SCSI_INQUIRY_DATA device in devices) { // If the device has been claimed by a class driver then passthrough IOCTLs must go through the class driver if (!device.DeviceClaimed) { PeripheralDeviceType deviceType = (PeripheralDeviceType)(device.InquiryData[0] & 0x1F); if (deviceType == PeripheralDeviceType.DirectAccessBlockDevice | deviceType == PeripheralDeviceType.SequentialAccessDevice | deviceType == PeripheralDeviceType.CDRomDevice) { byte?associatedLUN = m_logicalUnitManager.FindAssociatedLUN(device.PathId, device.TargetId, device.Lun); if (!associatedLUN.HasValue) { associatedLUN = m_logicalUnitManager.FindUnusedLUN(); LogicalUnit logicalUnit = new LogicalUnit(); logicalUnit.AssociatedLun = associatedLUN.Value; logicalUnit.PathId = device.PathId; logicalUnit.TargetId = device.TargetId; logicalUnit.TargetLun = device.Lun; logicalUnit.DeviceType = deviceType; m_logicalUnitManager.AddLogicalUnit(logicalUnit); Log(Severity.Verbose, "Assigned virtual LUN {0} to device PathId: {1}, TargetId: {2}, LUN: {3}", associatedLUN.Value, device.PathId, device.TargetId, device.Lun); } if (!associatedLUN.HasValue) { throw new NotImplementedException("The maximum number of LUNs supported has been reached"); } parameter.LUNList.Add(associatedLUN.Value); } } } response = parameter.GetBytes(); Log(Severity.Verbose, "DeviceIoControl/IOCTL_SCSI_GET_INQUIRY_DATA reported {0} usable devices", parameter.LUNList.Count); status = SCSIStatusCodeName.Good; } Marshal.FreeHGlobal(outBuffer); return(status); }
public SupportedVitaLProductDataPages(byte[] buffer, int offset) { PeripheralQualifier = (byte)(buffer[offset + 0] >> 5); PeripheralDeviceType = (PeripheralDeviceType)(buffer[offset + 0] & 0x1F); PageLength = buffer[offset + 3]; for (int index = 0; index < PageLength; index++) { SupportedPageList.Add(buffer[offset + 4 + index]); } }
public BlockLimitsVPDPage(byte[] buffer, int offset) { PeripheralQualifier = (byte)(buffer[offset + 0] >> 5); PeripheralDeviceType = (PeripheralDeviceType)(buffer[offset + 0] & 0x1F); PageCode = (VitalProductDataPageName)buffer[offset + 1]; PageLength = buffer[offset + 3]; OptimalTransferLengthGranularity = BigEndianConverter.ToUInt16(buffer, offset + 6); MaximumTransferLength = BigEndianConverter.ToUInt32(buffer, offset + 8); OptimalTransferLength = BigEndianConverter.ToUInt32(buffer, offset + 12); }
public static string strDeviceType(PeripheralDeviceType devtype) { switch (devtype) { case PeripheralDeviceType.BLOCK: return("Block Device"); case PeripheralDeviceType.CDROM: return("CD/DVD-ROM"); default: return("Unknown SCSI Device."); } }
public StandardInquiryData(byte[] buffer, int offset) { PeripheralQualifier = (byte)(buffer[offset + 0] >> 5); PeripheralDeviceType = (PeripheralDeviceType)(buffer[offset + 0] & 0x1F); RMB = (buffer[offset + 1] & 0x80) != 0; Version = buffer[offset + 2]; if (Version != 2) { return; } NormACA = (buffer[offset + 3] & 0x20) != 0; HiSup = (buffer[offset + 3] & 0x10) != 0; ResponseDataFormat = (byte)(buffer[offset + 3] & 0x0F); AdditionalLength = buffer[offset + 4]; if (AdditionalLength < 91) // Standard Inquiry data should be at least 96 bytes (so the AdditionalLength must be at least 96 - 5) { return; } SCCS = (buffer[offset + 5] & 0x80) != 0; ACC = (buffer[offset + 5] & 0x40) != 0; TPGS = (byte)((buffer[offset + 5] >> 4) & 0x03); ThirdPartyCopy = (buffer[offset + 5] & 0x08) != 0; Protect = (buffer[offset + 5] & 0x01) != 0; EncServ = (buffer[offset + 6] & 0x40) != 0; VS1 = (buffer[offset + 6] & 0x20) != 0; MultiP = (buffer[offset + 6] & 0x10) != 0; MChngr = (buffer[offset + 6] & 0x08) != 0; Addr16 = (buffer[offset + 6] & 0x01) != 0; WBus16 = (buffer[offset + 7] & 0x20) != 0; Sync = (buffer[offset + 7] & 0x10) != 0; CmdQue = (buffer[offset + 7] & 0x02) != 0; VS2 = (buffer[offset + 7] & 0x01) != 0; VendorIdentification = Encoding.ASCII.GetString(buffer, 8, 8); ProductIdentification = Encoding.ASCII.GetString(buffer, 16, 16); ProductRevisionLevel = Encoding.ASCII.GetString(buffer, 32, 4); DriveSerialNumber = BigEndianConverter.ToUInt64(buffer, 36); Clocking = (byte)((buffer[offset + 56] >> 2) & 0x03); QAS = (buffer[offset + 56] & 0x02) != 0; IUS = (buffer[offset + 56] & 0x01) != 0; for (int index = 0; index < 8; index++) { VersionDescriptorName versionDescriptor = (VersionDescriptorName)BigEndianConverter.ToUInt16(buffer, offset + 58 + index * 2); VersionDescriptors.Add(versionDescriptor); } }
public static uint GetDeviceReadTransferLength(byte[] commandBytes, PeripheralDeviceType deviceType, uint blockSize) { if (deviceType == PeripheralDeviceType.DirectAccessBlockDevice || deviceType == PeripheralDeviceType.CDRomDevice) { return(GetBlockDeviceReadTransferLength(commandBytes, blockSize)); } else if (deviceType == PeripheralDeviceType.SequentialAccessDevice) { return(SCSICommandParser.GetSequentialAccessDeviceReadTransferLength(commandBytes, blockSize)); } throw new NotSupportedException("Device Type Not Supported!"); }
public DeviceIdentificationVPDPage(byte[] buffer, int offset) { PeripheralQualifier = (byte)(buffer[offset + 0] >> 5); PeripheralDeviceType = (PeripheralDeviceType)(buffer[offset + 0] & 0x1F); PageCode = (VitalProductDataPageName)buffer[offset + 1]; PageLength = BigEndianConverter.ToUInt16(buffer, 2); int parameterOffset = 4; while (parameterOffset < PageLength) { IdentificationDescriptor descriptor = new IdentificationDescriptor(buffer, offset + parameterOffset); IdentificationDescriptorList.Add(descriptor); parameterOffset += descriptor.Length; } }
// Parse CDB allocation length (bytes) based on SPC-3, SSC-3, and SBC-3 public static uint GetCDBTransferLength(byte[] commandBytes, PeripheralDeviceType deviceType) { switch ((SCSIOpCodeName)commandBytes[0]) { case SCSIOpCodeName.RecoverBufferedData: // DATA_IN (2-4) return(BigEndianReader.ReadUInt24(commandBytes, 2)); case SCSIOpCodeName.ReadBlockLimits: // DATA_IN (6 bytes) return(6); case SCSIOpCodeName.ReadCapacity10: // DATA_IN (8 bytes) return(8); case SCSIOpCodeName.ReadPosition: // DATA_IN (7-8) if (deviceType == PeripheralDeviceType.SequentialAccessDevice) { if (commandBytes[1] == 0x00 || commandBytes[1] == 0x01) { return(20); } else if (commandBytes[1] == 0x06) { return(32); } else { return(BigEndianConverter.ToUInt16(commandBytes, 7)); } } else { return(BigEndianConverter.ToUInt16(commandBytes, 7)); } case SCSIOpCodeName.ReportDensitySupport: // DATA_IN (7-8) case SCSIOpCodeName.LogSelect10: // DATA_IN (7-8) case SCSIOpCodeName.LogSense10: // DATA_IN (7-8) case SCSIOpCodeName.ModeSelect10: // DATA_IN (7-8) case SCSIOpCodeName.ModeSense10: // DATA_IN (7-8) case SCSIOpCodeName.PersistentReserveIn: // DATA_IN (7-8) case SCSIOpCodeName.ReadLong10: // DATA_IN (7-8) case SCSIOpCodeName.ReadDefectData10: // DATA_IN (7-8) return(BigEndianConverter.ToUInt16(commandBytes, 7)); case SCSIOpCodeName.ModeSelect6: // DATA_IN (4) case SCSIOpCodeName.ModeSense6: // DATA_IN (4) case SCSIOpCodeName.RequestSense: // DATA_IN (4) return((uint)commandBytes[4]); case SCSIOpCodeName.ReadAttribute16: // DATA_IN (10-13) case SCSIOpCodeName.ThirdPartyCopyIn: // DATA_IN (10-13) ? return(BigEndianConverter.ToUInt32(commandBytes, 10)); case SCSIOpCodeName.ReadBuffer10: // DATA_IN (6-8) return(BigEndianReader.ReadUInt24(commandBytes, 6)); case SCSIOpCodeName.ReceiveDiagnosticResults: // DATA_IN (3-4) case SCSIOpCodeName.Inquiry: // DATA_IN (3-4) return(BigEndianConverter.ToUInt16(commandBytes, 3)); case SCSIOpCodeName.ReportLUNs: // DATA_IN (6-9) case SCSIOpCodeName.SecurityProtocolIn: // DATA_IN (6-9) case SCSIOpCodeName.ReadDefectData12: // DATA_IN (6-9) return(BigEndianConverter.ToUInt32(commandBytes, 6)); case SCSIOpCodeName.ServiceActionIn16: if (commandBytes[1] == (byte)ServiceAction.ReadLong16) // DATA_IN (12-13) { return(BigEndianConverter.ToUInt16(commandBytes, 12)); } if (commandBytes[1] == (byte)ServiceAction.ReadCapacity16) // DATA_IN (10-13) { return(BigEndianConverter.ToUInt32(commandBytes, 10)); } return(512); default: // XXX: Need to complete SBC-3 (ex: XDREAD) return(512); } }