public SCSIStatusCodeName Read(SCSICommandDescriptorBlock command, LUNStructure lun, out byte[] response) { Disk disk = m_disks[lun]; int sectorCount = (int)command.TransferLength; Log(Severity.Verbose, "LUN {0}: Reading {1} blocks starting from LBA {2}", (ushort)lun, sectorCount, (long)command.LogicalBlockAddress64); try { response = disk.ReadSectors((long)command.LogicalBlockAddress64, sectorCount); return(SCSIStatusCodeName.Good); } catch (ArgumentOutOfRangeException) { Log(Severity.Error, "Read error: LBA out of range"); response = FormatSenseData(SenseDataParameter.GetIllegalRequestLBAOutOfRangeSenseData()); return(SCSIStatusCodeName.CheckCondition); } catch (CyclicRedundancyCheckException) { Log(Severity.Error, "Read error: CRC error"); response = FormatSenseData(SenseDataParameter.GetWriteFaultSenseData()); return(SCSIStatusCodeName.CheckCondition); } catch (IOException ex) { Log(Severity.Error, "Read error: {0}", ex.ToString()); response = FormatSenseData(SenseDataParameter.GetMediumErrorUnrecoverableReadErrorSenseData()); return(SCSIStatusCodeName.CheckCondition); } }
public SCSIStatusCodeName Write(SCSICommandDescriptorBlock command, LUNStructure lun, byte[] data, out byte[] response) { Disk disk = m_disks[lun]; if (disk.IsReadOnly) { Log(Severity.Verbose, "LUN {0}: Refused attempt to write to a read-only disk", lun); SenseDataParameter senseData = SenseDataParameter.GetDataProtectSenseData(); response = senseData.GetBytes(); return(SCSIStatusCodeName.CheckCondition); } Log(Severity.Verbose, "LUN {0}: Writing {1} blocks starting from LBA {2}", (ushort)lun, command.TransferLength, (long)command.LogicalBlockAddress64); try { disk.WriteSectors((long)command.LogicalBlockAddress64, data); response = new byte[0]; return(SCSIStatusCodeName.Good); } catch (ArgumentOutOfRangeException) { Log(Severity.Error, "Write error: LBA out of range"); response = FormatSenseData(SenseDataParameter.GetIllegalRequestLBAOutOfRangeSenseData()); return(SCSIStatusCodeName.CheckCondition); } catch (IOException ex) { Log(Severity.Error, "Write error: {0}", ex.ToString()); response = FormatSenseData(SenseDataParameter.GetMediumErrorWriteFaultSenseData()); return(SCSIStatusCodeName.CheckCondition); } }
/// <summary> /// This implementation is not thread-safe. /// </summary> public override SCSIStatusCodeName ExecuteCommand(byte[] commandBytes, LUNStructure lun, byte[] data, out byte[] response) { SCSICommandDescriptorBlock command; try { command = SCSICommandDescriptorBlock.FromBytes(commandBytes, 0); } catch (UnsupportedSCSICommandException) { Log(Severity.Error, "Unsupported SCSI Command (0x{0})", commandBytes[0].ToString("X")); response = FormatSenseData(SenseDataParameter.GetIllegalRequestUnsupportedCommandCodeSenseData()); return(SCSIStatusCodeName.CheckCondition); } return(ExecuteCommand(command, lun, data, out response)); }
/// <summary> /// This implementation is not thread-safe. /// </summary> public SCSIStatusCodeName ExecuteCommand(SCSICommandDescriptorBlock command, LUNStructure lun, byte[] data, out byte[] response) { Log(Severity.Verbose, "Executing command: {0}", command.OpCode); if (command.OpCode == SCSIOpCodeName.ReportLUNs) { uint allocationLength = command.TransferLength; return(ReportLUNs(allocationLength, out response)); } else if (lun >= m_disks.Count) { Log(Severity.Warning, "Initiator error: tried to execute command on LUN {0} which does not exist", lun); response = FormatSenseData(SenseDataParameter.GetIllegalRequestInvalidLUNSenseData()); return(SCSIStatusCodeName.CheckCondition); } else if (command.OpCode == SCSIOpCodeName.TestUnitReady) { return(TestUnitReady(lun, out response)); } else if (command.OpCode == SCSIOpCodeName.RequestSense) { uint allocationLength = command.TransferLength; return(RequestSense(lun, allocationLength, out response)); } else if (command.OpCode == SCSIOpCodeName.Inquiry) { return(Inquiry((InquiryCommand)command, lun, out response)); } else if (command.OpCode == SCSIOpCodeName.Reserve6) { return(Reserve6(lun, out response)); } else if (command.OpCode == SCSIOpCodeName.Release6) { return(Release6(lun, out response)); } else if (command.OpCode == SCSIOpCodeName.ModeSense6) { return(ModeSense6((ModeSense6CommandDescriptorBlock)command, lun, out response)); } else if (command.OpCode == SCSIOpCodeName.ReadCapacity10) { return(ReadCapacity10(lun, out response)); } else if (command.OpCode == SCSIOpCodeName.Read6 || command.OpCode == SCSIOpCodeName.Read10 || command.OpCode == SCSIOpCodeName.Read16) { return(Read(command, lun, out response)); } else if (command.OpCode == SCSIOpCodeName.Write6 || command.OpCode == SCSIOpCodeName.Write10 || command.OpCode == SCSIOpCodeName.Write16) { return(Write(command, lun, data, out response)); } else if (command.OpCode == SCSIOpCodeName.Verify10 || command.OpCode == SCSIOpCodeName.Verify16) { return(Verify(lun, out response)); } else if (command.OpCode == SCSIOpCodeName.SynchronizeCache10) { return(SynchronizeCache10(lun, out response)); } else if (command.OpCode == SCSIOpCodeName.ServiceActionIn16 && command.ServiceAction == ServiceAction.ReadCapacity16) { uint allocationLength = command.TransferLength; return(ReadCapacity16(lun, allocationLength, out response)); } else { Log(Severity.Error, "Unsupported SCSI Command (0x{0})", command.OpCode.ToString("X")); response = FormatSenseData(SenseDataParameter.GetIllegalRequestUnsupportedCommandCodeSenseData()); return(SCSIStatusCodeName.CheckCondition); } }