diff --git a/ChangeLog b/ChangeLog index 51c67b9d2..48eea150a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2016-10-14 Natalia Portillo + + * EVPD.cs: + * Inquiry.cs: Added Seagate EVPD and INQUIRY fields. + 2016-10-14 Natalia Portillo * Modes.cs: Added Apple OEM MODE page 30h. diff --git a/SCSI/EVPD.cs b/SCSI/EVPD.cs index b42c5851c..0ce204e69 100644 --- a/SCSI/EVPD.cs +++ b/SCSI/EVPD.cs @@ -2333,7 +2333,7 @@ namespace DiscImageChef.Decoders.SCSI decoded.PageLength = (byte)(pageResponse[3] + 4); decoded.PageCode = pageResponse[1]; - if(pageResponse[3] == 92 && pageResponse.Length < 96) + if(pageResponse[3] == 92 && pageResponse.Length >= 96) { decoded.Component = new byte[26]; decoded.Version = new byte[19]; @@ -2449,6 +2449,91 @@ namespace DiscImageChef.Decoders.SCSI #endregion EVPD Pages 0xC0 to 0xC5 (HP): Drive component revision level pages + #region EVPD Page 0xC0 (Seagate): Firmware numbers page + + /// + /// Firmware numbers page + /// Page code 0xC0 (Seagate) + /// + public struct Page_C0_Seagate + { + /// + /// The peripheral qualifier. + /// + public PeripheralQualifiers PeripheralQualifier; + /// + /// The type of the peripheral device. + /// + public PeripheralDeviceTypes PeripheralDeviceType; + /// + /// The page code. + /// + public byte PageCode; + /// + /// The length of the page. + /// + public byte PageLength; + public byte[] ControllerFirmware; + public byte[] BootFirmware; + public byte[] ServoFirmware; + } + + public static Page_C0_Seagate? DecodePage_C0_Seagate(byte[] pageResponse) + { + if(pageResponse == null) + return null; + + if(pageResponse[1] != 0xC0) + return null; + + if(pageResponse[3] != 12) + return null; + + if(pageResponse.Length != 16) + return null; + + Page_C0_Seagate decoded = new Page_C0_Seagate(); + + decoded.PeripheralQualifier = (PeripheralQualifiers)((pageResponse[0] & 0xE0) >> 5); + decoded.PeripheralDeviceType = (PeripheralDeviceTypes)(pageResponse[0] & 0x1F); + decoded.PageLength = (byte)(pageResponse[3] + 4); + decoded.PageCode = pageResponse[1]; + + decoded.ControllerFirmware = new byte[4]; + decoded.BootFirmware = new byte[4]; + decoded.ServoFirmware = new byte[4]; + + Array.Copy(pageResponse, 4, decoded.ControllerFirmware, 0, 4); + Array.Copy(pageResponse, 8, decoded.BootFirmware, 0, 4); + Array.Copy(pageResponse, 12, decoded.ServoFirmware, 0, 4) + + return decoded; + } + + public static string PrettifyPage_C0_Seagate(byte[] pageResponse) + { + return PrettifyPage_C0_Seagate(DecodePage_C0_Seagate(pageResponse)); + } + + public static string PrettifyPage_C0_Seagate(Page_C0_Seagate? modePage) + { + if(!modePage.HasValue) + return null; + + Page_C0_Seagate page = modePage.Value; + StringBuilder sb = new StringBuilder(); + + sb.AppendLine("Seagate Firmware Numbers page:"); + + sb.AppendFormat("\tController firmware version: {0}", StringHandlers.CToString(page.ControllerFirmware)).AppendLine(); + sb.AppendFormat("\tBoot firmware version: {0}", StringHandlers.CToString(page.BootFirmware)).AppendLine(); + sb.AppendFormat("\tServo firmware version: {0}", StringHandlers.CToString(page.ServoFirmware)).AppendLine(); + + return sb.ToString(); + } + + #endregion EVPD Page 0xC0 (Seagate): Firmware numbers page + } } diff --git a/SCSI/Inquiry.cs b/SCSI/Inquiry.cs index 778e4110e..528d874a9 100644 --- a/SCSI/Inquiry.cs +++ b/SCSI/Inquiry.cs @@ -143,6 +143,13 @@ namespace DiscImageChef.Decoders.SCSI decoded.ProductRevisionLevel = new byte[4]; Array.Copy(SCSIInquiryResponse, 32, decoded.ProductRevisionLevel, 0, 4); } + if(SCSIInquiryResponse.Length >= 44) + { + // Seagate 1 + decoded.SeagatePresent = true; + decoded.Seagate_DriveSerialNumber = new byte[8]; + Array.Copy(SCSIInquiryResponse, 36, decoded.Seagate_DriveSerialNumber, 0, 8); + } if(SCSIInquiryResponse.Length >= 49) { // HP @@ -225,6 +232,20 @@ namespace DiscImageChef.Decoders.SCSI decoded.VendorSpecific2 = new byte[SCSIInquiryResponse.Length - 96]; Array.Copy(SCSIInquiryResponse, 96, decoded.VendorSpecific2, 0, SCSIInquiryResponse.Length - 96); } + if(SCSIInquiryResponse.Length >= 144) + { + // Seagate 2 + decoded.Seagate2Present = true; + decoded.Seagate_Copyright = new byte[48]; + Array.Copy(SCSIInquiryResponse, 96, decoded.Seagate_Copyright, 0, 48); + } + if(SCSIInquiryResponse.Length >= 148) + { + // Seagate 2 + decoded.Seagate3Present = true; + decoded.Seagate_ServoPROMPartNo = new byte[4]; + Array.Copy(SCSIInquiryResponse, 144, decoded.Seagate_ServoPROMPartNo, 0, 4); + } return decoded; } @@ -1985,6 +2006,23 @@ namespace DiscImageChef.Decoders.SCSI } #endregion HP vendor prettifying + #region Seagate vendor prettifying + if((response.SeagatePresent || response.Seagate2Present || response.Seagate3Present) + && StringHandlers.CToString(response.VendorIdentification).ToLowerInvariant().Trim() == "seagate") + { + sb.AppendLine("Seagate vendor-specific information:"); + + if(response.SeagatePresent) + sb.AppendFormat("Drive serial number: {0}", StringHandlers.CToString(response.Seagate_DriveSerialNumber)).AppendLine(); + + if(response.Seagate2Present) + sb.AppendFormat("Drive copyright: {0}", StringHandlers.CToString(response.Seagate_Copyright)).AppendLine(); + + if(response.Seagate3Present) + sb.AppendFormat("Drive servo part number: {0}", PrintHex.ByteArrayToHexArrayString(response.Seagate_ServoPROMPartNo, 40)).AppendLine(); + } + #endregion Seagate vendor prettifying + #if DEBUG if(response.DeviceTypeModifier != 0) sb.AppendFormat("Vendor's device type modifier = 0x{0:X2}", response.DeviceTypeModifier).AppendLine(); @@ -2410,6 +2448,36 @@ namespace DiscImageChef.Decoders.SCSI /// public byte[] HP_OBDR; #endregion HP vendor unique inquiry data structure + + #region Seagate vendor unique inquiry data structure + /// + /// Means that bytes 36 to 43 are filled + /// + public bool SeagatePresent; + /// + /// Drive Serial Number + /// Bytes 36 to 43 + /// + public byte[] Seagate_DriveSerialNumber; + /// + /// Means that bytes 96 to 143 are filled + /// + public bool Seagate2Present; + /// + /// Contains Seagate copyright notice + /// Bytes 96 to 143 + /// + public byte[] Seagate_Copyright; + /// + /// Means that bytes 144 to 147 are filled + /// + public bool Seagate3Present; + /// + /// Reserved Seagate field + /// Bytes 144 to 147 + /// + public byte[] Seagate_ServoPROMPartNo; + #endregion Seagate vendor unique inquiry data structure } #endregion Public structures