diff --git a/ChangeLog b/ChangeLog index 3800531..373fee0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-10-30 Natalia Portillo + + * SCSI/Modes.cs: + Implemented decoding mode page 01h. + 2015-10-30 Natalia Portillo * SCSI/Modes.cs: diff --git a/SCSI/Modes.cs b/SCSI/Modes.cs index 31e4b56..4804cf1 100644 --- a/SCSI/Modes.cs +++ b/SCSI/Modes.cs @@ -2106,7 +2106,6 @@ namespace DiscImageChef.Decoders.SCSI return decoded; } - public static string PrettifyModePage_0B(byte[] pageResponse) { return PrettifyModePage_0B(DecodeModePage_0B(pageResponse)); @@ -2131,6 +2130,161 @@ namespace DiscImageChef.Decoders.SCSI return sb.ToString(); } #endregion Mode Page 0x0B: Medium types supported page + + #region Mode Page 0x0C: Notch page + // TODO: Implement this page + #endregion Mode Page 0x0C: Notch page + + #region Mode Page 0x01: Read-write error recovery page + /// + /// Disconnect-reconnect page + /// Page code 0x01 + /// 12 bytes in SCSI-2 + /// + public struct ModePage_01 + { + /// + /// Parameters can be saved + /// + public bool PS; + /// + /// Automatic Write Reallocation Enabled + /// + public bool AWRE; + /// + /// Automatic Read Reallocation Enabled + /// + public bool ARRE; + /// + /// Transfer block + /// + public bool TB; + /// + /// Read continuous + /// + public bool RC; + /// + /// Enable early recovery + /// + public bool EER; + /// + /// Post error reporting + /// + public bool PER; + /// + /// Disable transfer on error + /// + public bool DTE; + /// + /// Disable correction + /// + public bool DCR; + /// + /// How many times to retry a read operation + /// + public byte ReadRetryCount; + /// + /// How many bits of largest data burst error is maximum to apply error correction on it + /// + public byte CorrectionSpan; + /// + /// Offset to move the heads + /// + public sbyte HeadOffsetCount; + /// + /// Incremental position to which the recovered data strobe shall be adjusted + /// + public sbyte DataStrobeOffsetCount; + /// + /// How many times to retry a write operation + /// + public byte WriteRetryCount; + /// + /// Maximum time in ms to use in data error recovery procedures + /// + public ushort RecoveryTimeLimit; + } + + public static ModePage_01? DecodeModePage_01(byte[] pageResponse) + { + if (pageResponse == null) + return null; + + if ((pageResponse[0] & 0x3F) != 0x01) + return null; + + if (pageResponse[1] + 2 != pageResponse.Length) + return null; + + if (pageResponse.Length < 12) + return null; + + ModePage_01 decoded = new ModePage_01(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + decoded.AWRE |= (pageResponse[2] & 0x80) == 0x80; + decoded.ARRE |= (pageResponse[2] & 0x40) == 0x40; + decoded.TB |= (pageResponse[2] & 0x20) == 0x20; + decoded.RC |= (pageResponse[2] & 0x10) == 0x10; + decoded.EER |= (pageResponse[2] & 0x08) == 0x08; + decoded.PER |= (pageResponse[2] & 0x04) == 0x04; + decoded.DTE |= (pageResponse[2] & 0x02) == 0x02; + decoded.DCR |= (pageResponse[2] & 0x01) == 0x01; + + decoded.ReadRetryCount = pageResponse[3]; + decoded.CorrectionSpan = pageResponse[4]; + decoded.HeadOffsetCount = (sbyte)pageResponse[5]; + decoded.DataStrobeOffsetCount = (sbyte)pageResponse[6]; + decoded.WriteRetryCount = pageResponse[8]; + decoded.RecoveryTimeLimit = (ushort)((pageResponse[10] << 8) + pageResponse[11]); + + return decoded; + } + + public static string PrettifyModePage_01(byte[] pageResponse) + { + return PrettifyModePage_01(DecodeModePage_01(pageResponse)); + } + + public static string PrettifyModePage_01(ModePage_01? modePage) + { + if (!modePage.HasValue) + return null; + + ModePage_01 page = modePage.Value; + StringBuilder sb = new StringBuilder(); + + sb.AppendLine("SCSI Read-write error recovery page:"); + + if (page.PS) + sb.AppendLine("\tParameters can be saved"); + + if (page.AWRE) + sb.AppendLine("\tAutomatic write reallocation is enabled"); + if (page.ARRE) + sb.AppendLine("\tAutomatic read reallocation is enabled"); + if (page.TB) + sb.AppendLine("\tData not recovered within limits shall be transferred back before a CHECK CONDITION"); + if (page.RC) + sb.AppendLine("\tDrive will transfer the entire requested length without delaying to perform error recovery"); + if (page.EER) + sb.AppendLine("\tDrive will use the most expedient form of error recovery first"); + if (page.PER) + sb.AppendLine("\tDrive shall report recovered errors"); + if (page.DTE) + sb.AppendLine("\tTransfer will be terminated upon error detection"); + if (page.DCR) + sb.AppendLine("\tError correction is disabled"); + if (page.ReadRetryCount > 0) + sb.AppendFormat("\tDrive will repeat read operations {0} times", page.ReadRetryCount).AppendLine(); + if (page.WriteRetryCount > 0) + sb.AppendFormat("\tDrive will repeat write operations {0} times", page.WriteRetryCount).AppendLine(); + if (page.RecoveryTimeLimit > 0) + sb.AppendFormat("\tDrive will employ a maximum of {0} ms to recover data", page.RecoveryTimeLimit).AppendLine(); + + return sb.ToString(); + } + #endregion Mode Page 0x01: Read-write error recovery page } }