From 87e27f8073df656b3f9384b5316357db467f3d0f Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Fri, 30 Oct 2015 01:15:56 +0000 Subject: [PATCH] Implemented decoding mode page 03h. --- ChangeLog | 5 ++ SCSI/Modes.cs | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 148 insertions(+) diff --git a/ChangeLog b/ChangeLog index 5a1a428..8d64921 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-10-30 Natalia Portillo + + * SCSI/Modes.cs: + Implemented decoding mode page 03h. + 2015-10-29 Natalia Portillo * SCSI/Modes.cs: diff --git a/SCSI/Modes.cs b/SCSI/Modes.cs index cf66127..424ac58 100644 --- a/SCSI/Modes.cs +++ b/SCSI/Modes.cs @@ -1919,6 +1919,149 @@ namespace DiscImageChef.Decoders.SCSI return sb.ToString(); } #endregion Mode Page 0x05: Flexible disk page + + #region Mode Page 0x03: Format device page + /// + /// Disconnect-reconnect page + /// Page code 0x03 + /// 24 bytes in SCSI-2 + /// + public struct ModePage_03 + { + /// + /// Parameters can be saved + /// + public bool PS; + /// + /// Tracks per zone to use in dividing the capacity for the purpose of allocating alternate sectors + /// + public ushort TracksPerZone; + /// + /// Number of sectors per zone that shall be reserved for defect handling + /// + public ushort AltSectorsPerZone; + /// + /// Number of tracks per zone that shall be reserved for defect handling + /// + public ushort AltTracksPerZone; + /// + /// Number of tracks per LUN that shall be reserved for defect handling + /// + public ushort AltTracksPerLun; + /// + /// Number of physical sectors per track + /// + public ushort SectorsPerTrack; + /// + /// Bytes per physical sector + /// + public ushort BytesPerSector; + /// + /// Interleave value, target dependent + /// + public ushort Interleave; + /// + /// Sectors between last block of one track and first block of the next + /// + public ushort TrackSkew; + /// + /// Sectors between last block of a cylinder and first block of the next one + /// + public ushort CylinderSkew; + /// + /// Soft-sectored + /// + public bool SSEC; + /// + /// Hard-sectored + /// + public bool HSEC; + /// + /// Removable + /// + public bool RMB; + /// + /// If set, address are allocated progressively in a surface before going to the next. + /// Otherwise, it goes by cylinders + /// + public bool SURF; + } + + public static ModePage_03? DecodeModePage_03(byte[] pageResponse) + { + if (pageResponse == null) + return null; + + if ((pageResponse[0] & 0x3F) != 0x05) + return null; + + if (pageResponse[1] + 2 != pageResponse.Length) + return null; + + if (pageResponse.Length < 24) + return null; + + ModePage_03 decoded = new ModePage_03(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + decoded.TracksPerZone = (ushort)((pageResponse[2] << 8) + pageResponse[3]); + decoded.AltSectorsPerZone = (ushort)((pageResponse[4] << 8) + pageResponse[5]); + decoded.AltTracksPerZone = (ushort)((pageResponse[6] << 8) + pageResponse[7]); + decoded.AltTracksPerLun = (ushort)((pageResponse[8] << 8) + pageResponse[9]); + decoded.SectorsPerTrack = (ushort)((pageResponse[10] << 8) + pageResponse[11]); + decoded.BytesPerSector = (ushort)((pageResponse[12] << 8) + pageResponse[13]); + decoded.Interleave = (ushort)((pageResponse[14] << 8) + pageResponse[15]); + decoded.TrackSkew = (ushort)((pageResponse[16] << 8) + pageResponse[17]); + decoded.CylinderSkew = (ushort)((pageResponse[18] << 8) + pageResponse[19]); + decoded.SSEC |= (pageResponse[20] & 0x80) == 0x80; + decoded.HSEC |= (pageResponse[20] & 0x40) == 0x40; + decoded.RMB |= (pageResponse[20] & 0x20) == 0x20; + decoded.SURF |= (pageResponse[20] & 0x10) == 0x10; + + return decoded; + } + + public static string PrettifyModePage_03(byte[] pageResponse) + { + return PrettifyModePage_03(DecodeModePage_03(pageResponse)); + } + + public static string PrettifyModePage_03(ModePage_03? modePage) + { + if (!modePage.HasValue) + return null; + + ModePage_03 page = modePage.Value; + StringBuilder sb = new StringBuilder(); + + sb.AppendLine("SCSI Format device page:"); + + if (page.PS) + sb.AppendLine("\tParameters can be saved"); + + sb.AppendFormat("\t{0} tracks per zone to use in dividing the capacity for the purpose of allocating alternate sectors", page.TracksPerZone).AppendLine(); + sb.AppendFormat("\t{0} sectors per zone that shall be reserved for defect handling", page.AltSectorsPerZone).AppendLine(); + sb.AppendFormat("\t{0} tracks per zone that shall be reserved for defect handling", page.AltTracksPerZone).AppendLine(); + sb.AppendFormat("\t{0} tracks per LUN that shall be reserved for defect handling", page.AltTracksPerLun).AppendLine(); + sb.AppendFormat("\t{0} physical sectors per track", page.SectorsPerTrack).AppendLine(); + sb.AppendFormat("\t{0} Bytes per physical sector", page.BytesPerSector).AppendLine(); + sb.AppendFormat("\tTarget-dependent interleave value is {0}", page.Interleave).AppendLine(); + sb.AppendFormat("\t{0} sectors between last block of one track and first block of the next", page.TrackSkew).AppendLine(); + sb.AppendFormat("\t{0} sectors between last block of a cylinder and first block of the next one", page.CylinderSkew).AppendLine(); + if (page.SSEC) + sb.AppendLine("\tDrive supports soft-sectoring format"); + if (page.HSEC) + sb.AppendLine("\tDrive supports hard-sectoring format"); + if (page.RMB) + sb.AppendLine("\tDrive media is removable"); + if (page.SURF) + sb.AppendLine("\tSector addressing is progressively incremented in one surface before going to the next"); + else + sb.AppendLine("\tSector addressing is progressively incremented in one cylinder before going to the next"); + + return sb.ToString(); + } + #endregion Mode Page 0x03: Format device page } }