diff --git a/DiscImageChef.Decoders/ChangeLog b/DiscImageChef.Decoders/ChangeLog index 67a8d7460..61c6a2d10 100644 --- a/DiscImageChef.Decoders/ChangeLog +++ b/DiscImageChef.Decoders/ChangeLog @@ -1,3 +1,9 @@ +2016-10-13 Natalia Portillo + + * EVPD.cs: + * Inquiry.cs: Added Quantum vendor INQUIRY values and EVPD + page C0h. + 2016-10-13 Natalia Portillo * EVPD.cs: Added EVPD page 89h, SCSI to ATA translation layer diff --git a/DiscImageChef.Decoders/SCSI/EVPD.cs b/DiscImageChef.Decoders/SCSI/EVPD.cs index b8b845770..396a3ca13 100644 --- a/DiscImageChef.Decoders/SCSI/EVPD.cs +++ b/DiscImageChef.Decoders/SCSI/EVPD.cs @@ -864,7 +864,7 @@ namespace DiscImageChef.Decoders.SCSI if(pageResponse[1] != 0x85) return null; - if((pageResponse[2] << 4) + pageResponse[3] + 4 != pageResponse.Length) + if((pageResponse[2] << 8) + pageResponse[3] + 4 != pageResponse.Length) return null; if(pageResponse.Length < 4) @@ -874,7 +874,7 @@ namespace DiscImageChef.Decoders.SCSI decoded.PeripheralQualifier = (PeripheralQualifiers)((pageResponse[0] & 0xE0) >> 5); decoded.PeripheralDeviceType = (PeripheralDeviceTypes)(pageResponse[0] & 0x1F); - decoded.PageLength = (ushort)((pageResponse[2] << 4) + pageResponse[3] + 4); + decoded.PageLength = (ushort)((pageResponse[2] << 8) + pageResponse[3] + 4); int position = 4; List descriptors = new List(); @@ -884,7 +884,7 @@ namespace DiscImageChef.Decoders.SCSI NetworkDescriptor descriptor = new NetworkDescriptor(); descriptor.Association = (IdentificationAssociation)((pageResponse[position] & 0x60) >> 5); descriptor.Type = (NetworkServiceTypes)(pageResponse[position] & 0x1F); - descriptor.Length = (ushort)((pageResponse[position + 2] << 4) + pageResponse[position + 3]); + descriptor.Length = (ushort)((pageResponse[position + 2] << 8) + pageResponse[position + 3]); descriptor.Address = new byte[descriptor.Length]; Array.Copy(pageResponse, position + 4, descriptor.Address, 0, descriptor.Length); @@ -1125,7 +1125,7 @@ namespace DiscImageChef.Decoders.SCSI decoded.PeripheralQualifier = (PeripheralQualifiers)((pageResponse[0] & 0xE0) >> 5); decoded.PeripheralDeviceType = (PeripheralDeviceTypes)(pageResponse[0] & 0x1F); - decoded.PageLength = (byte)((pageResponse[2] << 4) + pageResponse[3] + 4); + decoded.PageLength = (byte)(pageResponse[3] + 4); decoded.ActivateMicrocode = (byte)((pageResponse[4] & 0xC0) >> 6); decoded.SPT = (byte)((pageResponse[4] & 0x38) >> 3); @@ -1321,7 +1321,7 @@ namespace DiscImageChef.Decoders.SCSI if(pageResponse[1] != 0x89) return null; - if((pageResponse[2] << 4) + pageResponse[3] + 4 != pageResponse.Length) + if((pageResponse[2] << 8) + pageResponse[3] + 4 != pageResponse.Length) return null; if(pageResponse.Length < 572) @@ -1331,7 +1331,7 @@ namespace DiscImageChef.Decoders.SCSI decoded.PeripheralQualifier = (PeripheralQualifiers)((pageResponse[0] & 0xE0) >> 5); decoded.PeripheralDeviceType = (PeripheralDeviceTypes)(pageResponse[0] & 0x1F); - decoded.PageLength = (ushort)((pageResponse[2] << 4) + pageResponse[3] + 4); + decoded.PageLength = (ushort)((pageResponse[2] << 8) + pageResponse[3] + 4); decoded.VendorIdentification = new byte[8]; decoded.ProductIdentification = new byte[16]; @@ -1407,6 +1407,103 @@ namespace DiscImageChef.Decoders.SCSI #endregion EVPD Page 0x89: ATA Information page + #region EVPD Page 0xC0 (Quantum): Firmware Build Information page + + /// + /// Firmware Build Information page + /// Page code 0xC0 (Quantum) + /// + public struct Page_C0_Quantum + { + /// + /// 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; + /// + /// Servo firmware checksum + /// + public ushort ServoFirmwareChecksum; + /// + /// Servo EEPROM checksum + /// + public ushort ServoEEPROMChecksum; + /// + /// Read/Write firmware checksum + /// + public uint ReadWriteFirmwareChecksum; + /// + /// Read/Write firmware build data + /// + public byte[] ReadWriteFirmwareBuildData; + } + + public static Page_C0_Quantum? DecodePage_C0_Quantum(byte[] pageResponse) + { + if(pageResponse == null) + return null; + + if(pageResponse[1] != 0xC0) + return null; + + if(pageResponse[3] != 20) + return null; + + if(pageResponse.Length != 36) + return null; + + Page_C0_Quantum decoded = new Page_C0_Quantum(); + + decoded.PeripheralQualifier = (PeripheralQualifiers)((pageResponse[0] & 0xE0) >> 5); + decoded.PeripheralDeviceType = (PeripheralDeviceTypes)(pageResponse[0] & 0x1F); + decoded.PageLength = (byte)(pageResponse[3] + 4); + + decoded.ServoFirmwareChecksum = (ushort)((pageResponse[4] << 8) + pageResponse[5]); + decoded.ServoEEPROMChecksum = (ushort)((pageResponse[6] << 8) + pageResponse[7]); + decoded.ReadWriteFirmwareChecksum = (uint)((pageResponse[8] << 24) + (pageResponse[9] << 16) + (pageResponse[10] << 8) + pageResponse[11]); + decoded.ReadWriteFirmwareBuildData = new byte[24]; + Array.Copy(pageResponse, 12, decoded.ReadWriteFirmwareBuildData, 0, 24); + + return decoded; + } + + public static string PrettifyPage_C0_Quantum(byte[] pageResponse) + { + return PrettifyPage_C0_Quantum(DecodePage_C0_Quantum(pageResponse)); + } + + // TODO: Decode ATA signature? + public static string PrettifyPage_C0_Quantum(Page_C0_Quantum? modePage) + { + if(!modePage.HasValue) + return null; + + Page_C0_Quantum page = modePage.Value; + StringBuilder sb = new StringBuilder(); + + sb.AppendLine("Quantum Firmware Build Information page:"); + + sb.AppendFormat("\tServo firmware checksum: 0x{0:X4}", page.ServoFirmwareChecksum).AppendLine(); + sb.AppendFormat("\tEEPROM firmware checksum: 0x{0:X4}", page.ServoEEPROMChecksum).AppendLine(); + sb.AppendFormat("\tRead/write firmware checksum: 0x{0:X8}", page.ReadWriteFirmwareChecksum).AppendLine(); + sb.AppendFormat("\tRead/write firmware build date: {0}", StringHandlers.CToString(page.ReadWriteFirmwareBuildData)).AppendLine(); + + return sb.ToString(); + } + + #endregion EVPD Page 0xC0 (Quantum): Firmware Build Information page + } } diff --git a/DiscImageChef.Decoders/SCSI/Inquiry.cs b/DiscImageChef.Decoders/SCSI/Inquiry.cs index 1b20580c5..e75f60854 100644 --- a/DiscImageChef.Decoders/SCSI/Inquiry.cs +++ b/DiscImageChef.Decoders/SCSI/Inquiry.cs @@ -146,6 +146,28 @@ namespace DiscImageChef.Decoders.SCSI { decoded.VendorSpecific = new byte[20]; Array.Copy(SCSIInquiryResponse, 36, decoded.VendorSpecific, 0, 20); + + // Quantum + decoded.QuantumPresent = true; + decoded.Qt_ProductFamily = (byte)((SCSIInquiryResponse[36] & 0xF0) >> 4); + decoded.Qt_ReleasedFirmware = (byte)(SCSIInquiryResponse[36] & 0x0F); + decoded.Qt_FirmwareMajorVersion = SCSIInquiryResponse[37]; + decoded.Qt_FirmwareMinorVersion = SCSIInquiryResponse[38]; + decoded.Qt_EEPROMFormatMajorVersion = SCSIInquiryResponse[39]; + decoded.Qt_EEPROMFormatMinorVersion = SCSIInquiryResponse[40]; + decoded.Qt_FirmwarePersonality = SCSIInquiryResponse[41]; + decoded.Qt_FirmwareSubPersonality = SCSIInquiryResponse[42]; + decoded.Qt_TapeDirectoryFormatVersion = SCSIInquiryResponse[43]; + decoded.Qt_ControllerHardwareVersion = SCSIInquiryResponse[44]; + decoded.Qt_DriveEEPROMVersion = SCSIInquiryResponse[45]; + decoded.Qt_DriveHardwareVersion = SCSIInquiryResponse[46]; + decoded.Qt_MediaLoaderFirmwareVersion = SCSIInquiryResponse[47]; + decoded.Qt_MediaLoaderHardwareVersion = SCSIInquiryResponse[48]; + decoded.Qt_MediaLoaderMechanicalVersion = SCSIInquiryResponse[49]; + decoded.Qt_MediaLoaderPresent = SCSIInquiryResponse[50] > 0; + decoded.Qt_LibraryPresent = SCSIInquiryResponse[51] > 0; + decoded.Qt_ModuleRevision = new byte[4]; + Array.Copy(SCSIInquiryResponse, 52, decoded.Qt_ModuleRevision, 0, 4); } if(SCSIInquiryResponse.Length >= 57) { @@ -1866,6 +1888,107 @@ namespace DiscImageChef.Decoders.SCSI } } + #region Quantum vendor prettifying + if(response.QuantumPresent && StringHandlers.CToString(response.VendorIdentification).ToLowerInvariant() == "quantum") + { + sb.AppendLine("Quantum vendor-specific information:"); + /// + /// The product family. + /// Byte 36, bits 7 to 5 + /// + switch(response.Qt_ProductFamily) + { + case 0: + sb.AppendLine("Product family is not specified"); + break; + case 1: + sb.AppendLine("Product family is 2.6 GB"); + break; + case 2: + sb.AppendLine("Product family is 6.0 GB"); + break; + case 3: + sb.AppendLine("Product family is 10.0/20.0 GB"); + break; + case 5: + sb.AppendLine("Product family is 20.0/40.0 GB"); + break; + case 6: + sb.AppendLine("Product family is 15.0/30.0 GB"); + break; + default: + sb.AppendFormat("Product family: {0}", response.Qt_ProductFamily).AppendLine(); + break; + } + + /// + /// The released firmware. + /// Byte 36, bits 4 to 0 + /// + sb.AppendFormat("Release firmware: {0}", response.Qt_ReleasedFirmware).AppendLine(); + /// + /// The . + /// Byte 37 + /// + sb.AppendFormat("Firmware version: {0}.{1}", response.Qt_FirmwareMajorVersion, response.Qt_FirmwareMinorVersion).AppendLine(); + /// + /// The EEPROM format major version. + /// Byte 39 + /// + sb.AppendFormat("EEPROM format version: {0}.{1}", response.Qt_EEPROMFormatMajorVersion, response.Qt_EEPROMFormatMinorVersion).AppendLine(); + /// + /// The firmware personality. + /// Byte 41 + /// + sb.AppendFormat("Firmware personality: {0}", response.Qt_FirmwarePersonality).AppendLine(); + /// + /// The firmware sub personality. + /// Byte 42 + /// + sb.AppendFormat("Firmware subpersonality: {0}", response.Qt_FirmwareSubPersonality).AppendLine(); + /// + /// The tape directory format version. + /// Byte 43 + /// + sb.AppendFormat("Tape directory format version: {0}", response.Qt_TapeDirectoryFormatVersion).AppendLine(); + /// + /// The controller hardware version. + /// Byte 44 + /// + sb.AppendFormat("Controller hardware version: {0}", response.Qt_ControllerHardwareVersion).AppendLine(); + /// + /// The drive EEPROM version. + /// Byte 45 + /// + sb.AppendFormat("Drive EEPROM version: {0}", response.Qt_DriveEEPROMVersion).AppendLine(); + /// + /// The drive hardware version. + /// Byte 46 + /// + sb.AppendFormat("Drive hardware version: {0}", response.Qt_DriveHardwareVersion).AppendLine(); + /// + /// The media loader firmware version. + /// Byte 47 + /// + sb.AppendFormat("Media loader firmware version: {0}", response.Qt_MediaLoaderFirmwareVersion).AppendLine(); + /// + /// The media loader hardware version. + /// Byte 48 + /// + sb.AppendFormat("Media loader hardware version: {0}", response.Qt_MediaLoaderHardwareVersion).AppendLine(); + /// + /// The media loader mechanical version. + /// Byte 49 + /// + sb.AppendFormat("Media loader mechanical version: {0}", response.Qt_MediaLoaderMechanicalVersion).AppendLine(); + if(response.Qt_LibraryPresent) + sb.AppendLine("Library is present"); + if(response.Qt_MediaLoaderPresent) + sb.AppendLine("Media loader is present"); + sb.AppendFormat("Module revision: {0}", StringHandlers.CToString(response.Qt_ModuleRevision)).AppendLine(); + } + #endregion Quantum vendor prettifying + #if DEBUG if(response.DeviceTypeModifier != 0) sb.AppendFormat("Vendor's device type modifier = 0x{0:X2}", response.DeviceTypeModifier).AppendLine(); @@ -2151,6 +2274,104 @@ namespace DiscImageChef.Decoders.SCSI /// Bytes 96 to end /// public byte[] VendorSpecific2; + + // Per DLT4000/DLT4500/DLT4700 Cartridge Tape Subsystem Product Manual + #region Quantum vendor unique inquiry data structure + /// + /// Means that the INQUIRY response contains 56 bytes or more, so this data has been filled + /// + public bool QuantumPresent; + /// + /// The product family. + /// Byte 36, bits 7 to 5 + /// + public byte Qt_ProductFamily; + /// + /// The released firmware. + /// Byte 36, bits 4 to 0 + /// + public byte Qt_ReleasedFirmware; + /// + /// The firmware major version. + /// Byte 37 + /// + public byte Qt_FirmwareMajorVersion; + /// + /// The firmware minor version. + /// Byte 38 + /// + public byte Qt_FirmwareMinorVersion; + /// + /// The EEPROM format major version. + /// Byte 39 + /// + public byte Qt_EEPROMFormatMajorVersion; + /// + /// The EEPROM format minor version. + /// Byte 40 + /// + public byte Qt_EEPROMFormatMinorVersion; + /// + /// The firmware personality. + /// Byte 41 + /// + public byte Qt_FirmwarePersonality; + /// + /// The firmware sub personality. + /// Byte 42 + /// + public byte Qt_FirmwareSubPersonality; + /// + /// The tape directory format version. + /// Byte 43 + /// + public byte Qt_TapeDirectoryFormatVersion; + /// + /// The controller hardware version. + /// Byte 44 + /// + public byte Qt_ControllerHardwareVersion; + /// + /// The drive EEPROM version. + /// Byte 45 + /// + public byte Qt_DriveEEPROMVersion; + /// + /// The drive hardware version. + /// Byte 46 + /// + public byte Qt_DriveHardwareVersion; + /// + /// The media loader firmware version. + /// Byte 47 + /// + public byte Qt_MediaLoaderFirmwareVersion; + /// + /// The media loader hardware version. + /// Byte 48 + /// + public byte Qt_MediaLoaderHardwareVersion; + /// + /// The media loader mechanical version. + /// Byte 49 + /// + public byte Qt_MediaLoaderMechanicalVersion; + /// + /// Is a media loader present? + /// Byte 50 + /// + public bool Qt_MediaLoaderPresent; + /// + /// Is a library present? + /// Byte 51 + /// + public bool Qt_LibraryPresent; + /// + /// The module revision. + /// Bytes 52 to 55 + /// + public byte[] Qt_ModuleRevision; + #endregion Quantum vendor unique inquiry data structure } #endregion Public structures diff --git a/DiscImageChef/ChangeLog b/DiscImageChef/ChangeLog index 856832b8e..06439e7ff 100644 --- a/DiscImageChef/ChangeLog +++ b/DiscImageChef/ChangeLog @@ -1,3 +1,8 @@ +2016-10-13 Natalia Portillo + + * Commands/DeviceInfo.cs: + Added Quantum vendor INQUIRY values and EVPD page C0h. + 2016-10-13 Natalia Portillo * Commands/DeviceInfo.cs: diff --git a/DiscImageChef/Commands/DeviceInfo.cs b/DiscImageChef/Commands/DeviceInfo.cs index e300cff9d..2ddce425a 100644 --- a/DiscImageChef/Commands/DeviceInfo.cs +++ b/DiscImageChef/Commands/DeviceInfo.cs @@ -301,6 +301,15 @@ namespace DiscImageChef.Commands doWriteFile(options.OutputPrefix, string.Format("_scsi_evpd_{0:X2}h.bin", page), string.Format("SCSI INQUIRY EVPD {0:X2}h", page), inqBuf); } } + else if(page == 0xC0 && StringHandlers.CToString(inq.Value.VendorIdentification).ToLowerInvariant() == "quantum") + { + sense = dev.ScsiInquiry(out inqBuf, out senseBuf, page); + if(!sense) + { + DicConsole.WriteLine("{0}", Decoders.SCSI.EVPD.PrettifyPage_C0_Quantum(inqBuf)); + doWriteFile(options.OutputPrefix, string.Format("_scsi_evpd_{0:X2}h.bin", page), string.Format("SCSI INQUIRY EVPD {0:X2}h", page), inqBuf); + } + } else { if(page != 0x00)