// /*************************************************************************** // Aaru Data Preservation Suite // ---------------------------------------------------------------------------- // // Filename : Identify.cs // Author(s) : Natalia Portillo // // Component : Common structures for ATA devices. // // --[ Description ] ---------------------------------------------------------- // // Defines a high level interpretation of the ATA IDENTIFY response. // // --[ License ] -------------------------------------------------------------- // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // // ---------------------------------------------------------------------------- // Copyright © 2011-2023 Natalia Portillo // ****************************************************************************/ // ReSharper disable UnusedMember.Global using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; using System.Text; using Aaru.Console; using Aaru.Helpers; using Marshal = Aaru.Helpers.Marshal; namespace Aaru.CommonTypes.Structs.Devices.ATA; /// /// Information from following standards: T10-791D rev. 4c (ATA) T10-948D rev. 4c (ATA-2) T13-1153D rev. 18 /// (ATA/ATAPI-4) T13-1321D rev. 3 (ATA/ATAPI-5) T13-1410D rev. 3b (ATA/ATAPI-6) T13-1532D rev. 4b (ATA/ATAPI-7) /// T13-1699D rev. 3f (ATA8-ACS) T13-1699D rev. 4a (ATA8-ACS) T13-2015D rev. 2 (ACS-2) T13-2161D rev. 5 (ACS-3) CF+ /// & CF Specification rev. 1.4 (CFA) /// [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static class Identify { const string MODULE_NAME = "ATA/ATAPI IDENTIFY decoder"; /// Capabilities flag bits. [Flags] public enum CapabilitiesBit : ushort { /// ATAPI: Interleaved DMA supported InterleavedDMA = 0x8000, /// ATAPI: Command queueing supported CommandQueue = 0x4000, /// Standby timer values are standard StandardStandbyTimer = 0x2000, /// ATAPI: Overlap operation supported OverlapOperation = 0x2000, /// ATAPI: ATA software reset required Obsoleted in ATA/ATAPI-4 RequiresATASoftReset = 0x1000, /// IORDY is supported IORDY = 0x0800, /// IORDY can be disabled CanDisableIORDY = 0x0400, /// LBA is supported LBASupport = 0x0200, /// DMA is supported DMASupport = 0x0100, /// Vendor unique Obsoleted in ATA/ATAPI-4 VendorBit7 = 0x0080, /// Vendor unique Obsoleted in ATA/ATAPI-4 VendorBit6 = 0x0040, /// Vendor unique Obsoleted in ATA/ATAPI-4 VendorBit5 = 0x0020, /// Vendor unique Obsoleted in ATA/ATAPI-4 VendorBit4 = 0x0010, /// Vendor unique Obsoleted in ATA/ATAPI-4 VendorBit3 = 0x0008, /// Vendor unique Obsoleted in ATA/ATAPI-4 VendorBit2 = 0x0004, /// Long Physical Alignment setting bit 1 PhysicalAlignment1 = 0x0002, /// Long Physical Alignment setting bit 0 PhysicalAlignment0 = 0x0001 } /// More capabilities flag bits. [Flags] public enum CapabilitiesBit2 : ushort { /// MUST NOT be set MustBeClear = 0x8000, /// MUST be set MustBeSet = 0x4000, #pragma warning disable 1591 Reserved13 = 0x2000, Reserved12 = 0x1000, Reserved11 = 0x0800, Reserved10 = 0x0400, Reserved09 = 0x0200, Reserved08 = 0x0100, Reserved07 = 0x0080, Reserved06 = 0x0040, Reserved05 = 0x0020, Reserved04 = 0x0010, Reserved03 = 0x0008, Reserved02 = 0x0004, Reserved01 = 0x0002, #pragma warning restore 1591 /// Indicates a device specific minimum standby timer value SpecificStandbyTimer = 0x0001 } /// Even more capabilities flag bits. [Flags] public enum CapabilitiesBit3 : byte { /// BLOCK ERASE EXT supported BlockErase = 0x0080, /// OVERWRITE EXT supported Overwrite = 0x0040, /// CRYPTO SCRAMBLE EXT supported CryptoScramble = 0x0020, /// Sanitize feature set is supported Sanitize = 0x0010, /// If unset, sanitize commands are specified by ACS-2 SanitizeCommands = 0x0008, /// SANITIZE ANTIFREEZE LOCK EXT is supported SanitizeAntifreeze = 0x0004, #pragma warning disable 1591 Reserved01 = 0x0002, #pragma warning restore 1591 /// Multiple logical sector setting is valid MultipleValid = 0x0001 } /// Command set flag bits. [Flags] public enum CommandSetBit : ushort { /// Already obsolete in ATA/ATAPI-4, reserved in ATA3 Obsolete15 = 0x8000, /// NOP is supported Nop = 0x4000, /// READ BUFFER is supported ReadBuffer = 0x2000, /// WRITE BUFFER is supported WriteBuffer = 0x1000, /// Already obsolete in ATA/ATAPI-4, reserved in ATA3 Obsolete11 = 0x0800, /// Host Protected Area is supported HPA = 0x0400, /// DEVICE RESET is supported DeviceReset = 0x0200, /// SERVICE interrupt is supported Service = 0x0100, /// Release is supported Release = 0x0080, /// Look-ahead is supported LookAhead = 0x0040, /// Write cache is supported WriteCache = 0x0020, /// PACKET command set is supported Packet = 0x0010, /// Power Management feature set is supported PowerManagement = 0x0008, /// Removable Media feature set is supported RemovableMedia = 0x0004, /// Security Mode feature set is supported SecurityMode = 0x0002, /// SMART feature set is supported SMART = 0x0001 } /// More command set flag bits. [Flags] public enum CommandSetBit2 : ushort { /// MUST NOT be set MustBeClear = 0x8000, /// MUST BE SET MustBeSet = 0x4000, /// FLUSH CACHE EXT supported FlushCacheExt = 0x2000, /// FLUSH CACHE supported FlushCache = 0x1000, /// Device Configuration Overlay feature set supported DCO = 0x0800, /// 48-bit LBA supported LBA48 = 0x0400, /// Automatic Acoustic Management supported AAM = 0x0200, /// SET MAX security extension supported SetMax = 0x0100, /// Address Offset Reserved Area Boot NCITS TR27:2001 AddressOffsetReservedAreaBoot = 0x0080, /// SET FEATURES required to spin-up SetFeaturesRequired = 0x0040, /// Power-Up in standby feature set supported PowerUpInStandby = 0x0020, /// Removable Media Status Notification feature set is supported RemovableNotification = 0x0010, /// Advanced Power Management feature set is supported APM = 0x0008, /// Compact Flash feature set is supported CompactFlash = 0x0004, /// READ DMA QUEUED and WRITE DMA QUEUED are supported RWQueuedDMA = 0x0002, /// DOWNLOAD MICROCODE is supported DownloadMicrocode = 0x0001 } /// Even more command set flag bits. [Flags] public enum CommandSetBit3 : ushort { /// MUST NOT be set MustBeClear = 0x8000, /// MUST BE SET MustBeSet = 0x4000, /// IDLE IMMEDIATE with UNLOAD FEATURE is supported IdleImmediate = 0x2000, /// Reserved for INCITS TR-37/2004 Reserved12 = 0x1000, /// Reserved for INCITS TR-37/2004 Reserved11 = 0x0800, /// URG bit is supported in WRITE STREAM DMA EXT and WRITE STREAM EXT WriteURG = 0x0400, /// URG bit is supported in READ STREAM DMA EXT and READ STREAM EXT ReadURG = 0x0200, /// 64-bit World Wide Name is supported WWN = 0x0100, /// WRITE DMA QUEUED FUA EXT is supported FUAWriteQ = 0x0080, /// WRITE DMA FUA EXT and WRITE MULTIPLE FUA EXT are supported FUAWrite = 0x0040, /// General Purpose Logging feature supported GPL = 0x0020, /// Streaming feature set is supported Streaming = 0x0010, /// Media Card Pass Through command set supported MCPT = 0x0008, /// Media serial number supported MediaSerial = 0x0004, /// SMART self-test supported SMARTSelfTest = 0x0002, /// SMART error logging supported SMARTLog = 0x0001 } /// Yet more command set flag bits. [Flags] public enum CommandSetBit4 : ushort { /// MUST NOT be set MustBeClear = 0x8000, /// MUST be set MustBeSet = 0x4000, #pragma warning disable 1591 Reserved13 = 0x2000, Reserved12 = 0x1000, Reserved11 = 0x0800, Reserved10 = 0x0400, #pragma warning restore 1591 /// DSN feature set is supported DSN = 0x0200, /// Accessible Max Address Configuration is supported AMAC = 0x0100, /// Extended Power Conditions is supported ExtPowerCond = 0x0080, /// Extended Status Reporting is supported ExtStatusReport = 0x0040, /// Free-fall Control feature set is supported FreeFallControl = 0x0020, /// Supports segmented feature in DOWNLOAD MICROCODE SegmentedDownloadMicrocode = 0x0010, /// READ/WRITE DMA EXT GPL are supported RWDMAExtGpl = 0x0008, /// WRITE UNCORRECTABLE is supported WriteUnc = 0x0004, /// Write/Read/Verify is supported WRV = 0x0002, /// Reserved for DT1825 DT1825 = 0x0001 } /// Yet again more command set flag bits. [Flags] public enum CommandSetBit5 : ushort { /// Supports CFast Specification CFast = 0x8000, /// Deterministic read after TRIM is supported DeterministicTrim = 0x4000, /// Long physical sector alignment error reporting control is supported LongPhysSectorAligError = 0x2000, /// DEVICE CONFIGURATION IDENTIFY DMA and DEVICE CONFIGURATION SET DMA are supported DeviceConfDMA = 0x1000, /// READ BUFFER DMA is supported ReadBufferDMA = 0x0800, /// WRITE BUFFER DMA is supported WriteBufferDMA = 0x0400, /// SET PASSWORD DMA and SET UNLOCK DMA are supported SetMaxDMA = 0x0200, /// DOWNLOAD MICROCODE DMA is supported DownloadMicroCodeDMA = 0x0100, /// Reserved for IEEE-1667 IEEE1667 = 0x0080, /// Optional ATA 28-bit commands are supported Ata28 = 0x0040, /// Read zero after TRIM is supported ReadZeroTrim = 0x0020, /// Device encrypts all user data Encrypted = 0x0010, /// Extended number of user addressable sectors is supported ExtSectors = 0x0008, /// All write cache is non-volatile AllCacheNV = 0x0004, /// Zoned capabilities bit 1 ZonedBit1 = 0x0002, /// Zoned capabilities bit 0 ZonedBit0 = 0x0001 } /// Data set management flag bits. [Flags] public enum DataSetMgmtBit : ushort { #pragma warning disable 1591 Reserved15 = 0x8000, Reserved14 = 0x4000, Reserved13 = 0x2000, Reserved12 = 0x1000, Reserved11 = 0x0800, Reserved10 = 0x0400, Reserved09 = 0x0200, Reserved08 = 0x0100, Reserved07 = 0x0080, Reserved06 = 0x0040, Reserved05 = 0x0020, Reserved04 = 0x0010, Reserved03 = 0x0008, Reserved02 = 0x0004, Reserved01 = 0x0002, #pragma warning restore 1591 /// TRIM is supported Trim = 0x0001 } /// Device form factor public enum DeviceFormFactorEnum : ushort { /// Size not reported NotReported = 0, /// 5.25" FiveAndQuarter = 1, /// 3.5" ThreeAndHalf = 2, /// 2.5" TwoAndHalf = 3, /// 1.8" OnePointEight = 4, /// Less than 1.8" LessThanOnePointEight = 5 } /// Extended identify flag bits. [Flags] public enum ExtendedIdentifyBit : byte { /// Reserved Reserved07 = 0x80, /// Reserved Reserved06 = 0x40, /// Reserved Reserved05 = 0x20, /// Reserved Reserved04 = 0x10, /// Reserved Reserved03 = 0x08, /// Identify word 88 is valid Word88Valid = 0x04, /// Identify words 64 to 70 are valid Words64to70Valid = 0x02, /// Identify words 54 to 58 are valid Words54to58Valid = 0x01 } /// General configuration flag bits. [Flags] public enum GeneralConfigurationBit : ushort { /// Set on ATAPI NonMagnetic = 0x8000, /// Format speed tolerance gap is required Obsoleted in ATA-2 FormatGapReq = 0x4000, /// Track offset option is available Obsoleted in ATA-2 TrackOffset = 0x2000, /// Data strobe offset option is available Obsoleted in ATA-2 DataStrobeOffset = 0x1000, /// Rotational speed tolerance is higher than 0,5% Obsoleted in ATA-2 RotationalSpeedTolerance = 0x0800, /// Disk transfer rate is > 10 Mb/s Obsoleted in ATA-2 UltraFastIDE = 0x0400, /// Disk transfer rate is > 5 Mb/s but <= 10 Mb/s Obsoleted in ATA-2 FastIDE = 0x0200, /// Disk transfer rate is <= 5 Mb/s Obsoleted in ATA-2 SlowIDE = 0x0100, /// Drive uses removable media Removable = 0x0080, /// Drive is fixed Obsoleted in ATA/ATAPI-6 Fixed = 0x0040, /// Spindle motor control is implemented Obsoleted in ATA-2 SpindleControl = 0x0020, /// Head switch time is bigger than 15 µsec. Obsoleted in ATA-2 HighHeadSwitch = 0x0010, /// Drive is not MFM encoded Obsoleted in ATA-2 NotMFM = 0x0008, /// Drive is soft sectored Obsoleted in ATA-2 SoftSector = 0x0004, /// Response incomplete Since ATA/ATAPI-5 IncompleteResponse = 0x0004, /// Drive is hard sectored Obsoleted in ATA-2 HardSector = 0x0002, /// Reserved Reserved = 0x0001 } /// Word 80 Major version [Flags] public enum MajorVersionBit : ushort { #pragma warning disable 1591 Reserved15 = 0x8000, Reserved14 = 0x4000, Reserved13 = 0x2000, Reserved12 = 0x1000, #pragma warning restore 1591 /// ACS-4 ACS4 = 0x0800, /// ACS-3 ACS3 = 0x0400, /// ACS-2 ACS2 = 0x0200, /// ATA8-ACS Ata8ACS = 0x0100, /// ATA/ATAPI-7 AtaAtapi7 = 0x0080, /// ATA/ATAPI-6 AtaAtapi6 = 0x0040, /// ATA/ATAPI-5 AtaAtapi5 = 0x0020, /// ATA/ATAPI-4 AtaAtapi4 = 0x0010, /// ATA-3 Ata3 = 0x0008, /// ATA-2 Ata2 = 0x0004, /// ATA-1 Ata1 = 0x0002, #pragma warning disable 1591 Reserved00 = 0x0001 #pragma warning restore 1591 } /// SATA capabilities flags [Flags] public enum SATACapabilitiesBit : ushort { /// Supports READ LOG DMA EXT ReadLogDMAExt = 0x8000, /// Supports device automatic partial to slumber transitions DevSlumbTrans = 0x4000, /// Supports host automatic partial to slumber transitions HostSlumbTrans = 0x2000, /// Supports NCQ priority NCQPriority = 0x1000, /// Supports unload while NCQ commands are outstanding UnloadNCQ = 0x0800, /// Supports PHY Event Counters PHYEventCounter = 0x0400, /// Supports receipt of host initiated power management requests PowerReceipt = 0x0200, /// Supports NCQ NCQ = 0x0100, #pragma warning disable 1591 Reserved07 = 0x0080, Reserved06 = 0x0040, Reserved05 = 0x0020, Reserved04 = 0x0010, #pragma warning restore 1591 /// Supports SATA Gen. 3 Signaling Speed (6.0Gb/s) Gen3Speed = 0x0008, /// Supports SATA Gen. 2 Signaling Speed (3.0Gb/s) Gen2Speed = 0x0004, /// Supports SATA Gen. 1 Signaling Speed (1.5Gb/s) Gen1Speed = 0x0002, /// MUST NOT be set Clear = 0x0001 } /// More SATA capabilities flags [Flags] public enum SATACapabilitiesBit2 : ushort { #pragma warning disable 1591 Reserved15 = 0x8000, Reserved14 = 0x4000, Reserved13 = 0x2000, Reserved12 = 0x1000, Reserved11 = 0x0800, Reserved10 = 0x0400, Reserved09 = 0x0200, Reserved08 = 0x0100, Reserved07 = 0x0080, #pragma warning restore 1591 /// Supports RECEIVE FPDMA QUEUED and SEND FPDMA QUEUED FPDMAQ = 0x0040, /// Supports NCQ Queue Management NCQMgmt = 0x0020, /// ATAPI: Supports host environment detect HostEnvDetect = 0x0020, /// Supports NCQ streaming NCQStream = 0x0010, /// ATAPI: Supports device attention on slimline connected devices DevAttSlimline = 0x0010, /// Coded value indicating current negotiated Serial ATA signal speed CurrentSpeedBit2 = 0x0008, /// Coded value indicating current negotiated Serial ATA signal speed CurrentSpeedBit1 = 0x0004, /// Coded value indicating current negotiated Serial ATA signal speed CurrentSpeedBit0 = 0x0002, /// MUST NOT be set Clear = 0x0001 } /// SATA features flags [Flags] public enum SATAFeaturesBit : ushort { #pragma warning disable 1591 Reserved15 = 0x8000, Reserved14 = 0x4000, Reserved13 = 0x2000, Reserved12 = 0x1000, Reserved11 = 0x0800, Reserved10 = 0x0400, Reserved09 = 0x0200, Reserved08 = 0x0100, #pragma warning restore 1591 /// Supports NCQ autosense NCQAutoSense = 0x0080, /// Automatic Partial to Slumber transitions are enabled EnabledSlumber = 0x0080, /// Supports Software Settings Preservation SettingsPreserve = 0x0040, /// Supports hardware feature control HardwareFeatureControl = 0x0020, /// ATAPI: Asynchronous notification AsyncNotification = 0x0020, /// Supports in-order data delivery InOrderData = 0x0010, /// Supports initiating power management InitPowerMgmt = 0x0008, /// Supports DMA Setup auto-activation DMASetup = 0x0004, /// Supports non-zero buffer offsets NonZeroBufferOffset = 0x0002, /// MUST NOT be set Clear = 0x0001 } /// SCT Command Transport flags [Flags] public enum SCTCommandTransportBit : ushort { #pragma warning disable 1591 Vendor15 = 0x8000, Vendor14 = 0x4000, Vendor13 = 0x2000, Vendor12 = 0x1000, Reserved11 = 0x0800, Reserved10 = 0x0400, Reserved09 = 0x0200, Reserved08 = 0x0100, Reserved07 = 0x0080, Reserved06 = 0x0040, #pragma warning restore 1591 /// SCT Command Transport Data Tables supported DataTables = 0x0020, /// SCT Command Transport Features Control supported FeaturesControl = 0x0010, /// SCT Command Transport Error Recovery Control supported ErrorRecoveryControl = 0x0008, /// SCT Command Transport Write Same supported WriteSame = 0x0004, /// SCT Command Transport Long Sector Address supported LongSectorAccess = 0x0002, /// SCT Command Transport supported Supported = 0x0001 } /// Security status flag bits. [Flags] public enum SecurityStatusBit : ushort { #pragma warning disable 1591 Reserved15 = 0x8000, Reserved14 = 0x4000, Reserved13 = 0x2000, Reserved12 = 0x1000, Reserved11 = 0x0800, Reserved10 = 0x0400, Reserved09 = 0x0200, #pragma warning restore 1591 /// Maximum security level Maximum = 0x0100, #pragma warning disable 1591 Reserved07 = 0x0080, Reserved06 = 0x0040, #pragma warning restore 1591 /// Supports enhanced security erase Enhanced = 0x0020, /// Security count expired Expired = 0x0010, /// Security frozen Frozen = 0x0008, /// Security locked Locked = 0x0004, /// Security enabled Enabled = 0x0002, /// Security supported Supported = 0x0001 } /// Specific configuration flags public enum SpecificConfigurationEnum : ushort { /// Device requires SET FEATURES to spin up and IDENTIFY DEVICE response is incomplete RequiresSetIncompleteResponse = 0x37C8, /// Device requires SET FEATURES to spin up and IDENTIFY DEVICE response is complete RequiresSetCompleteResponse = 0x738C, /// Device does not requires SET FEATURES to spin up and IDENTIFY DEVICE response is incomplete NotRequiresSetIncompleteResponse = 0x8C73, /// Device does not requires SET FEATURES to spin up and IDENTIFY DEVICE response is complete NotRequiresSetCompleteResponse = 0xC837 } /// Transfer mode flags [Flags] public enum TransferMode : byte { #pragma warning disable 1591 Mode7 = 0x80, Mode6 = 0x40, Mode5 = 0x20, Mode4 = 0x10, Mode3 = 0x08, Mode2 = 0x04, Mode1 = 0x02, Mode0 = 0x01 #pragma warning restore 1591 } /// Trusted Computing flags [Flags] public enum TrustedComputingBit : ushort { /// MUST NOT be set Clear = 0x8000, /// MUST be set Set = 0x4000, #pragma warning disable 1591 Reserved13 = 0x2000, Reserved12 = 0x1000, Reserved11 = 0x0800, Reserved10 = 0x0400, Reserved09 = 0x0200, Reserved08 = 0x0100, Reserved07 = 0x0080, Reserved06 = 0x0040, Reserved05 = 0x0020, Reserved04 = 0x0010, Reserved03 = 0x0008, Reserved02 = 0x0004, Reserved01 = 0x0002, #pragma warning restore 1591 /// Trusted Computing feature set is supported TrustedComputing = 0x0001 } /// IDENTIFY DEVICE decoded response [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 2)] public struct IdentifyDevice { /// /// Word 0 General device configuration On ATAPI devices: Bits 12 to 8 indicate device type as SCSI defined Bits 6 /// to 5: 0 = Device shall set DRQ within 3 ms of receiving PACKET 1 = Device shall assert INTRQ when DRQ is set to one /// 2 = Device shall set DRQ within 50 µs of receiving PACKET Bits 1 to 0: 0 = 12 byte command packet 1 = 16 byte /// command packet CompactFlash is 0x848A (non magnetic, removable, not MFM, hardsector, and UltraFAST) /// public GeneralConfigurationBit GeneralConfiguration; /// Word 1 Cylinders in default translation mode Obsoleted in ATA/ATAPI-6 public ushort Cylinders; /// Word 2 Specific configuration public SpecificConfigurationEnum SpecificConfiguration; /// Word 3 Heads in default translation mode Obsoleted in ATA/ATAPI-6 public ushort Heads; /// Word 4 Unformatted bytes per track in default translation mode Obsoleted in ATA-2 public ushort UnformattedBPT; /// Word 5 Unformatted bytes per sector in default translation mode Obsoleted in ATA-2 public ushort UnformattedBPS; /// Word 6 Sectors per track in default translation mode Obsoleted in ATA/ATAPI-6 public ushort SectorsPerTrack; /// Words 7 to 8 CFA: Number of sectors per card public uint SectorsPerCard; /// Word 9 Vendor unique Obsoleted in ATA/ATAPI-4 public ushort VendorWord9; /// Words 10 to 19 Device serial number, right justified, padded with spaces [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)] public string SerialNumber; /// /// Word 20 Manufacturer defined Obsoleted in ATA-2 0x0001 = single ported single sector buffer 0x0002 = dual /// ported multi sector buffer 0x0003 = dual ported multi sector buffer with reading /// public ushort BufferType; /// Word 21 Size of buffer in 512 byte increments Obsoleted in ATA-2 public ushort BufferSize; /// Word 22 Bytes of ECC available in READ/WRITE LONG commands Obsoleted in ATA/ATAPI-4 public ushort EccBytes; /// Words 23 to 26 Firmware revision, left justified, padded with spaces [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)] public string FirmwareRevision; /// Words 27 to 46 Model number, left justified, padded with spaces [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 40)] public string Model; /// /// Word 47 bits 7 to 0 Maximum number of sectors that can be transferred per interrupt on read and write multiple /// commands /// public byte MultipleMaxSectors; /// Word 47 bits 15 to 8 Vendor unique ATA/ATAPI-4 says it must be 0x80 public byte VendorWord47; /// /// Word 48 ATA-1: Set to 1 if it can perform doubleword I/O ATA-2 to ATA/ATAPI-7: Reserved ATA8-ACS: Trusted /// Computing feature set /// public TrustedComputingBit TrustedComputing; /// Word 49 Capabilities public CapabilitiesBit Capabilities; /// Word 50 Capabilities public CapabilitiesBit2 Capabilities2; /// Word 51 bits 7 to 0 Vendor unique Obsoleted in ATA/ATAPI-4 public byte VendorWord51; /// Word 51 bits 15 to 8 Transfer timing mode in PIO Obsoleted in ATA/ATAPI-4 public byte PIOTransferTimingMode; /// Word 52 bits 7 to 0 Vendor unique Obsoleted in ATA/ATAPI-4 public byte VendorWord52; /// Word 52 bits 15 to 8 Transfer timing mode in DMA Obsoleted in ATA/ATAPI-4 public byte DMATransferTimingMode; /// Word 53 bits 7 to 0 Reports if words 54 to 58 are valid public ExtendedIdentifyBit ExtendedIdentify; /// Word 53 bits 15 to 8 Free-fall Control Sensitivity public byte FreeFallSensitivity; /// Word 54 Cylinders in current translation mode Obsoleted in ATA/ATAPI-6 public ushort CurrentCylinders; /// Word 55 Heads in current translation mode Obsoleted in ATA/ATAPI-6 public ushort CurrentHeads; /// Word 56 Sectors per track in current translation mode Obsoleted in ATA/ATAPI-6 public ushort CurrentSectorsPerTrack; /// Words 57 to 58 Total sectors currently user-addressable Obsoleted in ATA/ATAPI-6 public uint CurrentSectors; /// Word 59 bits 7 to 0 Number of sectors currently set to transfer on a READ/WRITE MULTIPLE command public byte MultipleSectorNumber; /// Word 59 bits 15 to 8 Indicates if is valid public CapabilitiesBit3 Capabilities3; /// Words 60 to 61 If drive supports LBA, how many sectors are addressable using LBA public uint LBASectors; /// /// Word 62 bits 7 to 0 Single word DMA modes available Obsoleted in ATA/ATAPI-4 In ATAPI it's not obsolete, /// indicates UDMA mode (UDMA7 is instead MDMA0) /// public TransferMode DMASupported; /// /// Word 62 bits 15 to 8 Single word DMA mode currently active Obsoleted in ATA/ATAPI-4 In ATAPI it's not /// obsolete, bits 0 and 1 indicate MDMA mode+1, bit 10 indicates DMA is supported and bit 15 indicates DMADIR bit in /// PACKET is required for DMA transfers /// public TransferMode DMAActive; /// Word 63 bits 7 to 0 Multiword DMA modes available public TransferMode MDMASupported; /// Word 63 bits 15 to 8 Multiword DMA mode currently active public TransferMode MDMAActive; /// Word 64 bits 7 to 0 Supported Advanced PIO transfer modes public TransferMode APIOSupported; /// Word 64 bits 15 to 8 Reserved public byte ReservedWord64; /// Word 65 Minimum MDMA transfer cycle time per word in nanoseconds public ushort MinMDMACycleTime; /// Word 66 Recommended MDMA transfer cycle time per word in nanoseconds public ushort RecMDMACycleTime; /// Word 67 Minimum PIO transfer cycle time without flow control in nanoseconds public ushort MinPIOCycleTimeNoFlow; /// Word 68 Minimum PIO transfer cycle time with IORDY flow control in nanoseconds public ushort MinPIOCycleTimeFlow; /// Word 69 Additional supported public CommandSetBit5 CommandSet5; /// Word 70 Reserved public ushort ReservedWord70; /// Word 71 ATAPI: Typical time in ns from receipt of PACKET to release bus public ushort PacketBusRelease; /// Word 72 ATAPI: Typical time in ns from receipt of SERVICE to clear BSY public ushort ServiceBusyClear; /// Word 73 Reserved public ushort ReservedWord73; /// Word 74 Reserved public ushort ReservedWord74; /// Word 75 Maximum Queue depth public ushort MaxQueueDepth; /// Word 76 Serial ATA Capabilities public SATACapabilitiesBit SATACapabilities; /// Word 77 Serial ATA Additional Capabilities public SATACapabilitiesBit2 SATACapabilities2; /// Word 78 Supported Serial ATA features public SATAFeaturesBit SATAFeatures; /// Word 79 Enabled Serial ATA features public SATAFeaturesBit EnabledSATAFeatures; /// Word 80 Major version of ATA/ATAPI standard supported public MajorVersionBit MajorVersion; /// Word 81 Minimum version of ATA/ATAPI standard supported public ushort MinorVersion; /// Word 82 Supported command/feature sets public CommandSetBit CommandSet; /// Word 83 Supported command/feature sets public CommandSetBit2 CommandSet2; /// Word 84 Supported command/feature sets public CommandSetBit3 CommandSet3; /// Word 85 Enabled command/feature sets public CommandSetBit EnabledCommandSet; /// Word 86 Enabled command/feature sets public CommandSetBit2 EnabledCommandSet2; /// Word 87 Enabled command/feature sets public CommandSetBit3 EnabledCommandSet3; /// Word 88 bits 7 to 0 Supported Ultra DMA transfer modes public TransferMode UDMASupported; /// Word 88 bits 15 to 8 Selected Ultra DMA transfer modes public TransferMode UDMAActive; /// Word 89 Time required for security erase completion public ushort SecurityEraseTime; /// Word 90 Time required for enhanced security erase completion public ushort EnhancedSecurityEraseTime; /// Word 91 Current advanced power management value public ushort CurrentAPM; /// Word 92 Master password revision code public ushort MasterPasswordRevisionCode; /// Word 93 Hardware reset result public ushort HardwareResetResult; /// Word 94 bits 7 to 0 Current AAM value public byte CurrentAAM; /// Word 94 bits 15 to 8 Vendor's recommended AAM value public byte RecommendedAAM; /// Word 95 Stream minimum request size public ushort StreamMinReqSize; /// Word 96 Streaming transfer time in DMA public ushort StreamTransferTimeDMA; /// Word 97 Streaming access latency in DMA and PIO public ushort StreamAccessLatency; /// Words 98 to 99 Streaming performance granularity public uint StreamPerformanceGranularity; /// Words 100 to 103 48-bit LBA addressable sectors public ulong LBA48Sectors; /// Word 104 Streaming transfer time in PIO public ushort StreamTransferTimePIO; /// Word 105 Maximum number of 512-byte block per DATA SET MANAGEMENT command public ushort DataSetMgmtSize; /// /// Word 106 Bit 15 should be zero Bit 14 should be one Bit 13 set indicates device has multiple logical sectors /// per physical sector Bit 12 set indicates logical sector has more than 256 words (512 bytes) Bits 11 to 4 are /// reserved Bits 3 to 0 indicate power of two of logical sectors per physical sector /// public ushort PhysLogSectorSize; /// Word 107 Interseek delay for ISO-7779 acoustic testing, in microseconds public ushort InterseekDelay; /// Words 108 to 111 World Wide Name public ulong WWN; /// Words 112 to 115 Reserved for WWN extension to 128 bit public ulong WWNExtension; /// Word 116 Reserved for technical report public ushort ReservedWord116; /// Words 117 to 118 Words per logical sector public uint LogicalSectorWords; /// Word 119 Supported command/feature sets public CommandSetBit4 CommandSet4; /// Word 120 Supported command/feature sets public CommandSetBit4 EnabledCommandSet4; /// Words 121 to 125 Reserved [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] public ushort[] ReservedWords121; /// Word 126 ATAPI byte count limit public ushort ATAPIByteCount; /// /// Word 127 Removable Media Status Notification feature set support Bits 15 to 2 are reserved Bits 1 to 0 must be /// 0 for not supported or 1 for supported. 2 and 3 are reserved. Obsoleted in ATA8-ACS /// public ushort RemovableStatusSet; /// Word 128 Security status public SecurityStatusBit SecurityStatus; /// Words 129 to 159 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 31)] public ushort[] ReservedWords129; /// /// Word 160 CFA power mode Bit 15 must be set Bit 13 indicates mode 1 is required for one or more commands Bit 12 /// indicates mode 1 is disabled Bits 11 to 0 indicates maximum current in mA /// public ushort CFAPowerMode; /// Words 161 to 167 Reserved for CFA [MarshalAs(UnmanagedType.ByValArray, SizeConst = 7)] public ushort[] ReservedCFA; /// Word 168 Bits 15 to 4, reserved Bits 3 to 0, device nominal form factor public DeviceFormFactorEnum DeviceFormFactor; /// Word 169 DATA SET MANAGEMENT support public DataSetMgmtBit DataSetMgmt; /// Words 170 to 173 Additional product identifier [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)] public string AdditionalPID; /// Word 174 Reserved public ushort ReservedWord174; /// Word 175 Reserved public ushort ReservedWord175; /// Words 176 to 195 Current media serial number [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 40)] public string MediaSerial; /// Words 196 to 205 Current media manufacturer [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)] public string MediaManufacturer; /// Word 206 SCT Command Transport features public SCTCommandTransportBit SCTCommandTransport; /// Word 207 Reserved for CE-ATA public ushort ReservedCEATAWord207; /// Word 208 Reserved for CE-ATA public ushort ReservedCEATAWord208; /// /// Word 209 Alignment of logical block within a larger physical block Bit 15 shall be cleared to zero Bit 14 /// shall be set to one Bits 13 to 0 indicate logical sector offset within the first physical sector /// public ushort LogicalAlignment; /// Words 210 to 211 Write/Read/Verify sector count mode 3 only public uint WRVSectorCountMode3; /// Words 212 to 213 Write/Read/Verify sector count mode 2 only public uint WRVSectorCountMode2; /// /// Word 214 NV Cache capabilities Bits 15 to 12 feature set version Bits 11 to 18 power mode feature set version /// Bits 7 to 5 reserved Bit 4 feature set enabled Bits 3 to 2 reserved Bit 1 power mode feature set enabled Bit 0 /// power mode feature set supported /// public ushort NVCacheCaps; /// Words 215 to 216 NV Cache Size in Logical BLocks public uint NVCacheSize; /// Word 217 Nominal media rotation rate In ACS-1 meant NV Cache read speed in MB/s public ushort NominalRotationRate; /// Word 218 NV Cache write speed in MB/s Reserved since ACS-2 public ushort NVCacheWriteSpeed; /// Word 219 bits 7 to 0 Estimated device spin up in seconds public byte NVEstimatedSpinUp; /// Word 219 bits 15 to 8 NV Cache reserved public byte NVReserved; /// Word 220 bits 7 to 0 Write/Read/Verify feature set current mode public byte WRVMode; /// Word 220 bits 15 to 8 Reserved public byte WRVReserved; /// Word 221 Reserved public ushort ReservedWord221; /// /// Word 222 Transport major revision number Bits 15 to 12 indicate transport type. 0 parallel, 1 serial, 0xE /// PCIe. Bits 11 to 0 indicate revision /// public ushort TransportMajorVersion; /// Word 223 Transport minor revision number public ushort TransportMinorVersion; /// Words 224 to 229 Reserved for CE-ATA [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] public ushort[] ReservedCEATA224; /// Words 230 to 233 48-bit LBA if Word 69 bit 3 is set public ulong ExtendedUserSectors; /// Word 234 Minimum number of 512 byte units per DOWNLOAD MICROCODE mode 3 public ushort MinDownloadMicroMode3; /// Word 235 Maximum number of 512 byte units per DOWNLOAD MICROCODE mode 3 public ushort MaxDownloadMicroMode3; /// Words 236 to 254 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 19)] public ushort[] ReservedWords; /// Word 255 bits 7 to 0 Should be 0xA5 public byte Signature; /// Word 255 bits 15 to 8 Checksum public byte Checksum; } /// Decodes a raw IDENTIFY DEVICE response /// Raw IDENTIFY DEVICE response /// Decoded IDENTIFY DEVICE public static IdentifyDevice? Decode(byte[] IdentifyDeviceResponse) { if(IdentifyDeviceResponse == null) return null; if(IdentifyDeviceResponse.Length != 512) { AaruConsole.DebugWriteLine(MODULE_NAME, Localization.IDENTIFY_response_is_different_than_512_bytes_not_decoding); return null; } IdentifyDevice ATAID = Marshal.ByteArrayToStructureLittleEndian(IdentifyDeviceResponse); ATAID.WWN = DescrambleWWN(ATAID.WWN); ATAID.WWNExtension = DescrambleWWN(ATAID.WWNExtension); ATAID.SerialNumber = DescrambleATAString(IdentifyDeviceResponse, 10 * 2, 20); ATAID.FirmwareRevision = DescrambleATAString(IdentifyDeviceResponse, 23 * 2, 8); ATAID.Model = DescrambleATAString(IdentifyDeviceResponse, 27 * 2, 40); ATAID.AdditionalPID = DescrambleATAString(IdentifyDeviceResponse, 170 * 2, 8); ATAID.MediaSerial = DescrambleATAString(IdentifyDeviceResponse, 176 * 2, 40); ATAID.MediaManufacturer = DescrambleATAString(IdentifyDeviceResponse, 196 * 2, 20); return ATAID; } /// Encodes a raw IDENTIFY DEVICE response /// Decoded IDENTIFY DEVICE /// Raw IDENTIFY DEVICE response public static byte[] Encode(IdentifyDevice? identify) { if(identify is null) return null; IdentifyDevice ataId = identify.Value; ataId.WWN = DescrambleWWN(ataId.WWN); ataId.WWNExtension = DescrambleWWN(ataId.WWNExtension); byte[] buf = new byte[512]; nint ptr = System.Runtime.InteropServices.Marshal.AllocHGlobal(512); System.Runtime.InteropServices.Marshal.StructureToPtr(ataId, ptr, false); System.Runtime.InteropServices.Marshal.Copy(ptr, buf, 0, 512); System.Runtime.InteropServices.Marshal.FreeHGlobal(ptr); byte[] str = ScrambleATAString(ataId.SerialNumber, 20); Array.Copy(str, 0, buf, 10 * 2, 20); str = ScrambleATAString(ataId.FirmwareRevision, 8); Array.Copy(str, 0, buf, 23 * 2, 8); str = ScrambleATAString(ataId.Model, 40); Array.Copy(str, 0, buf, 27 * 2, 40); str = ScrambleATAString(ataId.AdditionalPID, 8); Array.Copy(str, 0, buf, 170 * 2, 8); str = ScrambleATAString(ataId.MediaSerial, 40); Array.Copy(str, 0, buf, 176 * 2, 40); str = ScrambleATAString(ataId.MediaManufacturer, 20); Array.Copy(str, 0, buf, 196 * 2, 20); return buf; } static ulong DescrambleWWN(ulong WWN) { byte[] qwb = BitConverter.GetBytes(WWN); byte[] qword = new byte[8]; qword[7] = qwb[1]; qword[6] = qwb[0]; qword[5] = qwb[3]; qword[4] = qwb[2]; qword[3] = qwb[5]; qword[2] = qwb[4]; qword[1] = qwb[7]; qword[0] = qwb[6]; return BitConverter.ToUInt64(qword, 0); } static string DescrambleATAString(IList buffer, int offset, int length) { byte[] outbuf = buffer[offset + length - 1] != 0x00 ? new byte[length + 1] : new byte[length]; for(int i = 0; i < length; i += 2) { outbuf[i] = buffer[offset + i + 1]; outbuf[i + 1] = buffer[offset + i]; } string outStr = StringHandlers.CToString(outbuf); return outStr.Trim(); } static byte[] ScrambleATAString(string str, int length) { byte[] buf = new byte[length]; for(int i = 0; i < length; i++) buf[i] = 0x20; if(str is null) return buf; byte[] bytes = Encoding.ASCII.GetBytes(str); if(bytes.Length % 2 != 0) { byte[] tmp = new byte[bytes.Length + 1]; tmp[^1] = 0x20; Array.Copy(bytes, 0, tmp, 0, bytes.Length); bytes = tmp; } for(int i = 0; i < bytes.Length; i += 2) { buf[i] = bytes[i + 1]; buf[i + 1] = bytes[i]; } return buf; } }