bool ScsiReadBlocks(out byte[] buffer, ulong block, uint count, out double duration, out bool recoveredError, out bool blankCheck) { bool sense; byte[] senseBuf; buffer = null; duration = 0; recoveredError = false; blankCheck = false; if (CanReadRaw) { if (_readLong16) { sense = _dev.ReadLong16(out buffer, out senseBuf, false, block, LongBlockSize, _timeout, out duration); } else if (_readLong10) { sense = _dev.ReadLong10(out buffer, out senseBuf, false, false, (uint)block, (ushort)LongBlockSize, _timeout, out duration); } else if (_syqReadLong10) { sense = _dev.SyQuestReadLong10(out buffer, out senseBuf, (uint)block, LongBlockSize, _timeout, out duration); } else if (_syqReadLong6) { sense = _dev.SyQuestReadLong6(out buffer, out senseBuf, (uint)block, LongBlockSize, _timeout, out duration); } else if (_hldtstReadRaw) { sense = _dev.HlDtStReadRawDvd(out buffer, out senseBuf, (uint)block, LongBlockSize, _timeout, out duration); } else if (_plextorReadRaw) { sense = _dev.PlextorReadRawDvd(out buffer, out senseBuf, (uint)block, LongBlockSize, _timeout, out duration); } else { return(true); } } else { if (_read6) { sense = _dev.Read6(out buffer, out senseBuf, (uint)block, LogicalBlockSize, (byte)count, _timeout, out duration); } else if (_read10) { sense = _dev.Read10(out buffer, out senseBuf, 0, false, false, false, false, (uint)block, LogicalBlockSize, 0, (ushort)count, _timeout, out duration); } else if (_read12) { sense = _dev.Read12(out buffer, out senseBuf, 0, false, false, false, false, (uint)block, LogicalBlockSize, 0, count, false, _timeout, out duration); } else if (_read16) { sense = _dev.Read16(out buffer, out senseBuf, 0, false, false, false, block, LogicalBlockSize, 0, count, false, _timeout, out duration); } else { return(true); } } if (sense || _dev.Error) { _errorLog?.WriteLine(block, _dev.Error, _dev.LastError, senseBuf); } if (!sense && !_dev.Error) { return(false); } recoveredError = Sense.DecodeFixed(senseBuf)?.SenseKey == SenseKeys.RecoveredError || Sense.DecodeDescriptor(senseBuf)?.SenseKey == SenseKeys.RecoveredError; blankCheck = Sense.DecodeFixed(senseBuf)?.SenseKey == SenseKeys.BlankCheck || Sense.DecodeDescriptor(senseBuf)?.SenseKey == SenseKeys.BlankCheck; AaruConsole.DebugWriteLine("SCSI Reader", "READ error:\n{0}", Sense.PrettifySense(senseBuf)); return(sense); }
/// <summary>Register an SCSI error after trying to read</summary> /// <param name="block">Starting block</param> /// <param name="osError"><c>true</c> if operating system returned an error status instead of the device</param> /// <param name="errno">Operating system error number</param> /// <param name="senseBuffer">REQUEST SENSE response buffer</param> public void WriteLine(ulong block, bool osError, int errno, byte[] senseBuffer) { if (osError) { _logSw.WriteLine("SCSI reading LBA {0} operating system error: {1}.", block, errno); _logSw.Flush(); if (senseBuffer is null || senseBuffer.Length == 0 || senseBuffer.All(s => s == 0)) { return; } } FixedSense? decodedFixedSense = Sense.DecodeFixed(senseBuffer); DescriptorSense?decodedDescriptorSense = Sense.DecodeDescriptor(senseBuffer); string prettySense = Sense.PrettifySense(senseBuffer); string hexSense = string.Join(' ', senseBuffer.Select(b => $"{b:X2}")); if (decodedFixedSense.HasValue) { if (prettySense != null) { if (prettySense.StartsWith("SCSI SENSE: ", StringComparison.Ordinal)) { prettySense = prettySense.Substring(12); } if (prettySense.EndsWith('\n')) { prettySense = prettySense.Substring(0, prettySense.Length - 1); } prettySense = prettySense.Replace("\n", " - "); _logSw.WriteLine("SCSI reading LBA {0} error: SENSE {1} ASC {2:X2}h ASCQ {3:X2}h, {4}, {5}.", block, decodedFixedSense?.SenseKey, decodedFixedSense?.ASC, decodedFixedSense?.ASCQ, hexSense, prettySense); } else { _logSw.WriteLine("SCSI reading LBA {0} error: SENSE {1} ASC {2:X2}h ASCQ {3:X2}h, {4}.", block, decodedFixedSense?.SenseKey, decodedFixedSense?.ASC, decodedFixedSense?.ASCQ, hexSense); } } else if (decodedDescriptorSense.HasValue) { if (prettySense != null) { if (prettySense.StartsWith("SCSI SENSE: ", StringComparison.Ordinal)) { prettySense = prettySense.Substring(12); } if (prettySense.EndsWith('\n')) { prettySense = prettySense.Substring(0, prettySense.Length - 1); } prettySense = prettySense.Replace("\n", " - "); _logSw.WriteLine("SCSI reading LBA {0} error: SENSE {1} ASC {2:X2}h ASCQ {3:X2}h, {4}, {5}.", block, decodedDescriptorSense?.SenseKey, decodedDescriptorSense?.ASC, decodedDescriptorSense?.ASCQ, hexSense, prettySense); } else { _logSw.WriteLine("SCSI reading LBA {0} error: SENSE {1} ASC {2:X2}h ASCQ {3:X2}h, {4}.", block, decodedDescriptorSense?.SenseKey, decodedDescriptorSense?.ASC, decodedDescriptorSense?.ASCQ, hexSense); } } else { if (prettySense != null) { if (prettySense.StartsWith("SCSI SENSE: ", StringComparison.Ordinal)) { prettySense = prettySense.Substring(12); } if (prettySense.EndsWith('\n')) { prettySense = prettySense.Substring(0, prettySense.Length - 1); } prettySense = prettySense.Replace("\n", " - "); _logSw.WriteLine("SCSI reading LBA {0} error: {1}, {2}.", block, hexSense, prettySense); } else { _logSw.WriteLine("SCSI reading LBA {0} error: {1}", block, hexSense); } } _logSw.Flush(); }