From 8d149cd30f4fb3b47ffd3b2b4d34db101819fe02 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Fri, 30 Oct 2015 02:50:05 +0000 Subject: [PATCH] Implemented decoding mode page 04h. --- ChangeLog | 5 ++ SCSI/Modes.cs | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 137 insertions(+) diff --git a/ChangeLog b/ChangeLog index 373fee0..b18420f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-10-30 Natalia Portillo + + * SCSI/Modes.cs: + Implemented decoding mode page 04h. + 2015-10-30 Natalia Portillo * SCSI/Modes.cs: diff --git a/SCSI/Modes.cs b/SCSI/Modes.cs index 4804cf1..9acdefa 100644 --- a/SCSI/Modes.cs +++ b/SCSI/Modes.cs @@ -2285,6 +2285,138 @@ namespace DiscImageChef.Decoders.SCSI return sb.ToString(); } #endregion Mode Page 0x01: Read-write error recovery page + + #region Mode Page 0x04: Rigid disk drive geometry page + /// + /// Disconnect-reconnect page + /// Page code 0x04 + /// 24 bytes in SCSI-2 + /// + public struct ModePage_04 + { + /// + /// Parameters can be saved + /// + public bool PS; + /// + /// Cylinders used for data storage + /// + public uint Cylinders; + /// + /// Heads for reading and/or writing + /// + public byte Heads; + /// + /// Cylinder where write precompensation starts + /// + public uint WritePrecompCylinder; + /// + /// Cylinder where write current reduction starts + /// + public uint WriteReduceCylinder; + /// + /// Step rate in 100 ns units + /// + public ushort DriveStepRate; + /// + /// Cylinder where the heads park + /// + public int LandingCylinder; + /// + /// Rotational position locking + /// + public byte RPL; + /// + /// Rotational skew to apply when synchronized + /// + public byte RotationalOffset; + /// + /// Medium speed in rpm + /// + public ushort MediumRotationRate; + } + + public static ModePage_04? DecodeModePage_04(byte[] pageResponse) + { + if (pageResponse == null) + return null; + + if ((pageResponse[0] & 0x3F) != 0x04) + return null; + + if (pageResponse[1] + 2 != pageResponse.Length) + return null; + + if (pageResponse.Length < 24) + return null; + + ModePage_04 decoded = new ModePage_04(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + decoded.Cylinders = (uint)((pageResponse[2] << 16) + (pageResponse[3] << 8) + pageResponse[4]); + decoded.Heads = pageResponse[5]; + decoded.WritePrecompCylinder = (uint)((pageResponse[6] << 16) + (pageResponse[7] << 8) + pageResponse[8]); + decoded.WriteReduceCylinder = (uint)((pageResponse[9] << 16) + (pageResponse[10] << 8) + pageResponse[11]); + decoded.DriveStepRate = (ushort)((pageResponse[12] << 8) + pageResponse[13]); + decoded.LandingCylinder = ((pageResponse[14] << 16) + (pageResponse[15] << 8) + pageResponse[16]); + decoded.RPL = (byte)(pageResponse[17] & 0x03); + decoded.RotationalOffset = pageResponse[18]; + decoded.MediumRotationRate = (ushort)((pageResponse[20] << 8) + pageResponse[21]); + + return decoded; + } + + public static string PrettifyModePage_04(byte[] pageResponse) + { + return PrettifyModePage_04(DecodeModePage_04(pageResponse)); + } + + public static string PrettifyModePage_04(ModePage_04? modePage) + { + if (!modePage.HasValue) + return null; + + ModePage_04 page = modePage.Value; + StringBuilder sb = new StringBuilder(); + + sb.AppendLine("SCSI Rigid disk drive geometry page:"); + + if (page.PS) + sb.AppendLine("\tParameters can be saved"); + + sb.AppendFormat("\t{0} heads", page.Heads).AppendLine(); + sb.AppendFormat("\t{0} cylinders", page.Cylinders).AppendLine(); + if(page.WritePrecompCylinder < page.Cylinders) + sb.AppendFormat("\tWrite pre-compensation starts at cylinder {0}", page.WritePrecompCylinder).AppendLine(); + if(page.WriteReduceCylinder < page.Cylinders) + sb.AppendFormat("\tWrite current reduction starts at cylinder {0}", page.WriteReduceCylinder).AppendLine(); + if (page.DriveStepRate > 0) + sb.AppendFormat("\tDrive steps in {0} ns", (uint)page.DriveStepRate * 100).AppendLine(); + + sb.AppendFormat("\tHeads park in cylinder {0}", page.LandingCylinder).AppendLine(); + + if (page.MediumRotationRate > 0) + sb.AppendFormat("\tMedium rotates at {0} rpm", page.MediumRotationRate).AppendLine(); + + switch (page.RPL) + { + case 0: + sb.AppendLine("\tSpindle synchronization is disable or unsupported"); + break; + case 1: + sb.AppendLine("\tTarget operates as a synchronized-spindle slave"); + break; + case 2: + sb.AppendLine("\tTarget operates as a synchronized-spindle master"); + break; + case 3: + sb.AppendLine("\tTarget operates as a synchronized-spindle master control"); + break; + } + + return sb.ToString(); + } + #endregion Mode Page 0x04: Rigid disk drive geometry page } }