// /*************************************************************************** // The Disc Image Chef // ---------------------------------------------------------------------------- // // Filename : Ata.cs // Author(s) : Natalia Portillo // // Component : DiscImageChef Server. // // --[ Description ] ---------------------------------------------------------- // // Decodes ATA information from reports. // // --[ License ] -------------------------------------------------------------- // // This library is free software; you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as // published by the Free Software Foundation; either version 2.1 of the // License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, see . // // ---------------------------------------------------------------------------- // Copyright © 2011-2018 Natalia Portillo // ****************************************************************************/ using System.Collections.Generic; using DiscImageChef.Decoders.SCSI; using DiscImageChef.Metadata; using static DiscImageChef.Decoders.ATA.Identify; namespace DiscImageChef.Server.App_Start { public static class Ata { /// /// Takes the ATA part of a device report and prints it as a list of values and another list of key=value pairs to be /// sequenced by ASP.NET in the rendering /// /// ATA part of a device report /// true if compact flash device /// true if atapi device /// true if removabledevice /// List to put values on /// List to put key=value pairs on /// List of tested media public static void Report(ataType ataReport, bool cfa, bool atapi, ref bool removable, ref List ataOneValue, ref Dictionary ataTwoValue, ref testedMediaType[] testedMedia) { uint logicalsectorsize = 0; if(ataReport.ModelSpecified && !string.IsNullOrEmpty(ataReport.Model)) ataTwoValue.Add("Model", ataReport.Model); if(ataReport.FirmwareRevisionSpecified && !string.IsNullOrEmpty(ataReport.FirmwareRevision)) ataTwoValue.Add("Firmware revision", ataReport.FirmwareRevision); if(ataReport.AdditionalPIDSpecified && !string.IsNullOrEmpty(ataReport.AdditionalPID)) ataTwoValue.Add("Additional product ID", ataReport.AdditionalPID); bool ata1 = false, ata2 = false, ata3 = false, ata4 = false, ata5 = false, ata6 = false, ata7 = false, acs = false, acs2 = false, acs3 = false, acs4 = false; if(ataReport.MajorVersionSpecified && ((ushort)ataReport.MajorVersion == 0x0000 || (ushort)ataReport.MajorVersion == 0xFFFF)) { // Obsolete in ATA-2, if present, device supports ATA-1 if(ataReport.GeneralConfigurationSpecified) ata1 |= ataReport.GeneralConfiguration.HasFlag(GeneralConfigurationBit.FastIDE) || ataReport.GeneralConfiguration.HasFlag(GeneralConfigurationBit.SlowIDE) || ataReport.GeneralConfiguration.HasFlag(GeneralConfigurationBit.UltraFastIDE); ata2 |= ataReport.ExtendedIdentifySpecified; if(!ata1 && !ata2 && !atapi && !cfa) ata2 = true; ata4 |= atapi; ata3 |= cfa; if(cfa && ata1) ata1 = false; if(cfa && ata2) ata2 = false; } else { if(ataReport.MajorVersionSpecified) { ata1 |= ataReport.MajorVersion.HasFlag(MajorVersionBit.Ata1); ata2 |= ataReport.MajorVersion.HasFlag(MajorVersionBit.Ata2); ata3 |= ataReport.MajorVersion.HasFlag(MajorVersionBit.Ata3); ata4 |= ataReport.MajorVersion.HasFlag(MajorVersionBit.AtaAtapi4); ata5 |= ataReport.MajorVersion.HasFlag(MajorVersionBit.AtaAtapi5); ata6 |= ataReport.MajorVersion.HasFlag(MajorVersionBit.AtaAtapi6); ata7 |= ataReport.MajorVersion.HasFlag(MajorVersionBit.AtaAtapi7); acs |= ataReport.MajorVersion.HasFlag(MajorVersionBit.Ata8ACS); acs2 |= ataReport.MajorVersion.HasFlag(MajorVersionBit.ACS2); acs3 |= ataReport.MajorVersion.HasFlag(MajorVersionBit.ACS3); acs4 |= ataReport.MajorVersion.HasFlag(MajorVersionBit.ACS4); } } int maxatalevel = 0; int minatalevel = 255; string tmpString = ""; if(ata1) { tmpString += "ATA-1 "; maxatalevel = 1; if(minatalevel > 1) minatalevel = 1; } if(ata2) { tmpString += "ATA-2 "; maxatalevel = 2; if(minatalevel > 2) minatalevel = 2; } if(ata3) { tmpString += "ATA-3 "; maxatalevel = 3; if(minatalevel > 3) minatalevel = 3; } if(ata4) { tmpString += "ATA/ATAPI-4 "; maxatalevel = 4; if(minatalevel > 4) minatalevel = 4; } if(ata5) { tmpString += "ATA/ATAPI-5 "; maxatalevel = 5; if(minatalevel > 5) minatalevel = 5; } if(ata6) { tmpString += "ATA/ATAPI-6 "; maxatalevel = 6; if(minatalevel > 6) minatalevel = 6; } if(ata7) { tmpString += "ATA/ATAPI-7 "; maxatalevel = 7; if(minatalevel > 7) minatalevel = 7; } if(acs) { tmpString += "ATA8-ACS "; maxatalevel = 8; if(minatalevel > 8) minatalevel = 8; } if(acs2) { tmpString += "ATA8-ACS2 "; maxatalevel = 9; if(minatalevel > 9) minatalevel = 9; } if(acs3) { tmpString += "ATA8-ACS3 "; maxatalevel = 10; if(minatalevel > 10) minatalevel = 10; } if(acs4) { tmpString += "ATA8-ACS4 "; maxatalevel = 11; if(minatalevel > 11) minatalevel = 11; } if(tmpString != "") ataTwoValue.Add("Supported ATA versions", tmpString); if(maxatalevel >= 3 && ataReport.MinorVersionSpecified) { switch(ataReport.MinorVersion) { case 0x0000: case 0xFFFF: tmpString = "Minor ATA version not specified"; break; case 0x0001: tmpString = "ATA (ATA-1) X3T9.2 781D prior to revision 4"; break; case 0x0002: tmpString = "ATA-1 published, ANSI X3.221-1994"; break; case 0x0003: tmpString = "ATA (ATA-1) X3T9.2 781D revision 4"; break; case 0x0004: tmpString = "ATA-2 published, ANSI X3.279-1996"; break; case 0x0005: tmpString = "ATA-2 X3T10 948D prior to revision 2k"; break; case 0x0006: tmpString = "ATA-3 X3T10 2008D revision 1"; break; case 0x0007: tmpString = "ATA-2 X3T10 948D revision 2k"; break; case 0x0008: tmpString = "ATA-3 X3T10 2008D revision 0"; break; case 0x0009: tmpString = "ATA-2 X3T10 948D revision 3"; break; case 0x000A: tmpString = "ATA-3 published, ANSI X3.298-1997"; break; case 0x000B: tmpString = "ATA-3 X3T10 2008D revision 6"; break; case 0x000C: tmpString = "ATA-3 X3T13 2008D revision 7"; break; case 0x000D: tmpString = "ATA/ATAPI-4 X3T13 1153D revision 6"; break; case 0x000E: tmpString = "ATA/ATAPI-4 T13 1153D revision 13"; break; case 0x000F: tmpString = "ATA/ATAPI-4 X3T13 1153D revision 7"; break; case 0x0010: tmpString = "ATA/ATAPI-4 T13 1153D revision 18"; break; case 0x0011: tmpString = "ATA/ATAPI-4 T13 1153D revision 15"; break; case 0x0012: tmpString = "ATA/ATAPI-4 published, ANSI INCITS 317-1998"; break; case 0x0013: tmpString = "ATA/ATAPI-5 T13 1321D revision 3"; break; case 0x0014: tmpString = "ATA/ATAPI-4 T13 1153D revision 14"; break; case 0x0015: tmpString = "ATA/ATAPI-5 T13 1321D revision 1"; break; case 0x0016: tmpString = "ATA/ATAPI-5 published, ANSI INCITS 340-2000"; break; case 0x0017: tmpString = "ATA/ATAPI-4 T13 1153D revision 17"; break; case 0x0018: tmpString = "ATA/ATAPI-6 T13 1410D revision 0"; break; case 0x0019: tmpString = "ATA/ATAPI-6 T13 1410D revision 3a"; break; case 0x001A: tmpString = "ATA/ATAPI-7 T13 1532D revision 1"; break; case 0x001B: tmpString = "ATA/ATAPI-6 T13 1410D revision 2"; break; case 0x001C: tmpString = "ATA/ATAPI-6 T13 1410D revision 1"; break; case 0x001D: tmpString = "ATA/ATAPI-7 published ANSI INCITS 397-2005"; break; case 0x001E: tmpString = "ATA/ATAPI-7 T13 1532D revision 0"; break; case 0x001F: tmpString = "ACS-3 Revision 3b"; break; case 0x0021: tmpString = "ATA/ATAPI-7 T13 1532D revision 4a"; break; case 0x0022: tmpString = "ATA/ATAPI-6 published, ANSI INCITS 361-2002"; break; case 0x0027: tmpString = "ATA8-ACS revision 3c"; break; case 0x0028: tmpString = "ATA8-ACS revision 6"; break; case 0x0029: tmpString = "ATA8-ACS revision 4"; break; case 0x0031: tmpString = "ACS-2 Revision 2"; break; case 0x0033: tmpString = "ATA8-ACS Revision 3e"; break; case 0x0039: tmpString = "ATA8-ACS Revision 4c"; break; case 0x0042: tmpString = "ATA8-ACS Revision 3f"; break; case 0x0052: tmpString = "ATA8-ACS revision 3b"; break; case 0x006D: tmpString = "ACS-3 Revision 5"; break; case 0x0082: tmpString = "ACS-2 published, ANSI INCITS 482-2012"; break; case 0x0107: tmpString = "ATA8-ACS revision 2d"; break; case 0x0110: tmpString = "ACS-2 Revision 3"; break; case 0x011B: tmpString = "ACS-3 Revision 4"; break; default: tmpString = $"Unknown ATA revision 0x{ataReport.MinorVersion:X4}"; break; } ataTwoValue.Add("Maximum ATA revision supported", tmpString); } if(ataReport.TransportMajorVersionSpecified) { tmpString = ""; switch((ataReport.TransportMajorVersion & 0xF000) >> 12) { case 0x0: if((ataReport.TransportMajorVersion & 0x0002) == 0x0002) tmpString += "ATA/ATAPI-7 "; if((ataReport.TransportMajorVersion & 0x0001) == 0x0001) tmpString += "ATA8-APT "; ataTwoValue.Add("Parallel ATA device", tmpString); break; case 0x1: if((ataReport.TransportMajorVersion & 0x0001) == 0x0001) tmpString += "ATA8-AST "; if((ataReport.TransportMajorVersion & 0x0002) == 0x0002) tmpString += "SATA 1.0a "; if((ataReport.TransportMajorVersion & 0x0004) == 0x0004) tmpString += "SATA II Extensions "; if((ataReport.TransportMajorVersion & 0x0008) == 0x0008) tmpString += "SATA 2.5 "; if((ataReport.TransportMajorVersion & 0x0010) == 0x0010) tmpString += "SATA 2.6 "; if((ataReport.TransportMajorVersion & 0x0020) == 0x0020) tmpString += "SATA 3.0 "; if((ataReport.TransportMajorVersion & 0x0040) == 0x0040) tmpString += "SATA 3.1 "; ataTwoValue.Add("Serial ATA device: ", tmpString); break; case 0xE: ataTwoValue.Add("SATA Express device", "No version"); break; default: ataTwoValue.Add("Unknown transport type", $"0x{(ataReport.TransportMajorVersion & 0xF000) >> 12:X1}"); break; } } if(atapi && ataReport.GeneralConfigurationSpecified) { // Bits 12 to 8, SCSI Peripheral Device Type switch((PeripheralDeviceTypes)(((ushort)ataReport.GeneralConfiguration & 0x1F00) >> 8)) { case PeripheralDeviceTypes.DirectAccess: //0x00, ataOneValue.Add("ATAPI Direct-access device"); break; case PeripheralDeviceTypes.SequentialAccess: //0x01, ataOneValue.Add("ATAPI Sequential-access device"); break; case PeripheralDeviceTypes.PrinterDevice: //0x02, ataOneValue.Add("ATAPI Printer device"); break; case PeripheralDeviceTypes.ProcessorDevice: //0x03, ataOneValue.Add("ATAPI Processor device"); break; case PeripheralDeviceTypes.WriteOnceDevice: //0x04, ataOneValue.Add("ATAPI Write-once device"); break; case PeripheralDeviceTypes.MultiMediaDevice: //0x05, ataOneValue.Add("ATAPI CD-ROM/DVD/etc device"); break; case PeripheralDeviceTypes.ScannerDevice: //0x06, ataOneValue.Add("ATAPI Scanner device"); break; case PeripheralDeviceTypes.OpticalDevice: //0x07, ataOneValue.Add("ATAPI Optical memory device"); break; case PeripheralDeviceTypes.MediumChangerDevice: //0x08, ataOneValue.Add("ATAPI Medium change device"); break; case PeripheralDeviceTypes.CommsDevice: //0x09, ataOneValue.Add("ATAPI Communications device"); break; case PeripheralDeviceTypes.PrePressDevice1: //0x0A, ataOneValue.Add("ATAPI Graphics arts pre-press device (defined in ASC IT8)"); break; case PeripheralDeviceTypes.PrePressDevice2: //0x0B, ataOneValue.Add("ATAPI Graphics arts pre-press device (defined in ASC IT8)"); break; case PeripheralDeviceTypes.ArrayControllerDevice: //0x0C, ataOneValue.Add("ATAPI Array controller device"); break; case PeripheralDeviceTypes.EnclosureServiceDevice: //0x0D, ataOneValue.Add("ATAPI Enclosure services device"); break; case PeripheralDeviceTypes.SimplifiedDevice: //0x0E, ataOneValue.Add("ATAPI Simplified direct-access device"); break; case PeripheralDeviceTypes.OCRWDevice: //0x0F, ataOneValue.Add("ATAPI Optical card reader/writer device"); break; case PeripheralDeviceTypes.BridgingExpander: //0x10, ataOneValue.Add("ATAPI Bridging Expanders"); break; case PeripheralDeviceTypes.ObjectDevice: //0x11, ataOneValue.Add("ATAPI Object-based Storage Device"); break; case PeripheralDeviceTypes.ADCDevice: //0x12, ataOneValue.Add("ATAPI Automation/Drive Interface"); break; case PeripheralDeviceTypes.WellKnownDevice: //0x1E, ataOneValue.Add("ATAPI Well known logical unit"); break; case PeripheralDeviceTypes.UnknownDevice: //0x1F ataOneValue.Add("ATAPI Unknown or no device type"); break; default: ataOneValue .Add($"ATAPI Unknown device type field value 0x{((ushort)ataReport.GeneralConfiguration & 0x1F00) >> 8:X2}"); break; } // ATAPI DRQ behaviour switch(((ushort)ataReport.GeneralConfiguration & 0x60) >> 5) { case 0: ataOneValue.Add("Device shall set DRQ within 3 ms of receiving PACKET"); break; case 1: ataOneValue.Add("Device shall assert INTRQ when DRQ is set to one"); break; case 2: ataOneValue.Add("Device shall set DRQ within 50 µs of receiving PACKET"); break; default: ataOneValue .Add($"Unknown ATAPI DRQ behaviour code {((ushort)ataReport.GeneralConfiguration & 0x60) >> 5}"); break; } // ATAPI PACKET size switch((ushort)ataReport.GeneralConfiguration & 0x03) { case 0: ataOneValue.Add("ATAPI device uses 12 byte command packet"); break; case 1: ataOneValue.Add("ATAPI device uses 16 byte command packet"); break; default: ataOneValue .Add($"Unknown ATAPI packet size code {(ushort)ataReport.GeneralConfiguration & 0x03}"); break; } } else if(!cfa && ataReport.GeneralConfigurationSpecified) { if(minatalevel >= 5) if(ataReport.GeneralConfiguration.HasFlag(GeneralConfigurationBit.IncompleteResponse)) ataOneValue.Add("Incomplete identify response"); if(ataReport.GeneralConfiguration.HasFlag(GeneralConfigurationBit.NonMagnetic)) ataOneValue.Add("Device uses non-magnetic media"); if(ataReport.GeneralConfiguration.HasFlag(GeneralConfigurationBit.Removable)) ataOneValue.Add("Device is removable"); if(minatalevel <= 5) if(ataReport.GeneralConfiguration.HasFlag(GeneralConfigurationBit.Fixed)) ataOneValue.Add("Device is fixed"); if(ata1) { if(ataReport.GeneralConfiguration.HasFlag(GeneralConfigurationBit.SlowIDE)) ataOneValue.Add("Device transfer rate is <= 5 Mb/s"); if(ataReport.GeneralConfiguration.HasFlag(GeneralConfigurationBit.FastIDE)) ataOneValue.Add("Device transfer rate is > 5 Mb/s but <= 10 Mb/s"); if(ataReport.GeneralConfiguration.HasFlag(GeneralConfigurationBit.UltraFastIDE)) ataOneValue.Add("Device transfer rate is > 10 Mb/s"); if(ataReport.GeneralConfiguration.HasFlag(GeneralConfigurationBit.SoftSector)) ataOneValue.Add("Device is soft sectored"); if(ataReport.GeneralConfiguration.HasFlag(GeneralConfigurationBit.HardSector)) ataOneValue.Add("Device is hard sectored"); if(ataReport.GeneralConfiguration.HasFlag(GeneralConfigurationBit.NotMFM)) ataOneValue.Add("Device is not MFM encoded"); if(ataReport.GeneralConfiguration.HasFlag(GeneralConfigurationBit.FormatGapReq)) ataOneValue.Add("Format speed tolerance gap is required"); if(ataReport.GeneralConfiguration.HasFlag(GeneralConfigurationBit.TrackOffset)) ataOneValue.Add("Track offset option is available"); if(ataReport.GeneralConfiguration.HasFlag(GeneralConfigurationBit.DataStrobeOffset)) ataOneValue.Add("Data strobe offset option is available"); if(ataReport.GeneralConfiguration.HasFlag(GeneralConfigurationBit.RotationalSpeedTolerance)) ataOneValue.Add("Rotational speed tolerance is higher than 0,5%"); if(ataReport.GeneralConfiguration.HasFlag(GeneralConfigurationBit.SpindleControl)) ataOneValue.Add("Spindle motor control is implemented"); if(ataReport.GeneralConfiguration.HasFlag(GeneralConfigurationBit.HighHeadSwitch)) ataOneValue.Add("Head switch time is bigger than 15 µs."); } } if(ataReport.SpecificConfigurationSpecified && (ushort)ataReport.SpecificConfiguration != 0x0000 && (ushort)ataReport.SpecificConfiguration != 0xFFFF) switch(ataReport.SpecificConfiguration) { case SpecificConfigurationEnum.RequiresSetIncompleteResponse: ataOneValue .Add("Device requires SET FEATURES to spin up and IDENTIFY DEVICE response is incomplete."); break; case SpecificConfigurationEnum.RequiresSetCompleteResponse: ataOneValue .Add("Device requires SET FEATURES to spin up and IDENTIFY DEVICE response is complete."); break; case SpecificConfigurationEnum.NotRequiresSetIncompleteResponse: ataOneValue .Add("Device does not require SET FEATURES to spin up and IDENTIFY DEVICE response is incomplete."); break; case SpecificConfigurationEnum.NotRequiresSetCompleteResponse: ataOneValue .Add("Device does not require SET FEATURES to spin up and IDENTIFY DEVICE response is complete."); break; default: ataOneValue .Add($"Unknown device specific configuration 0x{(ushort)ataReport.SpecificConfiguration:X4}"); break; } // Obsolete since ATA-2, however, it is yet used in ATA-8 devices if(ataReport.BufferSizeSpecified && ataReport.BufferTypeSpecified && ataReport.BufferSize != 0x0000 && ataReport.BufferSize != 0xFFFF && ataReport.BufferType != 0x0000 && ataReport.BufferType != 0xFFFF) switch(ataReport.BufferType) { case 1: ataOneValue .Add($"{ataReport.BufferSize * logicalsectorsize / 1024} KiB of single ported single sector buffer"); break; case 2: ataOneValue .Add($"{ataReport.BufferSize * logicalsectorsize / 1024} KiB of dual ported multi sector buffer"); break; case 3: ataOneValue .Add($"{ataReport.BufferSize * logicalsectorsize / 1024} KiB of dual ported multi sector buffer with read caching"); break; default: ataOneValue .Add($"{ataReport.BufferSize * logicalsectorsize / 1024} KiB of unknown type {ataReport.BufferType} buffer"); break; } if(ataReport.CapabilitiesSpecified) { ataOneValue.Add("Device capabilities:"); if(ataReport.Capabilities.HasFlag(CapabilitiesBit.StandardStanbyTimer)) ataOneValue.Add("Standby time values are standard"); if(ataReport.Capabilities.HasFlag(CapabilitiesBit.IORDY)) ataOneValue.Add(ataReport.Capabilities.HasFlag(CapabilitiesBit.CanDisableIORDY) ? "IORDY is supported and can be disabled" : "IORDY is supported"); if(ataReport.Capabilities.HasFlag(CapabilitiesBit.DMASupport)) ataOneValue.Add("DMA is supported"); if(ataReport.Capabilities.HasFlag(CapabilitiesBit.PhysicalAlignment1) || ataReport.Capabilities.HasFlag(CapabilitiesBit.PhysicalAlignment0)) ataOneValue.Add($"Long Physical Alignment setting is {(ushort)ataReport.Capabilities & 0x03}"); if(atapi) { if(ataReport.Capabilities.HasFlag(CapabilitiesBit.InterleavedDMA)) ataOneValue.Add("ATAPI device supports interleaved DMA"); if(ataReport.Capabilities.HasFlag(CapabilitiesBit.CommandQueue)) ataOneValue.Add("ATAPI device supports command queueing"); if(ataReport.Capabilities.HasFlag(CapabilitiesBit.OverlapOperation)) ataOneValue.Add("ATAPI device supports overlapped operations"); if(ataReport.Capabilities.HasFlag(CapabilitiesBit.RequiresATASoftReset)) ataOneValue.Add("ATAPI device requires ATA software reset"); } } if(ataReport.Capabilities2Specified) if(ataReport.Capabilities2.HasFlag(CapabilitiesBit2.MustBeSet) && !ataReport.Capabilities2.HasFlag(CapabilitiesBit2.MustBeClear)) if(ataReport.Capabilities2.HasFlag(CapabilitiesBit2.SpecificStandbyTimer)) ataOneValue.Add("Device indicates a specific minimum standby timer value"); if(ataReport.Capabilities3Specified) if(ataReport.Capabilities3.HasFlag(CapabilitiesBit3.MultipleValid)) { ataOneValue .Add($"A maximum of {ataReport.MultipleSectorNumber} sectors can be transferred per interrupt on READ/WRITE MULTIPLE"); ataOneValue.Add($"Device supports setting a maximum of {ataReport.MultipleMaxSectors} sectors"); } if(ata1 && ataReport.TrustedComputingSpecified) if(ataReport.TrustedComputing.HasFlag(TrustedComputingBit.TrustedComputing)) ataOneValue.Add("Device supports doubleword I/O"); if(minatalevel <= 3) { if(ataReport.PIOTransferTimingModeSpecified) ataTwoValue.Add("PIO timing mode", $"{ataReport.PIOTransferTimingMode}"); if(ataReport.DMATransferTimingModeSpecified) ataTwoValue.Add("DMA timing mode", $"{ataReport.DMATransferTimingMode}"); } if(ataReport.APIOSupportedSpecified) { tmpString = ""; if(ataReport.APIOSupported.HasFlag(TransferMode.Mode0)) tmpString += "PIO0 "; if(ataReport.APIOSupported.HasFlag(TransferMode.Mode1)) tmpString += "PIO1 "; if(ataReport.APIOSupported.HasFlag(TransferMode.Mode2)) tmpString += "PIO2 "; if(ataReport.APIOSupported.HasFlag(TransferMode.Mode3)) tmpString += "PIO3 "; if(ataReport.APIOSupported.HasFlag(TransferMode.Mode4)) tmpString += "PIO4 "; if(ataReport.APIOSupported.HasFlag(TransferMode.Mode5)) tmpString += "PIO5 "; if(ataReport.APIOSupported.HasFlag(TransferMode.Mode6)) tmpString += "PIO6 "; if(ataReport.APIOSupported.HasFlag(TransferMode.Mode7)) tmpString += "PIO7 "; ataTwoValue.Add("Advanced PIO", tmpString); } if(minatalevel <= 3 && !atapi && ataReport.DMASupportedSpecified) { tmpString = ""; if(ataReport.DMASupported.HasFlag(TransferMode.Mode0)) { tmpString += "DMA0 "; if(ataReport.DMAActive.HasFlag(TransferMode.Mode0) && ataReport.DMAActiveSpecified) tmpString += "(active) "; } if(ataReport.DMASupported.HasFlag(TransferMode.Mode1)) { tmpString += "DMA1 "; if(ataReport.DMAActive.HasFlag(TransferMode.Mode1) && ataReport.DMAActiveSpecified) tmpString += "(active) "; } if(ataReport.DMASupported.HasFlag(TransferMode.Mode2)) { tmpString += "DMA2 "; if(ataReport.DMAActive.HasFlag(TransferMode.Mode2) && ataReport.DMAActiveSpecified) tmpString += "(active) "; } if(ataReport.DMASupported.HasFlag(TransferMode.Mode3)) { tmpString += "DMA3 "; if(ataReport.DMAActive.HasFlag(TransferMode.Mode3) && ataReport.DMAActiveSpecified) tmpString += "(active) "; } if(ataReport.DMASupported.HasFlag(TransferMode.Mode4)) { tmpString += "DMA4 "; if(ataReport.DMAActive.HasFlag(TransferMode.Mode4) && ataReport.DMAActiveSpecified) tmpString += "(active) "; } if(ataReport.DMASupported.HasFlag(TransferMode.Mode5)) { tmpString += "DMA5 "; if(ataReport.DMAActive.HasFlag(TransferMode.Mode5) && ataReport.DMAActiveSpecified) tmpString += "(active) "; } if(ataReport.DMASupported.HasFlag(TransferMode.Mode6)) { tmpString += "DMA6 "; if(ataReport.DMAActive.HasFlag(TransferMode.Mode6) && ataReport.DMAActiveSpecified) tmpString += "(active) "; } if(ataReport.DMASupported.HasFlag(TransferMode.Mode7)) { tmpString += "DMA7 "; if(ataReport.DMAActive.HasFlag(TransferMode.Mode7) && ataReport.DMAActiveSpecified) tmpString += "(active) "; } ataTwoValue.Add("Single-word DMA", tmpString); } if(ataReport.MDMASupportedSpecified) { tmpString = ""; if(ataReport.MDMASupported.HasFlag(TransferMode.Mode0)) { tmpString += "MDMA0 "; if(ataReport.MDMAActive.HasFlag(TransferMode.Mode0) && ataReport.MDMAActiveSpecified) tmpString += "(active) "; } if(ataReport.MDMASupported.HasFlag(TransferMode.Mode1)) { tmpString += "MDMA1 "; if(ataReport.MDMAActive.HasFlag(TransferMode.Mode1) && ataReport.MDMAActiveSpecified) tmpString += "(active) "; } if(ataReport.MDMASupported.HasFlag(TransferMode.Mode2)) { tmpString += "MDMA2 "; if(ataReport.MDMAActive.HasFlag(TransferMode.Mode2) && ataReport.MDMAActiveSpecified) tmpString += "(active) "; } if(ataReport.MDMASupported.HasFlag(TransferMode.Mode3)) { tmpString += "MDMA3 "; if(ataReport.MDMAActive.HasFlag(TransferMode.Mode3) && ataReport.MDMAActiveSpecified) tmpString += "(active) "; } if(ataReport.MDMASupported.HasFlag(TransferMode.Mode4)) { tmpString += "MDMA4 "; if(ataReport.MDMAActive.HasFlag(TransferMode.Mode4) && ataReport.MDMAActiveSpecified) tmpString += "(active) "; } if(ataReport.MDMASupported.HasFlag(TransferMode.Mode5)) { tmpString += "MDMA5 "; if(ataReport.MDMAActive.HasFlag(TransferMode.Mode5) && ataReport.MDMAActiveSpecified) tmpString += "(active) "; } if(ataReport.MDMASupported.HasFlag(TransferMode.Mode6)) { tmpString += "MDMA6 "; if(ataReport.MDMAActive.HasFlag(TransferMode.Mode6) && ataReport.MDMAActiveSpecified) tmpString += "(active) "; } if(ataReport.MDMASupported.HasFlag(TransferMode.Mode7)) { tmpString += "MDMA7 "; if(ataReport.MDMAActive.HasFlag(TransferMode.Mode7) && ataReport.MDMAActiveSpecified) tmpString += "(active) "; } ataTwoValue.Add("Multi-word DMA", tmpString); } if(ataReport.UDMASupportedSpecified) { tmpString = ""; if(ataReport.UDMASupported.HasFlag(TransferMode.Mode0)) { tmpString += "UDMA0 "; if(ataReport.UDMAActive.HasFlag(TransferMode.Mode0) && ataReport.UDMAActiveSpecified) tmpString += "(active) "; } if(ataReport.UDMASupported.HasFlag(TransferMode.Mode1)) { tmpString += "UDMA1 "; if(ataReport.UDMAActive.HasFlag(TransferMode.Mode1) && ataReport.UDMAActiveSpecified) tmpString += "(active) "; } if(ataReport.UDMASupported.HasFlag(TransferMode.Mode2)) { tmpString += "UDMA2 "; if(ataReport.UDMAActive.HasFlag(TransferMode.Mode2) && ataReport.UDMAActiveSpecified) tmpString += "(active) "; } if(ataReport.UDMASupported.HasFlag(TransferMode.Mode3)) { tmpString += "UDMA3 "; if(ataReport.UDMAActive.HasFlag(TransferMode.Mode3) && ataReport.UDMAActiveSpecified) tmpString += "(active) "; } if(ataReport.UDMASupported.HasFlag(TransferMode.Mode4)) { tmpString += "UDMA4 "; if(ataReport.UDMAActive.HasFlag(TransferMode.Mode4) && ataReport.UDMAActiveSpecified) tmpString += "(active) "; } if(ataReport.UDMASupported.HasFlag(TransferMode.Mode5)) { tmpString += "UDMA5 "; if(ataReport.UDMAActive.HasFlag(TransferMode.Mode5) && ataReport.UDMAActiveSpecified) tmpString += "(active) "; } if(ataReport.UDMASupported.HasFlag(TransferMode.Mode6)) { tmpString += "UDMA6 "; if(ataReport.UDMAActive.HasFlag(TransferMode.Mode6) && ataReport.UDMAActiveSpecified) tmpString += "(active) "; } if(ataReport.UDMASupported.HasFlag(TransferMode.Mode7)) { tmpString += "UDMA7 "; if(ataReport.UDMAActive.HasFlag(TransferMode.Mode7) && ataReport.UDMAActiveSpecified) tmpString += "(active) "; } ataTwoValue.Add("Ultra DMA", tmpString); } if(ataReport.MinMDMACycleTime != 0 && ataReport.RecommendedMDMACycleTime != 0) ataOneValue.Add($"At minimum {ataReport.MinMDMACycleTime} ns. transfer cycle time per word in MDMA, " + $"{ataReport.RecommendedMDMACycleTime} ns. recommended"); if(ataReport.MinPIOCycleTimeNoFlow != 0) ataOneValue.Add($"At minimum {ataReport.MinPIOCycleTimeNoFlow} ns. transfer cycle time per word in PIO, " + "without flow control"); if(ataReport.MinPIOCycleTimeFlow != 0) ataOneValue.Add($"At minimum {ataReport.MinPIOCycleTimeFlow} ns. transfer cycle time per word in PIO, " + "with IORDY flow control"); if(ataReport.MaxQueueDepth != 0) ataOneValue.Add($"{ataReport.MaxQueueDepth + 1} depth of queue maximum"); if(atapi) { if(ataReport.PacketBusRelease != 0) ataOneValue.Add($"{ataReport.PacketBusRelease} ns. typical to release bus from receipt of PACKET"); if(ataReport.ServiceBusyClear != 0) ataOneValue .Add($"{ataReport.ServiceBusyClear} ns. typical to clear BSY bit from receipt of SERVICE"); } if(ataReport.TransportMajorVersionSpecified && ((ataReport.TransportMajorVersion & 0xF000) >> 12 == 0x1 || (ataReport.TransportMajorVersion & 0xF000) >> 12 == 0xE)) { if(!ataReport.SATACapabilities.HasFlag(SATACapabilitiesBit.Clear)) { if(ataReport.SATACapabilities.HasFlag(SATACapabilitiesBit.Gen1Speed)) ataOneValue.Add("SATA 1.5Gb/s is supported"); if(ataReport.SATACapabilities.HasFlag(SATACapabilitiesBit.Gen2Speed)) ataOneValue.Add("SATA 3.0Gb/s is supported"); if(ataReport.SATACapabilities.HasFlag(SATACapabilitiesBit.Gen3Speed)) ataOneValue.Add("SATA 6.0Gb/s is supported"); if(ataReport.SATACapabilities.HasFlag(SATACapabilitiesBit.PowerReceipt)) ataOneValue.Add("Receipt of host initiated power management requests is supported"); if(ataReport.SATACapabilities.HasFlag(SATACapabilitiesBit.PHYEventCounter)) ataOneValue.Add("PHY Event counters are supported"); if(ataReport.SATACapabilities.HasFlag(SATACapabilitiesBit.HostSlumbTrans)) ataOneValue.Add("Supports host automatic partial to slumber transitions is supported"); if(ataReport.SATACapabilities.HasFlag(SATACapabilitiesBit.DevSlumbTrans)) ataOneValue.Add("Supports device automatic partial to slumber transitions is supported"); if(ataReport.SATACapabilities.HasFlag(SATACapabilitiesBit.NCQ)) { ataOneValue.Add("NCQ is supported"); if(ataReport.SATACapabilities.HasFlag(SATACapabilitiesBit.NCQPriority)) ataOneValue.Add("NCQ priority is supported"); if(ataReport.SATACapabilities.HasFlag(SATACapabilitiesBit.UnloadNCQ)) ataOneValue.Add("Unload is supported with outstanding NCQ commands"); } } if(ataReport.SATACapabilities2Specified && !ataReport.SATACapabilities2.HasFlag(SATACapabilitiesBit2.Clear)) { if(ataReport.SATACapabilitiesSpecified && !ataReport.SATACapabilities.HasFlag(SATACapabilitiesBit.Clear) && ataReport.SATACapabilities.HasFlag(SATACapabilitiesBit.NCQ)) { if(ataReport.SATACapabilities2.HasFlag(SATACapabilitiesBit2.NCQMgmt)) ataOneValue.Add("NCQ queue management is supported"); if(ataReport.SATACapabilities2.HasFlag(SATACapabilitiesBit2.NCQStream)) ataOneValue.Add("NCQ streaming is supported"); } if(ataReport.SATACapabilities2Specified && atapi) { if(ataReport.SATACapabilities2.HasFlag(SATACapabilitiesBit2.HostEnvDetect)) ataOneValue.Add("ATAPI device supports host environment detection"); if(ataReport.SATACapabilities2.HasFlag(SATACapabilitiesBit2.DevAttSlimline)) ataOneValue.Add("ATAPI device supports attention on slimline connected devices"); } } } if(ataReport.InterseekDelay != 0x0000 && ataReport.InterseekDelay != 0xFFFF) ataOneValue.Add($"{ataReport.InterseekDelay} microseconds of interseek delay for ISO-7779 accoustic testing"); if((ushort)ataReport.DeviceFormFactor != 0x0000 && (ushort)ataReport.DeviceFormFactor != 0xFFFF) switch(ataReport.DeviceFormFactor) { case DeviceFormFactorEnum.FiveAndQuarter: ataOneValue.Add("Device nominal size is 5.25\""); break; case DeviceFormFactorEnum.ThreeAndHalf: ataOneValue.Add("Device nominal size is 3.5\""); break; case DeviceFormFactorEnum.TwoAndHalf: ataOneValue.Add("Device nominal size is 2.5\""); break; case DeviceFormFactorEnum.OnePointEight: ataOneValue.Add("Device nominal size is 1.8\""); break; case DeviceFormFactorEnum.LessThanOnePointEight: ataOneValue.Add("Device nominal size is smaller than 1.8\""); break; default: ataOneValue.Add($"Device nominal size field value {ataReport.DeviceFormFactor} is unknown"); break; } if(atapi) if(ataReport.ATAPIByteCount > 0) ataOneValue.Add($"{ataReport.ATAPIByteCount} bytes count limit for ATAPI"); if(cfa) if((ataReport.CFAPowerMode & 0x8000) == 0x8000) { ataOneValue.Add("CompactFlash device supports power mode 1"); if((ataReport.CFAPowerMode & 0x2000) == 0x2000) ataOneValue.Add("CompactFlash power mode 1 required for one or more commands"); if((ataReport.CFAPowerMode & 0x1000) == 0x1000) ataOneValue.Add("CompactFlash power mode 1 is disabled"); ataOneValue.Add($"CompactFlash device uses a maximum of {ataReport.CFAPowerMode & 0x0FFF} mA"); } if(ataReport.CommandSetSpecified || ataReport.CommandSet2Specified || ataReport.CommandSet3Specified || ataReport.CommandSet4Specified || ataReport.CommandSet5Specified) ataOneValue.Add("Command set and features:"); if(ataReport.CommandSetSpecified) { if(ataReport.CommandSet.HasFlag(CommandSetBit.Nop)) if(ataReport.EnabledCommandSet.HasFlag(CommandSetBit.Nop) && ataReport.EnabledCommandSetSpecified) ataOneValue.Add("NOP is supported and enabled"); else ataOneValue.Add("NOP is supported"); if(ataReport.CommandSet.HasFlag(CommandSetBit.ReadBuffer)) if(ataReport.EnabledCommandSet.HasFlag(CommandSetBit.ReadBuffer) && ataReport.EnabledCommandSetSpecified) ataOneValue.Add("READ BUFFER is supported and enabled"); else ataOneValue.Add("READ BUFFER is supported"); if(ataReport.CommandSet.HasFlag(CommandSetBit.WriteBuffer)) if(ataReport.EnabledCommandSet.HasFlag(CommandSetBit.WriteBuffer) && ataReport.EnabledCommandSetSpecified) ataOneValue.Add("WRITE BUFFER is supported and enabled"); else ataOneValue.Add("WRITE BUFFER is supported"); if(ataReport.CommandSet.HasFlag(CommandSetBit.HPA)) if(ataReport.EnabledCommandSet.HasFlag(CommandSetBit.HPA) && ataReport.EnabledCommandSetSpecified) ataOneValue.Add("Host Protected Area is supported and enabled"); else ataOneValue.Add("Host Protected Area is supported"); if(ataReport.CommandSet.HasFlag(CommandSetBit.DeviceReset)) if(ataReport.EnabledCommandSet.HasFlag(CommandSetBit.DeviceReset) && ataReport.EnabledCommandSetSpecified) ataOneValue.Add("DEVICE RESET is supported and enabled"); else ataOneValue.Add("DEVICE RESET is supported"); if(ataReport.CommandSet.HasFlag(CommandSetBit.Service)) if(ataReport.EnabledCommandSet.HasFlag(CommandSetBit.Service) && ataReport.EnabledCommandSetSpecified) ataOneValue.Add("SERVICE interrupt is supported and enabled"); else ataOneValue.Add("SERVICE interrupt is supported"); if(ataReport.CommandSet.HasFlag(CommandSetBit.Release)) if(ataReport.EnabledCommandSet.HasFlag(CommandSetBit.Release) && ataReport.EnabledCommandSetSpecified) ataOneValue.Add("Release is supported and enabled"); else ataOneValue.Add("Release is supported"); if(ataReport.CommandSet.HasFlag(CommandSetBit.LookAhead)) if(ataReport.EnabledCommandSet.HasFlag(CommandSetBit.LookAhead) && ataReport.EnabledCommandSetSpecified) ataOneValue.Add("Look-ahead read is supported and enabled"); else ataOneValue.Add("Look-ahead read is supported"); if(ataReport.CommandSet.HasFlag(CommandSetBit.WriteCache)) if(ataReport.EnabledCommandSet.HasFlag(CommandSetBit.WriteCache) && ataReport.EnabledCommandSetSpecified) ataOneValue.Add("Write cache is supported and enabled"); else ataOneValue.Add("Write cache is supported"); if(ataReport.CommandSet.HasFlag(CommandSetBit.Packet)) if(ataReport.EnabledCommandSet.HasFlag(CommandSetBit.Packet) && ataReport.EnabledCommandSetSpecified ) ataOneValue.Add("PACKET is supported and enabled"); else ataOneValue.Add("PACKET is supported"); if(ataReport.CommandSet.HasFlag(CommandSetBit.PowerManagement)) if(ataReport.EnabledCommandSet.HasFlag(CommandSetBit.PowerManagement) && ataReport.EnabledCommandSetSpecified) ataOneValue.Add("Power management is supported and enabled"); else ataOneValue.Add("Power management is supported"); if(ataReport.CommandSet.HasFlag(CommandSetBit.RemovableMedia)) if(ataReport.EnabledCommandSet.HasFlag(CommandSetBit.RemovableMedia) && ataReport.EnabledCommandSetSpecified) ataOneValue.Add("Removable media feature set is supported and enabled"); else ataOneValue.Add("Removable media feature set is supported"); if(ataReport.CommandSet.HasFlag(CommandSetBit.SecurityMode)) if(ataReport.EnabledCommandSet.HasFlag(CommandSetBit.SecurityMode) && ataReport.EnabledCommandSetSpecified) ataOneValue.Add("Security mode is supported and enabled"); else ataOneValue.Add("Security mode is supported"); if(ataReport.Capabilities.HasFlag(CapabilitiesBit.LBASupport)) ataOneValue.Add("28-bit LBA is supported"); } if(ataReport.CommandSet2Specified && ataReport.CommandSet2.HasFlag(CommandSetBit2.MustBeSet) && !ataReport.CommandSet2.HasFlag(CommandSetBit2.MustBeClear)) { if(ataReport.CommandSet2.HasFlag(CommandSetBit2.LBA48)) if(ataReport.EnabledCommandSet2.HasFlag(CommandSetBit2.LBA48) && ataReport.EnabledCommandSet2Specified) ataOneValue.Add("48-bit LBA is supported and enabled"); else ataOneValue.Add("48-bit LBA is supported"); if(ataReport.CommandSet2.HasFlag(CommandSetBit2.FlushCache)) if(ataReport.EnabledCommandSet2.HasFlag(CommandSetBit2.FlushCache) && ataReport.EnabledCommandSet2Specified) ataOneValue.Add("FLUSH CACHE is supported and enabled"); else ataOneValue.Add("FLUSH CACHE is supported"); if(ataReport.CommandSet2.HasFlag(CommandSetBit2.FlushCacheExt)) if(ataReport.EnabledCommandSet2.HasFlag(CommandSetBit2.FlushCacheExt) && ataReport.EnabledCommandSet2Specified) ataOneValue.Add("FLUSH CACHE EXT is supported and enabled"); else ataOneValue.Add("FLUSH CACHE EXT is supported"); if(ataReport.CommandSet2.HasFlag(CommandSetBit2.DCO)) if(ataReport.EnabledCommandSet2.HasFlag(CommandSetBit2.DCO) && ataReport.EnabledCommandSet2Specified ) ataOneValue.Add("Device Configuration Overlay feature set is supported and enabled"); else ataOneValue.Add("Device Configuration Overlay feature set is supported"); if(ataReport.CommandSet2.HasFlag(CommandSetBit2.AAM)) if(ataReport.EnabledCommandSet2.HasFlag(CommandSetBit2.AAM) && ataReport.EnabledCommandSet2Specified ) ataOneValue .Add($"Automatic Acoustic Management is supported and enabled with value {ataReport.CurrentAAM} (vendor recommends {ataReport.RecommendedAAM}"); else ataOneValue.Add("Automatic Acoustic Management is supported"); if(ataReport.CommandSet2.HasFlag(CommandSetBit2.SetMax)) if(ataReport.EnabledCommandSet2.HasFlag(CommandSetBit2.SetMax) && ataReport.EnabledCommandSet2Specified) ataOneValue.Add("SET MAX security extension is supported and enabled"); else ataOneValue.Add("SET MAX security extension is supported"); if(ataReport.CommandSet2.HasFlag(CommandSetBit2.AddressOffsetReservedAreaBoot)) if(ataReport.EnabledCommandSet2.HasFlag(CommandSetBit2.AddressOffsetReservedAreaBoot) && ataReport.EnabledCommandSet2Specified) ataOneValue.Add("Address Offset Reserved Area Boot is supported and enabled"); else ataOneValue.Add("Address Offset Reserved Area Boot is supported"); if(ataReport.CommandSet2.HasFlag(CommandSetBit2.SetFeaturesRequired)) ataOneValue.Add("SET FEATURES is required before spin-up"); if(ataReport.CommandSet2.HasFlag(CommandSetBit2.PowerUpInStandby)) if(ataReport.EnabledCommandSet2.HasFlag(CommandSetBit2.PowerUpInStandby) && ataReport.EnabledCommandSet2Specified) ataOneValue.Add("Power-up in standby is supported and enabled"); else ataOneValue.Add("Power-up in standby is supported"); if(ataReport.CommandSet2.HasFlag(CommandSetBit2.RemovableNotification)) if(ataReport.EnabledCommandSet2.HasFlag(CommandSetBit2.RemovableNotification) && ataReport.EnabledCommandSet2Specified) ataOneValue.Add("Removable Media Status Notification is supported and enabled"); else ataOneValue.Add("Removable Media Status Notification is supported"); if(ataReport.CommandSet2.HasFlag(CommandSetBit2.APM)) if(ataReport.EnabledCommandSet2.HasFlag(CommandSetBit2.APM) && ataReport.EnabledCommandSet2Specified ) ataOneValue .Add($"Advanced Power Management is supported and enabled with value {ataReport.CurrentAPM}"); else ataOneValue.Add("Advanced Power Management is supported"); if(ataReport.CommandSet2.HasFlag(CommandSetBit2.CompactFlash)) if(ataReport.EnabledCommandSet2.HasFlag(CommandSetBit2.CompactFlash) && ataReport.EnabledCommandSet2Specified) ataOneValue.Add("CompactFlash feature set is supported and enabled"); else ataOneValue.Add("CompactFlash feature set is supported"); if(ataReport.CommandSet2.HasFlag(CommandSetBit2.RWQueuedDMA)) if(ataReport.EnabledCommandSet2.HasFlag(CommandSetBit2.RWQueuedDMA) && ataReport.EnabledCommandSet2Specified) ataOneValue.Add("READ DMA QUEUED and WRITE DMA QUEUED are supported and enabled"); else ataOneValue.Add("READ DMA QUEUED and WRITE DMA QUEUED are supported"); if(ataReport.CommandSet2.HasFlag(CommandSetBit2.DownloadMicrocode)) if(ataReport.EnabledCommandSet2.HasFlag(CommandSetBit2.DownloadMicrocode) && ataReport.EnabledCommandSet2Specified) ataOneValue.Add("DOWNLOAD MICROCODE is supported and enabled"); else ataOneValue.Add("DOWNLOAD MICROCODE is supported"); } if(ataReport.CommandSet.HasFlag(CommandSetBit.SMART) && ataReport.CommandSetSpecified) if(ataReport.EnabledCommandSet.HasFlag(CommandSetBit.SMART) && ataReport.EnabledCommandSetSpecified) ataOneValue.Add("S.M.A.R.T. is supported and enabled"); else ataOneValue.Add("S.M.A.R.T. is supported"); if(ataReport.SCTCommandTransport.HasFlag(SCTCommandTransportBit.Supported) && ataReport.SCTCommandTransportSpecified) ataOneValue.Add("S.M.A.R.T. Command Transport is supported"); if(ataReport.CommandSet3Specified && ataReport.CommandSet3.HasFlag(CommandSetBit3.MustBeSet) && !ataReport.CommandSet3.HasFlag(CommandSetBit3.MustBeClear)) { if(ataReport.CommandSet3.HasFlag(CommandSetBit3.SMARTSelfTest)) if(ataReport.EnabledCommandSet3.HasFlag(CommandSetBit3.SMARTSelfTest) && ataReport.EnabledCommandSet3Specified) ataOneValue.Add("S.M.A.R.T. self-testing is supported and enabled"); else ataOneValue.Add("S.M.A.R.T. self-testing is supported"); if(ataReport.CommandSet3.HasFlag(CommandSetBit3.SMARTLog)) if(ataReport.EnabledCommandSet3.HasFlag(CommandSetBit3.SMARTLog) && ataReport.EnabledCommandSet3Specified) ataOneValue.Add("S.M.A.R.T. error logging is supported and enabled"); else ataOneValue.Add("S.M.A.R.T. error logging is supported"); if(ataReport.CommandSet3.HasFlag(CommandSetBit3.IdleImmediate)) if(ataReport.EnabledCommandSet3.HasFlag(CommandSetBit3.IdleImmediate) && ataReport.EnabledCommandSet3Specified) ataOneValue.Add("IDLE IMMEDIATE with UNLOAD FEATURE is supported and enabled"); else ataOneValue.Add("IDLE IMMEDIATE with UNLOAD FEATURE is supported"); if(ataReport.CommandSet3.HasFlag(CommandSetBit3.WriteURG)) ataOneValue.Add("URG bit is supported in WRITE STREAM DMA EXT and WRITE STREAM EXT"); if(ataReport.CommandSet3.HasFlag(CommandSetBit3.ReadURG)) ataOneValue.Add("URG bit is supported in READ STREAM DMA EXT and READ STREAM EXT"); if(ataReport.CommandSet3.HasFlag(CommandSetBit3.WWN)) ataOneValue.Add("Device has a World Wide Name"); if(ataReport.CommandSet3.HasFlag(CommandSetBit3.FUAWriteQ)) if(ataReport.EnabledCommandSet3.HasFlag(CommandSetBit3.FUAWriteQ) && ataReport.EnabledCommandSet3Specified) ataOneValue.Add("WRITE DMA QUEUED FUA EXT is supported and enabled"); else ataOneValue.Add("WRITE DMA QUEUED FUA EXT is supported"); if(ataReport.CommandSet3.HasFlag(CommandSetBit3.FUAWrite)) if(ataReport.EnabledCommandSet3.HasFlag(CommandSetBit3.FUAWrite) && ataReport.EnabledCommandSet3Specified) ataOneValue.Add("WRITE DMA FUA EXT and WRITE MULTIPLE FUA EXT are supported and enabled"); else ataOneValue.Add("WRITE DMA FUA EXT and WRITE MULTIPLE FUA EXT are supported"); if(ataReport.CommandSet3.HasFlag(CommandSetBit3.GPL)) if(ataReport.EnabledCommandSet3.HasFlag(CommandSetBit3.GPL) && ataReport.EnabledCommandSet3Specified ) ataOneValue.Add("General Purpose Logging is supported and enabled"); else ataOneValue.Add("General Purpose Logging is supported"); if(ataReport.CommandSet3.HasFlag(CommandSetBit3.Streaming)) if(ataReport.EnabledCommandSet3.HasFlag(CommandSetBit3.Streaming) && ataReport.EnabledCommandSet3Specified) ataOneValue.Add("Streaming feature set is supported and enabled"); else ataOneValue.Add("Streaming feature set is supported"); if(ataReport.CommandSet3.HasFlag(CommandSetBit3.MCPT) && ataReport.EnabledCommandSet3Specified) ataOneValue.Add(ataReport.EnabledCommandSet3.HasFlag(CommandSetBit3.MCPT) ? "Media Card Pass Through command set is supported and enabled" : "Media Card Pass Through command set is supported"); if(ataReport.CommandSet3.HasFlag(CommandSetBit3.MediaSerial) && ataReport.EnabledCommandSet3Specified) ataOneValue.Add(ataReport.EnabledCommandSet3.HasFlag(CommandSetBit3.MediaSerial) ? "Media Serial is supported and valid" : "Media Serial is supported"); } if(ataReport.CommandSet4Specified && ataReport.CommandSet4.HasFlag(CommandSetBit4.MustBeSet) && !ataReport.CommandSet4.HasFlag(CommandSetBit4.MustBeClear)) { if(ataReport.CommandSet4.HasFlag(CommandSetBit4.DSN)) if(ataReport.EnabledCommandSet4.HasFlag(CommandSetBit4.DSN) && ataReport.EnabledCommandSet4Specified ) ataOneValue.Add("DSN feature set is supported and enabled"); else ataOneValue.Add("DSN feature set is supported"); if(ataReport.CommandSet4.HasFlag(CommandSetBit4.AMAC)) if(ataReport.EnabledCommandSet4.HasFlag(CommandSetBit4.AMAC) && ataReport.EnabledCommandSet4Specified) ataOneValue.Add("Accessible Max Address Configuration is supported and enabled"); else ataOneValue.Add("Accessible Max Address Configuration is supported"); if(ataReport.CommandSet4.HasFlag(CommandSetBit4.ExtPowerCond)) if(ataReport.EnabledCommandSet4.HasFlag(CommandSetBit4.ExtPowerCond) && ataReport.EnabledCommandSet4Specified) ataOneValue.Add("Extended Power Conditions are supported and enabled"); else ataOneValue.Add("Extended Power Conditions are supported"); if(ataReport.CommandSet4.HasFlag(CommandSetBit4.ExtStatusReport)) if(ataReport.EnabledCommandSet4.HasFlag(CommandSetBit4.ExtStatusReport) && ataReport.EnabledCommandSet4Specified) ataOneValue.Add("Extended Status Reporting is supported and enabled"); else ataOneValue.Add("Extended Status Reporting is supported"); if(ataReport.CommandSet4.HasFlag(CommandSetBit4.FreeFallControl)) if(ataReport.EnabledCommandSet4.HasFlag(CommandSetBit4.FreeFallControl) && ataReport.EnabledCommandSet4Specified) ataOneValue.Add("Free-fall control feature set is supported and enabled"); else ataOneValue.Add("Free-fall control feature set is supported"); if(ataReport.CommandSet4.HasFlag(CommandSetBit4.SegmentedDownloadMicrocode)) if(ataReport.EnabledCommandSet4.HasFlag(CommandSetBit4.SegmentedDownloadMicrocode) && ataReport.EnabledCommandSet4Specified) ataOneValue.Add("Segmented feature in DOWNLOAD MICROCODE is supported and enabled"); else ataOneValue.Add("Segmented feature in DOWNLOAD MICROCODE is supported"); if(ataReport.CommandSet4.HasFlag(CommandSetBit4.RWDMAExtGpl)) if(ataReport.EnabledCommandSet4.HasFlag(CommandSetBit4.RWDMAExtGpl) && ataReport.EnabledCommandSet4Specified) ataOneValue.Add("READ/WRITE DMA EXT GPL are supported and enabled"); else ataOneValue.Add("READ/WRITE DMA EXT GPL are supported"); if(ataReport.CommandSet4.HasFlag(CommandSetBit4.WriteUnc)) if(ataReport.EnabledCommandSet4.HasFlag(CommandSetBit4.WriteUnc) && ataReport.EnabledCommandSet4Specified) ataOneValue.Add("WRITE UNCORRECTABLE is supported and enabled"); else ataOneValue.Add("WRITE UNCORRECTABLE is supported"); if(ataReport.CommandSet4.HasFlag(CommandSetBit4.WRV)) { if(ataReport.EnabledCommandSet4.HasFlag(CommandSetBit4.WRV) && ataReport.EnabledCommandSet4Specified ) ataOneValue.Add("Write/Read/Verify is supported and enabled"); else ataOneValue.Add("Write/Read/Verify is supported"); ataOneValue.Add($"{ataReport.WRVSectorCountMode2} sectors for Write/Read/Verify mode 2"); ataOneValue.Add($"{ataReport.WRVSectorCountMode3} sectors for Write/Read/Verify mode 3"); if(ataReport.EnabledCommandSet4.HasFlag(CommandSetBit4.WRV) && ataReport.EnabledCommandSet4Specified ) ataOneValue.Add($"Current Write/Read/Verify mode: {ataReport.WRVMode}"); } if(ataReport.CommandSet4.HasFlag(CommandSetBit4.DT1825)) if(ataReport.EnabledCommandSet4.HasFlag(CommandSetBit4.DT1825) && ataReport.EnabledCommandSet4Specified) ataOneValue.Add("DT1825 is supported and enabled"); else ataOneValue.Add("DT1825 is supported"); } if(ataReport.Capabilities3Specified) { if(ataReport.Capabilities3.HasFlag(CapabilitiesBit3.BlockErase)) ataOneValue.Add("BLOCK ERASE EXT is supported"); if(ataReport.Capabilities3.HasFlag(CapabilitiesBit3.Overwrite)) ataOneValue.Add("OVERWRITE EXT is supported"); if(ataReport.Capabilities3.HasFlag(CapabilitiesBit3.CryptoScramble)) ataOneValue.Add("CRYPTO SCRAMBLE EXT is supported"); } if(ataReport.CommandSet5Specified) { if(ataReport.CommandSet5.HasFlag(CommandSetBit5.DeviceConfDMA)) ataOneValue.Add("DEVICE CONFIGURATION IDENTIFY DMA and DEVICE CONFIGURATION SET DMA are supported"); if(ataReport.CommandSet5.HasFlag(CommandSetBit5.ReadBufferDMA)) ataOneValue.Add("READ BUFFER DMA is supported"); if(ataReport.CommandSet5.HasFlag(CommandSetBit5.WriteBufferDMA)) ataOneValue.Add("WRITE BUFFER DMA is supported"); if(ataReport.CommandSet5.HasFlag(CommandSetBit5.DownloadMicroCodeDMA)) ataOneValue.Add("DOWNLOAD MICROCODE DMA is supported"); if(ataReport.CommandSet5.HasFlag(CommandSetBit5.SetMaxDMA)) ataOneValue.Add("SET PASSWORD DMA and SET UNLOCK DMA are supported"); if(ataReport.CommandSet5.HasFlag(CommandSetBit5.Ata28)) ataOneValue.Add("Not all 28-bit commands are supported"); if(ataReport.CommandSet5.HasFlag(CommandSetBit5.CFast)) ataOneValue.Add("Device follows CFast specification"); if(ataReport.CommandSet5.HasFlag(CommandSetBit5.IEEE1667)) ataOneValue.Add("Device follows IEEE-1667"); if(ataReport.CommandSet5.HasFlag(CommandSetBit5.DeterministicTrim)) { ataOneValue.Add("Read after TRIM is deterministic"); if(ataReport.CommandSet5.HasFlag(CommandSetBit5.ReadZeroTrim)) ataOneValue.Add("Read after TRIM returns empty data"); } if(ataReport.CommandSet5.HasFlag(CommandSetBit5.LongPhysSectorAligError)) ataOneValue.Add("Device supports Long Physical Sector Alignment Error Reporting Control"); if(ataReport.CommandSet5.HasFlag(CommandSetBit5.Encrypted)) ataOneValue.Add("Device encrypts all user data"); if(ataReport.CommandSet5.HasFlag(CommandSetBit5.AllCacheNV)) ataOneValue.Add("Device's write cache is non-volatile"); if(ataReport.CommandSet5.HasFlag(CommandSetBit5.ZonedBit0) || ataReport.CommandSet5.HasFlag(CommandSetBit5.ZonedBit1)) ataOneValue.Add("Device is zoned"); } if(ataReport.Capabilities3Specified) if(ataReport.Capabilities3.HasFlag(CapabilitiesBit3.Sanitize)) { ataOneValue.Add("Sanitize feature set is supported"); ataOneValue.Add(ataReport.Capabilities3.HasFlag(CapabilitiesBit3.SanitizeCommands) ? "Sanitize commands are specified by ACS-3 or higher" : "Sanitize commands are specified by ACS-2"); if(ataReport.Capabilities3.HasFlag(CapabilitiesBit3.SanitizeAntifreeze)) ataOneValue.Add("SANITIZE ANTIFREEZE LOCK EXT is supported"); } if(!ata1 && maxatalevel >= 8 && ataReport.TrustedComputingSpecified) if(ataReport.TrustedComputing.HasFlag(TrustedComputingBit.Set) && !ataReport.TrustedComputing.HasFlag(TrustedComputingBit.Clear) && ataReport.TrustedComputing.HasFlag(TrustedComputingBit.TrustedComputing)) ataOneValue.Add("Trusted Computing feature set is supported"); if(ataReport.TransportMajorVersionSpecified && ((ataReport.TransportMajorVersion & 0xF000) >> 12 == 0x1 || (ataReport.TransportMajorVersion & 0xF000) >> 12 == 0xE)) { if(ataReport.SATACapabilitiesSpecified) if(!ataReport.SATACapabilities.HasFlag(SATACapabilitiesBit.Clear)) if(ataReport.SATACapabilities.HasFlag(SATACapabilitiesBit.ReadLogDMAExt)) ataOneValue.Add("READ LOG DMA EXT is supported"); if(ataReport.SATACapabilities2Specified) if(!ataReport.SATACapabilities2.HasFlag(SATACapabilitiesBit2.Clear)) if(ataReport.SATACapabilities2.HasFlag(SATACapabilitiesBit2.FPDMAQ)) ataOneValue.Add("RECEIVE FPDMA QUEUED and SEND FPDMA QUEUED are supported"); if(ataReport.SATAFeaturesSpecified) if(!ataReport.SATAFeatures.HasFlag(SATAFeaturesBit.Clear)) { if(ataReport.SATAFeatures.HasFlag(SATAFeaturesBit.NonZeroBufferOffset)) if(ataReport.EnabledSATAFeatures.HasFlag(SATAFeaturesBit.NonZeroBufferOffset) && ataReport.EnabledSATAFeaturesSpecified) ataOneValue.Add("Non-zero buffer offsets are supported and enabled"); else ataOneValue.Add("Non-zero buffer offsets are supported"); if(ataReport.SATAFeatures.HasFlag(SATAFeaturesBit.DMASetup)) if(ataReport.EnabledSATAFeatures.HasFlag(SATAFeaturesBit.DMASetup) && ataReport.EnabledSATAFeaturesSpecified) ataOneValue.Add("DMA Setup auto-activation is supported and enabled"); else ataOneValue.Add("DMA Setup auto-activation is supported"); if(ataReport.SATAFeatures.HasFlag(SATAFeaturesBit.InitPowerMgmt)) if(ataReport.EnabledSATAFeatures.HasFlag(SATAFeaturesBit.InitPowerMgmt) && ataReport.EnabledSATAFeaturesSpecified) ataOneValue.Add("Device-initiated power management is supported and enabled"); else ataOneValue.Add("Device-initiated power management is supported"); if(ataReport.SATAFeatures.HasFlag(SATAFeaturesBit.InOrderData)) if(ataReport.EnabledSATAFeatures.HasFlag(SATAFeaturesBit.InOrderData) && ataReport.EnabledSATAFeaturesSpecified) ataOneValue.Add("In-order data delivery is supported and enabled"); else ataOneValue.Add("In-order data delivery is supported"); if(!atapi) if(ataReport.SATAFeatures.HasFlag(SATAFeaturesBit.HardwareFeatureControl)) if(ataReport.EnabledSATAFeatures.HasFlag(SATAFeaturesBit.HardwareFeatureControl) && ataReport.EnabledSATAFeaturesSpecified) ataOneValue.Add("Hardware Feature Control is supported and enabled"); else ataOneValue.Add("Hardware Feature Control is supported"); if(atapi) if(ataReport.SATAFeatures.HasFlag(SATAFeaturesBit.AsyncNotification) && ataReport.EnabledSATAFeaturesSpecified) if(ataReport.EnabledSATAFeatures.HasFlag(SATAFeaturesBit.AsyncNotification) && ataReport.EnabledSATAFeaturesSpecified) ataOneValue.Add("Asynchronous notification is supported"); else ataOneValue.Add("Asynchronous notification is supported"); if(ataReport.SATAFeatures.HasFlag(SATAFeaturesBit.SettingsPreserve)) if(ataReport.EnabledSATAFeatures.HasFlag(SATAFeaturesBit.SettingsPreserve) && ataReport.EnabledSATAFeaturesSpecified) ataOneValue.Add("Software Settings Preservation is supported"); else ataOneValue.Add("Software Settings Preservation is supported"); if(ataReport.SATAFeatures.HasFlag(SATAFeaturesBit.NCQAutoSense)) ataOneValue.Add("NCQ Autosense is supported"); if(ataReport.EnabledSATAFeatures.HasFlag(SATAFeaturesBit.EnabledSlumber)) ataOneValue.Add("Automatic Partial to Slumber transitions are enabled"); } } if((ataReport.RemovableStatusSet & 0x03) > 0) ataOneValue.Add("Removable Media Status Notification feature set is supported"); if(ataReport.FreeFallSensitivity != 0x00 && ataReport.FreeFallSensitivity != 0xFF) ataOneValue.Add($"Free-fall sensitivity set to {ataReport.FreeFallSensitivity}"); if(ataReport.DataSetMgmtSpecified && ataReport.DataSetMgmt.HasFlag(DataSetMgmtBit.Trim)) ataOneValue.Add("TRIM is supported"); if(ataReport.DataSetMgmtSizeSpecified && ataReport.DataSetMgmtSize > 0) ataOneValue.Add($"DATA SET MANAGEMENT can receive a maximum of {ataReport.DataSetMgmtSize} blocks of 512 bytes"); if(ataReport.SecurityStatusSpecified && ataReport.SecurityStatus.HasFlag(SecurityStatusBit.Supported)) { ataOneValue.Add("Security:"); if(ataReport.SecurityStatus.HasFlag(SecurityStatusBit.Enabled)) { ataOneValue.Add("Security is enabled"); ataOneValue.Add(ataReport.SecurityStatus.HasFlag(SecurityStatusBit.Locked) ? "Security is locked" : "Security is not locked"); ataOneValue.Add(ataReport.SecurityStatus.HasFlag(SecurityStatusBit.Frozen) ? "Security is frozen" : "Security is not frozen"); ataOneValue.Add(ataReport.SecurityStatus.HasFlag(SecurityStatusBit.Expired) ? "Security count has expired" : "Security count has notexpired"); ataOneValue.Add(ataReport.SecurityStatus.HasFlag(SecurityStatusBit.Maximum) ? "Security level is maximum" : "Security level is high"); } else ataOneValue.Add("Security is not enabled"); if(ataReport.SecurityStatus.HasFlag(SecurityStatusBit.Enhanced)) ataOneValue.Add("Supports enhanced security erase"); ataOneValue.Add($"{ataReport.SecurityEraseTime * 2} minutes to complete secure erase"); if(ataReport.SecurityStatus.HasFlag(SecurityStatusBit.Enhanced)) ataOneValue .Add($"{ataReport.EnhancedSecurityEraseTime * 2} minutes to complete enhanced secure erase"); ataOneValue.Add($"Master password revision code: {ataReport.MasterPasswordRevisionCode}"); } if(ataReport.CommandSet3Specified && ataReport.CommandSet3.HasFlag(CommandSetBit3.MustBeSet) && !ataReport.CommandSet3.HasFlag(CommandSetBit3.MustBeClear) && ataReport.CommandSet3.HasFlag(CommandSetBit3.Streaming)) { ataOneValue.Add("Streaming:"); ataOneValue.Add($"Minimum request size is {ataReport.StreamMinReqSize}"); ataOneValue.Add($"Streaming transfer time in PIO is {ataReport.StreamTransferTimePIO}"); ataOneValue.Add($"Streaming transfer time in DMA is {ataReport.StreamTransferTimeDMA}"); ataOneValue.Add($"Streaming access latency is {ataReport.StreamAccessLatency}"); ataOneValue.Add($"Streaming performance granularity is {ataReport.StreamPerformanceGranularity}"); } if(ataReport.SCTCommandTransportSpecified && ataReport.SCTCommandTransport.HasFlag(SCTCommandTransportBit.Supported)) { ataOneValue.Add("S.M.A.R.T. Command Transport (SCT):"); if(ataReport.SCTCommandTransport.HasFlag(SCTCommandTransportBit.LongSectorAccess)) ataOneValue.Add("SCT Long Sector Address is supported"); if(ataReport.SCTCommandTransport.HasFlag(SCTCommandTransportBit.WriteSame)) ataOneValue.Add("SCT Write Same is supported"); if(ataReport.SCTCommandTransport.HasFlag(SCTCommandTransportBit.ErrorRecoveryControl)) ataOneValue.Add("SCT Error Recovery Control is supported"); if(ataReport.SCTCommandTransport.HasFlag(SCTCommandTransportBit.FeaturesControl)) ataOneValue.Add("SCT Features Control is supported"); if(ataReport.SCTCommandTransport.HasFlag(SCTCommandTransportBit.DataTables)) ataOneValue.Add("SCT Data Tables are supported"); } if(ataReport.NVCacheCapsSpecified && (ataReport.NVCacheCaps & 0x0010) == 0x0010) { ataOneValue.Add("Non-Volatile Cache:"); ataOneValue.Add($"Version {(ataReport.NVCacheCaps & 0xF000) >> 12}"); if((ataReport.NVCacheCaps & 0x0001) == 0x0001) { ataOneValue.Add((ataReport.NVCacheCaps & 0x0002) == 0x0002 ? "Power mode feature set is supported and enabled" : "Power mode feature set is supported"); ataOneValue.Add($"Version {(ataReport.NVCacheCaps & 0x0F00) >> 8}"); } ataOneValue.Add($"Non-Volatile Cache is {ataReport.NVCacheSize * logicalsectorsize} bytes"); } if(ataReport.ReadCapabilities != null) { removable = false; ataOneValue.Add(""); if(ataReport.ReadCapabilities.NominalRotationRateSpecified && ataReport.ReadCapabilities.NominalRotationRate != 0x0000 && ataReport.ReadCapabilities.NominalRotationRate != 0xFFFF) ataOneValue.Add(ataReport.ReadCapabilities.NominalRotationRate == 0x0001 ? "Device does not rotate." : $"Device rotates at {ataReport.ReadCapabilities.NominalRotationRate} rpm"); if(!atapi) { if(ataReport.ReadCapabilities.BlockSizeSpecified) { ataTwoValue.Add("Logical sector size", $"{ataReport.ReadCapabilities.BlockSize} bytes"); logicalsectorsize = ataReport.ReadCapabilities.BlockSize; } if(ataReport.ReadCapabilities.PhysicalBlockSizeSpecified) ataTwoValue.Add("Physical sector size", $"{ataReport.ReadCapabilities.PhysicalBlockSize} bytes"); if(ataReport.ReadCapabilities.LongBlockSizeSpecified) ataTwoValue.Add("READ LONG sector size", $"{ataReport.ReadCapabilities.LongBlockSize} bytes"); if(ataReport.ReadCapabilities.BlockSizeSpecified && ataReport.ReadCapabilities.PhysicalBlockSizeSpecified && ataReport.ReadCapabilities.BlockSize != ataReport.ReadCapabilities.PhysicalBlockSize && (ataReport.ReadCapabilities.LogicalAlignment & 0x8000) == 0x0000 && (ataReport.ReadCapabilities.LogicalAlignment & 0x4000) == 0x4000) ataOneValue .Add($"Logical sector starts at offset {ataReport.ReadCapabilities.LogicalAlignment & 0x3FFF} from physical sector"); if(ataReport.ReadCapabilities.CHS != null && ataReport.ReadCapabilities.CurrentCHS != null) { int currentSectors = ataReport.ReadCapabilities.CurrentCHS.Cylinders * ataReport.ReadCapabilities.CurrentCHS.Heads * ataReport.ReadCapabilities.CurrentCHS.Sectors; ataTwoValue.Add("Cylinders", $"{ataReport.ReadCapabilities.CHS.Cylinders} max., {ataReport.ReadCapabilities.CurrentCHS.Cylinders} current"); ataTwoValue.Add("Heads", $"{ataReport.ReadCapabilities.CHS.Heads} max., {ataReport.ReadCapabilities.CurrentCHS.Heads} current"); ataTwoValue.Add("Sectors per track", $"{ataReport.ReadCapabilities.CHS.Sectors} max., {ataReport.ReadCapabilities.CurrentCHS.Sectors} current"); ataTwoValue.Add("Sectors addressable in CHS mode", $"{ataReport.ReadCapabilities.CHS.Cylinders * ataReport.ReadCapabilities.CHS.Heads * ataReport.ReadCapabilities.CHS.Sectors} max., {currentSectors} current"); ataTwoValue.Add("Device size in CHS mode", $"{(ulong)currentSectors * logicalsectorsize} bytes, {(ulong)currentSectors * logicalsectorsize / 1000 / 1000} Mb, {(double)((ulong)currentSectors * logicalsectorsize) / 1024 / 1024:F2} MiB"); } else if(ataReport.ReadCapabilities.CHS != null) { int currentSectors = ataReport.ReadCapabilities.CHS.Cylinders * ataReport.ReadCapabilities.CHS.Heads * ataReport.ReadCapabilities.CHS.Sectors; ataTwoValue.Add("Cylinders", $"{ataReport.ReadCapabilities.CHS.Cylinders}"); ataTwoValue.Add("Heads", $"{ataReport.ReadCapabilities.CHS.Heads}"); ataTwoValue.Add("Sectors per track", $"{ataReport.ReadCapabilities.CHS.Sectors}"); ataTwoValue.Add("Sectors addressable in CHS mode", $"{currentSectors}"); ataTwoValue.Add("Device size in CHS mode", $"{(ulong)currentSectors * logicalsectorsize} bytes, {(ulong)currentSectors * logicalsectorsize / 1000 / 1000} Mb, {(double)((ulong)currentSectors * logicalsectorsize) / 1024 / 1024:F2} MiB"); } if(ataReport.ReadCapabilities.LBASectorsSpecified) { ataTwoValue.Add("Sectors addressable in sectors in 28-bit LBA mode", $"{ataReport.ReadCapabilities.LBASectors}"); if((ulong)ataReport.ReadCapabilities.LBASectors * logicalsectorsize / 1024 / 1024 > 1000000) ataTwoValue.Add("Device size in 28-bit LBA mode", $"{(ulong)ataReport.ReadCapabilities.LBASectors * logicalsectorsize} bytes, {(ulong)ataReport.ReadCapabilities.LBASectors * logicalsectorsize / 1000 / 1000 / 1000 / 1000} Tb, {(double)((ulong)ataReport.ReadCapabilities.LBASectors * logicalsectorsize) / 1024 / 1024 / 1024 / 1024:F2} TiB"); else if((ulong)ataReport.ReadCapabilities.LBASectors * logicalsectorsize / 1024 / 1024 > 1000) ataTwoValue.Add("Device size in 28-bit LBA mode", $"{(ulong)ataReport.ReadCapabilities.LBASectors * logicalsectorsize} bytes, {(ulong)ataReport.ReadCapabilities.LBASectors * logicalsectorsize / 1000 / 1000 / 1000} Gb, {(double)((ulong)ataReport.ReadCapabilities.LBASectors * logicalsectorsize) / 1024 / 1024 / 1024:F2} GiB"); else ataTwoValue.Add("Device size in 28-bit LBA mode", $"{(ulong)ataReport.ReadCapabilities.LBASectors * logicalsectorsize} bytes, {(ulong)ataReport.ReadCapabilities.LBASectors * logicalsectorsize / 1000 / 1000} Mb, {(double)((ulong)ataReport.ReadCapabilities.LBASectors * logicalsectorsize) / 1024 / 1024:F2} MiB"); } if(ataReport.ReadCapabilities.LBA48SectorsSpecified) { ataTwoValue.Add("Sectors addressable in sectors in 48-bit LBA mode", $"{ataReport.ReadCapabilities.LBA48Sectors}"); if(ataReport.ReadCapabilities.LBA48Sectors * logicalsectorsize / 1024 / 1024 > 1000000) ataTwoValue.Add("Device size in 48-bit LBA mode", $"{ataReport.ReadCapabilities.LBA48Sectors * logicalsectorsize} bytes, {ataReport.ReadCapabilities.LBA48Sectors * logicalsectorsize / 1000 / 1000 / 1000 / 1000} Tb, {(double)(ataReport.ReadCapabilities.LBA48Sectors * logicalsectorsize) / 1024 / 1024 / 1024 / 1024:F2} TiB"); else if(ataReport.ReadCapabilities.LBA48Sectors * logicalsectorsize / 1024 / 1024 > 1000) ataTwoValue.Add("Device size in 48-bit LBA mode", $"{ataReport.ReadCapabilities.LBA48Sectors * logicalsectorsize} bytes, {ataReport.ReadCapabilities.LBA48Sectors * logicalsectorsize / 1000 / 1000 / 1000} Gb, {(double)(ataReport.ReadCapabilities.LBA48Sectors * logicalsectorsize) / 1024 / 1024 / 1024:F2} GiB"); else ataTwoValue.Add("Device size in 48-bit LBA mode", $"{ataReport.ReadCapabilities.LBA48Sectors * logicalsectorsize} bytes, {ataReport.ReadCapabilities.LBA48Sectors * logicalsectorsize / 1000 / 1000} Mb, {(double)(ataReport.ReadCapabilities.LBA48Sectors * logicalsectorsize) / 1024 / 1024:F2} MiB"); } if(ata1 || cfa) { if(ataReport.ReadCapabilities.UnformattedBPT > 0) ataTwoValue.Add("Bytes per unformatted track", $"{ataReport.ReadCapabilities.UnformattedBPT}"); if(ataReport.ReadCapabilities.UnformattedBPS > 0) ataTwoValue.Add("Bytes per unformatted sector", $"{ataReport.ReadCapabilities.UnformattedBPS}"); } } if(ataReport.ReadCapabilities.SupportsRead) ataOneValue.Add("Device supports READ SECTOR(S) command in CHS mode"); if(ataReport.ReadCapabilities.SupportsReadRetry) ataOneValue.Add("Device supports READ SECTOR(S) RETRY command in CHS mode"); if(ataReport.ReadCapabilities.SupportsReadDma) ataOneValue.Add("Device supports READ DMA command in CHS mode"); if(ataReport.ReadCapabilities.SupportsReadDmaRetry) ataOneValue.Add("Device supports READ DMA RETRY command in CHS mode"); if(ataReport.ReadCapabilities.SupportsReadLong) ataOneValue.Add("Device supports READ LONG command in CHS mode"); if(ataReport.ReadCapabilities.SupportsReadLongRetry) ataOneValue.Add("Device supports READ LONG RETRY command in CHS mode"); if(ataReport.ReadCapabilities.SupportsReadLba) ataOneValue.Add("Device supports READ SECTOR(S) command in 28-bit LBA mode"); if(ataReport.ReadCapabilities.SupportsReadRetryLba) ataOneValue.Add("Device supports READ SECTOR(S) RETRY command in 28-bit LBA mode"); if(ataReport.ReadCapabilities.SupportsReadDmaLba) ataOneValue.Add("Device supports READ DMA command in 28-bit LBA mode"); if(ataReport.ReadCapabilities.SupportsReadDmaRetryLba) ataOneValue.Add("Device supports READ DMA RETRY command in 28-bit LBA mode"); if(ataReport.ReadCapabilities.SupportsReadLongLba) ataOneValue.Add("Device supports READ LONG command in 28-bit LBA mode"); if(ataReport.ReadCapabilities.SupportsReadLongRetryLba) ataOneValue.Add("Device supports READ LONG RETRY command in 28-bit LBA mode"); if(ataReport.ReadCapabilities.SupportsReadLba48) ataOneValue.Add("Device supports READ SECTOR(S) command in 48-bit LBA mode"); if(ataReport.ReadCapabilities.SupportsReadDmaLba48) ataOneValue.Add("Device supports READ DMA command in 48-bit LBA mode"); if(ataReport.ReadCapabilities.SupportsSeek) ataOneValue.Add("Device supports SEEK command in CHS mode"); if(ataReport.ReadCapabilities.SupportsSeekLba) ataOneValue.Add("Device supports SEEK command in 28-bit LBA mode"); } else testedMedia = ataReport.RemovableMedias; } } }