diff --git a/DiscImageChef.Decoders/ChangeLog b/DiscImageChef.Decoders/ChangeLog index e2a2fc9b..4d7b58f8 100644 --- a/DiscImageChef.Decoders/ChangeLog +++ b/DiscImageChef.Decoders/ChangeLog @@ -1,3 +1,8 @@ +2015-10-31 Natalia Portillo + + * SCSI/Modes.cs: + Implemented Mode Page 0x0F: Data compression page. + 2015-10-31 Natalia Portillo * SCSI/Modes.cs: diff --git a/DiscImageChef.Decoders/SCSI/Modes.cs b/DiscImageChef.Decoders/SCSI/Modes.cs index e20f6866..405bc3af 100644 --- a/DiscImageChef.Decoders/SCSI/Modes.cs +++ b/DiscImageChef.Decoders/SCSI/Modes.cs @@ -4952,6 +4952,169 @@ namespace DiscImageChef.Decoders.SCSI return sb.ToString(); } #endregion Mode Page 0x1C subpage 0x01: Background Control mode page + + #region Mode Page 0x0F: Data compression page + /// + /// Data compression page + /// Page code 0x0F + /// 16 bytes in SSC-1 + /// + public struct ModePage_0F + { + /// + /// Parameters can be saved + /// + public bool PS; + /// + /// Data compression enabled + /// + public bool DCE; + /// + /// Data compression capable + /// + public bool DCC; + /// + /// Data decompression enabled + /// + public bool DDE; + /// + /// Report exception on decompression + /// + public byte RED; + /// + /// Compression algorithm + /// + public uint CompressionAlgo; + /// + /// Decompression algorithm + /// + public uint DecompressionAlgo; + } + + public static ModePage_0F? DecodeModePage_0F(byte[] pageResponse) + { + if (pageResponse == null) + return null; + + if ((pageResponse[0] & 0x40) == 0x40) + return null; + + if ((pageResponse[0] & 0x3F) != 0x0F) + return null; + + if (pageResponse[1] + 2 != pageResponse.Length) + return null; + + if (pageResponse.Length < 24) + return null; + + ModePage_0F decoded = new ModePage_0F(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + + decoded.DCE |= (pageResponse[2] & 0x80) == 0x80; + decoded.DCC |= (pageResponse[2] & 0x40) == 0x40; + decoded.DDE |= (pageResponse[3] & 0x80) == 0x80; + decoded.RED = (byte)((pageResponse[3] & 0x60) >> 5); + + decoded.CompressionAlgo = (uint)((pageResponse[4] << 24) + (pageResponse[5] << 16) + (pageResponse[6] << 8) + pageResponse[7]); + decoded.DecompressionAlgo = (uint)((pageResponse[8] << 24) + (pageResponse[9] << 16) + (pageResponse[10] << 8) + pageResponse[11]); + + return decoded; + } + + public static string PrettifyModePage_0F(byte[] pageResponse) + { + return PrettifyModePage_0F(DecodeModePage_0F(pageResponse)); + } + + public static string PrettifyModePage_0F(ModePage_0F? modePage) + { + if (!modePage.HasValue) + return null; + + ModePage_0F page = modePage.Value; + StringBuilder sb = new StringBuilder(); + + sb.AppendLine("SCSI Data compression page:"); + + if (page.PS) + sb.AppendLine("\tParameters can be saved"); + + if (page.DCC) + { + sb.AppendLine("\tDrive supports data compression"); + if (page.DCE) + { + sb.Append("\tData compression is enabled with "); + switch (page.CompressionAlgo) + { + case 3: + sb.AppendLine("IBM ALDC with 512 byte buffer"); + break; + case 4: + sb.AppendLine("IBM ALDC with 1024 byte buffer"); + break; + case 5: + sb.AppendLine("IBM ALDC with 2048 byte buffer"); + break; + case 0x10: + sb.AppendLine("IBM IDRC"); + break; + case 0x20: + sb.AppendLine("DCLZ"); + break; + case 0xFF: + sb.AppendLine("an unregistered compression algorithm"); + break; + default: + sb.AppendFormat("an unknown algorithm coded {0}", page.CompressionAlgo).AppendLine(); + break; + } + } + if (page.DDE) + { + sb.AppendLine("\tData decompression is enabled"); + if (page.DecompressionAlgo == 0) + sb.AppendLine("\tLast data read was uncompressed"); + else + { + sb.Append("\tLast data read was compressed with "); + switch (page.CompressionAlgo) + { + case 3: + sb.AppendLine("IBM ALDC with 512 byte buffer"); + break; + case 4: + sb.AppendLine("IBM ALDC with 1024 byte buffer"); + break; + case 5: + sb.AppendLine("IBM ALDC with 2048 byte buffer"); + break; + case 0x10: + sb.AppendLine("IBM IDRC"); + break; + case 0x20: + sb.AppendLine("DCLZ"); + break; + case 0xFF: + sb.AppendLine("an unregistered compression algorithm"); + break; + default: + sb.AppendFormat("an unknown algorithm coded {0}", page.CompressionAlgo).AppendLine(); + break; + } + } + } + + sb.AppendFormat("\tReport exception on compression is set to {0}", page.RED).AppendLine(); + } + else + sb.AppendLine("\tDrive does not support data compression"); + + return sb.ToString(); + } + #endregion Mode Page 0x0F: Data compression page } }