Files
Aaru/SCSI/Sense.cs

1249 lines
45 KiB
C#
Raw Normal View History

// /***************************************************************************
// The Disc Image Chef
// ----------------------------------------------------------------------------
//
// Filename : Sense.cs
// Version : 1.0
// Author(s) : Natalia Portillo
//
// Component : Component
//
// Revision : $Revision$
// Last change by : $Author$
// Date : $Date$
//
// --[ Description ] ----------------------------------------------------------
//
// Description
//
// --[ License ] --------------------------------------------------------------
//
// 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 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright (C) 2011-2015 Claunia.com
// ****************************************************************************/
// //$Id$
using System;
using System.Text;
namespace DiscImageChef.Decoders.SCSI
{
public enum SenseType
{
StandardSense,
ExtendedSenseFixedCurrent,
ExtendedSenseFixedPast,
ExtendedSenseDescriptorCurrent,
ExtendedSenseDescriptorPast,
Invalid,
Unknown
}
public struct StandardSense
{
/// <summary>
/// If set, <see cref="LBA"/> is valid
/// </summary>
public bool AddressValid;
/// <summary>
/// Error class, 0 to 6
/// </summary>
public byte ErrorClass;
/// <summary>
/// Error type
/// </summary>
public byte ErrorType;
/// <summary>
/// Private usage
/// </summary>
public byte Private;
/// <summary>
/// LBA where error happened
/// </summary>
public uint LBA;
}
public enum SenseKeys : byte
{
/// <summary>
/// No information to be reported, but bits should be checked
/// </summary>
NoSense = 0,
/// <summary>
/// Target performed some recovery to successfully complete last command
/// </summary>
RecoveredError = 1,
/// <summary>
/// Target is not ready
/// </summary>
NotReady = 2,
/// <summary>
/// Non-recoverable medium error occurred
/// </summary>
MediumError = 3,
/// <summary>
/// Non-recoverable hardware error occurred
/// </summary>
HardwareError = 4,
/// <summary>
/// Target has received an illegal request
/// </summary>
IllegalRequest = 5,
/// <summary>
/// Target requires initiator attention
/// </summary>
UnitAttention = 6,
/// <summary>
/// A protected command has been denied
/// </summary>
DataProtect = 7,
/// <summary>
/// A blank block has been tried to read or a non-rewritable one to write
/// </summary>
BlankCheck = 8,
/// <summary>
/// For private/vendor usage
/// </summary>
PrivateUse = 9,
/// <summary>
/// COPY command aborted
/// </summary>
CopyAborted = 0xA,
/// <summary>
/// Command aborted
/// </summary>
AbortedCommand = 0xB,
/// <summary>
/// SEARCH command has been satisfied
/// </summary>
Equal = 0xC,
/// <summary>
/// End-of-medium reached with data remaining in buffer
/// </summary>
VolumeOverflow = 0xD,
/// <summary>
/// COMPARE failed
/// </summary>
Miscompare = 0xE,
/// <summary>
/// Reserved
/// </summary>
Reserved = 0xF
}
public struct FixedSense
{
/// <summary>
/// If set, <see cref="Information"/> is valid
/// </summary>
public bool InformationValid;
/// <summary>
/// Contains number of current segment descriptor
/// </summary>
public byte SegmentNumber;
/// <summary>
/// If set indicates current command has read a filemark or a setmark
/// </summary>
public bool Filemark;
/// <summary>
/// If set indicates device has arrived end-of-medium
/// </summary>
public bool EOM;
/// <summary>
/// Means the requested logical block length did not match the logical block length on the medium
/// </summary>
public bool ILI;
/// <summary>
/// Contains the sense key
/// </summary>
public SenseKeys SenseKey;
/// <summary>
/// Additional information
/// </summary>
public uint Information;
/// <summary>
/// Additional sense length
/// </summary>
public byte AdditionalLength;
/// <summary>
/// Command specific information field
/// </summary>
public uint CommandSpecific;
/// <summary>
/// Additional sense code
/// </summary>
public byte ASC;
/// <summary>
/// Additional sense code qualifier
/// </summary>
public byte ASCQ;
public byte FieldReplaceable;
/// <summary>
/// If set, <see cref="SenseKeySpecific"/> is valid
/// </summary>
public bool SKSV;
public uint SenseKeySpecific;
public byte[] AdditionalSense;
}
public static class Sense
{
/// <summary>
/// Gets the SCSI SENSE type to help chosing the correct decoding function
/// </summary>
/// <returns>The type.</returns>
/// <param name="sense">Sense bytes.</param>
public static SenseType GetType(byte[] sense)
{
if (sense == null)
return SenseType.Invalid;
if (sense.Length < 4)
return SenseType.Invalid;
if ((sense[0] & 0x70) != 0x70)
return sense.Length != 4 ? SenseType.Invalid : SenseType.StandardSense;
switch (sense[0] & 0x0F)
{
case 0:
return SenseType.ExtendedSenseFixedCurrent;
case 1:
return SenseType.ExtendedSenseFixedPast;
case 2:
return SenseType.ExtendedSenseDescriptorCurrent;
case 3:
return SenseType.ExtendedSenseDescriptorPast;
default:
return SenseType.Unknown;
}
}
public static StandardSense? DecodeStandard(byte[] sense)
{
if (GetType(sense) != SenseType.StandardSense)
return null;
StandardSense decoded = new StandardSense();
decoded.AddressValid |= (sense[0] & 0x80) == 0x80;
decoded.ErrorClass = (byte)((sense[0] & 0x70) >> 4);
decoded.ErrorType = (byte)(sense[0] & 0x0F);
decoded.Private = (byte)((sense[1] & 0x80) >> 4);
decoded.LBA = (uint)(((sense[1] & 0x0F) << 16) + (sense[2] << 8) + sense[3]);
return decoded;
}
public static FixedSense? DecodeFixed(byte[] sense)
{
string foo;
return DecodeFixed(sense, out foo);
}
public static FixedSense? DecodeFixed(byte[] sense, out string senseDescription)
{
senseDescription = null;
if((sense[0] & 0x7F) != 0x70 ||
(sense[0] & 0x7F) != 0x71)
return null;
if (sense.Length < 8)
return null;
FixedSense decoded = new FixedSense();
decoded.InformationValid |= (sense[0] & 0x80) == 0x80;
decoded.SegmentNumber = sense[1];
decoded.Filemark |= (sense[2] & 0x80) == 0x80;
decoded.EOM |= (sense[2] & 0x40) == 0x40;
decoded.ILI |= (sense[2] & 0x20) == 0x20;
decoded.SenseKey = (SenseKeys)(sense[2] & 0x0F);
decoded.Information = (uint)((sense[3] << 24) + (sense[4] << 16) + (sense[5] << 8) + sense[6]);
decoded.AdditionalLength = sense[7];
if (sense.Length != decoded.AdditionalLength + 8)
return decoded;
if(sense.Length >= 12)
decoded.CommandSpecific = (uint)((sense[8] << 24) + (sense[9] << 16) + (sense[10] << 8) + sense[11]);
if (sense.Length >= 14)
{
decoded.ASC = sense[12];
decoded.ASCQ = sense[13];
senseDescription = GetSenseDescription(decoded.ASC, decoded.ASCQ);
}
if (sense.Length >= 15)
decoded.FieldReplaceable = sense[14];
if(sense.Length >= 18)
decoded.SenseKeySpecific = (uint)((sense[15] << 16) + (sense[16] << 8) + sense[17]);
if (sense.Length > 18)
{
decoded.AdditionalSense = new byte[sense.Length - 18];
Array.Copy(sense, 18, decoded.AdditionalSense, 0, decoded.AdditionalSense.Length);
}
return decoded;
}
public static string PrettifySense(byte[] sense)
{
SenseType type = GetType(sense);
switch (type)
{
case SenseType.StandardSense:
return PrettifySense(DecodeStandard(sense));
case SenseType.ExtendedSenseFixedCurrent:
case SenseType.ExtendedSenseFixedPast:
return PrettifySense(DecodeFixed(sense));
default:
return null;
}
}
public static string PrettifySense(StandardSense? sense)
{
if (!sense.HasValue)
return null;
return sense.Value.AddressValid ? String.Format("Error class {0} type {1} happened on block {2}\n",
sense.Value.ErrorClass, sense.Value.ErrorType, sense.Value.LBA) :
String.Format("Error class {0} type {1}\n", sense.Value.ErrorClass,
sense.Value.ErrorType);
}
public static string PrettifySense(FixedSense? sense)
{
if (!sense.HasValue)
return null;
FixedSense decoded = sense.Value;
StringBuilder sb = new StringBuilder();
sb.AppendFormat("SCSI SENSE: {0}", GetSenseKey(decoded.SenseKey)).AppendLine();
if (decoded.SegmentNumber > 0)
sb.AppendFormat("On segment {0}", decoded.SegmentNumber).AppendLine();
if (decoded.Filemark)
sb.AppendLine("Filemark or setmark found");
if (decoded.EOM)
sb.AppendLine("End-of-medium/partition found");
if (decoded.ILI)
sb.AppendLine("Incorrect length indicator");
if (decoded.InformationValid)
sb.AppendFormat("On logical block {0}", decoded.Information);
if (decoded.AdditionalLength < 6)
return sb.ToString();
sb.AppendLine(GetSenseDescription(decoded.ASC, decoded.ASCQ));
if (decoded.AdditionalLength < 10)
return sb.ToString();
if (decoded.SKSV)
{
switch (decoded.SenseKey)
{
case SenseKeys.IllegalRequest:
{
if ((decoded.SenseKeySpecific & 0x400000) == 0x400000)
sb.AppendLine("Illegal field in CDB");
else
sb.AppendLine("Illegal field in data parameters");
if ((decoded.SenseKeySpecific & 0x200000) == 0x200000)
sb.AppendFormat("Invalid value in bit {0} in field {1} of CDB",
(decoded.SenseKeySpecific & 0x70000) >> 16,
decoded.SenseKeySpecific & 0xFFFF).AppendLine();
else
sb.AppendFormat("Invalid value in field {0} of CDB",
decoded.SenseKeySpecific & 0xFFFF).AppendLine();
}
break;
case SenseKeys.NotReady:
sb.AppendFormat("Format progress {0:P}", (double)(decoded.SenseKeySpecific & 0xFFFF) / 65536).AppendLine();
break;
case SenseKeys.RecoveredError:
case SenseKeys.HardwareError:
case SenseKeys.MediumError:
sb.AppendFormat("Actual retry count is {0}", decoded.SenseKeySpecific & 0xFFFF).AppendLine();
break;
}
}
return sb.ToString();
}
public static string GetSenseKey(SenseKeys key)
{
switch (key)
{
case SenseKeys.AbortedCommand:
return "ABORTED COMMAND";
case SenseKeys.BlankCheck:
return "BLANK CHECK";
case SenseKeys.CopyAborted:
return "COPY ABORTED";
case SenseKeys.DataProtect:
return "DATA PROTECT";
case SenseKeys.Equal:
return "EQUAL";
case SenseKeys.HardwareError:
return "HARDWARE ERROR";
case SenseKeys.IllegalRequest:
return "ILLEGAL REQUEST";
case SenseKeys.MediumError:
return "MEDIUM ERROR";
case SenseKeys.Miscompare:
return "MISCOMPARE";
case SenseKeys.NoSense:
return "NO SENSE";
case SenseKeys.PrivateUse:
return "PRIVATE USE";
case SenseKeys.RecoveredError:
return "RECOVERED ERROR";
case SenseKeys.Reserved:
return "RETURN";
case SenseKeys.UnitAttention:
return "UNIT ATTENTION";
case SenseKeys.VolumeOverflow:
return "VOLUME OVERFLOW";
default:
return "UNKNOWN";
}
}
public static string GetSenseDescription(byte ASC, byte ASCQ)
{
switch (ASC)
{
case 0x00:
switch (ASCQ)
{
case 0x00:
return "NO ADDITIONAL SENSE INFORMATION";
case 0x01:
return "FILEMARK DETECTED";
case 0x02:
return "END-OF-PARTITION/MEDIUM DETECTED";
case 0x03:
return "SETMARK DETECTED";
case 0x04:
return "BEGINNING-OF-PARTITION/MEDIUM DETECTED";
case 0x05:
return "END-OF-DATA DETECTED";
case 0x06:
return "I/O PROCESS TERMINATED";
case 0x11:
return "AUDIO PLAY OPERATION IN PROGRESS";
case 0x12:
return "AUDIO PLAY OPERATION PAUSED";
case 0x13:
return "AUDIO PLAY OPERATION SUCCESSFULLY COMPLETED";
case 0x14:
return "AUDIO PLAY OPERATION STOPPED DUE TO ERROR";
case 0x15:
return "NO CURRENT AUDIO STATUS TO RETURN";
}
break;
case 0x01:
switch (ASCQ)
{
case 0x00:
return "NO INDEX/SECTOR SIGNAL";
}
break;
case 0x02:
switch (ASCQ)
{
case 0x00:
return "NO SEEK COMPLETE";
}
break;
case 0x03:
switch (ASCQ)
{
case 0x00:
return "PERIPHERAL DEVICE WRITE FAULT";
case 0x01:
return "NO WRITE CURRENT";
case 0x02:
return "EXCESSIVE WRITE ERRORS";
}
break;
case 0x04:
switch (ASCQ)
{
case 0x00:
return "LOGICAL UNIT NOT READY, CAUSE NOT REPORTABLE";
case 0x01:
return "LOGICAL UNIT IS IN PROCESS OF BECOMING READY";
case 0x02:
return "LOGICAL UNIT NOT READY, INITIALIZING COMMAND REQUIRED";
case 0x03:
return "LOGICAL UNIT NOT READY, MANUAL INTERVENTION REQUIRED";
case 0x04:
return "LOGICAL UNIT NOT READY, FORMAT IN PROGRESS";
}
break;
case 0x05:
switch (ASCQ)
{
case 0x00:
return "LOGICAL UNIT DOES NOT RESPOND TO SELECTION";
}
break;
case 0x06:
switch (ASCQ)
{
case 0x00:
return "REFERENCE POSITION FOUND";
}
break;
case 0x07:
switch (ASCQ)
{
case 0x00:
return "MULTIPLE PERIPHERAL DEVICES SELECTED";
}
break;
case 0x08:
switch (ASCQ)
{
case 0x00:
return "LOGICAL UNIT COMMUNICATION FAILURE";
case 0x01:
return "LOGICAL UNIT COMMUNICATION TIME-OUT";
case 0x02:
return "LOGICAL UNIT COMMUNICATION PARITY ERROR";
}
break;
case 0x09:
switch (ASCQ)
{
case 0x00:
return "TRACK FLOLLOWING ERROR";
case 0x01:
return "TRACKING SERVO FAILURE";
case 0x02:
return "FOCUS SERVO FAILURE";
case 0x03:
return "SPINDLE SERVO FAILURE";
}
break;
case 0x0A:
switch (ASCQ)
{
case 0x00:
return "ERROR LOG OVERFLOW";
}
break;
case 0x0C:
switch (ASCQ)
{
case 0x00:
return "WRITE ERROR";
case 0x01:
return "WRITE ERROR RECOVERED WITH AUTO REALLOCATION";
case 0x02:
return "WRITE ERROR - AUTO REALLOCATION FAILED";
}
break;
case 0x10:
switch (ASCQ)
{
case 0x00:
return "ID CRC OR ECC ERROR";
}
break;
case 0x11:
switch (ASCQ)
{
case 0x00:
return "UNRECOVERED READ ERROR";
case 0x01:
return "READ RETRIES EXHAUSTED";
case 0x02:
return "ERROR TOO LONG TO CORRECT";
case 0x03:
return "MULTIPLE READ ERRORS";
case 0x04:
return "UNRECOVERED READ ERROR - AUTO REALLOCATE FAILED";
case 0x05:
return "L-EC UNCORRECTABLE ERROR";
case 0x06:
return "CIRC UNRECOVERED ERROR";
case 0x07:
return "DATA RESYNCHRONIZATION ERROR";
case 0x08:
return "INCOMPLETE BLOCK READ";
case 0x09:
return "NO GAP FOUND";
case 0x0A:
return "MISCORRECTED ERROR";
case 0x0B:
return "UNRECOVERED READ ERROR - RECOMMENDED REASSIGNMENT";
case 0x0C:
return "UNRECOVERED READ ERROR - RECOMMENDED REWRITE THE DATA";
}
break;
case 0x12:
switch (ASCQ)
{
case 0x00:
return "ADDRESS MARK NOT FOUND FOR ID FIELD";
}
break;
case 0x13:
switch (ASCQ)
{
case 0x00:
return "ADDRESS MARK NOT FOUND FOR DATA FIELD";
}
break;
case 0x14:
switch (ASCQ)
{
case 0x00:
return "RECORDED ENTITY NOT FOUND";
case 0x01:
return "RECORD NOT FOUND";
case 0x02:
return "FILEMARK OR SETMARK NOT FOUND";
case 0x03:
return "END-OF-DATA NOT FOUND";
case 0x04:
return "BLOCK SEQUENCE ERROR";
}
break;
case 0x15:
switch (ASCQ)
{
case 0x00:
return "RANDOM POSITIONING ERROR";
case 0x01:
return "MECHANICAL POSITIONING ERROR";
case 0x02:
return "POSITIONING ERROR DETECTED BY READ OF MEDIUM";
}
break;
case 0x16:
switch (ASCQ)
{
case 0x00:
return "DATA SYNCHRONIZATION MARK ERROR";
}
break;
case 0x17:
switch (ASCQ)
{
case 0x00:
return "RECOVERED DATA WITH NO ERROR CORRECTION APPLIED";
case 0x01:
return "RECOVERED DATA WITH RETRIES";
case 0x02:
return "RECOVERED DATA WITH POSITIVE HEAD OFFSET";
case 0x03:
return "RECOVERED DATA WITH NEGATIVE HEAD OFFSET";
case 0x04:
return "RECOVERED DATA WITH RETRIES AND/OR CIRC APPLIED";
case 0x05:
return "RECOVERED DATA USING PREVIOUS SECTOR ID";
case 0x06:
return "RECOVERED DATA WITHOUT ECC - DATA AUTO-REALLOCATED";
case 0x07:
return "RECOVERED DATA WITHOUT ECC - RECOMMENDED REASSIGNMENT";
case 0x08:
return "RECOVERED DATA WITHOUT ECC - RECOMMENDED REWRITE";
}
break;
case 0x18:
switch (ASCQ)
{
case 0x00:
return "RECOVERED DATA WITH ERROR CORRECTION APPLIED";
case 0x01:
return "RECOVERED DATA WITH ERROR CORRECTION & RETRIES APPLIED";
case 0x02:
return "RECOVERED DATA - DATA AUTO-REALLOCATED";
case 0x03:
return "RECOVERED DATA WITH CIRC";
case 0x04:
return "RECOVERED DATA WITH L-EC";
case 0x05:
return "RECOVERED DATA - RECOMMENDED REASSIGNMENT";
case 0x06:
return "RECOVERED DATA - RECOMMENDED REWRITE";
}
break;
case 0x19:
switch (ASCQ)
{
case 0x00:
return "DEFECT LIST ERROR";
case 0x01:
return "DEFECT LIST NOT AVAILABLE";
case 0x02:
return "DEFECT LIST ERROR IN PRIMARY LIST";
case 0x03:
return "DEFECT LIST ERROR IN GROWN LIST";
}
break;
case 0x1A:
switch (ASCQ)
{
case 0x00:
return "PARAMETER LIST LENGTH ERROR";
}
break;
case 0x1B:
switch (ASCQ)
{
case 0x00:
return "SYNCHRONOUS DATA TRANSFER ERROR";
}
break;
case 0x1C:
switch (ASCQ)
{
case 0x00:
return "DEFECT LIST NOT FOUND";
case 0x01:
return "PRIMARY DEFECT LIST NOT FOUND";
case 0x02:
return "GROWN DEFECT LIST NOT FOUND";
}
break;
case 0x1D:
switch (ASCQ)
{
case 0x00:
return "MISCOMPARE DURING VERIFY OPERATION";
}
break;
case 0x1E:
switch (ASCQ)
{
case 0x00:
return "RECOVERED ID WITH ECC";
}
break;
case 0x20:
switch (ASCQ)
{
case 0x00:
return "INVALID COMMAND OPERATION CODE";
}
break;
case 0x21:
switch (ASCQ)
{
case 0x00:
return "LOGICAL BLOCK ADDRESS OUT OF RANGE";
case 0x01:
return "INVALID ELEMENT ADDRESS";
}
break;
case 0x22:
switch (ASCQ)
{
case 0x00:
return "ILLEGAL FUNCTION";
}
break;
case 0x24:
switch (ASCQ)
{
case 0x00:
return "ILLEGAL FIELD IN CDB";
}
break;
case 0x25:
switch (ASCQ)
{
case 0x00:
return "LOGICAL UNIT NOT SUPPORTED";
}
break;
case 0x26:
switch (ASCQ)
{
case 0x00:
return "INVALID FIELD IN PARAMETER LIST";
case 0x01:
return "PARAMETER NOT SUPPORTED";
case 0x02:
return "PARAMETER VALUE INVALID";
case 0x03:
return "THRESHOLD PARAMETERS NOT SUPPORTED";
}
break;
case 0x27:
switch (ASCQ)
{
case 0x00:
return "WRITE PROTECTED";
}
break;
case 0x28:
switch (ASCQ)
{
case 0x00:
return "NOT READY TO READY TRANSITION (MEDIUM MAY HAVE CHANGED)";
case 0x01:
return "IMPORT OR EXPORT ELEMENT ACCESSED";
}
break;
case 0x29:
switch (ASCQ)
{
case 0x00:
return "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED";
}
break;
case 0x2A:
switch (ASCQ)
{
case 0x00:
return "PARAMETERS CHANGED";
case 0x01:
return "MODE PARAMETERS CHANGED";
case 0x02:
return "LOG PARAMETERS CHANGED";
}
break;
case 0x2B:
switch (ASCQ)
{
case 0x00:
return "COPY CANNOT EXECUTE SINCE HOST CANNOT DISCONNECT";
}
break;
case 0x2C:
switch (ASCQ)
{
case 0x00:
return "COMMAND SEQUENCE ERROR";
case 0x01:
return "TOO MANY WINDOWS SPECIFIED";
case 0x02:
return "INVALID COMBINATION OF WINDOWS SPECIFIED";
}
break;
case 0x2D:
switch (ASCQ)
{
case 0x00:
return "OVERWRITE ERROR ON UPDATE IN PLACE";
}
break;
case 0x2F:
switch (ASCQ)
{
case 0x00:
return "COMMANDS CLEARED BY ANOTHER INITIATOR";
}
break;
case 0x30:
switch (ASCQ)
{
case 0x00:
return "INCOMPATIBLE MEDIUM INSTALLED";
case 0x01:
return "CANNOT READ MEDIUM - UNKNOWN FORMAT";
case 0x02:
return "CANNOT READ MEDIUM - INCOMPATIBLE FORMAT";
case 0x03:
return "CLEANING CARTRIDGE INSTALLED";
}
break;
case 0x31:
switch (ASCQ)
{
case 0x00:
return "MEDIUM FORMAT CORRUPTED";
case 0x01:
return "FORMAT COMMAND FAILED";
}
break;
case 0x32:
switch (ASCQ)
{
case 0x00:
return "NO DEFECT SPARE LOCATION AVAILABLE";
case 0x01:
return "DEFECT LIST UPDATE FAILURE";
}
break;
case 0x33:
switch (ASCQ)
{
case 0x00:
return "TAPE LENGTH ERROR";
}
break;
case 0x36:
switch (ASCQ)
{
case 0x00:
return "RIBBON, INK, OR TONER FAILURE";
}
break;
case 0x37:
switch (ASCQ)
{
case 0x00:
return "ROUNDED PARAMETER";
}
break;
case 0x39:
switch (ASCQ)
{
case 0x00:
return "SAVING PARAMETERS NOT SUPPORTED";
}
break;
case 0x3A:
switch (ASCQ)
{
case 0x00:
return "MEDIUM NOT PRESENT";
}
break;
case 0x3B:
switch (ASCQ)
{
case 0x00:
return "SEQUENTIAL POSITIONING ERROR";
case 0x01:
return "TAPE POSITION ERROR AT BEGINNING-OF-MEDIUM";
case 0x02:
return "TAPE POSITION ERROR AT END-OF-MEDIUM";
case 0x03:
return "TAPE OR ELECTRONIC VERTICAL FORMS UNIT NOT READY";
case 0x04:
return "SLEW FAILURE";
case 0x05:
return "PAPER JAM";
case 0x06:
return "FAILED TO SENSE TOP-OF-FORM";
case 0x07:
return "FAILED TO SENSE BOTTOM-OF-FORM";
case 0x08:
return "REPOSITION ERROR";
case 0x09:
return "READ PAST END OF MEDIUM";
case 0x0A:
return "READ PAST BEGINNING OF MEDIUM";
case 0x0B:
return "POSITION PAST END OF MEDIUM";
case 0x0C:
return "POSITION PAST BEGINNING OF MEDIUM";
case 0x0D:
return "MEDIUM DESTINATION ELEMENT FULL";
case 0x0E:
return "MEDIUM SOURCE ELEMENT EMPTY";
}
break;
case 0x3D:
switch (ASCQ)
{
case 0x00:
return "INVALID BITS IN IDENTIFY MESSAGE";
}
break;
case 0x3E:
switch (ASCQ)
{
case 0x00:
return "LOGICAL UNIT HAS NOT SELF-CONFIGURED YET";
}
break;
case 0x3F:
switch (ASCQ)
{
case 0x00:
return "TARGET OPERATING CONDITIONS HAVE CHANGED";
case 0x01:
return "MICROCODE HAS BEEN CHANGED";
case 0x02:
return "CHANGED OPERATING DEFINITION";
case 0x03:
return "INQUIRY DATA HAS CHANGED";
}
break;
case 0x40:
switch (ASCQ)
{
case 0x00:
return "RAM FAILURE";
default:
return String.Format("DIAGNOSTIC FAILURE ON COMPONENT {0:X2}h", ASCQ);
}
case 0x41:
switch (ASCQ)
{
case 0x00:
return "DATA PATH FAILURE";
}
break;
case 0x42:
switch (ASCQ)
{
case 0x00:
return "POWER-ON OR SELF-TEST FAILURE";
}
break;
case 0x43:
switch (ASCQ)
{
case 0x00:
return "MESSAGE ERROR";
}
break;
case 0x44:
switch (ASCQ)
{
case 0x00:
return "INTERNAL TARGET FAILURE";
}
break;
case 0x45:
switch (ASCQ)
{
case 0x00:
return "SELECT OR RESELECT FAILURE";
}
break;
case 0x46:
switch (ASCQ)
{
case 0x00:
return "UNSUCCESSFUL SOFT RESET";
}
break;
case 0x47:
switch (ASCQ)
{
case 0x00:
return "SCSI PARITY ERROR";
}
break;
case 0x48:
switch (ASCQ)
{
case 0x00:
return "INITIATOR DETECTED ERROR MESSAGE RECEIVED";
}
break;
case 0x49:
switch (ASCQ)
{
case 0x00:
return "INVALID MESSAGE ERROR";
}
break;
case 0x4A:
switch (ASCQ)
{
case 0x00:
return "COMMAND PHASE ERROR";
}
break;
case 0x4B:
switch (ASCQ)
{
case 0x00:
return "DATA PHASE ERROR";
}
break;
case 0x4C:
switch (ASCQ)
{
case 0x00:
return "LOGICAL UNIT FAILED SELF-CONFIGURATION";
}
break;
case 0x4E:
switch (ASCQ)
{
case 0x00:
return "OVERLAPPED COMMANDS ATTEMPTED";
}
break;
case 0x50:
switch (ASCQ)
{
case 0x00:
return "WRITE APPEND ERROR";
case 0x01:
return "WRITE APPEND POSITION ERROR";
case 0x02:
return "POSITION ERROR RELATED TO TIMING";
}
break;
case 0x51:
switch (ASCQ)
{
case 0x00:
return "ERASE FAILURE";
}
break;
case 0x52:
switch (ASCQ)
{
case 0x00:
return "CARTRIDGE FAULT";
}
break;
case 0x53:
switch (ASCQ)
{
case 0x00:
return "MEDIA LOAD OR EJECT FAILED";
case 0x01:
return "UNLOAD TAPE FAILURE";
case 0x02:
return "MEDIUM REMOVAL PREVENTED";
}
break;
case 0x54:
switch (ASCQ)
{
case 0x00:
return "SCSI TO HOST SYSTEM INTERFACE FAILURE";
}
break;
case 0x55:
switch (ASCQ)
{
case 0x00:
return "SYSTEM RESOURCE FAILURE";
}
break;
case 0x57:
switch (ASCQ)
{
case 0x00:
return "UNABLE TO RECOVER TABLE-OF-CONTENTS";
}
break;
case 0x58:
switch (ASCQ)
{
case 0x00:
return "GENERATION DOES NOT EXIST";
}
break;
case 0x59:
switch (ASCQ)
{
case 0x00:
return "UPDATED BLOCK READ";
}
break;
case 0x5A:
switch (ASCQ)
{
case 0x00:
return "OPERATOR REQUEST OR STATE CHANGE INPUT";
case 0x01:
return "OPERATOR MEDIUM REMOVAL REQUEST";
case 0x02:
return "OPERATOR SELECTED WRITE PROTECT";
case 0x03:
return "OPERATOR SELECTED WRITE PERMIT";
}
break;
case 0x5B:
switch (ASCQ)
{
case 0x00:
return "LOG EXCEPTION";
case 0x01:
return "THRESHOLD CONDITION MET";
case 0x02:
return "LOG COUNTER AT MAXIMUM";
case 0x03:
return "LOG LIST CODES EXHAUSTED";
}
break;
case 0x5C:
switch (ASCQ)
{
case 0x00:
return "RPL STATUS CHANGE";
case 0x01:
return "SPINDLES SYNCHRONIZED";
case 0x02:
return "SPINDLES NOT SYNCHRONIZED";
}
break;
case 0x60:
switch (ASCQ)
{
case 0x00:
return "LAMP FAILURE";
}
break;
case 0x61:
switch (ASCQ)
{
case 0x00:
return "VIDEO ACQUISTION ERROR";
case 0x01:
return "UNABLE TO ACQUIRE VIDEO";
case 0x02:
return "OUT OF FOCUS";
}
break;
case 0x62:
switch (ASCQ)
{
case 0x00:
return "SCAN HEAD POSITIONING ERROR";
}
break;
case 0x63:
switch (ASCQ)
{
case 0x00:
return "END OF USER AREA ENCOUNTERED ON THIS TRACK";
}
break;
case 0x64:
switch (ASCQ)
{
case 0x00:
return "ILLEGAL MODE FOR THIS TRACK";
}
break;
}
return ASC >= 0x80 ? ASCQ >= 0x80 ?
String.Format("VENDOR-SPECIFIC ASC {0:X2}h WITH VENDOR-SPECIFIC ASCQ {1:X2}h", ASC, ASCQ) :
String.Format("VENDOR-SPECIFIC ASC {0:X2}h WITH ASCQ {1:X2}h", ASC, ASCQ) :
ASCQ >= 0x80 ? String.Format("ASC {0:X2}h WITH VENDOR-SPECIFIC ASCQ {1:X2}h", ASC, ASCQ) :
String.Format("ASC {0:X2}h WITH ASCQ {1:X2}h", ASC, ASCQ);
}
}
}