diff --git a/ATA/Identify.cs b/ATA/Identify.cs index 72d34c4..642a568 100644 --- a/ATA/Identify.cs +++ b/ATA/Identify.cs @@ -42,1829 +42,388 @@ using Marshal = DiscImageChef.Helpers.Marshal; namespace DiscImageChef.Decoders.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) + /// 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")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static class Identify { - [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; - } - - /// - /// 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 - } - - /// - /// Capabilities flag bits. - /// + /// 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 - /// - StandardStanbyTimer = 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 - /// + /// ATAPI: Interleaved DMA supported + InterleavedDMA = 0x8000, /// ATAPI: Command queueing supported + CommandQueue = 0x4000, /// Standby timer values are standard + StandardStanbyTimer = 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 } - /// - /// 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 - } - - /// - /// More capabilities flag bits. - /// + /// More capabilities flag bits. [Flags] public enum CapabilitiesBit2 : ushort { - /// - /// MUST NOT be set - /// - MustBeClear = 0x8000, - /// - /// MUST be set - /// - MustBeSet = 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, - /// - /// Indicates a device specific minimum standby timer value - /// + /// MUST NOT be set + MustBeClear = 0x8000, /// MUST be set + MustBeSet = 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, /// Indicates a device specific minimum standby timer value SpecificStandbyTimer = 0x0001 } [Flags] - public enum TransferMode : byte + public enum CapabilitiesBit3 : byte { - Mode7 = 0x80, - Mode6 = 0x40, - Mode5 = 0x20, - Mode4 = 0x10, - Mode3 = 0x08, - Mode2 = 0x04, - Mode1 = 0x02, - Mode0 = 0x01 + /// 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, Reserved01 = 0x0002, /// Multiple logical sector setting is valid + MultipleValid = 0x0001 } - /// - /// More capabilities flag bits. - /// + /// More capabilities 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 - /// + /// 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 capabilities flag bits. - /// + /// More capabilities 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 - /// + /// 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 } - /// - /// More capabilities flag bits. - /// + /// More capabilities 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, - /// - /// Sstreaming 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 - /// + /// 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, /// Sstreaming 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 } - /// - /// More capabilities flag bits. - /// - [Flags] - public enum SecurityStatusBit : ushort - { - Reserved15 = 0x8000, - Reserved14 = 0x4000, - Reserved13 = 0x2000, - Reserved12 = 0x1000, - Reserved11 = 0x0800, - Reserved10 = 0x0400, - Reserved09 = 0x0200, - /// - /// Maximum security level - /// - Maximum = 0x0100, - Reserved07 = 0x0080, - Reserved06 = 0x0040, - /// - /// 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 - } - - /// - /// Word 80 - /// Major version - /// - [Flags] - public enum MajorVersionBit : ushort - { - Reserved15 = 0x8000, - Reserved14 = 0x4000, - Reserved13 = 0x2000, - Reserved12 = 0x1000, - /// - /// 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, - Reserved00 = 0x0001 - } - - 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 - } - - [Flags] - public enum TrustedComputingBit : ushort - { - /// - /// MUST NOT be set - /// - Clear = 0x8000, - /// - /// MUST be set - /// - Set = 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, - /// - /// Trusted Computing feature set is supported - /// - TrustedComputing = 0x0001 - } - - /// - /// More capabilities flag bits. - /// + /// More capabilities flag bits. [Flags] public enum CommandSetBit4 : ushort { - /// - /// MUST NOT be set - /// - MustBeClear = 0x8000, - /// - /// MUST be set - /// - MustBeSet = 0x4000, - Reserved13 = 0x2000, - Reserved12 = 0x1000, - Reserved11 = 0x0800, - Reserved10 = 0x0400, - /// - /// 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 - /// + /// MUST NOT be set + MustBeClear = 0x8000, /// MUST be set + MustBeSet = 0x4000, Reserved13 = 0x2000, Reserved12 = 0x1000, Reserved11 = 0x0800, + Reserved10 = 0x0400, /// 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 } [Flags] - public enum SCTCommandTransportBit : ushort + public enum CommandSetBit5 : ushort { - Vendor15 = 0x8000, - Vendor14 = 0x4000, - Vendor13 = 0x2000, - Vendor12 = 0x1000, - Reserved11 = 0x0800, - Reserved10 = 0x0400, - Reserved09 = 0x0200, - Reserved08 = 0x0100, - Reserved07 = 0x0080, - Reserved06 = 0x0040, - /// - /// 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 + /// 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 + } + + [Flags] + public enum DataSetMgmtBit : ushort + { + 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, + /// TRIM is suported + Trim = 0x0001 + } + + 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 + { + Reserved15 = 0x8000, Reserved14 = 0x4000, Reserved13 = 0x2000, + Reserved12 = 0x1000, /// 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, Reserved00 = 0x0001 } [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 priroty - /// - 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, - Reserved07 = 0x0080, - Reserved06 = 0x0040, - Reserved05 = 0x0020, - Reserved04 = 0x0010, - /// - /// 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 - /// + /// 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 priroty + 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, Reserved07 = 0x0080, Reserved06 = 0x0040, Reserved05 = 0x0020, + Reserved04 = 0x0010, /// 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 + } + + [Flags] + public enum SATACapabilitiesBit2 : ushort + { + Reserved15 = 0x8000, Reserved14 = 0x4000, Reserved13 = 0x2000, + Reserved12 = 0x1000, Reserved11 = 0x0800, Reserved10 = 0x0400, + Reserved09 = 0x0200, Reserved08 = 0x0100, Reserved07 = 0x0080, + /// 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 } [Flags] public enum SATAFeaturesBit : ushort { - Reserved15 = 0x8000, - Reserved14 = 0x4000, - Reserved13 = 0x2000, - Reserved12 = 0x1000, - Reserved11 = 0x0800, - Reserved10 = 0x0400, - Reserved09 = 0x0200, - Reserved08 = 0x0100, - /// - /// 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 - /// + Reserved15 = 0x8000, Reserved14 = 0x4000, Reserved13 = 0x2000, + Reserved12 = 0x1000, Reserved11 = 0x0800, Reserved10 = 0x0400, + Reserved09 = 0x0200, Reserved08 = 0x0100, /// 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 } [Flags] - public enum CapabilitiesBit3 : byte + public enum SCTCommandTransportBit : ushort { - /// - /// 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, - Reserved01 = 0x0002, - /// - /// Multiple logical sector setting is valid - /// - MultipleValid = 0x0001 + Vendor15 = 0x8000, Vendor14 = 0x4000, Vendor13 = 0x2000, + Vendor12 = 0x1000, Reserved11 = 0x0800, Reserved10 = 0x0400, + Reserved09 = 0x0200, Reserved08 = 0x0100, Reserved07 = 0x0080, + Reserved06 = 0x0040, /// 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 + } + + /// More capabilities flag bits. + [Flags] + public enum SecurityStatusBit : ushort + { + Reserved15 = 0x8000, Reserved14 = 0x4000, Reserved13 = 0x2000, + Reserved12 = 0x1000, Reserved11 = 0x0800, Reserved10 = 0x0400, + Reserved09 = 0x0200, /// Maximum security level + Maximum = 0x0100, Reserved07 = 0x0080, Reserved06 = 0x0040, /// 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 + } + + 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 } [Flags] - public enum CommandSetBit5 : ushort + public enum TransferMode : byte { - /// - /// 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 - } - - 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 + Mode7 = 0x80, Mode6 = 0x40, Mode5 = 0x20, + Mode4 = 0x10, Mode3 = 0x08, Mode2 = 0x04, + Mode1 = 0x02, Mode0 = 0x01 } [Flags] - public enum DataSetMgmtBit : ushort + public enum TrustedComputingBit : ushort { - 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, - /// - /// TRIM is suported - /// - Trim = 0x0001 - } - - [Flags] - public enum SATACapabilitiesBit2 : ushort - { - Reserved15 = 0x8000, - Reserved14 = 0x4000, - Reserved13 = 0x2000, - Reserved12 = 0x1000, - Reserved11 = 0x0800, - Reserved10 = 0x0400, - Reserved09 = 0x0200, - Reserved08 = 0x0100, - Reserved07 = 0x0080, - /// - /// 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 + /// MUST NOT be set + Clear = 0x8000, /// MUST be set + Set = 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, /// Trusted Computing feature set is supported + TrustedComputing = 0x0001 } public static IdentifyDevice? Decode(byte[] IdentifyDeviceResponse) { - if(IdentifyDeviceResponse == null) return null; + if(IdentifyDeviceResponse == null) + return null; if(IdentifyDeviceResponse.Length != 512) { DicConsole.DebugWriteLine("ATA/ATAPI IDENTIFY decoder", "IDENTIFY response is different than 512 bytes, not decoding."); + return null; } - IdentifyDevice ATAID = Marshal.ByteArrayToStructureLittleEndian(IdentifyDeviceResponse); + var ATAID = Marshal.ByteArrayToStructureLittleEndian(IdentifyDeviceResponse); ATAID.WWN = DescrambleWWN(ATAID.WWN); ATAID.WWNExtension = DescrambleWWN(ATAID.WWNExtension); @@ -1881,7 +440,8 @@ namespace DiscImageChef.Decoders.ATA public static byte[] Encode(IdentifyDevice? identify) { - if(identify is null) return null; + if(identify is null) + return null; IdentifyDevice ataId = identify.Value; @@ -1912,36 +472,48 @@ namespace DiscImageChef.Decoders.ATA public static string Prettify(byte[] IdentifyDeviceResponse) { - if(IdentifyDeviceResponse.Length != 512) return null; + if(IdentifyDeviceResponse.Length != 512) + return null; IdentifyDevice? decoded = Decode(IdentifyDeviceResponse); + return Prettify(decoded); } public static string Prettify(IdentifyDevice? IdentifyDeviceResponse) { - if(IdentifyDeviceResponse == null) return null; + if(IdentifyDeviceResponse == null) + return null; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); bool atapi = false; bool cfa = false; IdentifyDevice ATAID = IdentifyDeviceResponse.Value; + if(ATAID.GeneralConfiguration.HasFlag(GeneralConfigurationBit.NonMagnetic)) if((ushort)ATAID.GeneralConfiguration != 0x848A) atapi = true; else cfa = true; - if(atapi) sb.AppendLine("ATAPI device"); - else if(cfa) sb.AppendLine("CompactFlash device"); - else sb.AppendLine("ATA device"); + if(atapi) + sb.AppendLine("ATAPI device"); + else if(cfa) + sb.AppendLine("CompactFlash device"); + else + sb.AppendLine("ATA device"); + + if(ATAID.Model != "") + sb.AppendFormat("Model: {0}", ATAID.Model).AppendLine(); - if(ATAID.Model != "") sb.AppendFormat("Model: {0}", ATAID.Model).AppendLine(); if(ATAID.FirmwareRevision != "") sb.AppendFormat("Firmware revision: {0}", ATAID.FirmwareRevision).AppendLine(); - if(ATAID.SerialNumber != "") sb.AppendFormat("Serial #: {0}", ATAID.SerialNumber).AppendLine(); + + if(ATAID.SerialNumber != "") + sb.AppendFormat("Serial #: {0}", ATAID.SerialNumber).AppendLine(); + if(ATAID.AdditionalPID != "") sb.AppendFormat("Additional product ID: {0}", ATAID.AdditionalPID).AppendLine(); @@ -1952,26 +524,20 @@ namespace DiscImageChef.Decoders.ATA { if(ATAID.MediaManufacturer != "") sb.AppendFormat("Media manufacturer: {0}", ATAID.MediaManufacturer).AppendLine(); - if(ATAID.MediaSerial != "") sb.AppendFormat("Media serial #: {0}", ATAID.MediaSerial).AppendLine(); + + if(ATAID.MediaSerial != "") + sb.AppendFormat("Media serial #: {0}", ATAID.MediaSerial).AppendLine(); } if(ATAID.EnabledCommandSet3.HasFlag(CommandSetBit3.WWN)) sb.AppendFormat("World Wide Name: {0:X16}", ATAID.WWN).AppendLine(); } - bool ata1 = false, - ata2 = false, - ata3 = false, - ata4 = false, - ata5 = false, - ata6 = false, - ata7 = false, - acs = false, - acs2 = false, - acs3 = false, - acs4 = false; + bool ata1 = false, ata2 = false, ata3 = false, ata4 = false, ata5 = false, ata6 = false, ata7 = false, + acs = false, acs2 = false, acs3 = false, acs4 = false; - if((ushort)ATAID.MajorVersion == 0x0000 || (ushort)ATAID.MajorVersion == 0xFFFF) + if((ushort)ATAID.MajorVersion == 0x0000 || + (ushort)ATAID.MajorVersion == 0xFFFF) { // Obsolete in ATA-2, if present, device supports ATA-1 ata1 |= ATAID.GeneralConfiguration.HasFlag(GeneralConfigurationBit.FastIDE) || @@ -1980,13 +546,20 @@ namespace DiscImageChef.Decoders.ATA ata2 |= ATAID.ExtendedIdentify.HasFlag(ExtendedIdentifyBit.Words64to70Valid); - if(!ata1 && !ata2 && !atapi && !cfa) ata2 = true; + if(!ata1 && + !ata2 && + !atapi && + !cfa) + ata2 = true; ata4 |= atapi; ata3 |= cfa; - if(cfa && ata1) ata1 = false; - if(cfa && ata2) ata2 = false; + if(cfa && ata1) + ata1 = false; + + if(cfa && ata2) + ata2 = false; ata5 |= ATAID.Signature == 0xA5; } @@ -2008,233 +581,305 @@ namespace DiscImageChef.Decoders.ATA int maxatalevel = 0; int minatalevel = 255; sb.Append("Supported ATA versions: "); + if(ata1) { sb.Append("ATA-1 "); maxatalevel = 1; - if(minatalevel > 1) minatalevel = 1; + + if(minatalevel > 1) + minatalevel = 1; } if(ata2) { sb.Append("ATA-2 "); maxatalevel = 2; - if(minatalevel > 2) minatalevel = 2; + + if(minatalevel > 2) + minatalevel = 2; } if(ata3) { sb.Append("ATA-3 "); maxatalevel = 3; - if(minatalevel > 3) minatalevel = 3; + + if(minatalevel > 3) + minatalevel = 3; } if(ata4) { sb.Append("ATA/ATAPI-4 "); maxatalevel = 4; - if(minatalevel > 4) minatalevel = 4; + + if(minatalevel > 4) + minatalevel = 4; } if(ata5) { sb.Append("ATA/ATAPI-5 "); maxatalevel = 5; - if(minatalevel > 5) minatalevel = 5; + + if(minatalevel > 5) + minatalevel = 5; } if(ata6) { sb.Append("ATA/ATAPI-6 "); maxatalevel = 6; - if(minatalevel > 6) minatalevel = 6; + + if(minatalevel > 6) + minatalevel = 6; } if(ata7) { sb.Append("ATA/ATAPI-7 "); maxatalevel = 7; - if(minatalevel > 7) minatalevel = 7; + + if(minatalevel > 7) + minatalevel = 7; } if(acs) { sb.Append("ATA8-ACS "); maxatalevel = 8; - if(minatalevel > 8) minatalevel = 8; + + if(minatalevel > 8) + minatalevel = 8; } if(acs2) { sb.Append("ATA8-ACS2 "); maxatalevel = 9; - if(minatalevel > 9) minatalevel = 9; + + if(minatalevel > 9) + minatalevel = 9; } if(acs3) { sb.Append("ATA8-ACS3 "); maxatalevel = 10; - if(minatalevel > 10) minatalevel = 10; + + if(minatalevel > 10) + minatalevel = 10; } if(acs4) { sb.Append("ATA8-ACS4 "); maxatalevel = 11; - if(minatalevel > 11) minatalevel = 11; + + if(minatalevel > 11) + minatalevel = 11; } sb.AppendLine(); sb.Append("Maximum ATA revision supported: "); + if(maxatalevel >= 3) switch(ATAID.MinorVersion) { case 0x0000: case 0xFFFF: sb.AppendLine("Minor ATA version not specified"); + break; case 0x0001: sb.AppendLine("ATA (ATA-1) X3T9.2 781D prior to revision 4"); + break; case 0x0002: sb.AppendLine("ATA-1 published, ANSI X3.221-1994"); + break; case 0x0003: sb.AppendLine("ATA (ATA-1) X3T9.2 781D revision 4"); + break; case 0x0004: sb.AppendLine("ATA-2 published, ANSI X3.279-1996"); + break; case 0x0005: sb.AppendLine("ATA-2 X3T10 948D prior to revision 2k"); + break; case 0x0006: sb.AppendLine("ATA-3 X3T10 2008D revision 1"); + break; case 0x0007: sb.AppendLine("ATA-2 X3T10 948D revision 2k"); + break; case 0x0008: sb.AppendLine("ATA-3 X3T10 2008D revision 0"); + break; case 0x0009: sb.AppendLine("ATA-2 X3T10 948D revision 3"); + break; case 0x000A: sb.AppendLine("ATA-3 published, ANSI X3.298-1997"); + break; case 0x000B: sb.AppendLine("ATA-3 X3T10 2008D revision 6"); + break; case 0x000C: sb.AppendLine("ATA-3 X3T13 2008D revision 7"); + break; case 0x000D: sb.AppendLine("ATA/ATAPI-4 X3T13 1153D revision 6"); + break; case 0x000E: sb.AppendLine("ATA/ATAPI-4 T13 1153D revision 13"); + break; case 0x000F: sb.AppendLine("ATA/ATAPI-4 X3T13 1153D revision 7"); + break; case 0x0010: sb.AppendLine("ATA/ATAPI-4 T13 1153D revision 18"); + break; case 0x0011: sb.AppendLine("ATA/ATAPI-4 T13 1153D revision 15"); + break; case 0x0012: sb.AppendLine("ATA/ATAPI-4 published, ANSI INCITS 317-1998"); + break; case 0x0013: sb.AppendLine("ATA/ATAPI-5 T13 1321D revision 3"); + break; case 0x0014: sb.AppendLine("ATA/ATAPI-4 T13 1153D revision 14"); + break; case 0x0015: sb.AppendLine("ATA/ATAPI-5 T13 1321D revision 1"); + break; case 0x0016: sb.AppendLine("ATA/ATAPI-5 published, ANSI INCITS 340-2000"); + break; case 0x0017: sb.AppendLine("ATA/ATAPI-4 T13 1153D revision 17"); + break; case 0x0018: sb.AppendLine("ATA/ATAPI-6 T13 1410D revision 0"); + break; case 0x0019: sb.AppendLine("ATA/ATAPI-6 T13 1410D revision 3a"); + break; case 0x001A: sb.AppendLine("ATA/ATAPI-7 T13 1532D revision 1"); + break; case 0x001B: sb.AppendLine("ATA/ATAPI-6 T13 1410D revision 2"); + break; case 0x001C: sb.AppendLine("ATA/ATAPI-6 T13 1410D revision 1"); + break; case 0x001D: sb.AppendLine("ATA/ATAPI-7 published ANSI INCITS 397-2005"); + break; case 0x001E: sb.AppendLine("ATA/ATAPI-7 T13 1532D revision 0"); + break; case 0x001F: sb.AppendLine("ACS-3 Revision 3b"); + break; case 0x0021: sb.AppendLine("ATA/ATAPI-7 T13 1532D revision 4a"); + break; case 0x0022: sb.AppendLine("ATA/ATAPI-6 published, ANSI INCITS 361-2002"); + break; case 0x0027: sb.AppendLine("ATA8-ACS revision 3c"); + break; case 0x0028: sb.AppendLine("ATA8-ACS revision 6"); + break; case 0x0029: sb.AppendLine("ATA8-ACS revision 4"); + break; case 0x0031: sb.AppendLine("ACS-2 Revision 2"); + break; case 0x0033: sb.AppendLine("ATA8-ACS Revision 3e"); + break; case 0x0039: sb.AppendLine("ATA8-ACS Revision 4c"); + break; case 0x0042: sb.AppendLine("ATA8-ACS Revision 3f"); + break; case 0x0052: sb.AppendLine("ATA8-ACS revision 3b"); + break; case 0x006D: sb.AppendLine("ACS-3 Revision 5"); + break; case 0x0082: sb.AppendLine("ACS-2 published, ANSI INCITS 482-2012"); + break; case 0x0107: sb.AppendLine("ATA8-ACS revision 2d"); + break; case 0x0110: sb.AppendLine("ACS-2 Revision 3"); + break; case 0x011B: sb.AppendLine("ACS-3 Revision 4"); + break; default: sb.AppendFormat("Unknown ATA revision 0x{0:X4}", ATAID.MinorVersion).AppendLine(); + break; } @@ -2242,27 +887,51 @@ namespace DiscImageChef.Decoders.ATA { case 0x0: sb.Append("Parallel ATA device: "); - if((ATAID.TransportMajorVersion & 0x0002) == 0x0002) sb.Append("ATA/ATAPI-7 "); - if((ATAID.TransportMajorVersion & 0x0001) == 0x0001) sb.Append("ATA8-APT "); + + if((ATAID.TransportMajorVersion & 0x0002) == 0x0002) + sb.Append("ATA/ATAPI-7 "); + + if((ATAID.TransportMajorVersion & 0x0001) == 0x0001) + sb.Append("ATA8-APT "); + sb.AppendLine(); + break; case 0x1: sb.Append("Serial ATA device: "); - if((ATAID.TransportMajorVersion & 0x0001) == 0x0001) sb.Append("ATA8-AST "); - if((ATAID.TransportMajorVersion & 0x0002) == 0x0002) sb.Append("SATA 1.0a "); - if((ATAID.TransportMajorVersion & 0x0004) == 0x0004) sb.Append("SATA II Extensions "); - if((ATAID.TransportMajorVersion & 0x0008) == 0x0008) sb.Append("SATA 2.5 "); - if((ATAID.TransportMajorVersion & 0x0010) == 0x0010) sb.Append("SATA 2.6 "); - if((ATAID.TransportMajorVersion & 0x0020) == 0x0020) sb.Append("SATA 3.0 "); - if((ATAID.TransportMajorVersion & 0x0040) == 0x0040) sb.Append("SATA 3.1 "); + + if((ATAID.TransportMajorVersion & 0x0001) == 0x0001) + sb.Append("ATA8-AST "); + + if((ATAID.TransportMajorVersion & 0x0002) == 0x0002) + sb.Append("SATA 1.0a "); + + if((ATAID.TransportMajorVersion & 0x0004) == 0x0004) + sb.Append("SATA II Extensions "); + + if((ATAID.TransportMajorVersion & 0x0008) == 0x0008) + sb.Append("SATA 2.5 "); + + if((ATAID.TransportMajorVersion & 0x0010) == 0x0010) + sb.Append("SATA 2.6 "); + + if((ATAID.TransportMajorVersion & 0x0020) == 0x0020) + sb.Append("SATA 3.0 "); + + if((ATAID.TransportMajorVersion & 0x0040) == 0x0040) + sb.Append("SATA 3.1 "); + sb.AppendLine(); + break; case 0xE: sb.AppendLine("SATA Express device"); + break; default: - sb.AppendFormat("Unknown transport type 0x{0:X1}", (ATAID.TransportMajorVersion & 0xF000) >> 12) - .AppendLine(); + sb.AppendFormat("Unknown transport type 0x{0:X1}", (ATAID.TransportMajorVersion & 0xF000) >> 12). + AppendLine(); + break; } @@ -2273,70 +942,92 @@ namespace DiscImageChef.Decoders.ATA { case PeripheralDeviceTypes.DirectAccess: //0x00, sb.AppendLine("ATAPI Direct-access device"); + break; case PeripheralDeviceTypes.SequentialAccess: //0x01, sb.AppendLine("ATAPI Sequential-access device"); + break; case PeripheralDeviceTypes.PrinterDevice: //0x02, sb.AppendLine("ATAPI Printer device"); + break; case PeripheralDeviceTypes.ProcessorDevice: //0x03, sb.AppendLine("ATAPI Processor device"); + break; case PeripheralDeviceTypes.WriteOnceDevice: //0x04, sb.AppendLine("ATAPI Write-once device"); + break; case PeripheralDeviceTypes.MultiMediaDevice: //0x05, sb.AppendLine("ATAPI CD-ROM/DVD/etc device"); + break; case PeripheralDeviceTypes.ScannerDevice: //0x06, sb.AppendLine("ATAPI Scanner device"); + break; case PeripheralDeviceTypes.OpticalDevice: //0x07, sb.AppendLine("ATAPI Optical memory device"); + break; case PeripheralDeviceTypes.MediumChangerDevice: //0x08, sb.AppendLine("ATAPI Medium change device"); + break; case PeripheralDeviceTypes.CommsDevice: //0x09, sb.AppendLine("ATAPI Communications device"); + break; case PeripheralDeviceTypes.PrePressDevice1: //0x0A, sb.AppendLine("ATAPI Graphics arts pre-press device (defined in ASC IT8)"); + break; case PeripheralDeviceTypes.PrePressDevice2: //0x0B, sb.AppendLine("ATAPI Graphics arts pre-press device (defined in ASC IT8)"); + break; case PeripheralDeviceTypes.ArrayControllerDevice: //0x0C, sb.AppendLine("ATAPI Array controller device"); + break; case PeripheralDeviceTypes.EnclosureServiceDevice: //0x0D, sb.AppendLine("ATAPI Enclosure services device"); + break; case PeripheralDeviceTypes.SimplifiedDevice: //0x0E, sb.AppendLine("ATAPI Simplified direct-access device"); + break; case PeripheralDeviceTypes.OCRWDevice: //0x0F, sb.AppendLine("ATAPI Optical card reader/writer device"); + break; case PeripheralDeviceTypes.BridgingExpander: //0x10, sb.AppendLine("ATAPI Bridging Expanders"); + break; case PeripheralDeviceTypes.ObjectDevice: //0x11, sb.AppendLine("ATAPI Object-based Storage Device"); + break; case PeripheralDeviceTypes.ADCDevice: //0x12, sb.AppendLine("ATAPI Automation/Drive Interface"); + break; case PeripheralDeviceTypes.WellKnownDevice: //0x1E, sb.AppendLine("ATAPI Well known logical unit"); + break; case PeripheralDeviceTypes.UnknownDevice: //0x1F sb.AppendLine("ATAPI Unknown or no device type"); + break; default: sb.AppendFormat("ATAPI Unknown device type field value 0x{0:X2}", ((ushort)ATAID.GeneralConfiguration & 0x1F00) >> 8).AppendLine(); + break; } @@ -2345,16 +1036,20 @@ namespace DiscImageChef.Decoders.ATA { case 0: sb.AppendLine("Device shall set DRQ within 3 ms of receiving PACKET"); + break; case 1: sb.AppendLine("Device shall assert INTRQ when DRQ is set to one"); + break; case 2: sb.AppendLine("Device shall set DRQ within 50 µs of receiving PACKET"); + break; default: sb.AppendFormat("Unknown ATAPI DRQ behaviour code {0}", ((ushort)ATAID.GeneralConfiguration & 0x60) >> 5).AppendLine(); + break; } @@ -2363,13 +1058,16 @@ namespace DiscImageChef.Decoders.ATA { case 0: sb.AppendLine("ATAPI device uses 12 byte command packet"); + break; case 1: sb.AppendLine("ATAPI device uses 16 byte command packet"); + break; default: - sb.AppendFormat("Unknown ATAPI packet size code {0}", (ushort)ATAID.GeneralConfiguration & 0x03) - .AppendLine(); + sb.AppendFormat("Unknown ATAPI packet size code {0}", + (ushort)ATAID.GeneralConfiguration & 0x03).AppendLine(); + break; } } @@ -2378,6 +1076,7 @@ namespace DiscImageChef.Decoders.ATA if(minatalevel >= 5) if(ATAID.GeneralConfiguration.HasFlag(GeneralConfigurationBit.IncompleteResponse)) sb.AppendLine("Incomplete identify response"); + if(ATAID.GeneralConfiguration.HasFlag(GeneralConfigurationBit.NonMagnetic)) sb.AppendLine("Device uses non-magnetic media"); @@ -2392,54 +1091,71 @@ namespace DiscImageChef.Decoders.ATA { if(ATAID.GeneralConfiguration.HasFlag(GeneralConfigurationBit.SlowIDE)) sb.AppendLine("Device transfer rate is <= 5 Mb/s"); + if(ATAID.GeneralConfiguration.HasFlag(GeneralConfigurationBit.FastIDE)) sb.AppendLine("Device transfer rate is > 5 Mb/s but <= 10 Mb/s"); + if(ATAID.GeneralConfiguration.HasFlag(GeneralConfigurationBit.UltraFastIDE)) sb.AppendLine("Device transfer rate is > 10 Mb/s"); + if(ATAID.GeneralConfiguration.HasFlag(GeneralConfigurationBit.SoftSector)) sb.AppendLine("Device is soft sectored"); + if(ATAID.GeneralConfiguration.HasFlag(GeneralConfigurationBit.HardSector)) sb.AppendLine("Device is hard sectored"); + if(ATAID.GeneralConfiguration.HasFlag(GeneralConfigurationBit.NotMFM)) sb.AppendLine("Device is not MFM encoded"); + if(ATAID.GeneralConfiguration.HasFlag(GeneralConfigurationBit.FormatGapReq)) sb.AppendLine("Format speed tolerance gap is required"); + if(ATAID.GeneralConfiguration.HasFlag(GeneralConfigurationBit.TrackOffset)) sb.AppendLine("Track offset option is available"); + if(ATAID.GeneralConfiguration.HasFlag(GeneralConfigurationBit.DataStrobeOffset)) sb.AppendLine("Data strobe offset option is available"); + if(ATAID.GeneralConfiguration.HasFlag(GeneralConfigurationBit.RotationalSpeedTolerance)) sb.AppendLine("Rotational speed tolerance is higher than 0,5%"); + if(ATAID.GeneralConfiguration.HasFlag(GeneralConfigurationBit.SpindleControl)) sb.AppendLine("Spindle motor control is implemented"); + if(ATAID.GeneralConfiguration.HasFlag(GeneralConfigurationBit.HighHeadSwitch)) sb.AppendLine("Head switch time is bigger than 15 µs."); } } - if(ATAID.NominalRotationRate != 0x0000 && ATAID.NominalRotationRate != 0xFFFF) + if(ATAID.NominalRotationRate != 0x0000 && + ATAID.NominalRotationRate != 0xFFFF) if(ATAID.NominalRotationRate == 0x0001) sb.AppendLine("Device does not rotate."); else sb.AppendFormat("Device rotate at {0} rpm", ATAID.NominalRotationRate).AppendLine(); uint logicalsectorsize = 0; + if(!atapi) { uint physicalsectorsize; - if((ATAID.PhysLogSectorSize & 0x8000) == 0x0000 && (ATAID.PhysLogSectorSize & 0x4000) == 0x4000) + if((ATAID.PhysLogSectorSize & 0x8000) == 0x0000 && + (ATAID.PhysLogSectorSize & 0x4000) == 0x4000) { if((ATAID.PhysLogSectorSize & 0x1000) == 0x1000) - if(ATAID.LogicalSectorWords <= 255 || ATAID.LogicalAlignment == 0xFFFF) + if(ATAID.LogicalSectorWords <= 255 || + ATAID.LogicalAlignment == 0xFFFF) logicalsectorsize = 512; else logicalsectorsize = ATAID.LogicalSectorWords * 2; - else logicalsectorsize = 512; + else + logicalsectorsize = 512; if((ATAID.PhysLogSectorSize & 0x2000) == 0x2000) - physicalsectorsize = logicalsectorsize * (uint)Math.Pow(2, ATAID.PhysLogSectorSize & 0xF); - else physicalsectorsize = logicalsectorsize; + physicalsectorsize = logicalsectorsize * (uint)Math.Pow(2, ATAID.PhysLogSectorSize & 0xF); + else + physicalsectorsize = logicalsectorsize; } else { @@ -2450,28 +1166,35 @@ namespace DiscImageChef.Decoders.ATA sb.AppendFormat("Physical sector size: {0} bytes", physicalsectorsize).AppendLine(); sb.AppendFormat("Logical sector size: {0} bytes", logicalsectorsize).AppendLine(); - if(logicalsectorsize != physicalsectorsize && (ATAID.LogicalAlignment & 0x8000) == 0x0000 && - (ATAID.LogicalAlignment & 0x4000) == 0x4000) + if(logicalsectorsize != physicalsectorsize && + (ATAID.LogicalAlignment & 0x8000) == 0x0000 && + (ATAID.LogicalAlignment & 0x4000) == 0x4000) sb.AppendFormat("Logical sector starts at offset {0} from physical sector", ATAID.LogicalAlignment & 0x3FFF).AppendLine(); if(minatalevel <= 5) - if(ATAID.CurrentCylinders > 0 && ATAID.CurrentHeads > 0 && ATAID.CurrentSectorsPerTrack > 0) + if(ATAID.CurrentCylinders > 0 && + ATAID.CurrentHeads > 0 && + ATAID.CurrentSectorsPerTrack > 0) { - sb.AppendFormat("Cylinders: {0} max., {1} current", ATAID.Cylinders, ATAID.CurrentCylinders) - .AppendLine(); + sb.AppendFormat("Cylinders: {0} max., {1} current", ATAID.Cylinders, ATAID.CurrentCylinders). + AppendLine(); + sb.AppendFormat("Heads: {0} max., {1} current", ATAID.Heads, ATAID.CurrentHeads).AppendLine(); + sb.AppendFormat("Sectors per track: {0} max., {1} current", ATAID.SectorsPerTrack, ATAID.CurrentSectorsPerTrack).AppendLine(); + sb.AppendFormat("Sectors addressable in CHS mode: {0} max., {1} current", - ATAID.Cylinders * ATAID.Heads * ATAID.SectorsPerTrack, ATAID.CurrentSectors) - .AppendLine(); + ATAID.Cylinders * ATAID.Heads * ATAID.SectorsPerTrack, ATAID.CurrentSectors). + AppendLine(); } else { sb.AppendFormat("Cylinders: {0}", ATAID.Cylinders).AppendLine(); sb.AppendFormat("Heads: {0}", ATAID.Heads).AppendLine(); sb.AppendFormat("Sectors per track: {0}", ATAID.SectorsPerTrack).AppendLine(); + sb.AppendFormat("Sectors addressable in CHS mode: {0}", ATAID.Cylinders * ATAID.Heads * ATAID.SectorsPerTrack).AppendLine(); } @@ -2491,6 +1214,7 @@ namespace DiscImageChef.Decoders.ATA else { ulong currentSectors = (ulong)(ATAID.Cylinders * ATAID.Heads * ATAID.SectorsPerTrack); + sb.AppendFormat("Device size in CHS mode: {0} bytes, {1} Mb, {2} MiB", currentSectors * logicalsectorsize, currentSectors * logicalsectorsize / 1000 / 1000, @@ -2503,8 +1227,8 @@ namespace DiscImageChef.Decoders.ATA (ulong)ATAID.LBASectors * logicalsectorsize, (ulong)ATAID.LBASectors * logicalsectorsize / 1000 / 1000 / 1000 / 1000, - (ulong)ATAID.LBASectors * 512 / 1024 / 1024 / 1024 / 1024) - .AppendLine(); + (ulong)ATAID.LBASectors * 512 / 1024 / 1024 / 1024 / 1024). + AppendLine(); else if((ulong)ATAID.LBASectors * logicalsectorsize / 1024 / 1024 > 1000) sb.AppendFormat("Device size in 28-bit LBA mode: {0} bytes, {1} Gb, {2} GiB", (ulong)ATAID.LBASectors * logicalsectorsize, @@ -2523,15 +1247,15 @@ namespace DiscImageChef.Decoders.ATA ATAID.ExtendedUserSectors * logicalsectorsize, ATAID.ExtendedUserSectors * logicalsectorsize / 1000 / 1000 / 1000 / 1000, - ATAID.ExtendedUserSectors * logicalsectorsize / 1024 / 1024 / 1024 / 1024) - .AppendLine(); + ATAID.ExtendedUserSectors * logicalsectorsize / 1024 / 1024 / 1024 / 1024). + AppendLine(); else if(ATAID.ExtendedUserSectors * logicalsectorsize / 1024 / 1024 > 1000) sb.AppendFormat("Device size in 48-bit LBA mode: {0} bytes, {1} Gb, {2} GiB", ATAID.ExtendedUserSectors * logicalsectorsize, ATAID.ExtendedUserSectors * logicalsectorsize / 1000 / 1000 / 1000, - ATAID.ExtendedUserSectors * logicalsectorsize / 1024 / 1024 / 1024) - .AppendLine(); + ATAID.ExtendedUserSectors * logicalsectorsize / 1024 / 1024 / 1024). + AppendLine(); else sb.AppendFormat("Device size in 48-bit LBA mode: {0} bytes, {1} Mb, {2} MiB", ATAID.ExtendedUserSectors * logicalsectorsize, @@ -2544,8 +1268,8 @@ namespace DiscImageChef.Decoders.ATA ATAID.LBA48Sectors * logicalsectorsize, ATAID.LBA48Sectors * logicalsectorsize / 1000 / 1000 / 1000 / 1000, - ATAID.LBA48Sectors * logicalsectorsize / 1024 / 1024 / 1024 / 1024) - .AppendLine(); + ATAID.LBA48Sectors * logicalsectorsize / 1024 / 1024 / 1024 / 1024). + AppendLine(); else if(ATAID.LBA48Sectors * logicalsectorsize / 1024 / 1024 > 1000) sb.AppendFormat("Device size in 48-bit LBA mode: {0} bytes, {1} Gb, {2} GiB", ATAID.LBA48Sectors * logicalsectorsize, @@ -2560,73 +1284,94 @@ namespace DiscImageChef.Decoders.ATA if(ata1 || cfa) { - if(cfa) sb.AppendFormat("{0} sectors in card", ATAID.SectorsPerCard).AppendLine(); + if(cfa) + sb.AppendFormat("{0} sectors in card", ATAID.SectorsPerCard).AppendLine(); + if(ATAID.UnformattedBPT > 0) sb.AppendFormat("{0} bytes per unformatted track", ATAID.UnformattedBPT).AppendLine(); + if(ATAID.UnformattedBPS > 0) sb.AppendFormat("{0} bytes per unformatted sector", ATAID.UnformattedBPS).AppendLine(); } } - if((ushort)ATAID.SpecificConfiguration != 0x0000 && (ushort)ATAID.SpecificConfiguration != 0xFFFF) + if((ushort)ATAID.SpecificConfiguration != 0x0000 && + (ushort)ATAID.SpecificConfiguration != 0xFFFF) switch(ATAID.SpecificConfiguration) { case SpecificConfigurationEnum.RequiresSetIncompleteResponse: sb.AppendLine("Device requires SET FEATURES to spin up and IDENTIFY DEVICE response is incomplete."); + break; case SpecificConfigurationEnum.RequiresSetCompleteResponse: sb.AppendLine("Device requires SET FEATURES to spin up and IDENTIFY DEVICE response is complete."); + break; case SpecificConfigurationEnum.NotRequiresSetIncompleteResponse: sb.AppendLine("Device does not require SET FEATURES to spin up and IDENTIFY DEVICE response is incomplete."); + break; case SpecificConfigurationEnum.NotRequiresSetCompleteResponse: sb.AppendLine("Device does not require SET FEATURES to spin up and IDENTIFY DEVICE response is complete."); + break; default: sb.AppendFormat("Unknown device specific configuration 0x{0:X4}", (ushort)ATAID.SpecificConfiguration).AppendLine(); + break; } // Obsolete since ATA-2, however, it is yet used in ATA-8 devices - if(ATAID.BufferSize != 0x0000 && ATAID.BufferSize != 0xFFFF && ATAID.BufferType != 0x0000 && + if(ATAID.BufferSize != 0x0000 && + ATAID.BufferSize != 0xFFFF && + ATAID.BufferType != 0x0000 && ATAID.BufferType != 0xFFFF) switch(ATAID.BufferType) { case 1: - sb.AppendFormat("{0} KiB of single ported single sector buffer", ATAID.BufferSize * 512 / 1024) - .AppendLine(); + sb.AppendFormat("{0} KiB of single ported single sector buffer", ATAID.BufferSize * 512 / 1024). + AppendLine(); + break; case 2: - sb.AppendFormat("{0} KiB of dual ported multi sector buffer", ATAID.BufferSize * 512 / 1024) - .AppendLine(); + sb.AppendFormat("{0} KiB of dual ported multi sector buffer", ATAID.BufferSize * 512 / 1024). + AppendLine(); + break; case 3: sb.AppendFormat("{0} KiB of dual ported multi sector buffer with read caching", ATAID.BufferSize * 512 / 1024).AppendLine(); + break; default: sb.AppendFormat("{0} KiB of unknown type {1} buffer", ATAID.BufferSize * 512 / 1024, ATAID.BufferType).AppendLine(); + break; } - if(ATAID.EccBytes != 0x0000 && ATAID.EccBytes != 0xFFFF) + if(ATAID.EccBytes != 0x0000 && + ATAID.EccBytes != 0xFFFF) sb.AppendFormat("READ/WRITE LONG has {0} extra bytes", ATAID.EccBytes).AppendLine(); sb.AppendLine(); sb.Append("Device capabilities:"); + if(ATAID.Capabilities.HasFlag(CapabilitiesBit.StandardStanbyTimer)) sb.AppendLine().Append("Standby time values are standard"); + if(ATAID.Capabilities.HasFlag(CapabilitiesBit.IORDY)) { sb.AppendLine().Append("IORDY is supported"); - if(ATAID.Capabilities.HasFlag(CapabilitiesBit.CanDisableIORDY)) sb.Append(" and can be disabled"); + + if(ATAID.Capabilities.HasFlag(CapabilitiesBit.CanDisableIORDY)) + sb.Append(" and can be disabled"); } - if(ATAID.Capabilities.HasFlag(CapabilitiesBit.DMASupport)) sb.AppendLine().Append("DMA is supported"); + if(ATAID.Capabilities.HasFlag(CapabilitiesBit.DMASupport)) + sb.AppendLine().Append("DMA is supported"); if(ATAID.Capabilities2.HasFlag(CapabilitiesBit2.MustBeSet) && !ATAID.Capabilities2.HasFlag(CapabilitiesBit2.MustBeClear)) @@ -2635,9 +1380,10 @@ namespace DiscImageChef.Decoders.ATA if(ATAID.Capabilities3.HasFlag(CapabilitiesBit3.MultipleValid)) { - sb.AppendLine() - .AppendFormat("A maximum of {0} sectors can be transferred per interrupt on READ/WRITE MULTIPLE", + sb.AppendLine(). + AppendFormat("A maximum of {0} sectors can be transferred per interrupt on READ/WRITE MULTIPLE", ATAID.MultipleSectorNumber); + sb.AppendLine().AppendFormat("Device supports setting a maximum of {0} sectors", ATAID.MultipleMaxSectors); } @@ -2655,10 +1401,13 @@ namespace DiscImageChef.Decoders.ATA { if(ATAID.Capabilities.HasFlag(CapabilitiesBit.InterleavedDMA)) sb.AppendLine().Append("ATAPI device supports interleaved DMA"); + if(ATAID.Capabilities.HasFlag(CapabilitiesBit.CommandQueue)) sb.AppendLine().Append("ATAPI device supports command queueing"); + if(ATAID.Capabilities.HasFlag(CapabilitiesBit.OverlapOperation)) sb.AppendLine().Append("ATAPI device supports overlapped operations"); + if(ATAID.Capabilities.HasFlag(CapabilitiesBit.RequiresATASoftReset)) sb.AppendLine().Append("ATAPI device requires ATA software reset"); } @@ -2670,176 +1419,247 @@ namespace DiscImageChef.Decoders.ATA } sb.AppendLine().Append("Advanced PIO: "); - if(ATAID.APIOSupported.HasFlag(TransferMode.Mode0)) sb.Append("PIO0 "); - if(ATAID.APIOSupported.HasFlag(TransferMode.Mode1)) sb.Append("PIO1 "); - if(ATAID.APIOSupported.HasFlag(TransferMode.Mode2)) sb.Append("PIO2 "); - if(ATAID.APIOSupported.HasFlag(TransferMode.Mode3)) sb.Append("PIO3 "); - if(ATAID.APIOSupported.HasFlag(TransferMode.Mode4)) sb.Append("PIO4 "); - if(ATAID.APIOSupported.HasFlag(TransferMode.Mode5)) sb.Append("PIO5 "); - if(ATAID.APIOSupported.HasFlag(TransferMode.Mode6)) sb.Append("PIO6 "); - if(ATAID.APIOSupported.HasFlag(TransferMode.Mode7)) sb.Append("PIO7 "); - if(minatalevel <= 3 && !atapi) + if(ATAID.APIOSupported.HasFlag(TransferMode.Mode0)) + sb.Append("PIO0 "); + + if(ATAID.APIOSupported.HasFlag(TransferMode.Mode1)) + sb.Append("PIO1 "); + + if(ATAID.APIOSupported.HasFlag(TransferMode.Mode2)) + sb.Append("PIO2 "); + + if(ATAID.APIOSupported.HasFlag(TransferMode.Mode3)) + sb.Append("PIO3 "); + + if(ATAID.APIOSupported.HasFlag(TransferMode.Mode4)) + sb.Append("PIO4 "); + + if(ATAID.APIOSupported.HasFlag(TransferMode.Mode5)) + sb.Append("PIO5 "); + + if(ATAID.APIOSupported.HasFlag(TransferMode.Mode6)) + sb.Append("PIO6 "); + + if(ATAID.APIOSupported.HasFlag(TransferMode.Mode7)) + sb.Append("PIO7 "); + + if(minatalevel <= 3 && + !atapi) { sb.AppendLine().Append("Single-word DMA: "); + if(ATAID.DMASupported.HasFlag(TransferMode.Mode0)) { sb.Append("DMA0 "); - if(ATAID.DMAActive.HasFlag(TransferMode.Mode0)) sb.Append("(active) "); + + if(ATAID.DMAActive.HasFlag(TransferMode.Mode0)) + sb.Append("(active) "); } if(ATAID.DMASupported.HasFlag(TransferMode.Mode1)) { sb.Append("DMA1 "); - if(ATAID.DMAActive.HasFlag(TransferMode.Mode1)) sb.Append("(active) "); + + if(ATAID.DMAActive.HasFlag(TransferMode.Mode1)) + sb.Append("(active) "); } if(ATAID.DMASupported.HasFlag(TransferMode.Mode2)) { sb.Append("DMA2 "); - if(ATAID.DMAActive.HasFlag(TransferMode.Mode2)) sb.Append("(active) "); + + if(ATAID.DMAActive.HasFlag(TransferMode.Mode2)) + sb.Append("(active) "); } if(ATAID.DMASupported.HasFlag(TransferMode.Mode3)) { sb.Append("DMA3 "); - if(ATAID.DMAActive.HasFlag(TransferMode.Mode3)) sb.Append("(active) "); + + if(ATAID.DMAActive.HasFlag(TransferMode.Mode3)) + sb.Append("(active) "); } if(ATAID.DMASupported.HasFlag(TransferMode.Mode4)) { sb.Append("DMA4 "); - if(ATAID.DMAActive.HasFlag(TransferMode.Mode4)) sb.Append("(active) "); + + if(ATAID.DMAActive.HasFlag(TransferMode.Mode4)) + sb.Append("(active) "); } if(ATAID.DMASupported.HasFlag(TransferMode.Mode5)) { sb.Append("DMA5 "); - if(ATAID.DMAActive.HasFlag(TransferMode.Mode5)) sb.Append("(active) "); + + if(ATAID.DMAActive.HasFlag(TransferMode.Mode5)) + sb.Append("(active) "); } if(ATAID.DMASupported.HasFlag(TransferMode.Mode6)) { sb.Append("DMA6 "); - if(ATAID.DMAActive.HasFlag(TransferMode.Mode6)) sb.Append("(active) "); + + if(ATAID.DMAActive.HasFlag(TransferMode.Mode6)) + sb.Append("(active) "); } if(ATAID.DMASupported.HasFlag(TransferMode.Mode7)) { sb.Append("DMA7 "); - if(ATAID.DMAActive.HasFlag(TransferMode.Mode7)) sb.Append("(active) "); + + if(ATAID.DMAActive.HasFlag(TransferMode.Mode7)) + sb.Append("(active) "); } } sb.AppendLine().Append("Multi-word DMA: "); + if(ATAID.MDMASupported.HasFlag(TransferMode.Mode0)) { sb.Append("MDMA0 "); - if(ATAID.MDMAActive.HasFlag(TransferMode.Mode0)) sb.Append("(active) "); + + if(ATAID.MDMAActive.HasFlag(TransferMode.Mode0)) + sb.Append("(active) "); } if(ATAID.MDMASupported.HasFlag(TransferMode.Mode1)) { sb.Append("MDMA1 "); - if(ATAID.MDMAActive.HasFlag(TransferMode.Mode1)) sb.Append("(active) "); + + if(ATAID.MDMAActive.HasFlag(TransferMode.Mode1)) + sb.Append("(active) "); } if(ATAID.MDMASupported.HasFlag(TransferMode.Mode2)) { sb.Append("MDMA2 "); - if(ATAID.MDMAActive.HasFlag(TransferMode.Mode2)) sb.Append("(active) "); + + if(ATAID.MDMAActive.HasFlag(TransferMode.Mode2)) + sb.Append("(active) "); } if(ATAID.MDMASupported.HasFlag(TransferMode.Mode3)) { sb.Append("MDMA3 "); - if(ATAID.MDMAActive.HasFlag(TransferMode.Mode3)) sb.Append("(active) "); + + if(ATAID.MDMAActive.HasFlag(TransferMode.Mode3)) + sb.Append("(active) "); } if(ATAID.MDMASupported.HasFlag(TransferMode.Mode4)) { sb.Append("MDMA4 "); - if(ATAID.MDMAActive.HasFlag(TransferMode.Mode4)) sb.Append("(active) "); + + if(ATAID.MDMAActive.HasFlag(TransferMode.Mode4)) + sb.Append("(active) "); } if(ATAID.MDMASupported.HasFlag(TransferMode.Mode5)) { sb.Append("MDMA5 "); - if(ATAID.MDMAActive.HasFlag(TransferMode.Mode5)) sb.Append("(active) "); + + if(ATAID.MDMAActive.HasFlag(TransferMode.Mode5)) + sb.Append("(active) "); } if(ATAID.MDMASupported.HasFlag(TransferMode.Mode6)) { sb.Append("MDMA6 "); - if(ATAID.MDMAActive.HasFlag(TransferMode.Mode6)) sb.Append("(active) "); + + if(ATAID.MDMAActive.HasFlag(TransferMode.Mode6)) + sb.Append("(active) "); } if(ATAID.MDMASupported.HasFlag(TransferMode.Mode7)) { sb.Append("MDMA7 "); - if(ATAID.MDMAActive.HasFlag(TransferMode.Mode7)) sb.Append("(active) "); + + if(ATAID.MDMAActive.HasFlag(TransferMode.Mode7)) + sb.Append("(active) "); } sb.AppendLine().Append("Ultra DMA: "); + if(ATAID.UDMASupported.HasFlag(TransferMode.Mode0)) { sb.Append("UDMA0 "); - if(ATAID.UDMAActive.HasFlag(TransferMode.Mode0)) sb.Append("(active) "); + + if(ATAID.UDMAActive.HasFlag(TransferMode.Mode0)) + sb.Append("(active) "); } if(ATAID.UDMASupported.HasFlag(TransferMode.Mode1)) { sb.Append("UDMA1 "); - if(ATAID.UDMAActive.HasFlag(TransferMode.Mode1)) sb.Append("(active) "); + + if(ATAID.UDMAActive.HasFlag(TransferMode.Mode1)) + sb.Append("(active) "); } if(ATAID.UDMASupported.HasFlag(TransferMode.Mode2)) { sb.Append("UDMA2 "); - if(ATAID.UDMAActive.HasFlag(TransferMode.Mode2)) sb.Append("(active) "); + + if(ATAID.UDMAActive.HasFlag(TransferMode.Mode2)) + sb.Append("(active) "); } if(ATAID.UDMASupported.HasFlag(TransferMode.Mode3)) { sb.Append("UDMA3 "); - if(ATAID.UDMAActive.HasFlag(TransferMode.Mode3)) sb.Append("(active) "); + + if(ATAID.UDMAActive.HasFlag(TransferMode.Mode3)) + sb.Append("(active) "); } if(ATAID.UDMASupported.HasFlag(TransferMode.Mode4)) { sb.Append("UDMA4 "); - if(ATAID.UDMAActive.HasFlag(TransferMode.Mode4)) sb.Append("(active) "); + + if(ATAID.UDMAActive.HasFlag(TransferMode.Mode4)) + sb.Append("(active) "); } if(ATAID.UDMASupported.HasFlag(TransferMode.Mode5)) { sb.Append("UDMA5 "); - if(ATAID.UDMAActive.HasFlag(TransferMode.Mode5)) sb.Append("(active) "); + + if(ATAID.UDMAActive.HasFlag(TransferMode.Mode5)) + sb.Append("(active) "); } if(ATAID.UDMASupported.HasFlag(TransferMode.Mode6)) { sb.Append("UDMA6 "); - if(ATAID.UDMAActive.HasFlag(TransferMode.Mode6)) sb.Append("(active) "); + + if(ATAID.UDMAActive.HasFlag(TransferMode.Mode6)) + sb.Append("(active) "); } if(ATAID.UDMASupported.HasFlag(TransferMode.Mode7)) { sb.Append("UDMA7 "); - if(ATAID.UDMAActive.HasFlag(TransferMode.Mode7)) sb.Append("(active) "); + + if(ATAID.UDMAActive.HasFlag(TransferMode.Mode7)) + sb.Append("(active) "); } - if(ATAID.MinMDMACycleTime != 0 && ATAID.RecMDMACycleTime != 0) - sb.AppendLine() - .AppendFormat("At minimum {0} ns. transfer cycle time per word in MDMA, " + "{1} ns. recommended", + if(ATAID.MinMDMACycleTime != 0 && + ATAID.RecMDMACycleTime != 0) + sb.AppendLine(). + AppendFormat("At minimum {0} ns. transfer cycle time per word in MDMA, " + "{1} ns. recommended", ATAID.MinMDMACycleTime, ATAID.RecMDMACycleTime); + if(ATAID.MinPIOCycleTimeNoFlow != 0) - sb.AppendLine() - .AppendFormat("At minimum {0} ns. transfer cycle time per word in PIO, " + "without flow control", + sb.AppendLine(). + AppendFormat("At minimum {0} ns. transfer cycle time per word in PIO, " + "without flow control", ATAID.MinPIOCycleTimeNoFlow); + if(ATAID.MinPIOCycleTimeFlow != 0) - sb.AppendLine() - .AppendFormat("At minimum {0} ns. transfer cycle time per word in PIO, " + "with IORDY flow control", + sb.AppendLine(). + AppendFormat("At minimum {0} ns. transfer cycle time per word in PIO, " + "with IORDY flow control", ATAID.MinPIOCycleTimeFlow); if(ATAID.MaxQueueDepth != 0) @@ -2850,6 +1670,7 @@ namespace DiscImageChef.Decoders.ATA if(ATAID.PacketBusRelease != 0) sb.AppendLine().AppendFormat("{0} ns. typical to release bus from receipt of PACKET", ATAID.PacketBusRelease); + if(ATAID.ServiceBusyClear != 0) sb.AppendLine().AppendFormat("{0} ns. typical to clear BSY bit from receipt of SERVICE", ATAID.ServiceBusyClear); @@ -2862,24 +1683,32 @@ namespace DiscImageChef.Decoders.ATA { if(ATAID.SATACapabilities.HasFlag(SATACapabilitiesBit.Gen1Speed)) sb.AppendLine().Append("SATA 1.5Gb/s is supported"); + if(ATAID.SATACapabilities.HasFlag(SATACapabilitiesBit.Gen2Speed)) sb.AppendLine().Append("SATA 3.0Gb/s is supported"); + if(ATAID.SATACapabilities.HasFlag(SATACapabilitiesBit.Gen3Speed)) sb.AppendLine().Append("SATA 6.0Gb/s is supported"); + if(ATAID.SATACapabilities.HasFlag(SATACapabilitiesBit.PowerReceipt)) sb.AppendLine().Append("Receipt of host initiated power management requests is supported"); + if(ATAID.SATACapabilities.HasFlag(SATACapabilitiesBit.PHYEventCounter)) sb.AppendLine().Append("PHY Event counters are supported"); + if(ATAID.SATACapabilities.HasFlag(SATACapabilitiesBit.HostSlumbTrans)) sb.AppendLine().Append("Supports host automatic partial to slumber transitions is supported"); + if(ATAID.SATACapabilities.HasFlag(SATACapabilitiesBit.DevSlumbTrans)) sb.AppendLine().Append("Supports device automatic partial to slumber transitions is supported"); + if(ATAID.SATACapabilities.HasFlag(SATACapabilitiesBit.NCQ)) { sb.AppendLine().Append("NCQ is supported"); if(ATAID.SATACapabilities.HasFlag(SATACapabilitiesBit.NCQPriority)) sb.AppendLine().Append("NCQ priority is supported"); + if(ATAID.SATACapabilities.HasFlag(SATACapabilitiesBit.UnloadNCQ)) sb.AppendLine().Append("Unload is supported with outstanding NCQ commands"); } @@ -2892,6 +1721,7 @@ namespace DiscImageChef.Decoders.ATA { if(ATAID.SATACapabilities2.HasFlag(SATACapabilitiesBit2.NCQMgmt)) sb.AppendLine().Append("NCQ queue management is supported"); + if(ATAID.SATACapabilities2.HasFlag(SATACapabilitiesBit2.NCQStream)) sb.AppendLine().Append("NCQ streaming is supported"); } @@ -2900,6 +1730,7 @@ namespace DiscImageChef.Decoders.ATA { if(ATAID.SATACapabilities2.HasFlag(SATACapabilitiesBit2.HostEnvDetect)) sb.AppendLine().Append("ATAPI device supports host environment detection"); + if(ATAID.SATACapabilities2.HasFlag(SATACapabilitiesBit2.DevAttSlimline)) sb.AppendLine().Append("ATAPI device supports attention on slimline connected devices"); } @@ -2908,31 +1739,39 @@ namespace DiscImageChef.Decoders.ATA } } - if(ATAID.InterseekDelay != 0x0000 && ATAID.InterseekDelay != 0xFFFF) + if(ATAID.InterseekDelay != 0x0000 && + ATAID.InterseekDelay != 0xFFFF) sb.AppendLine().AppendFormat("{0} microseconds of interseek delay for ISO-7779 accoustic testing", ATAID.InterseekDelay); - if((ushort)ATAID.DeviceFormFactor != 0x0000 && (ushort)ATAID.DeviceFormFactor != 0xFFFF) + if((ushort)ATAID.DeviceFormFactor != 0x0000 && + (ushort)ATAID.DeviceFormFactor != 0xFFFF) switch(ATAID.DeviceFormFactor) { case DeviceFormFactorEnum.FiveAndQuarter: sb.AppendLine().Append("Device nominal size is 5.25\""); + break; case DeviceFormFactorEnum.ThreeAndHalf: sb.AppendLine().Append("Device nominal size is 3.5\""); + break; case DeviceFormFactorEnum.TwoAndHalf: sb.AppendLine().Append("Device nominal size is 2.5\""); + break; case DeviceFormFactorEnum.OnePointEight: sb.AppendLine().Append("Device nominal size is 1.8\""); + break; case DeviceFormFactorEnum.LessThanOnePointEight: sb.AppendLine().Append("Device nominal size is smaller than 1.8\""); + break; default: sb.AppendLine().AppendFormat("Device nominal size field value {0} is unknown", ATAID.DeviceFormFactor); + break; } @@ -2944,8 +1783,10 @@ namespace DiscImageChef.Decoders.ATA if((ATAID.CFAPowerMode & 0x8000) == 0x8000) { sb.AppendLine().Append("CompactFlash device supports power mode 1"); + if((ATAID.CFAPowerMode & 0x2000) == 0x2000) sb.AppendLine().Append("CompactFlash power mode 1 required for one or more commands"); + if((ATAID.CFAPowerMode & 0x1000) == 0x1000) sb.AppendLine().Append("CompactFlash power mode 1 is disabled"); @@ -2956,82 +1797,109 @@ namespace DiscImageChef.Decoders.ATA sb.AppendLine(); sb.AppendLine().Append("Command set and features:"); + if(ATAID.CommandSet.HasFlag(CommandSetBit.Nop)) { sb.AppendLine().Append("NOP is supported"); - if(ATAID.EnabledCommandSet.HasFlag(CommandSetBit.Nop)) sb.Append(" and enabled"); + + if(ATAID.EnabledCommandSet.HasFlag(CommandSetBit.Nop)) + sb.Append(" and enabled"); } if(ATAID.CommandSet.HasFlag(CommandSetBit.ReadBuffer)) { sb.AppendLine().Append("READ BUFFER is supported"); - if(ATAID.EnabledCommandSet.HasFlag(CommandSetBit.ReadBuffer)) sb.Append(" and enabled"); + + if(ATAID.EnabledCommandSet.HasFlag(CommandSetBit.ReadBuffer)) + sb.Append(" and enabled"); } if(ATAID.CommandSet.HasFlag(CommandSetBit.WriteBuffer)) { sb.AppendLine().Append("WRITE BUFFER is supported"); - if(ATAID.EnabledCommandSet.HasFlag(CommandSetBit.WriteBuffer)) sb.Append(" and enabled"); + + if(ATAID.EnabledCommandSet.HasFlag(CommandSetBit.WriteBuffer)) + sb.Append(" and enabled"); } if(ATAID.CommandSet.HasFlag(CommandSetBit.HPA)) { sb.AppendLine().Append("Host Protected Area is supported"); - if(ATAID.EnabledCommandSet.HasFlag(CommandSetBit.HPA)) sb.Append(" and enabled"); + + if(ATAID.EnabledCommandSet.HasFlag(CommandSetBit.HPA)) + sb.Append(" and enabled"); } if(ATAID.CommandSet.HasFlag(CommandSetBit.DeviceReset)) { sb.AppendLine().Append("DEVICE RESET is supported"); - if(ATAID.EnabledCommandSet.HasFlag(CommandSetBit.DeviceReset)) sb.Append(" and enabled"); + + if(ATAID.EnabledCommandSet.HasFlag(CommandSetBit.DeviceReset)) + sb.Append(" and enabled"); } if(ATAID.CommandSet.HasFlag(CommandSetBit.Service)) { sb.AppendLine().Append("SERVICE interrupt is supported"); - if(ATAID.EnabledCommandSet.HasFlag(CommandSetBit.Service)) sb.Append(" and enabled"); + + if(ATAID.EnabledCommandSet.HasFlag(CommandSetBit.Service)) + sb.Append(" and enabled"); } if(ATAID.CommandSet.HasFlag(CommandSetBit.Release)) { sb.AppendLine().Append("Release is supported"); - if(ATAID.EnabledCommandSet.HasFlag(CommandSetBit.Release)) sb.Append(" and enabled"); + + if(ATAID.EnabledCommandSet.HasFlag(CommandSetBit.Release)) + sb.Append(" and enabled"); } if(ATAID.CommandSet.HasFlag(CommandSetBit.LookAhead)) { sb.AppendLine().Append("Look-ahead read is supported"); - if(ATAID.EnabledCommandSet.HasFlag(CommandSetBit.LookAhead)) sb.Append(" and enabled"); + + if(ATAID.EnabledCommandSet.HasFlag(CommandSetBit.LookAhead)) + sb.Append(" and enabled"); } if(ATAID.CommandSet.HasFlag(CommandSetBit.WriteCache)) { sb.AppendLine().Append("Write cache is supported"); - if(ATAID.EnabledCommandSet.HasFlag(CommandSetBit.WriteCache)) sb.Append(" and enabled"); + + if(ATAID.EnabledCommandSet.HasFlag(CommandSetBit.WriteCache)) + sb.Append(" and enabled"); } if(ATAID.CommandSet.HasFlag(CommandSetBit.Packet)) { sb.AppendLine().Append("PACKET is supported"); - if(ATAID.EnabledCommandSet.HasFlag(CommandSetBit.Packet)) sb.Append(" and enabled"); + + if(ATAID.EnabledCommandSet.HasFlag(CommandSetBit.Packet)) + sb.Append(" and enabled"); } if(ATAID.CommandSet.HasFlag(CommandSetBit.PowerManagement)) { sb.AppendLine().Append("Power management is supported"); - if(ATAID.EnabledCommandSet.HasFlag(CommandSetBit.PowerManagement)) sb.Append(" and enabled"); + + if(ATAID.EnabledCommandSet.HasFlag(CommandSetBit.PowerManagement)) + sb.Append(" and enabled"); } if(ATAID.CommandSet.HasFlag(CommandSetBit.RemovableMedia)) { sb.AppendLine().Append("Removable media feature set is supported"); - if(ATAID.EnabledCommandSet.HasFlag(CommandSetBit.RemovableMedia)) sb.Append(" and enabled"); + + if(ATAID.EnabledCommandSet.HasFlag(CommandSetBit.RemovableMedia)) + sb.Append(" and enabled"); } if(ATAID.CommandSet.HasFlag(CommandSetBit.SecurityMode)) { sb.AppendLine().Append("Security mode is supported"); - if(ATAID.EnabledCommandSet.HasFlag(CommandSetBit.SecurityMode)) sb.Append(" and enabled"); + + if(ATAID.EnabledCommandSet.HasFlag(CommandSetBit.SecurityMode)) + sb.Append(" and enabled"); } if(ATAID.Capabilities.HasFlag(CapabilitiesBit.LBASupport)) @@ -3043,30 +1911,39 @@ namespace DiscImageChef.Decoders.ATA if(ATAID.CommandSet2.HasFlag(CommandSetBit2.LBA48)) { sb.AppendLine().Append("48-bit LBA is supported"); - if(ATAID.EnabledCommandSet2.HasFlag(CommandSetBit2.LBA48)) sb.Append(" and enabled"); + + if(ATAID.EnabledCommandSet2.HasFlag(CommandSetBit2.LBA48)) + sb.Append(" and enabled"); } if(ATAID.CommandSet2.HasFlag(CommandSetBit2.FlushCache)) { sb.AppendLine().Append("FLUSH CACHE is supported"); - if(ATAID.EnabledCommandSet2.HasFlag(CommandSetBit2.FlushCache)) sb.Append(" and enabled"); + + if(ATAID.EnabledCommandSet2.HasFlag(CommandSetBit2.FlushCache)) + sb.Append(" and enabled"); } if(ATAID.CommandSet2.HasFlag(CommandSetBit2.FlushCacheExt)) { sb.AppendLine().Append("FLUSH CACHE EXT is supported"); - if(ATAID.EnabledCommandSet2.HasFlag(CommandSetBit2.FlushCacheExt)) sb.Append(" and enabled"); + + if(ATAID.EnabledCommandSet2.HasFlag(CommandSetBit2.FlushCacheExt)) + sb.Append(" and enabled"); } if(ATAID.CommandSet2.HasFlag(CommandSetBit2.DCO)) { sb.AppendLine().Append("Device Configuration Overlay feature set is supported"); - if(ATAID.EnabledCommandSet2.HasFlag(CommandSetBit2.DCO)) sb.Append(" and enabled"); + + if(ATAID.EnabledCommandSet2.HasFlag(CommandSetBit2.DCO)) + sb.Append(" and enabled"); } if(ATAID.CommandSet2.HasFlag(CommandSetBit2.AAM)) { sb.AppendLine().Append("Automatic Acoustic Management is supported"); + if(ATAID.EnabledCommandSet2.HasFlag(CommandSetBit2.AAM)) sb.AppendFormat(" and enabled with value {0} (vendor recommends {1}", ATAID.CurrentAAM, ATAID.RecommendedAAM); @@ -3075,27 +1952,34 @@ namespace DiscImageChef.Decoders.ATA if(ATAID.CommandSet2.HasFlag(CommandSetBit2.SetMax)) { sb.AppendLine().Append("SET MAX security extension is supported"); - if(ATAID.EnabledCommandSet2.HasFlag(CommandSetBit2.SetMax)) sb.Append(" and enabled"); + + if(ATAID.EnabledCommandSet2.HasFlag(CommandSetBit2.SetMax)) + sb.Append(" and enabled"); } if(ATAID.CommandSet2.HasFlag(CommandSetBit2.AddressOffsetReservedAreaBoot)) { sb.AppendLine().Append("Address Offset Reserved Area Boot is supported"); + if(ATAID.EnabledCommandSet2.HasFlag(CommandSetBit2.AddressOffsetReservedAreaBoot)) sb.Append(" and enabled"); } if(ATAID.CommandSet2.HasFlag(CommandSetBit2.SetFeaturesRequired)) sb.AppendLine().Append("SET FEATURES is required before spin-up"); + if(ATAID.CommandSet2.HasFlag(CommandSetBit2.PowerUpInStandby)) { sb.AppendLine().Append("Power-up in standby is supported"); - if(ATAID.EnabledCommandSet2.HasFlag(CommandSetBit2.PowerUpInStandby)) sb.Append(" and enabled"); + + if(ATAID.EnabledCommandSet2.HasFlag(CommandSetBit2.PowerUpInStandby)) + sb.Append(" and enabled"); } if(ATAID.CommandSet2.HasFlag(CommandSetBit2.RemovableNotification)) { sb.AppendLine().Append("Removable Media Status Notification is supported"); + if(ATAID.EnabledCommandSet2.HasFlag(CommandSetBit2.RemovableNotification)) sb.Append(" and enabled"); } @@ -3103,6 +1987,7 @@ namespace DiscImageChef.Decoders.ATA if(ATAID.CommandSet2.HasFlag(CommandSetBit2.APM)) { sb.AppendLine().Append("Advanced Power Management is supported"); + if(ATAID.EnabledCommandSet2.HasFlag(CommandSetBit2.APM)) sb.AppendFormat(" and enabled with value {0}", ATAID.CurrentAPM); } @@ -3110,26 +1995,34 @@ namespace DiscImageChef.Decoders.ATA if(ATAID.CommandSet2.HasFlag(CommandSetBit2.CompactFlash)) { sb.AppendLine().Append("CompactFlash feature set is supported"); - if(ATAID.EnabledCommandSet2.HasFlag(CommandSetBit2.CompactFlash)) sb.Append(" and enabled"); + + if(ATAID.EnabledCommandSet2.HasFlag(CommandSetBit2.CompactFlash)) + sb.Append(" and enabled"); } if(ATAID.CommandSet2.HasFlag(CommandSetBit2.RWQueuedDMA)) { sb.AppendLine().Append("READ DMA QUEUED and WRITE DMA QUEUED are supported"); - if(ATAID.EnabledCommandSet2.HasFlag(CommandSetBit2.RWQueuedDMA)) sb.Append(" and enabled"); + + if(ATAID.EnabledCommandSet2.HasFlag(CommandSetBit2.RWQueuedDMA)) + sb.Append(" and enabled"); } if(ATAID.CommandSet2.HasFlag(CommandSetBit2.DownloadMicrocode)) { sb.AppendLine().Append("DOWNLOAD MICROCODE is supported"); - if(ATAID.EnabledCommandSet2.HasFlag(CommandSetBit2.DownloadMicrocode)) sb.Append(" and enabled"); + + if(ATAID.EnabledCommandSet2.HasFlag(CommandSetBit2.DownloadMicrocode)) + sb.Append(" and enabled"); } } if(ATAID.CommandSet.HasFlag(CommandSetBit.SMART)) { sb.AppendLine().Append("S.M.A.R.T. is supported"); - if(ATAID.EnabledCommandSet.HasFlag(CommandSetBit.SMART)) sb.Append(" and enabled"); + + if(ATAID.EnabledCommandSet.HasFlag(CommandSetBit.SMART)) + sb.Append(" and enabled"); } if(ATAID.SCTCommandTransport.HasFlag(SCTCommandTransportBit.Supported)) @@ -3141,61 +2034,82 @@ namespace DiscImageChef.Decoders.ATA if(ATAID.CommandSet3.HasFlag(CommandSetBit3.SMARTSelfTest)) { sb.AppendLine().Append("S.M.A.R.T. self-testing is supported"); - if(ATAID.EnabledCommandSet3.HasFlag(CommandSetBit3.SMARTSelfTest)) sb.Append(" and enabled"); + + if(ATAID.EnabledCommandSet3.HasFlag(CommandSetBit3.SMARTSelfTest)) + sb.Append(" and enabled"); } if(ATAID.CommandSet3.HasFlag(CommandSetBit3.SMARTLog)) { sb.AppendLine().Append("S.M.A.R.T. error logging is supported"); - if(ATAID.EnabledCommandSet3.HasFlag(CommandSetBit3.SMARTLog)) sb.Append(" and enabled"); + + if(ATAID.EnabledCommandSet3.HasFlag(CommandSetBit3.SMARTLog)) + sb.Append(" and enabled"); } if(ATAID.CommandSet3.HasFlag(CommandSetBit3.IdleImmediate)) { sb.AppendLine().Append("IDLE IMMEDIATE with UNLOAD FEATURE is supported"); - if(ATAID.EnabledCommandSet3.HasFlag(CommandSetBit3.IdleImmediate)) sb.Append(" and enabled"); + + if(ATAID.EnabledCommandSet3.HasFlag(CommandSetBit3.IdleImmediate)) + sb.Append(" and enabled"); } if(ATAID.CommandSet3.HasFlag(CommandSetBit3.WriteURG)) sb.AppendLine().Append("URG bit is supported in WRITE STREAM DMA EXT and WRITE STREAM EXT"); + if(ATAID.CommandSet3.HasFlag(CommandSetBit3.ReadURG)) sb.AppendLine().Append("URG bit is supported in READ STREAM DMA EXT and READ STREAM EXT"); + if(ATAID.CommandSet3.HasFlag(CommandSetBit3.WWN)) sb.AppendLine().Append("Device has a World Wide Name"); + if(ATAID.CommandSet3.HasFlag(CommandSetBit3.FUAWriteQ)) { sb.AppendLine().Append("WRITE DMA QUEUED FUA EXT is supported"); - if(ATAID.EnabledCommandSet3.HasFlag(CommandSetBit3.FUAWriteQ)) sb.Append(" and enabled"); + + if(ATAID.EnabledCommandSet3.HasFlag(CommandSetBit3.FUAWriteQ)) + sb.Append(" and enabled"); } if(ATAID.CommandSet3.HasFlag(CommandSetBit3.FUAWrite)) { sb.AppendLine().Append("WRITE DMA FUA EXT and WRITE MULTIPLE FUA EXT are supported"); - if(ATAID.EnabledCommandSet3.HasFlag(CommandSetBit3.FUAWrite)) sb.Append(" and enabled"); + + if(ATAID.EnabledCommandSet3.HasFlag(CommandSetBit3.FUAWrite)) + sb.Append(" and enabled"); } if(ATAID.CommandSet3.HasFlag(CommandSetBit3.GPL)) { sb.AppendLine().Append("General Purpose Logging is supported"); - if(ATAID.EnabledCommandSet3.HasFlag(CommandSetBit3.GPL)) sb.Append(" and enabled"); + + if(ATAID.EnabledCommandSet3.HasFlag(CommandSetBit3.GPL)) + sb.Append(" and enabled"); } if(ATAID.CommandSet3.HasFlag(CommandSetBit3.Streaming)) { sb.AppendLine().Append("Streaming feature set is supported"); - if(ATAID.EnabledCommandSet3.HasFlag(CommandSetBit3.Streaming)) sb.Append(" and enabled"); + + if(ATAID.EnabledCommandSet3.HasFlag(CommandSetBit3.Streaming)) + sb.Append(" and enabled"); } if(ATAID.CommandSet3.HasFlag(CommandSetBit3.MCPT)) { sb.AppendLine().Append("Media Card Pass Through command set is supported"); - if(ATAID.EnabledCommandSet3.HasFlag(CommandSetBit3.MCPT)) sb.Append(" and enabled"); + + if(ATAID.EnabledCommandSet3.HasFlag(CommandSetBit3.MCPT)) + sb.Append(" and enabled"); } if(ATAID.CommandSet3.HasFlag(CommandSetBit3.MediaSerial)) { sb.AppendLine().Append("Media Serial is supported"); - if(ATAID.EnabledCommandSet3.HasFlag(CommandSetBit3.MediaSerial)) sb.Append(" and valid"); + + if(ATAID.EnabledCommandSet3.HasFlag(CommandSetBit3.MediaSerial)) + sb.Append(" and valid"); } } @@ -3205,36 +2119,47 @@ namespace DiscImageChef.Decoders.ATA if(ATAID.CommandSet4.HasFlag(CommandSetBit4.DSN)) { sb.AppendLine().Append("DSN feature set is supported"); - if(ATAID.EnabledCommandSet4.HasFlag(CommandSetBit4.DSN)) sb.Append(" and enabled"); + + if(ATAID.EnabledCommandSet4.HasFlag(CommandSetBit4.DSN)) + sb.Append(" and enabled"); } if(ATAID.CommandSet4.HasFlag(CommandSetBit4.AMAC)) { sb.AppendLine().Append("Accessible Max Address Configuration is supported"); - if(ATAID.EnabledCommandSet4.HasFlag(CommandSetBit4.AMAC)) sb.Append(" and enabled"); + + if(ATAID.EnabledCommandSet4.HasFlag(CommandSetBit4.AMAC)) + sb.Append(" and enabled"); } if(ATAID.CommandSet4.HasFlag(CommandSetBit4.ExtPowerCond)) { sb.AppendLine().Append("Extended Power Conditions are supported"); - if(ATAID.EnabledCommandSet4.HasFlag(CommandSetBit4.ExtPowerCond)) sb.Append(" and enabled"); + + if(ATAID.EnabledCommandSet4.HasFlag(CommandSetBit4.ExtPowerCond)) + sb.Append(" and enabled"); } if(ATAID.CommandSet4.HasFlag(CommandSetBit4.ExtStatusReport)) { sb.AppendLine().Append("Extended Status Reporting is supported"); - if(ATAID.EnabledCommandSet4.HasFlag(CommandSetBit4.ExtStatusReport)) sb.Append(" and enabled"); + + if(ATAID.EnabledCommandSet4.HasFlag(CommandSetBit4.ExtStatusReport)) + sb.Append(" and enabled"); } if(ATAID.CommandSet4.HasFlag(CommandSetBit4.FreeFallControl)) { sb.AppendLine().Append("Free-fall control feature set is supported"); - if(ATAID.EnabledCommandSet4.HasFlag(CommandSetBit4.FreeFallControl)) sb.Append(" and enabled"); + + if(ATAID.EnabledCommandSet4.HasFlag(CommandSetBit4.FreeFallControl)) + sb.Append(" and enabled"); } if(ATAID.CommandSet4.HasFlag(CommandSetBit4.SegmentedDownloadMicrocode)) { sb.AppendLine().Append("Segmented feature in DOWNLOAD MICROCODE is supported"); + if(ATAID.EnabledCommandSet4.HasFlag(CommandSetBit4.SegmentedDownloadMicrocode)) sb.Append(" and enabled"); } @@ -3242,21 +2167,29 @@ namespace DiscImageChef.Decoders.ATA if(ATAID.CommandSet4.HasFlag(CommandSetBit4.RWDMAExtGpl)) { sb.AppendLine().Append("READ/WRITE DMA EXT GPL are supported"); - if(ATAID.EnabledCommandSet4.HasFlag(CommandSetBit4.RWDMAExtGpl)) sb.Append(" and enabled"); + + if(ATAID.EnabledCommandSet4.HasFlag(CommandSetBit4.RWDMAExtGpl)) + sb.Append(" and enabled"); } if(ATAID.CommandSet4.HasFlag(CommandSetBit4.WriteUnc)) { sb.AppendLine().Append("WRITE UNCORRECTABLE is supported"); - if(ATAID.EnabledCommandSet4.HasFlag(CommandSetBit4.WriteUnc)) sb.Append(" and enabled"); + + if(ATAID.EnabledCommandSet4.HasFlag(CommandSetBit4.WriteUnc)) + sb.Append(" and enabled"); } if(ATAID.CommandSet4.HasFlag(CommandSetBit4.WRV)) { sb.AppendLine().Append("Write/Read/Verify is supported"); - if(ATAID.EnabledCommandSet4.HasFlag(CommandSetBit4.WRV)) sb.Append(" and enabled"); + + if(ATAID.EnabledCommandSet4.HasFlag(CommandSetBit4.WRV)) + sb.Append(" and enabled"); + sb.AppendLine().AppendFormat("{0} sectors for Write/Read/Verify mode 2", ATAID.WRVSectorCountMode2); sb.AppendLine().AppendFormat("{0} sectors for Write/Read/Verify mode 3", ATAID.WRVSectorCountMode3); + if(ATAID.EnabledCommandSet4.HasFlag(CommandSetBit4.WRV)) sb.AppendLine().AppendFormat("Current Write/Read/Verify mode: {0}", ATAID.WRVMode); } @@ -3264,54 +2197,71 @@ namespace DiscImageChef.Decoders.ATA if(ATAID.CommandSet4.HasFlag(CommandSetBit4.DT1825)) { sb.AppendLine().Append("DT1825 is supported"); - if(ATAID.EnabledCommandSet4.HasFlag(CommandSetBit4.DT1825)) sb.Append(" and enabled"); + + if(ATAID.EnabledCommandSet4.HasFlag(CommandSetBit4.DT1825)) + sb.Append(" and enabled"); } } if(ATAID.Capabilities3.HasFlag(CapabilitiesBit3.BlockErase)) sb.AppendLine().Append("BLOCK ERASE EXT is supported"); + if(ATAID.Capabilities3.HasFlag(CapabilitiesBit3.Overwrite)) sb.AppendLine().Append("OVERWRITE EXT is supported"); + if(ATAID.Capabilities3.HasFlag(CapabilitiesBit3.CryptoScramble)) sb.AppendLine().Append("CRYPTO SCRAMBLE EXT is supported"); if(ATAID.CommandSet5.HasFlag(CommandSetBit5.DeviceConfDMA)) - sb.AppendLine() - .Append("DEVICE CONFIGURATION IDENTIFY DMA and DEVICE CONFIGURATION SET DMA are supported"); + sb.AppendLine(). + Append("DEVICE CONFIGURATION IDENTIFY DMA and DEVICE CONFIGURATION SET DMA are supported"); + if(ATAID.CommandSet5.HasFlag(CommandSetBit5.ReadBufferDMA)) sb.AppendLine().Append("READ BUFFER DMA is supported"); + if(ATAID.CommandSet5.HasFlag(CommandSetBit5.WriteBufferDMA)) sb.AppendLine().Append("WRITE BUFFER DMA is supported"); + if(ATAID.CommandSet5.HasFlag(CommandSetBit5.DownloadMicroCodeDMA)) sb.AppendLine().Append("DOWNLOAD MICROCODE DMA is supported"); + if(ATAID.CommandSet5.HasFlag(CommandSetBit5.SetMaxDMA)) sb.AppendLine().Append("SET PASSWORD DMA and SET UNLOCK DMA are supported"); + if(ATAID.CommandSet5.HasFlag(CommandSetBit5.Ata28)) sb.AppendLine().Append("Not all 28-bit commands are supported"); if(ATAID.CommandSet5.HasFlag(CommandSetBit5.CFast)) sb.AppendLine().Append("Device follows CFast specification"); - if(ATAID.CommandSet5.HasFlag(CommandSetBit5.IEEE1667)) sb.AppendLine().Append("Device follows IEEE-1667"); + + if(ATAID.CommandSet5.HasFlag(CommandSetBit5.IEEE1667)) + sb.AppendLine().Append("Device follows IEEE-1667"); if(ATAID.CommandSet5.HasFlag(CommandSetBit5.DeterministicTrim)) { sb.AppendLine().Append("Read after TRIM is deterministic"); + if(ATAID.CommandSet5.HasFlag(CommandSetBit5.ReadZeroTrim)) sb.AppendLine().Append("Read after TRIM returns empty data"); } if(ATAID.CommandSet5.HasFlag(CommandSetBit5.LongPhysSectorAligError)) sb.AppendLine().Append("Device supports Long Physical Sector Alignment Error Reporting Control"); + if(ATAID.CommandSet5.HasFlag(CommandSetBit5.Encrypted)) sb.AppendLine().Append("Device encrypts all user data"); + if(ATAID.CommandSet5.HasFlag(CommandSetBit5.AllCacheNV)) sb.AppendLine().Append("Device's write cache is non-volatile"); + if(ATAID.CommandSet5.HasFlag(CommandSetBit5.ZonedBit0) || - ATAID.CommandSet5.HasFlag(CommandSetBit5.ZonedBit1)) sb.AppendLine().Append("Device is zoned"); + ATAID.CommandSet5.HasFlag(CommandSetBit5.ZonedBit1)) + sb.AppendLine().Append("Device is zoned"); if(ATAID.Capabilities3.HasFlag(CapabilitiesBit3.Sanitize)) { sb.AppendLine().Append("Sanitize feature set is supported"); + sb.AppendLine().Append(ATAID.Capabilities3.HasFlag(CapabilitiesBit3.SanitizeCommands) ? "Sanitize commands are specified by ACS-3 or higher" : "Sanitize commands are specified by ACS-2"); @@ -3320,7 +2270,8 @@ namespace DiscImageChef.Decoders.ATA sb.AppendLine().Append("SANITIZE ANTIFREEZE LOCK EXT is supported"); } - if(!ata1 && maxatalevel >= 8) + if(!ata1 && + maxatalevel >= 8) if(ATAID.TrustedComputing.HasFlag(TrustedComputingBit.Set) && !ATAID.TrustedComputing.HasFlag(TrustedComputingBit.Clear) && ATAID.TrustedComputing.HasFlag(TrustedComputingBit.TrustedComputing)) @@ -3342,6 +2293,7 @@ namespace DiscImageChef.Decoders.ATA if(ATAID.SATAFeatures.HasFlag(SATAFeaturesBit.NonZeroBufferOffset)) { sb.AppendLine().Append("Non-zero buffer offsets are supported"); + if(ATAID.EnabledSATAFeatures.HasFlag(SATAFeaturesBit.NonZeroBufferOffset)) sb.Append(" and enabled"); } @@ -3349,25 +2301,32 @@ namespace DiscImageChef.Decoders.ATA if(ATAID.SATAFeatures.HasFlag(SATAFeaturesBit.DMASetup)) { sb.AppendLine().Append("DMA Setup auto-activation is supported"); - if(ATAID.EnabledSATAFeatures.HasFlag(SATAFeaturesBit.DMASetup)) sb.Append(" and enabled"); + + if(ATAID.EnabledSATAFeatures.HasFlag(SATAFeaturesBit.DMASetup)) + sb.Append(" and enabled"); } if(ATAID.SATAFeatures.HasFlag(SATAFeaturesBit.InitPowerMgmt)) { sb.AppendLine().Append("Device-initiated power management is supported"); - if(ATAID.EnabledSATAFeatures.HasFlag(SATAFeaturesBit.InitPowerMgmt)) sb.Append(" and enabled"); + + if(ATAID.EnabledSATAFeatures.HasFlag(SATAFeaturesBit.InitPowerMgmt)) + sb.Append(" and enabled"); } if(ATAID.SATAFeatures.HasFlag(SATAFeaturesBit.InOrderData)) { sb.AppendLine().Append("In-order data delivery is supported"); - if(ATAID.EnabledSATAFeatures.HasFlag(SATAFeaturesBit.InOrderData)) sb.Append(" and enabled"); + + if(ATAID.EnabledSATAFeatures.HasFlag(SATAFeaturesBit.InOrderData)) + sb.Append(" and enabled"); } if(!atapi) if(ATAID.SATAFeatures.HasFlag(SATAFeaturesBit.HardwareFeatureControl)) { sb.AppendLine().Append("Hardware Feature Control is supported"); + if(ATAID.EnabledSATAFeatures.HasFlag(SATAFeaturesBit.HardwareFeatureControl)) sb.Append(" and enabled"); } @@ -3376,6 +2335,7 @@ namespace DiscImageChef.Decoders.ATA if(ATAID.SATAFeatures.HasFlag(SATAFeaturesBit.AsyncNotification)) { sb.AppendLine().Append("Asynchronous notification is supported"); + if(ATAID.EnabledSATAFeatures.HasFlag(SATAFeaturesBit.AsyncNotification)) sb.Append(" and enabled"); } @@ -3383,12 +2343,14 @@ namespace DiscImageChef.Decoders.ATA if(ATAID.SATAFeatures.HasFlag(SATAFeaturesBit.SettingsPreserve)) { sb.AppendLine().Append("Software Settings Preservation is supported"); + if(ATAID.EnabledSATAFeatures.HasFlag(SATAFeaturesBit.SettingsPreserve)) sb.Append(" and enabled"); } if(ATAID.SATAFeatures.HasFlag(SATAFeaturesBit.NCQAutoSense)) sb.AppendLine().Append("NCQ Autosense is supported"); + if(ATAID.EnabledSATAFeatures.HasFlag(SATAFeaturesBit.EnabledSlumber)) sb.AppendLine().Append("Automatic Partial to Slumber transitions are enabled"); } @@ -3397,43 +2359,47 @@ namespace DiscImageChef.Decoders.ATA if((ATAID.RemovableStatusSet & 0x03) > 0) sb.AppendLine().Append("Removable Media Status Notification feature set is supported"); - if(ATAID.FreeFallSensitivity != 0x00 && ATAID.FreeFallSensitivity != 0xFF) + if(ATAID.FreeFallSensitivity != 0x00 && + ATAID.FreeFallSensitivity != 0xFF) sb.AppendLine().AppendFormat("Free-fall sensitivity set to {0}", ATAID.FreeFallSensitivity); - if(ATAID.DataSetMgmt.HasFlag(DataSetMgmtBit.Trim)) sb.AppendLine().Append("TRIM is supported"); + if(ATAID.DataSetMgmt.HasFlag(DataSetMgmtBit.Trim)) + sb.AppendLine().Append("TRIM is supported"); + if(ATAID.DataSetMgmtSize > 0) sb.AppendLine().AppendFormat("DATA SET MANAGEMENT can receive a maximum of {0} blocks of 512 bytes", ATAID.DataSetMgmtSize); sb.AppendLine().AppendLine(); + if(ATAID.SecurityStatus.HasFlag(SecurityStatusBit.Supported)) { sb.AppendLine("Security:"); + if(ATAID.SecurityStatus.HasFlag(SecurityStatusBit.Enabled)) { sb.AppendLine("Security is enabled"); - sb.AppendLine(ATAID.SecurityStatus.HasFlag(SecurityStatusBit.Locked) - ? "Security is locked" + + sb.AppendLine(ATAID.SecurityStatus.HasFlag(SecurityStatusBit.Locked) ? "Security is locked" : "Security is not locked"); - sb.AppendLine(ATAID.SecurityStatus.HasFlag(SecurityStatusBit.Frozen) - ? "Security is frozen" + sb.AppendLine(ATAID.SecurityStatus.HasFlag(SecurityStatusBit.Frozen) ? "Security is frozen" : "Security is not frozen"); - sb.AppendLine(ATAID.SecurityStatus.HasFlag(SecurityStatusBit.Expired) - ? "Security count has expired" + sb.AppendLine(ATAID.SecurityStatus.HasFlag(SecurityStatusBit.Expired) ? "Security count has expired" : "Security count has notexpired"); - sb.AppendLine(ATAID.SecurityStatus.HasFlag(SecurityStatusBit.Maximum) - ? "Security level is maximum" + sb.AppendLine(ATAID.SecurityStatus.HasFlag(SecurityStatusBit.Maximum) ? "Security level is maximum" : "Security level is high"); } - else sb.AppendLine("Security is not enabled"); + else + sb.AppendLine("Security is not enabled"); if(ATAID.SecurityStatus.HasFlag(SecurityStatusBit.Enhanced)) sb.AppendLine("Supports enhanced security erase"); sb.AppendFormat("{0} minutes to complete secure erase", ATAID.SecurityEraseTime * 2).AppendLine(); + if(ATAID.SecurityStatus.HasFlag(SecurityStatusBit.Enhanced)) sb.AppendFormat("{0} minutes to complete enhanced secure erase", ATAID.EnhancedSecurityEraseTime * 2).AppendLine(); @@ -3446,24 +2412,29 @@ namespace DiscImageChef.Decoders.ATA ATAID.CommandSet3.HasFlag(CommandSetBit3.Streaming)) { sb.AppendLine().AppendLine("Streaming:"); - sb.AppendFormat("Minimum request size is {0}", ATAID.StreamMinReqSize); - sb.AppendFormat("Streaming transfer time in PIO is {0}", ATAID.StreamTransferTimePIO); - sb.AppendFormat("Streaming transfer time in DMA is {0}", ATAID.StreamTransferTimeDMA); - sb.AppendFormat("Streaming access latency is {0}", ATAID.StreamAccessLatency); + sb.AppendFormat("Minimum request size is {0}", ATAID.StreamMinReqSize); + sb.AppendFormat("Streaming transfer time in PIO is {0}", ATAID.StreamTransferTimePIO); + sb.AppendFormat("Streaming transfer time in DMA is {0}", ATAID.StreamTransferTimeDMA); + sb.AppendFormat("Streaming access latency is {0}", ATAID.StreamAccessLatency); sb.AppendFormat("Streaming performance granularity is {0}", ATAID.StreamPerformanceGranularity); } if(ATAID.SCTCommandTransport.HasFlag(SCTCommandTransportBit.Supported)) { sb.AppendLine().AppendLine("S.M.A.R.T. Command Transport (SCT):"); + if(ATAID.SCTCommandTransport.HasFlag(SCTCommandTransportBit.LongSectorAccess)) sb.AppendLine("SCT Long Sector Address is supported"); + if(ATAID.SCTCommandTransport.HasFlag(SCTCommandTransportBit.WriteSame)) sb.AppendLine("SCT Write Same is supported"); + if(ATAID.SCTCommandTransport.HasFlag(SCTCommandTransportBit.ErrorRecoveryControl)) sb.AppendLine("SCT Error Recovery Control is supported"); + if(ATAID.SCTCommandTransport.HasFlag(SCTCommandTransportBit.FeaturesControl)) sb.AppendLine("SCT Features Control is supported"); + if(ATAID.SCTCommandTransport.HasFlag(SCTCommandTransportBit.DataTables)) sb.AppendLine("SCT Data Tables are supported"); } @@ -3472,70 +2443,115 @@ namespace DiscImageChef.Decoders.ATA { sb.AppendLine().AppendLine("Non-Volatile Cache:"); sb.AppendLine().AppendFormat("Version {0}", (ATAID.NVCacheCaps & 0xF000) >> 12).AppendLine(); + if((ATAID.NVCacheCaps & 0x0001) == 0x0001) { sb.Append("Power mode feature set is supported"); - if((ATAID.NVCacheCaps & 0x0002) == 0x0002) sb.Append(" and enabled"); + + if((ATAID.NVCacheCaps & 0x0002) == 0x0002) + sb.Append(" and enabled"); + sb.AppendLine(); sb.AppendLine().AppendFormat("Version {0}", (ATAID.NVCacheCaps & 0x0F00) >> 8).AppendLine(); } - sb.AppendLine().AppendFormat("Non-Volatile Cache is {0} bytes", ATAID.NVCacheSize * logicalsectorsize) - .AppendLine(); + sb.AppendLine().AppendFormat("Non-Volatile Cache is {0} bytes", ATAID.NVCacheSize * logicalsectorsize). + AppendLine(); } - #if DEBUG + #if DEBUG sb.AppendLine(); - if(ATAID.VendorWord9 != 0x0000 && ATAID.VendorWord9 != 0xFFFF) + + if(ATAID.VendorWord9 != 0x0000 && + ATAID.VendorWord9 != 0xFFFF) sb.AppendFormat("Word 9: 0x{0:X4}", ATAID.VendorWord9).AppendLine(); - if((ATAID.VendorWord47 & 0x7F) != 0x7F && (ATAID.VendorWord47 & 0x7F) != 0x00) + + if((ATAID.VendorWord47 & 0x7F) != 0x7F && + (ATAID.VendorWord47 & 0x7F) != 0x00) sb.AppendFormat("Word 47 bits 15 to 8: 0x{0:X2}", ATAID.VendorWord47).AppendLine(); - if(ATAID.VendorWord51 != 0x00 && ATAID.VendorWord51 != 0xFF) + + if(ATAID.VendorWord51 != 0x00 && + ATAID.VendorWord51 != 0xFF) sb.AppendFormat("Word 51 bits 7 to 0: 0x{0:X2}", ATAID.VendorWord51).AppendLine(); - if(ATAID.VendorWord52 != 0x00 && ATAID.VendorWord52 != 0xFF) + + if(ATAID.VendorWord52 != 0x00 && + ATAID.VendorWord52 != 0xFF) sb.AppendFormat("Word 52 bits 7 to 0: 0x{0:X2}", ATAID.VendorWord52).AppendLine(); - if(ATAID.ReservedWord64 != 0x00 && ATAID.ReservedWord64 != 0xFF) + + if(ATAID.ReservedWord64 != 0x00 && + ATAID.ReservedWord64 != 0xFF) sb.AppendFormat("Word 64 bits 15 to 8: 0x{0:X2}", ATAID.ReservedWord64).AppendLine(); - if(ATAID.ReservedWord70 != 0x0000 && ATAID.ReservedWord70 != 0xFFFF) + + if(ATAID.ReservedWord70 != 0x0000 && + ATAID.ReservedWord70 != 0xFFFF) sb.AppendFormat("Word 70: 0x{0:X4}", ATAID.ReservedWord70).AppendLine(); - if(ATAID.ReservedWord73 != 0x0000 && ATAID.ReservedWord73 != 0xFFFF) + + if(ATAID.ReservedWord73 != 0x0000 && + ATAID.ReservedWord73 != 0xFFFF) sb.AppendFormat("Word 73: 0x{0:X4}", ATAID.ReservedWord73).AppendLine(); - if(ATAID.ReservedWord74 != 0x0000 && ATAID.ReservedWord74 != 0xFFFF) + + if(ATAID.ReservedWord74 != 0x0000 && + ATAID.ReservedWord74 != 0xFFFF) sb.AppendFormat("Word 74: 0x{0:X4}", ATAID.ReservedWord74).AppendLine(); - if(ATAID.ReservedWord116 != 0x0000 && ATAID.ReservedWord116 != 0xFFFF) + + if(ATAID.ReservedWord116 != 0x0000 && + ATAID.ReservedWord116 != 0xFFFF) sb.AppendFormat("Word 116: 0x{0:X4}", ATAID.ReservedWord116).AppendLine(); + for(int i = 0; i < ATAID.ReservedWords121.Length; i++) - if(ATAID.ReservedWords121[i] != 0x0000 && ATAID.ReservedWords121[i] != 0xFFFF) + if(ATAID.ReservedWords121[i] != 0x0000 && + ATAID.ReservedWords121[i] != 0xFFFF) sb.AppendFormat("Word {1}: 0x{0:X4}", ATAID.ReservedWords121[i], 121 + i).AppendLine(); + for(int i = 0; i < ATAID.ReservedWords129.Length; i++) - if(ATAID.ReservedWords129[i] != 0x0000 && ATAID.ReservedWords129[i] != 0xFFFF) + if(ATAID.ReservedWords129[i] != 0x0000 && + ATAID.ReservedWords129[i] != 0xFFFF) sb.AppendFormat("Word {1}: 0x{0:X4}", ATAID.ReservedWords129[i], 129 + i).AppendLine(); + for(int i = 0; i < ATAID.ReservedCFA.Length; i++) - if(ATAID.ReservedCFA[i] != 0x0000 && ATAID.ReservedCFA[i] != 0xFFFF) + if(ATAID.ReservedCFA[i] != 0x0000 && + ATAID.ReservedCFA[i] != 0xFFFF) sb.AppendFormat("Word {1} (CFA): 0x{0:X4}", ATAID.ReservedCFA[i], 161 + i).AppendLine(); - if(ATAID.ReservedWord174 != 0x0000 && ATAID.ReservedWord174 != 0xFFFF) + if(ATAID.ReservedWord174 != 0x0000 && + ATAID.ReservedWord174 != 0xFFFF) sb.AppendFormat("Word 174: 0x{0:X4}", ATAID.ReservedWord174).AppendLine(); - if(ATAID.ReservedWord175 != 0x0000 && ATAID.ReservedWord175 != 0xFFFF) + + if(ATAID.ReservedWord175 != 0x0000 && + ATAID.ReservedWord175 != 0xFFFF) sb.AppendFormat("Word 175: 0x{0:X4}", ATAID.ReservedWord175).AppendLine(); - if(ATAID.ReservedCEATAWord207 != 0x0000 && ATAID.ReservedCEATAWord207 != 0xFFFF) + + if(ATAID.ReservedCEATAWord207 != 0x0000 && + ATAID.ReservedCEATAWord207 != 0xFFFF) sb.AppendFormat("Word 207 (CE-ATA): 0x{0:X4}", ATAID.ReservedCEATAWord207).AppendLine(); - if(ATAID.ReservedCEATAWord208 != 0x0000 && ATAID.ReservedCEATAWord208 != 0xFFFF) + + if(ATAID.ReservedCEATAWord208 != 0x0000 && + ATAID.ReservedCEATAWord208 != 0xFFFF) sb.AppendFormat("Word 208 (CE-ATA): 0x{0:X4}", ATAID.ReservedCEATAWord208).AppendLine(); - if(ATAID.NVReserved != 0x00 && ATAID.NVReserved != 0xFF) + + if(ATAID.NVReserved != 0x00 && + ATAID.NVReserved != 0xFF) sb.AppendFormat("Word 219 bits 15 to 8: 0x{0:X2}", ATAID.NVReserved).AppendLine(); - if(ATAID.WRVReserved != 0x00 && ATAID.WRVReserved != 0xFF) + + if(ATAID.WRVReserved != 0x00 && + ATAID.WRVReserved != 0xFF) sb.AppendFormat("Word 220 bits 15 to 8: 0x{0:X2}", ATAID.WRVReserved).AppendLine(); - if(ATAID.ReservedWord221 != 0x0000 && ATAID.ReservedWord221 != 0xFFFF) + + if(ATAID.ReservedWord221 != 0x0000 && + ATAID.ReservedWord221 != 0xFFFF) sb.AppendFormat("Word 221: 0x{0:X4}", ATAID.ReservedWord221).AppendLine(); + for(int i = 0; i < ATAID.ReservedCEATA224.Length; i++) - if(ATAID.ReservedCEATA224[i] != 0x0000 && ATAID.ReservedCEATA224[i] != 0xFFFF) + if(ATAID.ReservedCEATA224[i] != 0x0000 && + ATAID.ReservedCEATA224[i] != 0xFFFF) sb.AppendFormat("Word {1} (CE-ATA): 0x{0:X4}", ATAID.ReservedCEATA224[i], 224 + i).AppendLine(); + for(int i = 0; i < ATAID.ReservedWords.Length; i++) - if(ATAID.ReservedWords[i] != 0x0000 && ATAID.ReservedWords[i] != 0xFFFF) + if(ATAID.ReservedWords[i] != 0x0000 && + ATAID.ReservedWords[i] != 0xFFFF) sb.AppendFormat("Word {1}: 0x{0:X4}", ATAID.ReservedWords[i], 236 + i).AppendLine(); - #endif + #endif return sb.ToString(); } @@ -3567,15 +2583,19 @@ namespace DiscImageChef.Decoders.ATA } 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; + byte[] buf = new byte[length]; - if(str is null) return buf; + for(int i = 0; i < length; i++) + buf[i] = 0x20; + + if(str is null) + return buf; byte[] bytes = Encoding.ASCII.GetBytes(str); @@ -3595,7 +2615,359 @@ namespace DiscImageChef.Decoders.ATA string test1 = StringHandlers.CToString(buf); string test2 = DescrambleATAString(buf, 0, length); + return buf; } + + [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; + } } } \ No newline at end of file diff --git a/ATA/Registers.cs b/ATA/Registers.cs index 8e15cf4..ecb0f89 100644 --- a/ATA/Registers.cs +++ b/ATA/Registers.cs @@ -66,8 +66,8 @@ namespace DiscImageChef.Decoders.ATA public ushort LbaLow; public ushort LbaMid; public ushort LbaHigh; - public byte DeviceHead; - public byte Command; + public byte DeviceHead; + public byte Command; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] @@ -97,12 +97,12 @@ namespace DiscImageChef.Decoders.ATA [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] public struct AtaErrorRegistersLba48 { - public byte Status; - public byte Error; + public byte Status; + public byte Error; public ushort SectorCount; public ushort LbaLow; public ushort LbaMid; public ushort LbaHigh; - public byte DeviceHead; + public byte DeviceHead; } } \ No newline at end of file diff --git a/Blu-ray/BCA.cs b/Blu-ray/BCA.cs index a7eb9d1..a5a9381 100644 --- a/Blu-ray/BCA.cs +++ b/Blu-ray/BCA.cs @@ -38,44 +38,45 @@ using DiscImageChef.Console; namespace DiscImageChef.Decoders.Bluray { /// - /// Information from the following standards: - /// ANSI X3.304-1997 - /// T10/1048-D revision 9.0 - /// T10/1048-D revision 10a - /// T10/1228-D revision 7.0c - /// T10/1228-D revision 11a - /// T10/1363-D revision 10g - /// T10/1545-D revision 1d - /// T10/1545-D revision 5 - /// T10/1545-D revision 5a - /// T10/1675-D revision 2c - /// T10/1675-D revision 4 - /// T10/1836-D revision 2g + /// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a + /// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision + /// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] public static class BCA { + #region Public structures + public struct BurstCuttingArea + { + /// Bytes 0 to 1 Always 66 + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Byte 4 to 67 BCA data + public byte[] BCA; + } + #endregion Public structures #region Public methods public static BurstCuttingArea? Decode(byte[] BCAResponse) { - if(BCAResponse == null) return null; + if(BCAResponse == null) + return null; if(BCAResponse.Length != 68) { DicConsole.DebugWriteLine("BD BCA decoder", "Found incorrect Blu-ray BCA size ({0} bytes)", BCAResponse.Length); + return null; } - BurstCuttingArea decoded = new BurstCuttingArea + var decoded = new BurstCuttingArea { - DataLength = BigEndianBitConverter.ToUInt16(BCAResponse, 0), - Reserved1 = BCAResponse[2], - Reserved2 = BCAResponse[3], - BCA = new byte[64] + DataLength = BigEndianBitConverter.ToUInt16(BCAResponse, 0), Reserved1 = BCAResponse[2], + Reserved2 = BCAResponse[3], BCA = new byte[64] }; Array.Copy(BCAResponse, 4, decoded.BCA, 0, 64); @@ -85,16 +86,20 @@ namespace DiscImageChef.Decoders.Bluray public static string Prettify(BurstCuttingArea? BCAResponse) { - if(BCAResponse == null) return null; + if(BCAResponse == null) + return null; BurstCuttingArea response = BCAResponse.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); - #if DEBUG - if(response.Reserved1 != 0) sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); - if(response.Reserved2 != 0) sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); - #endif + #if DEBUG + if(response.Reserved1 != 0) + sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); + + if(response.Reserved2 != 0) + sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); + #endif sb.AppendFormat("Blu-ray Burst Cutting Area in hex follows:"); sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.BCA, 80)); @@ -104,31 +109,5 @@ namespace DiscImageChef.Decoders.Bluray public static string Prettify(byte[] BCAResponse) => Prettify(Decode(BCAResponse)); #endregion Public methods - - #region Public structures - public struct BurstCuttingArea - { - /// - /// Bytes 0 to 1 - /// Always 66 - /// - public ushort DataLength; - /// - /// Byte 2 - /// Reserved - /// - public byte Reserved1; - /// - /// Byte 3 - /// Reserved - /// - public byte Reserved2; - /// - /// Byte 4 to 67 - /// BCA data - /// - public byte[] BCA; - } - #endregion Public structures } } \ No newline at end of file diff --git a/Blu-ray/Cartridge.cs b/Blu-ray/Cartridge.cs index e15d7b7..3159370 100644 --- a/Blu-ray/Cartridge.cs +++ b/Blu-ray/Cartridge.cs @@ -38,53 +38,72 @@ using DiscImageChef.Console; namespace DiscImageChef.Decoders.Bluray { /// - /// Information from the following standards: - /// ANSI X3.304-1997 - /// T10/1048-D revision 9.0 - /// T10/1048-D revision 10a - /// T10/1228-D revision 7.0c - /// T10/1228-D revision 11a - /// T10/1363-D revision 10g - /// T10/1545-D revision 1d - /// T10/1545-D revision 5 - /// T10/1545-D revision 5a - /// T10/1675-D revision 2c - /// T10/1675-D revision 4 - /// T10/1836-D revision 2g + /// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a + /// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision + /// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] - [SuppressMessage("ReSharper", "UnassignedField.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global"), + SuppressMessage("ReSharper", "UnassignedField.Global")] public static class Cartridge { + #region Public structures + public struct CartridgeStatus + { + /// Bytes 0 to 1 Always 6 + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Byte 4, bit 7 Medium is inserted in a cartridge + public bool Cartridge; + /// Byte 4, bit 6 Medium taken out / put in a cartridge + public bool OUT; + /// Byte 4, bits 5 to 3 Reserved + public byte Reserved3; + /// Byte 4, bit 2 Cartridge sets write protection + public bool CWP; + /// Byte 4, bits 1 to 0 Reserved + public byte Reserved4; + /// Byte 5 Reserved + public byte Reserved5; + /// Byte 6 Reserved + public byte Reserved6; + /// Byte 7 Reserved + public byte Reserved7; + } + #endregion Public structures #region Public methods public static CartridgeStatus? Decode(byte[] CSResponse) { - if(CSResponse == null) return null; + if(CSResponse == null) + return null; if(CSResponse.Length != 8) { DicConsole.DebugWriteLine("BD Cartridge Status decoder", "Found incorrect Blu-ray Cartridge Status size ({0} bytes)", CSResponse.Length); + return null; } - CartridgeStatus decoded = new CartridgeStatus + var decoded = new CartridgeStatus { - DataLength = BigEndianBitConverter.ToUInt16(CSResponse, 0), - Reserved1 = CSResponse[2], + DataLength = BigEndianBitConverter.ToUInt16(CSResponse, 0), Reserved1 = CSResponse[2], Reserved2 = CSResponse[3], Cartridge = Convert.ToBoolean(CSResponse[4] & 0x80), - OUT = Convert.ToBoolean(CSResponse[4] & 0x40), - Reserved3 = (byte)((CSResponse[4] & 0x38) >> 3), - CWP = Convert.ToBoolean(CSResponse[4] & 0x04), - Reserved4 = (byte)(CSResponse[4] & 0x03), - Reserved5 = CSResponse[5], - Reserved6 = CSResponse[6], - Reserved7 = CSResponse[7] + OUT = + Convert.ToBoolean(CSResponse[4] & 0x40), + Reserved3 = (byte)((CSResponse[4] & 0x38) >> 3), + CWP = + Convert.ToBoolean(CSResponse[4] & 0x04), + Reserved4 = (byte)(CSResponse[4] & 0x03), + Reserved5 = CSResponse[5], + Reserved6 = + CSResponse[6], + Reserved7 = CSResponse[7] }; return decoded; @@ -92,36 +111,57 @@ namespace DiscImageChef.Decoders.Bluray public static string Prettify(CartridgeStatus? CSResponse) { - if(CSResponse == null) return null; + if(CSResponse == null) + return null; CartridgeStatus response = CSResponse.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); - #if DEBUG - if(response.Reserved1 != 0) sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); - if(response.Reserved2 != 0) sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); - if(response.Reserved3 != 0) sb.AppendFormat("Reserved3 = 0x{0:X8}", response.Reserved3).AppendLine(); - if(response.Reserved4 != 0) sb.AppendFormat("Reserved4 = 0x{0:X8}", response.Reserved4).AppendLine(); - if(response.Reserved5 != 0) sb.AppendFormat("Reserved5 = 0x{0:X8}", response.Reserved5).AppendLine(); - if(response.Reserved6 != 0) sb.AppendFormat("Reserved6 = 0x{0:X8}", response.Reserved6).AppendLine(); - if(response.Reserved7 != 0) sb.AppendFormat("Reserved7 = 0x{0:X8}", response.Reserved7).AppendLine(); - #endif + #if DEBUG + if(response.Reserved1 != 0) + sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); + + if(response.Reserved2 != 0) + sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); + + if(response.Reserved3 != 0) + sb.AppendFormat("Reserved3 = 0x{0:X8}", response.Reserved3).AppendLine(); + + if(response.Reserved4 != 0) + sb.AppendFormat("Reserved4 = 0x{0:X8}", response.Reserved4).AppendLine(); + + if(response.Reserved5 != 0) + sb.AppendFormat("Reserved5 = 0x{0:X8}", response.Reserved5).AppendLine(); + + if(response.Reserved6 != 0) + sb.AppendFormat("Reserved6 = 0x{0:X8}", response.Reserved6).AppendLine(); + + if(response.Reserved7 != 0) + sb.AppendFormat("Reserved7 = 0x{0:X8}", response.Reserved7).AppendLine(); + #endif if(response.Cartridge) { sb.AppendLine("Media is inserted in a cartridge"); - if(response.OUT) sb.AppendLine("Media has been taken out, or inserted in, the cartridge"); - if(response.CWP) sb.AppendLine("Media is write protected"); + + if(response.OUT) + sb.AppendLine("Media has been taken out, or inserted in, the cartridge"); + + if(response.CWP) + sb.AppendLine("Media is write protected"); } else { sb.AppendLine("Media is not in a cartridge"); - #if DEBUG - if(response.OUT) sb.AppendLine("Media has out bit marked, shouldn't"); - if(response.CWP) sb.AppendLine("Media has write protection bit marked, shouldn't"); - #endif + #if DEBUG + if(response.OUT) + sb.AppendLine("Media has out bit marked, shouldn't"); + + if(response.CWP) + sb.AppendLine("Media has write protection bit marked, shouldn't"); + #endif } return sb.ToString(); @@ -129,66 +169,5 @@ namespace DiscImageChef.Decoders.Bluray public static string Prettify(byte[] CSResponse) => Prettify(Decode(CSResponse)); #endregion Public methods - - #region Public structures - public struct CartridgeStatus - { - /// - /// Bytes 0 to 1 - /// Always 6 - /// - public ushort DataLength; - /// - /// Byte 2 - /// Reserved - /// - public byte Reserved1; - /// - /// Byte 3 - /// Reserved - /// - public byte Reserved2; - /// - /// Byte 4, bit 7 - /// Medium is inserted in a cartridge - /// - public bool Cartridge; - /// - /// Byte 4, bit 6 - /// Medium taken out / put in a cartridge - /// - public bool OUT; - /// - /// Byte 4, bits 5 to 3 - /// Reserved - /// - public byte Reserved3; - /// - /// Byte 4, bit 2 - /// Cartridge sets write protection - /// - public bool CWP; - /// - /// Byte 4, bits 1 to 0 - /// Reserved - /// - public byte Reserved4; - /// - /// Byte 5 - /// Reserved - /// - public byte Reserved5; - /// - /// Byte 6 - /// Reserved - /// - public byte Reserved6; - /// - /// Byte 7 - /// Reserved - /// - public byte Reserved7; - } - #endregion Public structures } } \ No newline at end of file diff --git a/Blu-ray/DDS.cs b/Blu-ray/DDS.cs index 4bae651..30c45aa 100644 --- a/Blu-ray/DDS.cs +++ b/Blu-ray/DDS.cs @@ -38,42 +38,84 @@ using DiscImageChef.Console; namespace DiscImageChef.Decoders.Bluray { /// - /// Information from the following standards: - /// ANSI X3.304-1997 - /// T10/1048-D revision 9.0 - /// T10/1048-D revision 10a - /// T10/1228-D revision 7.0c - /// T10/1228-D revision 11a - /// T10/1363-D revision 10g - /// T10/1545-D revision 1d - /// T10/1545-D revision 5 - /// T10/1545-D revision 5a - /// T10/1675-D revision 2c - /// T10/1675-D revision 4 - /// T10/1836-D revision 2g + /// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a + /// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision + /// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] public static class DDS { #region Private constants - /// - /// Disc Definition Structure Identifier "DS" - /// + /// Disc Definition Structure Identifier "DS" const ushort DDSIdentifier = 0x4453; #endregion Private constants + #region Public structures + public struct DiscDefinitionStructure + { + /// Bytes 0 to 1 Data Length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Bytes 4 to 5 "DS" + public ushort Signature; + /// Byte 6 DDS format + public byte Format; + /// Byte 7 Reserved + public byte Reserved3; + /// Bytes 8 to 11 DDS update count + public uint UpdateCount; + /// Bytes 12 to 19 Reserved + public ulong Reserved4; + /// Bytes 20 to 23 First PSN of Drive Area + public uint DriveAreaPSN; + /// Bytes 24 to 27 Reserved + public uint Reserved5; + /// Bytes 28 to 31 First PSN of Defect List + public uint DefectListPSN; + /// Bytes 32 to 35 Reserved + public uint Reserved6; + /// Bytes 36 to 39 PSN of LSN 0 of user data area + public uint PSNofLSNZero; + /// Bytes 40 to 43 Last LSN of user data area + public uint LastUserAreaLSN; + /// Bytes 44 to 47 ISA0 size + public uint ISA0; + /// Bytes 48 to 51 OSA size + public uint OSA; + /// Bytes 52 to 55 ISA1 size + public uint ISA1; + /// Byte 56 Spare Area full flags + public byte SpareAreaFullFlags; + /// Byte 57 Reserved + public byte Reserved7; + /// Byte 58 Disc type specific field + public byte DiscTypeSpecificField1; + /// Byte 59 Reserved + public byte Reserved8; + /// Byte 60 to 63 Disc type specific field + public uint DiscTypeSpecificField2; + /// Byte 64 to 67 Reserved + public uint Reserved9; + /// Bytes 68 to 99 Status bits of INFO1/2 and PAC1/2 on L0 and L1 + public byte[] StatusBits; + /// Bytes 100 to end Disc type specific data + public byte[] DiscTypeSpecificData; + } + #endregion Public structures + #region Public methods public static DiscDefinitionStructure? Decode(byte[] DDSResponse) { - if(DDSResponse == null) return null; + if(DDSResponse == null) + return null; - DiscDefinitionStructure decoded = new DiscDefinitionStructure + var decoded = new DiscDefinitionStructure { - DataLength = BigEndianBitConverter.ToUInt16(DDSResponse, 0), - Reserved1 = DDSResponse[2], + DataLength = BigEndianBitConverter.ToUInt16(DDSResponse, 0), Reserved1 = DDSResponse[2], Reserved2 = DDSResponse[3], Signature = BigEndianBitConverter.ToUInt16(DDSResponse, 4) }; @@ -82,6 +124,7 @@ namespace DiscImageChef.Decoders.Bluray { DicConsole.DebugWriteLine("BD DDS decoder", "Found incorrect DDS signature (0x{0:X4})", decoded.Signature); + return null; } @@ -114,11 +157,12 @@ namespace DiscImageChef.Decoders.Bluray public static string Prettify(DiscDefinitionStructure? DDSResponse) { - if(DDSResponse == null) return null; + if(DDSResponse == null) + return null; DiscDefinitionStructure response = DDSResponse.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendFormat("DDS Format: 0x{0:X2}", response.Format).AppendLine(); sb.AppendFormat("DDS has ben updated {0} times", response.UpdateCount).AppendLine(); @@ -137,153 +181,39 @@ namespace DiscImageChef.Decoders.Bluray sb.AppendFormat("Blu-ray DDS Disc Type Specific Data in hex follows:"); sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.DiscTypeSpecificData, 80)); - #if DEBUG - if(response.Reserved1 != 0) sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); - if(response.Reserved2 != 0) sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); - if(response.Reserved3 != 0) sb.AppendFormat("Reserved3 = 0x{0:X2}", response.Reserved3).AppendLine(); - if(response.Reserved4 != 0) sb.AppendFormat("Reserved4 = 0x{0:X16}", response.Reserved4).AppendLine(); - if(response.Reserved5 != 0) sb.AppendFormat("Reserved5 = 0x{0:X8}", response.Reserved5).AppendLine(); - if(response.Reserved6 != 0) sb.AppendFormat("Reserved6 = 0x{0:X8}", response.Reserved6).AppendLine(); - if(response.Reserved7 != 0) sb.AppendFormat("Reserved7 = 0x{0:X2}", response.Reserved7).AppendLine(); - if(response.Reserved8 != 0) sb.AppendFormat("Reserved8 = 0x{0:X2}", response.Reserved8).AppendLine(); - if(response.Reserved9 != 0) sb.AppendFormat("Reserved9 = 0x{0:X8}", response.Reserved9).AppendLine(); - #endif + #if DEBUG + if(response.Reserved1 != 0) + sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); + + if(response.Reserved2 != 0) + sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); + + if(response.Reserved3 != 0) + sb.AppendFormat("Reserved3 = 0x{0:X2}", response.Reserved3).AppendLine(); + + if(response.Reserved4 != 0) + sb.AppendFormat("Reserved4 = 0x{0:X16}", response.Reserved4).AppendLine(); + + if(response.Reserved5 != 0) + sb.AppendFormat("Reserved5 = 0x{0:X8}", response.Reserved5).AppendLine(); + + if(response.Reserved6 != 0) + sb.AppendFormat("Reserved6 = 0x{0:X8}", response.Reserved6).AppendLine(); + + if(response.Reserved7 != 0) + sb.AppendFormat("Reserved7 = 0x{0:X2}", response.Reserved7).AppendLine(); + + if(response.Reserved8 != 0) + sb.AppendFormat("Reserved8 = 0x{0:X2}", response.Reserved8).AppendLine(); + + if(response.Reserved9 != 0) + sb.AppendFormat("Reserved9 = 0x{0:X8}", response.Reserved9).AppendLine(); + #endif return sb.ToString(); } public static string Prettify(byte[] DDSResponse) => Prettify(Decode(DDSResponse)); #endregion Public methods - - #region Public structures - public struct DiscDefinitionStructure - { - /// - /// Bytes 0 to 1 - /// Data Length - /// - public ushort DataLength; - /// - /// Byte 2 - /// Reserved - /// - public byte Reserved1; - /// - /// Byte 3 - /// Reserved - /// - public byte Reserved2; - /// - /// Bytes 4 to 5 - /// "DS" - /// - public ushort Signature; - /// - /// Byte 6 - /// DDS format - /// - public byte Format; - /// - /// Byte 7 - /// Reserved - /// - public byte Reserved3; - /// - /// Bytes 8 to 11 - /// DDS update count - /// - public uint UpdateCount; - /// - /// Bytes 12 to 19 - /// Reserved - /// - public ulong Reserved4; - /// - /// Bytes 20 to 23 - /// First PSN of Drive Area - /// - public uint DriveAreaPSN; - /// - /// Bytes 24 to 27 - /// Reserved - /// - public uint Reserved5; - /// - /// Bytes 28 to 31 - /// First PSN of Defect List - /// - public uint DefectListPSN; - /// - /// Bytes 32 to 35 - /// Reserved - /// - public uint Reserved6; - /// - /// Bytes 36 to 39 - /// PSN of LSN 0 of user data area - /// - public uint PSNofLSNZero; - /// - /// Bytes 40 to 43 - /// Last LSN of user data area - /// - public uint LastUserAreaLSN; - /// - /// Bytes 44 to 47 - /// ISA0 size - /// - public uint ISA0; - /// - /// Bytes 48 to 51 - /// OSA size - /// - public uint OSA; - /// - /// Bytes 52 to 55 - /// ISA1 size - /// - public uint ISA1; - /// - /// Byte 56 - /// Spare Area full flags - /// - public byte SpareAreaFullFlags; - /// - /// Byte 57 - /// Reserved - /// - public byte Reserved7; - /// - /// Byte 58 - /// Disc type specific field - /// - public byte DiscTypeSpecificField1; - /// - /// Byte 59 - /// Reserved - /// - public byte Reserved8; - /// - /// Byte 60 to 63 - /// Disc type specific field - /// - public uint DiscTypeSpecificField2; - /// - /// Byte 64 to 67 - /// Reserved - /// - public uint Reserved9; - /// - /// Bytes 68 to 99 - /// Status bits of INFO1/2 and PAC1/2 on L0 and L1 - /// - public byte[] StatusBits; - /// - /// Bytes 100 to end - /// Disc type specific data - /// - public byte[] DiscTypeSpecificData; - } - #endregion Public structures } } \ No newline at end of file diff --git a/Blu-ray/DI.cs b/Blu-ray/DI.cs index 7b0bf9a..0b89a80 100644 --- a/Blu-ray/DI.cs +++ b/Blu-ray/DI.cs @@ -39,54 +39,64 @@ using DiscImageChef.Console; namespace DiscImageChef.Decoders.Bluray { /// - /// Information from the following standards: - /// ANSI X3.304-1997 - /// T10/1048-D revision 9.0 - /// T10/1048-D revision 10a - /// T10/1228-D revision 7.0c - /// T10/1228-D revision 11a - /// T10/1363-D revision 10g - /// T10/1545-D revision 1d - /// T10/1545-D revision 5 - /// T10/1545-D revision 5a - /// T10/1675-D revision 2c - /// T10/1675-D revision 4 - /// T10/1836-D revision 2g + /// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a + /// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision + /// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] public static class DI { + public enum BluSize : byte + { + /// 120mm + OneTwenty = 0, /// 80mm + Eighty = 1 + } + + public enum ChannelLength : byte + { + /// 74.5nm channel or 25Gb/layer + Seventy = 1, /// 69.0nm channel or 27Gb/layer + Sixty = 2 + } + + public enum HybridLayer : byte + { + /// No hybrid layer + None = 0, /// -ROM layer + ReadOnly = 1, /// -R layer + Recordable = 2, /// -RW layer + Rewritable = 3 + } + #region Private constants const string DiscTypeBDROM = "BDO"; const string DiscTypeBDRE = "BDW"; const string DiscTypeBDR = "BDR"; - /// - /// Disc Information Unit Identifier "DI" - /// + /// Disc Information Unit Identifier "DI" const ushort DIUIdentifier = 0x4449; #endregion Private constants #region Public methods public static DiscInformation? Decode(byte[] DIResponse) { - if(DIResponse == null) return null; + if(DIResponse == null) + return null; if(DIResponse.Length != 4100) { DicConsole.DebugWriteLine("BD Disc Information decoder", "Found incorrect Blu-ray Disc Information size ({0} bytes)", DIResponse.Length); + return null; } - DiscInformation decoded = new DiscInformation + var decoded = new DiscInformation { - DataLength = BigEndianBitConverter.ToUInt16(DIResponse, 0), - Reserved1 = DIResponse[2], + DataLength = BigEndianBitConverter.ToUInt16(DIResponse, 0), Reserved1 = DIResponse[2], Reserved2 = DIResponse[3] }; @@ -95,14 +105,16 @@ namespace DiscImageChef.Decoders.Bluray while(true) { - if(offset >= 4100) break; + if(offset >= 4100) + break; - DiscInformationUnits unit = new DiscInformationUnits + var unit = new DiscInformationUnits { Signature = BigEndianBitConverter.ToUInt16(DIResponse, 0 + offset) }; - if(unit.Signature != DIUIdentifier) break; + if(unit.Signature != DIUIdentifier) + break; unit.Format = DIResponse[2 + offset]; unit.UnitsPerBlock = (byte)((DIResponse[3 + offset] & 0xF8) >> 3); @@ -125,19 +137,24 @@ namespace DiscImageChef.Decoders.Bluray unit.RecordedPolarity = DIResponse[14 + offset]; unit.Bca = (byte)(DIResponse[16 + offset] & 0x0F); unit.MaxTransfer = DIResponse[17 + offset]; + unit.LastPsn = (uint)((DIResponse[20 + offset] << 24) + (DIResponse[21 + offset] << 16) + (DIResponse[22 + offset] << 8) + DIResponse[23 + offset]); + // TODO: In -R/-RE how does this relate to layer size??? unit.FirstAun = (uint)((DIResponse[24 + offset] << 24) + (DIResponse[25 + offset] << 16) + (DIResponse[26 + offset] << 8) + DIResponse[27 + offset]); + unit.LastAun = (uint)((DIResponse[28 + offset] << 24) + (DIResponse[29 + offset] << 16) + (DIResponse[30 + offset] << 8) + DIResponse[31 + offset]); + switch(Encoding.ASCII.GetString(unit.DiscTypeIdentifier)) { case DiscTypeBDROM: { unit.FormatDependentContents = new byte[32]; Array.Copy(DIResponse, 32 + offset, unit.FormatDependentContents, 0, 32); + break; } @@ -154,6 +171,7 @@ namespace DiscImageChef.Decoders.Bluray unit.ProductRevisionNumber = DIResponse[111 + offset]; offset += 14; + break; } @@ -162,6 +180,7 @@ namespace DiscImageChef.Decoders.Bluray DicConsole.DebugWriteLine("BD Disc Information decoder", "Found unknown disc type identifier \"{0}\"", Encoding.ASCII.GetString(unit.DiscTypeIdentifier)); + break; } } @@ -171,21 +190,25 @@ namespace DiscImageChef.Decoders.Bluray offset += unit.Length; } - if(units.Count <= 0) return decoded; + if(units.Count <= 0) + return decoded; decoded.Units = new DiscInformationUnits[units.Count]; - for(int i = 0; i < units.Count; i++) decoded.Units[i] = units[i]; + + for(int i = 0; i < units.Count; i++) + decoded.Units[i] = units[i]; return decoded; } public static string Prettify(DiscInformation? DIResponse) { - if(DIResponse == null) return null; + if(DIResponse == null) + return null; DiscInformation response = DIResponse.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); foreach(DiscInformationUnits unit in response.Units) { @@ -193,41 +216,53 @@ namespace DiscImageChef.Decoders.Bluray sb.AppendFormat("DI Unit Format: 0x{0:X2}", unit.Format).AppendLine(); sb.AppendFormat("There are {0} per block", unit.UnitsPerBlock).AppendLine(); sb.AppendFormat("This DI refers to layer {0}", unit.Layer).AppendLine(); + if(Encoding.ASCII.GetString(unit.DiscTypeIdentifier) == DiscTypeBDRE) sb.AppendFormat("Legacy value: 0x{0:X2}", unit.Legacy).AppendLine(); + sb.AppendLine(unit.Continuation ? "This DI continues previous unit" : "This DI starts a new unit"); sb.AppendFormat("DI Unit is {0} bytes", unit.Length).AppendLine(); - sb.AppendFormat("Disc type identifier: \"{0}\"", Encoding.ASCII.GetString(unit.DiscTypeIdentifier)) - .AppendLine(); + + sb.AppendFormat("Disc type identifier: \"{0}\"", Encoding.ASCII.GetString(unit.DiscTypeIdentifier)). + AppendLine(); + switch(unit.DiscSize) { case BluSize.OneTwenty: sb.AppendLine("Disc size: 120mm"); + break; case BluSize.Eighty: sb.AppendLine("Disc size: 80mm"); + break; default: sb.AppendFormat("Disc size: Unknown code {0}", (byte)unit.DiscSize).AppendLine(); + break; } sb.AppendFormat("Disc class: {0}", unit.DiscClass).AppendLine(); sb.AppendFormat("Disc version: {0}", unit.DiscVersion).AppendLine(); sb.AppendFormat("This disc has {0} layers", unit.Layers).AppendLine(); + switch(unit.DvdLayer) { case HybridLayer.None: sb.AppendLine("This disc does not contain a DVD layer."); + break; case HybridLayer.ReadOnly: sb.AppendLine("This disc contains a DVD-ROM layer."); + break; case HybridLayer.Recordable: sb.AppendLine("This disc contains a DVD-R layer."); + break; case HybridLayer.Rewritable: sb.AppendLine("This disc contains a DVD-RW layer."); + break; } @@ -235,15 +270,19 @@ namespace DiscImageChef.Decoders.Bluray { case HybridLayer.None: sb.AppendLine("This disc does not contain a CD layer."); + break; case HybridLayer.ReadOnly: sb.AppendLine("This disc contains a CD-ROM layer."); + break; case HybridLayer.Recordable: sb.AppendLine("This disc contains a CD-R layer."); + break; case HybridLayer.Rewritable: sb.AppendLine("This disc contains a CD-RW layer."); + break; } @@ -251,13 +290,16 @@ namespace DiscImageChef.Decoders.Bluray { case ChannelLength.Seventy: sb.AppendLine("Disc uses a 74.5nm channel giving 25 Gb per layer."); + break; case ChannelLength.Sixty: sb.AppendLine("Disc uses a 69.0nm channel giving 27 Gb per layer."); + break; default: - sb.AppendFormat("Disc uses unknown channel length with code {0}", (byte)unit.ChannelLength) - .AppendLine(); + sb.AppendFormat("Disc uses unknown channel length with code {0}", (byte)unit.ChannelLength). + AppendLine(); + break; } @@ -265,12 +307,15 @@ namespace DiscImageChef.Decoders.Bluray { case 0: sb.AppendLine("Disc uses positive polarity."); + break; case 1: sb.AppendLine("Disc uses negative polarity."); + break; default: sb.AppendFormat("Disc uses unknown polarity with code {0}", unit.Polarity).AppendLine(); + break; } @@ -279,13 +324,16 @@ namespace DiscImageChef.Decoders.Bluray { case 0: sb.AppendLine("Recorded marks have a lower reflectivity than unrecorded ones (HTL disc)."); + break; case 1: sb.AppendLine("Recorded marks have a higher reflectivity than unrecorded ones (LTH disc)."); + break; default: sb.AppendFormat("Disc uses unknown recorded reflectivity polarity with code {0}", unit.RecordedPolarity).AppendLine(); + break; } @@ -293,31 +341,39 @@ namespace DiscImageChef.Decoders.Bluray { case 0: sb.AppendLine("Disc doesn't have a BCA."); + break; case 1: sb.AppendLine("Disc has a BCA."); + break; default: sb.AppendFormat("Disc uses unknown BCA code {0}", unit.Bca).AppendLine(); + break; } if(unit.MaxTransfer > 0) sb.AppendFormat("Disc has a maximum transfer rate of {0} Mbit/sec.", unit.MaxTransfer).AppendLine(); - else sb.AppendLine("Disc does not specify a maximum transfer rate."); + else + sb.AppendLine("Disc does not specify a maximum transfer rate."); sb.AppendFormat("Last user data PSN for disc: {0}", unit.LastPsn).AppendLine(); - sb.AppendFormat("First address unit number of data zone in this layer: {0}", unit.FirstAun) - .AppendLine(); + + sb.AppendFormat("First address unit number of data zone in this layer: {0}", unit.FirstAun). + AppendLine(); + sb.AppendFormat("Last address unit number of data zone in this layer: {0}", unit.LastAun).AppendLine(); if(Encoding.ASCII.GetString(unit.DiscTypeIdentifier) == DiscTypeBDR || Encoding.ASCII.GetString(unit.DiscTypeIdentifier) == DiscTypeBDRE) { - sb.AppendFormat("Disc manufacturer ID: \"{0}\"", Encoding.ASCII.GetString(unit.ManufacturerID)) - .AppendLine(); - sb.AppendFormat("Disc media type ID: \"{0}\"", Encoding.ASCII.GetString(unit.MediaTypeID)) - .AppendLine(); + sb.AppendFormat("Disc manufacturer ID: \"{0}\"", Encoding.ASCII.GetString(unit.ManufacturerID)). + AppendLine(); + + sb.AppendFormat("Disc media type ID: \"{0}\"", Encoding.ASCII.GetString(unit.MediaTypeID)). + AppendLine(); + sb.AppendFormat("Disc timestamp: 0x{0:X2}", unit.TimeStamp).AppendLine(); sb.AppendFormat("Disc product revison number: {0}", unit.ProductRevisionNumber).AppendLine(); } @@ -335,219 +391,86 @@ namespace DiscImageChef.Decoders.Bluray #region Public structures public struct DiscInformation { - /// - /// Bytes 0 to 1 - /// Always 4098 - /// + /// Bytes 0 to 1 Always 4098 public ushort DataLength; - /// - /// Byte 2 - /// Reserved - /// + /// Byte 2 Reserved public byte Reserved1; - /// - /// Byte 3 - /// Reserved - /// + /// Byte 3 Reserved public byte Reserved2; - /// - /// Byte 4 to 4099 - /// Disc information units - /// + /// Byte 4 to 4099 Disc information units public DiscInformationUnits[] Units; } public struct DiscInformationUnits { - /// - /// Byte 0 - /// "DI" - /// + /// Byte 0 "DI" public ushort Signature; - /// - /// Byte 2 - /// Disc information format - /// + /// Byte 2 Disc information format public byte Format; - /// - /// Byte 3, bits 7 to 3 - /// Number of DI units per block - /// + /// Byte 3, bits 7 to 3 Number of DI units per block public byte UnitsPerBlock; - /// - /// Byte 3, bits 2 to 0 - /// Layer this DI refers to - /// + /// Byte 3, bits 2 to 0 Layer this DI refers to public byte Layer; - /// - /// Byte 4 - /// Reserved for BD-ROM, legacy information for BD-R/-RE - /// + /// Byte 4 Reserved for BD-ROM, legacy information for BD-R/-RE public byte Legacy; - /// - /// Byte 5 - /// Sequence number for this DI unit - /// + /// Byte 5 Sequence number for this DI unit public byte Sequence; - /// - /// Byte 6, bit 7 - /// If set this DI is a continuation of the previous one - /// + /// Byte 6, bit 7 If set this DI is a continuation of the previous one public bool Continuation; - /// - /// Byte 6, bits 6 to 0 - /// Number of bytes used by this DI unit, should be 64 for BD-ROM and 112 for BD-R/-RE - /// + /// Byte 6, bits 6 to 0 Number of bytes used by this DI unit, should be 64 for BD-ROM and 112 for BD-R/-RE public byte Length; - /// - /// Byte 7 - /// Reserved - /// + /// Byte 7 Reserved public byte Reserved; - /// - /// Bytes 8 to 10 - /// Disc type identifier - /// + /// Bytes 8 to 10 Disc type identifier public byte[] DiscTypeIdentifier; - /// - /// Byte 11, bits 7 to 6 - /// Disc size - /// + /// Byte 11, bits 7 to 6 Disc size public BluSize DiscSize; - /// - /// Byte 11, bits 5 to 4 - /// Disc class - /// + /// Byte 11, bits 5 to 4 Disc class public byte DiscClass; - /// - /// Byte 11, bits 3 to 0 - /// Disc version - /// + /// Byte 11, bits 3 to 0 Disc version public byte DiscVersion; - /// - /// Byte 12, bits 7 to 4 - /// Layers in this disc - /// + /// Byte 12, bits 7 to 4 Layers in this disc public byte Layers; - /// - /// Byte 12, bits 3 to 0 - /// Reserved - /// + /// Byte 12, bits 3 to 0 Reserved public byte Reserved2; - /// - /// Byte 13, bits 7 to 6 - /// DVD layer - /// + /// Byte 13, bits 7 to 6 DVD layer public HybridLayer DvdLayer; - /// - /// Byte 13, bits 5 to 4 - /// CD layer - /// + /// Byte 13, bits 5 to 4 CD layer public HybridLayer CdLayer; - /// - /// Byte 13, bits 3 to 0 - /// Channel length - /// + /// Byte 13, bits 3 to 0 Channel length public ChannelLength ChannelLength; - /// - /// Byte 14 - /// Polarity - /// + /// Byte 14 Polarity public byte Polarity; - /// - /// Byte 15 - /// Recorded polarity - /// + /// Byte 15 Recorded polarity public byte RecordedPolarity; - /// - /// Byte 16, bits 7 to 4 - /// Reserved - /// + /// Byte 16, bits 7 to 4 Reserved public byte Reserved3; - /// - /// Byte 16, bits 3 to 0 - /// If 0 no BCA, if 1 BCA, rest not defined - /// + /// Byte 16, bits 3 to 0 If 0 no BCA, if 1 BCA, rest not defined public byte Bca; - /// - /// Byte 17 - /// Maximum transfer speed in megabits/second, 0 if no maximum - /// + /// Byte 17 Maximum transfer speed in megabits/second, 0 if no maximum public byte MaxTransfer; - /// - /// Bytes 18 to 19 - /// Reserved - /// + /// Bytes 18 to 19 Reserved public ushort Reserved4; - /// - /// Bytes 20 to 23 - /// Last user data PSN for disc - /// + /// Bytes 20 to 23 Last user data PSN for disc public uint LastPsn; - /// - /// Bytes 24 to 27 - /// First address unit number of data zone in this layer - /// + /// Bytes 24 to 27 First address unit number of data zone in this layer public uint FirstAun; - /// - /// Bytes 28 to 31 - /// Last address unit number of data zone in this layer - /// + /// Bytes 28 to 31 Last address unit number of data zone in this layer public uint LastAun; /// - /// Bytes 32 to 63 for BD-ROM, bytes 32 to 99 for BD-R/-RE - /// Format dependent contents, disclosed in private blu-ray specifications + /// Bytes 32 to 63 for BD-ROM, bytes 32 to 99 for BD-R/-RE Format dependent contents, disclosed in private blu-ray + /// specifications /// public byte[] FormatDependentContents; - /// - /// Bytes 100 to 105, BD-R/-RE only - /// Manufacturer ID - /// + /// Bytes 100 to 105, BD-R/-RE only Manufacturer ID public byte[] ManufacturerID; - /// - /// Bytes 106 to 108, BD-R/-RE only - /// Media type ID - /// + /// Bytes 106 to 108, BD-R/-RE only Media type ID public byte[] MediaTypeID; - /// - /// Bytes 109 to 110, BD-R/-RE only - /// Timestamp - /// + /// Bytes 109 to 110, BD-R/-RE only Timestamp public ushort TimeStamp; - /// - /// Byte 111 - /// Product revision number - /// + /// Byte 111 Product revision number public byte ProductRevisionNumber; } #endregion Public structures - - public enum BluSize : byte - { - /// 120mm - OneTwenty = 0, - /// 80mm - Eighty = 1 - } - - public enum HybridLayer : byte - { - /// No hybrid layer - None = 0, - /// -ROM layer - ReadOnly = 1, - /// -R layer - Recordable = 2, - /// -RW layer - Rewritable = 3 - } - - public enum ChannelLength : byte - { - /// 74.5nm channel or 25Gb/layer - Seventy = 1, - /// 69.0nm channel or 27Gb/layer - Sixty = 2 - } } } \ No newline at end of file diff --git a/Blu-ray/Spare.cs b/Blu-ray/Spare.cs index e51387c..c408475 100644 --- a/Blu-ray/Spare.cs +++ b/Blu-ray/Spare.cs @@ -37,43 +37,49 @@ using DiscImageChef.Console; namespace DiscImageChef.Decoders.Bluray { /// - /// Information from the following standards: - /// ANSI X3.304-1997 - /// T10/1048-D revision 9.0 - /// T10/1048-D revision 10a - /// T10/1228-D revision 7.0c - /// T10/1228-D revision 11a - /// T10/1363-D revision 10g - /// T10/1545-D revision 1d - /// T10/1545-D revision 5 - /// T10/1545-D revision 5a - /// T10/1675-D revision 2c - /// T10/1675-D revision 4 - /// T10/1836-D revision 2g + /// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a + /// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision + /// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] public static class Spare { + #region Public structures + public struct SpareAreaInformation + { + /// Bytes 0 to 1 Always 14 + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Bytes 4 to 7 Reserved + public uint Reserved3; + /// Bytes 8 to 11 Free spare blocks + public uint FreeSpareBlocks; + /// Bytes 12 to 15 Allocated spare blocks + public uint AllocatedSpareBlocks; + } + #endregion Public structures #region Public methods public static SpareAreaInformation? Decode(byte[] SAIResponse) { - if(SAIResponse == null) return null; + if(SAIResponse == null) + return null; if(SAIResponse.Length != 16) { DicConsole.DebugWriteLine("BD Spare Area Information decoder", "Found incorrect Blu-ray Spare Area Information size ({0} bytes)", SAIResponse.Length); + return null; } - SpareAreaInformation decoded = new SpareAreaInformation + var decoded = new SpareAreaInformation { - DataLength = BigEndianBitConverter.ToUInt16(SAIResponse, 0), - Reserved1 = SAIResponse[2], + DataLength = BigEndianBitConverter.ToUInt16(SAIResponse, 0), Reserved1 = SAIResponse[2], Reserved2 = SAIResponse[3], Reserved3 = BigEndianBitConverter.ToUInt32(SAIResponse, 4), FreeSpareBlocks = BigEndianBitConverter.ToUInt32(SAIResponse, 8), @@ -85,17 +91,23 @@ namespace DiscImageChef.Decoders.Bluray public static string Prettify(SpareAreaInformation? SAIResponse) { - if(SAIResponse == null) return null; + if(SAIResponse == null) + return null; SpareAreaInformation response = SAIResponse.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); - #if DEBUG - if(response.Reserved1 != 0) sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); - if(response.Reserved2 != 0) sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); - if(response.Reserved3 != 0) sb.AppendFormat("Reserved3 = 0x{0:X8}", response.Reserved3).AppendLine(); - #endif + #if DEBUG + if(response.Reserved1 != 0) + sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); + + if(response.Reserved2 != 0) + sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); + + if(response.Reserved3 != 0) + sb.AppendFormat("Reserved3 = 0x{0:X8}", response.Reserved3).AppendLine(); + #endif sb.AppendFormat("{0} free spare blocks", response.FreeSpareBlocks).AppendLine(); sb.AppendFormat("{0} allocated spare blocks", response.AllocatedSpareBlocks).AppendLine(); @@ -104,41 +116,5 @@ namespace DiscImageChef.Decoders.Bluray public static string Prettify(byte[] SAIResponse) => Prettify(Decode(SAIResponse)); #endregion Public methods - - #region Public structures - public struct SpareAreaInformation - { - /// - /// Bytes 0 to 1 - /// Always 14 - /// - public ushort DataLength; - /// - /// Byte 2 - /// Reserved - /// - public byte Reserved1; - /// - /// Byte 3 - /// Reserved - /// - public byte Reserved2; - /// - /// Bytes 4 to 7 - /// Reserved - /// - public uint Reserved3; - /// - /// Bytes 8 to 11 - /// Free spare blocks - /// - public uint FreeSpareBlocks; - /// - /// Bytes 12 to 15 - /// Allocated spare blocks - /// - public uint AllocatedSpareBlocks; - } - #endregion Public structures } } \ No newline at end of file diff --git a/CD/ATIP.cs b/CD/ATIP.cs index 76970cf..9d9f573 100644 --- a/CD/ATIP.cs +++ b/CD/ATIP.cs @@ -38,201 +38,28 @@ using DiscImageChef.Console; namespace DiscImageChef.Decoders.CD { /// - /// Information from the following standards: - /// ANSI X3.304-1997 - /// T10/1048-D revision 9.0 - /// T10/1048-D revision 10a - /// T10/1228-D revision 7.0c - /// T10/1228-D revision 11a - /// T10/1363-D revision 10g - /// T10/1545-D revision 1d - /// T10/1545-D revision 5 - /// T10/1545-D revision 5a - /// T10/1675-D revision 2c - /// T10/1675-D revision 4 - /// T10/1836-D revision 2g + /// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a + /// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision + /// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] public static class ATIP { - public struct CDATIP - { - /// - /// Bytes 1 to 0 - /// Total size of returned session information minus this field - /// - public ushort DataLength; - /// - /// Byte 2 - /// Reserved - /// - public byte Reserved1; - /// - /// Byte 3 - /// Reserved - /// - public byte Reserved2; - /// - /// Byte 4, bits 7 to 4 - /// Indicative target writing power - /// - public byte ITWP; - /// - /// Byte 4, bit 3 - /// Set if DDCD - /// - public bool DDCD; - /// - /// Byte 4, bits 2 to 0 - /// Reference speed - /// - public byte ReferenceSpeed; - /// - /// Byte 5, bit 7 - /// Always unset - /// - public bool AlwaysZero; - /// - /// Byte 5, bit 6 - /// Unrestricted media - /// - public bool URU; - /// - /// Byte 5, bits 5 to 0 - /// Reserved - /// - public byte Reserved3; - /// - /// Byte 6, bit 7 - /// Always set - /// - public bool AlwaysOne; - /// - /// Byte 6, bit 6 - /// Set if rewritable (CD-RW or DDCD-RW) - /// - public bool DiscType; - /// - /// Byte 6, bits 5 to 3 - /// Disc subtype - /// - public byte DiscSubType; - /// - /// Byte 6, bit 2 - /// A1 values are valid - /// - public bool A1Valid; - /// - /// Byte 6, bit 1 - /// A2 values are valid - /// - public bool A2Valid; - /// - /// Byte 6, bit 0 - /// A3 values are valid - /// - public bool A3Valid; - /// - /// Byte 7 - /// Reserved - /// - public byte Reserved4; - /// - /// Byte 8 - /// ATIP Start time of Lead-In (Minute) - /// - public byte LeadInStartMin; - /// - /// Byte 9 - /// ATIP Start time of Lead-In (Second) - /// - public byte LeadInStartSec; - /// - /// Byte 10 - /// ATIP Start time of Lead-In (Frame) - /// - public byte LeadInStartFrame; - /// - /// Byte 11 - /// Reserved - /// - public byte Reserved5; - /// - /// Byte 12 - /// ATIP Last possible start time of Lead-Out (Minute) - /// - public byte LeadOutStartMin; - /// - /// Byte 13 - /// ATIP Last possible start time of Lead-Out (Second) - /// - public byte LeadOutStartSec; - /// - /// Byte 14 - /// ATIP Last possible start time of Lead-Out (Frame) - /// - public byte LeadOutStartFrame; - /// - /// Byte 15 - /// Reserved - /// - public byte Reserved6; - /// - /// Bytes 16 to 18 - /// A1 values - /// - public byte[] A1Values; - /// - /// Byte 19 - /// Reserved - /// - public byte Reserved7; - /// - /// Bytes 20 to 22 - /// A2 values - /// - public byte[] A2Values; - /// - /// Byte 23 - /// Reserved - /// - public byte Reserved8; - /// - /// Bytes 24 to 26 - /// A3 values - /// - public byte[] A3Values; - /// - /// Byte 27 - /// Reserved - /// - public byte Reserved9; - /// - /// Bytes 28 to 30 - /// S4 values - /// - public byte[] S4Values; - /// - /// Byte 31 - /// Reserved - /// - public byte Reserved10; - } - public static CDATIP? Decode(byte[] CDATIPResponse) { - if(CDATIPResponse == null) return null; + if(CDATIPResponse == null) + return null; - CDATIP decoded = new CDATIP(); + var decoded = new CDATIP(); - if(CDATIPResponse.Length != 32 && CDATIPResponse.Length != 28) + if(CDATIPResponse.Length != 32 && + CDATIPResponse.Length != 28) { DicConsole.DebugWriteLine("CD ATIP decoder", "Expected CD ATIP size (32 bytes) is not received size ({0} bytes), not decoding", CDATIPResponse.Length); + return null; } @@ -275,7 +102,8 @@ namespace DiscImageChef.Decoders.CD decoded.Reserved8 = CDATIPResponse[23]; decoded.Reserved9 = CDATIPResponse[27]; - if(CDATIPResponse.Length < 32) return decoded; + if(CDATIPResponse.Length < 32) + return decoded; decoded.S4Values = new byte[3]; Array.Copy(CDATIPResponse, 28, decoded.S4Values, 0, 3); @@ -286,72 +114,89 @@ namespace DiscImageChef.Decoders.CD public static string Prettify(CDATIP? CDATIPResponse) { - if(CDATIPResponse == null) return null; + if(CDATIPResponse == null) + return null; CDATIP response = CDATIPResponse.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); if(response.DDCD) { sb.AppendFormat("Indicative Target Writing Power: 0x{0:X2}", response.ITWP).AppendLine(); sb.AppendLine(response.DiscType ? "Disc is DDCD-RW" : "Disc is DDCD-R"); + switch(response.ReferenceSpeed) { case 2: sb.AppendLine("Reference speed is 4x"); + break; case 3: sb.AppendLine("Reference speed is 8x"); + break; default: sb.AppendFormat("Reference speed set is unknown: {0}", response.ReferenceSpeed).AppendLine(); + break; } sb.AppendFormat("ATIP Start time of Lead-in: 0x{0:X6}", (response.LeadInStartMin << 16) + (response.LeadInStartSec << 8) + response.LeadInStartFrame).AppendLine(); + sb.AppendFormat("ATIP Last possible start time of Lead-out: 0x{0:X6}", (response.LeadOutStartMin << 16) + (response.LeadOutStartSec << 8) + response.LeadOutStartFrame).AppendLine(); + sb.AppendFormat("S4 value: 0x{0:X6}", - (response.S4Values[0] << 16) + (response.S4Values[1] << 8) + response.S4Values[2]) - .AppendLine(); + (response.S4Values[0] << 16) + (response.S4Values[1] << 8) + response.S4Values[2]). + AppendLine(); } else { sb.AppendFormat("Indicative Target Writing Power: 0x{0:X2}", response.ITWP & 0x07).AppendLine(); + if(response.DiscType) { switch(response.DiscSubType) { case 0: sb.AppendLine("Disc is CD-RW"); + break; case 1: sb.AppendLine("Disc is High-Speed CD-RW"); + break; case 2: sb.AppendLine("Disc is Ultra-Speed CD-RW"); + break; case 3: sb.AppendLine("Disc is Ultra-Speed+ CD-RW"); + break; case 4: sb.AppendLine("Disc is medium type B, low beta category (B-) CD-RW"); + break; case 5: sb.AppendLine("Disc is medium type B, high beta category (B+) CD-RW"); + break; case 6: sb.AppendLine("Disc is medium type C, low beta category (C-) CD-RW"); + break; case 7: sb.AppendLine("Disc is medium type C, high beta category (C+) CD-RW"); + break; default: sb.AppendFormat("Unknown CD-RW disc subtype: {0}", response.DiscSubType).AppendLine(); + break; } @@ -359,44 +204,56 @@ namespace DiscImageChef.Decoders.CD { case 1: sb.AppendLine("Reference speed is 2x"); + break; default: - sb.AppendFormat("Reference speed set is unknown: {0}", response.ReferenceSpeed) - .AppendLine(); + sb.AppendFormat("Reference speed set is unknown: {0}", response.ReferenceSpeed). + AppendLine(); + break; } } else { sb.AppendLine("Disc is CD-R"); + switch(response.DiscSubType) { case 0: sb.AppendLine("Disc is normal speed (CLV) CD-R"); + break; case 1: sb.AppendLine("Disc is high speed (CAV) CD-R"); + break; case 2: sb.AppendLine("Disc is medium type A, low beta category (A-) CD-R"); + break; case 3: sb.AppendLine("Disc is medium type A, high beta category (A+) CD-R"); + break; case 4: sb.AppendLine("Disc is medium type B, low beta category (B-) CD-R"); + break; case 5: sb.AppendLine("Disc is medium type B, high beta category (B+) CD-R"); + break; case 6: sb.AppendLine("Disc is medium type C, low beta category (C-) CD-R"); + break; case 7: sb.AppendLine("Disc is medium type C, high beta category (C+) CD-R"); + break; default: sb.AppendFormat("Unknown CD-R disc subtype: {0}", response.DiscSubType).AppendLine(); + break; } } @@ -405,41 +262,48 @@ namespace DiscImageChef.Decoders.CD sb.AppendFormat("ATIP Start time of Lead-in: {0}:{1:D2}:{2:D2}", response.LeadInStartMin, response.LeadInStartSec, response.LeadInStartFrame).AppendLine(); + sb.AppendFormat("ATIP Last possible start time of Lead-out: {0}:{1:D2}:{2:D2}", - response.LeadOutStartMin, response.LeadOutStartSec, response.LeadOutStartFrame) - .AppendLine(); + response.LeadOutStartMin, response.LeadOutStartSec, response.LeadOutStartFrame). + AppendLine(); + if(response.A1Valid) sb.AppendFormat("A1 value: 0x{0:X6}", - (response.A1Values[0] << 16) + (response.A1Values[1] << 8) + response.A1Values[2]) - .AppendLine(); + (response.A1Values[0] << 16) + (response.A1Values[1] << 8) + response.A1Values[2]). + AppendLine(); + if(response.A2Valid) sb.AppendFormat("A2 value: 0x{0:X6}", - (response.A2Values[0] << 16) + (response.A2Values[1] << 8) + response.A2Values[2]) - .AppendLine(); + (response.A2Values[0] << 16) + (response.A2Values[1] << 8) + response.A2Values[2]). + AppendLine(); + if(response.A3Valid) sb.AppendFormat("A3 value: 0x{0:X6}", - (response.A3Values[0] << 16) + (response.A3Values[1] << 8) + response.A3Values[2]) - .AppendLine(); + (response.A3Values[0] << 16) + (response.A3Values[1] << 8) + response.A3Values[2]). + AppendLine(); + if(response.S4Values != null) sb.AppendFormat("S4 value: 0x{0:X6}", - (response.S4Values[0] << 16) + (response.S4Values[1] << 8) + response.S4Values[2]) - .AppendLine(); + (response.S4Values[0] << 16) + (response.S4Values[1] << 8) + response.S4Values[2]). + AppendLine(); } - if(response.LeadInStartMin != 97) return sb.ToString(); + if(response.LeadInStartMin != 97) + return sb.ToString(); int type = response.LeadInStartFrame % 10; int frm = response.LeadInStartFrame - type; - if(response.DiscType) sb.AppendLine("Disc uses phase change"); + if(response.DiscType) + sb.AppendLine("Disc uses phase change"); else - sb.AppendLine(type < 5 - ? "Disc uses long strategy type dye (Cyanine, AZO, etc...)" + sb.AppendLine(type < 5 ? "Disc uses long strategy type dye (Cyanine, AZO, etc...)" : "Disc uses short strategy type dye (Phthalocyanine, etc...)"); string manufacturer = ManufacturerFromATIP(response.LeadInStartSec, frm); - if(manufacturer != "") sb.AppendFormat("Disc manufactured by: {0}", manufacturer).AppendLine(); + if(manufacturer != "") + sb.AppendFormat("Disc manufactured by: {0}", manufacturer).AppendLine(); return sb.ToString(); } @@ -447,6 +311,7 @@ namespace DiscImageChef.Decoders.CD public static string Prettify(byte[] CDATIPResponse) { CDATIP? decoded = Decode(CDATIPResponse); + return Prettify(decoded); } @@ -457,166 +322,169 @@ namespace DiscImageChef.Decoders.CD case 15: switch(frm) { - case 00: return "TDK Corporation"; - case 10: return "Ritek Co."; - case 20: return "Mitsubishi Chemical Corporation"; - case 30: return "NAN-YA Plastics Corporation"; + case 00: return"TDK Corporation"; + case 10: return"Ritek Co."; + case 20: return"Mitsubishi Chemical Corporation"; + case 30: return"NAN-YA Plastics Corporation"; } break; case 16: switch(frm) { - case 20: return "Shenzen SG&Gast Digital Optical Discs"; - case 30: return "Grand Advance Technology Ltd."; + case 20: return"Shenzen SG&Gast Digital Optical Discs"; + case 30: return"Grand Advance Technology Ltd."; } break; case 17: - if(frm == 00) return "Moser Baer India Limited"; + if(frm == 00) + return"Moser Baer India Limited"; break; case 18: switch(frm) { - case 10: return "Wealth Fair Investment Ltd."; - case 60: return "Taroko International Co. Ltd."; + case 10: return"Wealth Fair Investment Ltd."; + case 60: return"Taroko International Co. Ltd."; } break; case 20: - if(frm == 10) return "CDA Datenträger Albrechts GmbH"; + if(frm == 10) + return"CDA Datenträger Albrechts GmbH"; break; case 21: switch(frm) { - case 10: return "Grupo Condor S.L."; - case 30: return "Bestdisc Technology Corporation"; - case 40: return "Optical Disc Manufacturing Equipment"; - case 50: return "Sound Sound Multi-Media Development Ltd."; + case 10: return"Grupo Condor S.L."; + case 30: return"Bestdisc Technology Corporation"; + case 40: return"Optical Disc Manufacturing Equipment"; + case 50: return"Sound Sound Multi-Media Development Ltd."; } break; case 22: switch(frm) { - case 00: return "Woongjin Media Corp."; - case 10: return "Seantram Technology Inc."; - case 20: return "Advanced Digital Media"; - case 30: return "EXIMPO"; - case 40: return "CIS Technology Inc."; - case 50: return "Hong Kong Digital Technology Co., Ltd."; - case 60: return "Acer Media Technology, Inc."; + case 00: return"Woongjin Media Corp."; + case 10: return"Seantram Technology Inc."; + case 20: return"Advanced Digital Media"; + case 30: return"EXIMPO"; + case 40: return"CIS Technology Inc."; + case 50: return"Hong Kong Digital Technology Co., Ltd."; + case 60: return"Acer Media Technology, Inc."; } break; case 23: switch(frm) { - case 00: return "Matsushita Electric Industrial Co., Ltd."; - case 10: return "Doremi Media Co., Ltd."; - case 20: return "Nacar Media s.r.l."; - case 30: return "Audio Distributors Co., Ltd."; - case 40: return "Victor Company of Japan, Ltd."; - case 50: return "Optrom Inc."; - case 60: return "Customer Pressing Oosterhout"; + case 00: return"Matsushita Electric Industrial Co., Ltd."; + case 10: return"Doremi Media Co., Ltd."; + case 20: return"Nacar Media s.r.l."; + case 30: return"Audio Distributors Co., Ltd."; + case 40: return"Victor Company of Japan, Ltd."; + case 50: return"Optrom Inc."; + case 60: return"Customer Pressing Oosterhout"; } break; case 24: switch(frm) { - case 00: return "Taiyo Yuden Company Ltd."; - case 10: return "SONY Corporation"; - case 20: return "Computer Support Italy s.r.l."; - case 30: return "Unitech Japan Inc."; - case 40: return "kdg mediatech AG"; - case 50: return "Guann Yinn Co., Ltd."; - case 60: return "Harmonic Hall Optical Disc Ltd."; + case 00: return"Taiyo Yuden Company Ltd."; + case 10: return"SONY Corporation"; + case 20: return"Computer Support Italy s.r.l."; + case 30: return"Unitech Japan Inc."; + case 40: return"kdg mediatech AG"; + case 50: return"Guann Yinn Co., Ltd."; + case 60: return"Harmonic Hall Optical Disc Ltd."; } break; case 25: switch(frm) { - case 00: return "MPO"; - case 20: return "Hitachi Maxell, Ltd."; - case 30: return "Infodisc Technology Co. Ltd."; - case 40: return "Vivastar AG"; - case 50: return "AMS Technology Inc."; - case 60: return "Xcitec Inc."; + case 00: return"MPO"; + case 20: return"Hitachi Maxell, Ltd."; + case 30: return"Infodisc Technology Co. Ltd."; + case 40: return"Vivastar AG"; + case 50: return"AMS Technology Inc."; + case 60: return"Xcitec Inc."; } break; case 26: switch(frm) { - case 00: return "Fornet International Pte Ltd."; - case 10: return "POSTECH Corporation"; - case 20: return "SKC Co., Ltd."; - case 30: return "Optical Disc Corporation"; - case 40: return "FUJI Photo Film Co., Ltd."; - case 50: return "Lead Data Inc."; - case 60: return "CMC Magnetics Corporation"; + case 00: return"Fornet International Pte Ltd."; + case 10: return"POSTECH Corporation"; + case 20: return"SKC Co., Ltd."; + case 30: return"Optical Disc Corporation"; + case 40: return"FUJI Photo Film Co., Ltd."; + case 50: return"Lead Data Inc."; + case 60: return"CMC Magnetics Corporation"; } break; case 27: switch(frm) { - case 00: return "Digital Storage Technology Co., Ltd."; - case 10: return "Plasmon Data systems Ltd."; - case 20: return "Princo Corporation"; - case 30: return "Pioneer Video Corporation"; - case 40: return "Kodak Japan Ltd."; - case 50: return "Mitsui Chemicals, Inc."; - case 60: return "Ricoh Company Ltd."; + case 00: return"Digital Storage Technology Co., Ltd."; + case 10: return"Plasmon Data systems Ltd."; + case 20: return"Princo Corporation"; + case 30: return"Pioneer Video Corporation"; + case 40: return"Kodak Japan Ltd."; + case 50: return"Mitsui Chemicals, Inc."; + case 60: return"Ricoh Company Ltd."; } break; case 28: switch(frm) { - case 00: return "Opti.Me.S. S.p.A."; - case 10: return "Gigastore Corporation"; - case 20: return "Multi Media Masters & Machinary SA"; - case 30: return "Auvistar Industry Co., Ltd."; - case 40: return "King Pro Mediatek Inc."; - case 50: return "Delphi Technology Inc."; - case 60: return "Friendly CD-Tek Co."; + case 00: return"Opti.Me.S. S.p.A."; + case 10: return"Gigastore Corporation"; + case 20: return"Multi Media Masters & Machinary SA"; + case 30: return"Auvistar Industry Co., Ltd."; + case 40: return"King Pro Mediatek Inc."; + case 50: return"Delphi Technology Inc."; + case 60: return"Friendly CD-Tek Co."; } break; case 29: switch(frm) { - case 00: return "Taeil Media Co., Ltd."; - case 10: return "Vanguard Disc Inc."; - case 20: return "Unidisc Technology Co., Ltd."; - case 30: return "Hile Optical Disc Technology Corp."; - case 40: return "Viva Magnetics Ltd."; - case 50: return "General Magnetics Ltd."; + case 00: return"Taeil Media Co., Ltd."; + case 10: return"Vanguard Disc Inc."; + case 20: return"Unidisc Technology Co., Ltd."; + case 30: return"Hile Optical Disc Technology Corp."; + case 40: return"Viva Magnetics Ltd."; + case 50: return"General Magnetics Ltd."; } break; case 30: - if(frm == 10) return "CDA Datenträger Albrechts GmbH"; + if(frm == 10) + return"CDA Datenträger Albrechts GmbH"; break; case 31: switch(frm) { - case 00: return "Ritek Co."; - case 30: return "Grand Advance Technology Ltd."; + case 00: return"Ritek Co."; + case 30: return"Grand Advance Technology Ltd."; } break; case 32: switch(frm) { - case 00: return "TDK Corporation"; - case 10: return "Prodisc Technology Inc."; + case 00: return"TDK Corporation"; + case 10: return"Prodisc Technology Inc."; } break; @@ -624,96 +492,165 @@ namespace DiscImageChef.Decoders.CD switch(frm) { case 20: - case 22: return "Mitsubishi Chemical Corporation"; + case 22: return"Mitsubishi Chemical Corporation"; } break; case 42: - if(frm == 20) return "Advanced Digital Media"; + if(frm == 20) + return"Advanced Digital Media"; break; case 45: switch(frm) { - case 00: return "Fornet International Pte Ltd."; - case 10: return "Unitech Japan Inc."; - case 20: return "Acer Media Technology, Inc."; - case 40: return "CIS Technology Inc."; - case 50: return "Guann Yinn Co., Ltd."; - case 60: return "Xcitec Inc."; + case 00: return"Fornet International Pte Ltd."; + case 10: return"Unitech Japan Inc."; + case 20: return"Acer Media Technology, Inc."; + case 40: return"CIS Technology Inc."; + case 50: return"Guann Yinn Co., Ltd."; + case 60: return"Xcitec Inc."; } break; case 46: switch(frm) { - case 00: return "Taiyo Yuden Company Ltd."; - case 10: return "Hong Kong Digital Technology Co., Ltd."; - case 20: return "Multi Media Masters & Machinary SA"; - case 30: return "Computer Support Italy s.r.l."; - case 40: return "FUJI Photo Film Co., Ltd."; - case 50: return "Auvistar Industry Co., Ltd."; - case 60: return "CMC Magnetics Corporation"; + case 00: return"Taiyo Yuden Company Ltd."; + case 10: return"Hong Kong Digital Technology Co., Ltd."; + case 20: return"Multi Media Masters & Machinary SA"; + case 30: return"Computer Support Italy s.r.l."; + case 40: return"FUJI Photo Film Co., Ltd."; + case 50: return"Auvistar Industry Co., Ltd."; + case 60: return"CMC Magnetics Corporation"; } break; case 47: switch(frm) { - case 10: return "Hitachi Maxell, Ltd."; - case 20: return "Princo Corporation"; - case 40: return "POSTECH Corporation"; - case 50: return "Ritek Co."; - case 60: return "Prodisc Technology Inc."; + case 10: return"Hitachi Maxell, Ltd."; + case 20: return"Princo Corporation"; + case 40: return"POSTECH Corporation"; + case 50: return"Ritek Co."; + case 60: return"Prodisc Technology Inc."; } break; case 48: switch(frm) { - case 00: return "Ricoh Company Ltd."; - case 10: return "Kodak Japan Ltd."; - case 20: return "Plasmon Data systems Ltd."; - case 30: return "Pioneer Video Corporation"; - case 40: return "Digital Storage Technology Co., Ltd."; - case 50: return "Mitsui Chemicals, Inc."; - case 60: return "Lead Data Inc."; + case 00: return"Ricoh Company Ltd."; + case 10: return"Kodak Japan Ltd."; + case 20: return"Plasmon Data systems Ltd."; + case 30: return"Pioneer Video Corporation"; + case 40: return"Digital Storage Technology Co., Ltd."; + case 50: return"Mitsui Chemicals, Inc."; + case 60: return"Lead Data Inc."; } break; case 49: switch(frm) { - case 00: return "TDK Corporation"; - case 10: return "Gigastore Corporation"; - case 20: return "King Pro Mediatek Inc."; - case 30: return "Opti.Me.S. S.p.A."; - case 40: return "Victor Company of Japan, Ltd."; - case 60: return "Matsushita Electric Industrial Co., Ltd."; + case 00: return"TDK Corporation"; + case 10: return"Gigastore Corporation"; + case 20: return"King Pro Mediatek Inc."; + case 30: return"Opti.Me.S. S.p.A."; + case 40: return"Victor Company of Japan, Ltd."; + case 60: return"Matsushita Electric Industrial Co., Ltd."; } break; case 50: switch(frm) { - case 10: return "Vanguard Disc Inc."; - case 20: return "Mitsubishi Chemical Corporation"; - case 30: return "CDA Datenträger Albrechts GmbH"; + case 10: return"Vanguard Disc Inc."; + case 20: return"Mitsubishi Chemical Corporation"; + case 30: return"CDA Datenträger Albrechts GmbH"; } break; case 51: switch(frm) { - case 10: return "Grand Advance Technology Ltd."; - case 20: return "Infodisc Technology Co. Ltd."; - case 50: return "Hile Optical Disc Technology Corp."; + case 10: return"Grand Advance Technology Ltd."; + case 20: return"Infodisc Technology Co. Ltd."; + case 50: return"Hile Optical Disc Technology Corp."; } break; } - return ""; + return""; + } + + public struct CDATIP + { + /// Bytes 1 to 0 Total size of returned session information minus this field + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Byte 4, bits 7 to 4 Indicative target writing power + public byte ITWP; + /// Byte 4, bit 3 Set if DDCD + public bool DDCD; + /// Byte 4, bits 2 to 0 Reference speed + public byte ReferenceSpeed; + /// Byte 5, bit 7 Always unset + public bool AlwaysZero; + /// Byte 5, bit 6 Unrestricted media + public bool URU; + /// Byte 5, bits 5 to 0 Reserved + public byte Reserved3; + /// Byte 6, bit 7 Always set + public bool AlwaysOne; + /// Byte 6, bit 6 Set if rewritable (CD-RW or DDCD-RW) + public bool DiscType; + /// Byte 6, bits 5 to 3 Disc subtype + public byte DiscSubType; + /// Byte 6, bit 2 A1 values are valid + public bool A1Valid; + /// Byte 6, bit 1 A2 values are valid + public bool A2Valid; + /// Byte 6, bit 0 A3 values are valid + public bool A3Valid; + /// Byte 7 Reserved + public byte Reserved4; + /// Byte 8 ATIP Start time of Lead-In (Minute) + public byte LeadInStartMin; + /// Byte 9 ATIP Start time of Lead-In (Second) + public byte LeadInStartSec; + /// Byte 10 ATIP Start time of Lead-In (Frame) + public byte LeadInStartFrame; + /// Byte 11 Reserved + public byte Reserved5; + /// Byte 12 ATIP Last possible start time of Lead-Out (Minute) + public byte LeadOutStartMin; + /// Byte 13 ATIP Last possible start time of Lead-Out (Second) + public byte LeadOutStartSec; + /// Byte 14 ATIP Last possible start time of Lead-Out (Frame) + public byte LeadOutStartFrame; + /// Byte 15 Reserved + public byte Reserved6; + /// Bytes 16 to 18 A1 values + public byte[] A1Values; + /// Byte 19 Reserved + public byte Reserved7; + /// Bytes 20 to 22 A2 values + public byte[] A2Values; + /// Byte 23 Reserved + public byte Reserved8; + /// Bytes 24 to 26 A3 values + public byte[] A3Values; + /// Byte 27 Reserved + public byte Reserved9; + /// Bytes 28 to 30 S4 values + public byte[] S4Values; + /// Byte 31 Reserved + public byte Reserved10; } } } \ No newline at end of file diff --git a/CD/CDTextOnLeadIn.cs b/CD/CDTextOnLeadIn.cs index d100b8e..7f4025c 100644 --- a/CD/CDTextOnLeadIn.cs +++ b/CD/CDTextOnLeadIn.cs @@ -38,178 +38,57 @@ using DiscImageChef.Console; namespace DiscImageChef.Decoders.CD { /// - /// Information from the following standards: - /// ANSI X3.304-1997 - /// T10/1048-D revision 9.0 - /// T10/1048-D revision 10a - /// T10/1228-D revision 7.0c - /// T10/1228-D revision 11a - /// T10/1363-D revision 10g - /// T10/1545-D revision 1d - /// T10/1545-D revision 5 - /// T10/1545-D revision 5a - /// T10/1675-D revision 2c - /// T10/1675-D revision 4 - /// T10/1836-D revision 2g + /// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a + /// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision + /// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] public static class CDTextOnLeadIn { public enum PackTypeIndicator : byte { - /// - /// Title of the track (or album if track == 0) - /// - Title = 0x80, - /// - /// Performer - /// - Performer = 0x81, - /// - /// Songwriter - /// - Songwriter = 0x82, - /// - /// Composer - /// - Composer = 0x83, - /// - /// Arranger - /// - Arranger = 0x84, - /// - /// Message from the content provider or artist - /// - Message = 0x85, - /// - /// Disc identification information - /// - DiscIdentification = 0x86, - /// - /// Genre identification - /// - GenreIdentification = 0x87, - /// - /// Table of content information - /// - TOCInformation = 0x88, - /// - /// Second table of content information - /// - SecondTOCInformation = 0x89, - /// - /// Reserved - /// - Reserved1 = 0x8A, - /// - /// Reserved - /// - Reserved2 = 0x8B, - /// - /// Reserved - /// - Reserved3 = 0x8C, - /// - /// Reserved for content provider only - /// - ReservedForContentProvider = 0x8D, - /// - /// UPC of album or ISRC of track - /// - UPCorISRC = 0x8E, - /// - /// Size information of the block - /// + /// Title of the track (or album if track == 0) + Title = 0x80, /// Performer + Performer = 0x81, /// Songwriter + Songwriter = 0x82, /// Composer + Composer = 0x83, /// Arranger + Arranger = 0x84, /// Message from the content provider or artist + Message = 0x85, /// Disc identification information + DiscIdentification = 0x86, /// Genre identification + GenreIdentification = 0x87, /// Table of content information + TOCInformation = 0x88, /// Second table of content information + SecondTOCInformation = 0x89, /// Reserved + Reserved1 = 0x8A, /// Reserved + Reserved2 = 0x8B, /// Reserved + Reserved3 = 0x8C, /// Reserved for content provider only + ReservedForContentProvider = 0x8D, /// UPC of album or ISRC of track + UPCorISRC = 0x8E, /// Size information of the block BlockSizeInformation = 0x8F } - public struct CDText - { - /// - /// Total size of returned CD-Text information minus this field - /// - public ushort DataLength; - /// - /// Reserved - /// - public byte Reserved1; - /// - /// Reserved - /// - public byte Reserved2; - /// - /// CD-Text data packs - /// - public CDTextPack[] DataPacks; - } - - public struct CDTextPack - { - /// - /// Byte 0 - /// Pack ID1 (Pack Type) - /// - public byte HeaderID1; - /// - /// Byte 1 - /// Pack ID2 (Track number) - /// - public byte HeaderID2; - /// - /// Byte 2 - /// Pack ID3 - /// - public byte HeaderID3; - /// - /// Byte 3, bit 7 - /// Double Byte Character Code - /// - public bool DBCC; - /// - /// Byte 3, bits 6 to 4 - /// Block number - /// - public byte BlockNumber; - /// - /// Byte 3, bits 3 to 0 - /// Character position - /// - public byte CharacterPosition; - /// - /// Bytes 4 to 15 - /// Text data - /// - public byte[] TextDataField; - /// - /// Bytes 16 to 17 - /// CRC16 - /// - public ushort CRC; - } - public static CDText? Decode(byte[] CDTextResponse) { - if(CDTextResponse == null) return null; + if(CDTextResponse == null) + return null; - CDText decoded = new CDText + var decoded = new CDText { - DataLength = BigEndianBitConverter.ToUInt16(CDTextResponse, 0), - Reserved1 = CDTextResponse[2], + DataLength = BigEndianBitConverter.ToUInt16(CDTextResponse, 0), Reserved1 = CDTextResponse[2], Reserved2 = CDTextResponse[3] }; decoded.DataPacks = new CDTextPack[(decoded.DataLength - 2) / 18]; - if(decoded.DataLength == 2) return null; + if(decoded.DataLength == 2) + return null; if(decoded.DataLength + 2 != CDTextResponse.Length) { DicConsole.DebugWriteLine("CD-TEXT decoder", "Expected CD-TEXT size ({0} bytes) is not received size ({1} bytes), not decoding", decoded.DataLength + 2, CDTextResponse.Length); + return null; } @@ -231,23 +110,27 @@ namespace DiscImageChef.Decoders.CD public static string Prettify(CDText? CDTextResponse) { - if(CDTextResponse == null) return null; + if(CDTextResponse == null) + return null; - CDText response = CDTextResponse.Value; - StringBuilder sb = new StringBuilder(); + CDText response = CDTextResponse.Value; + var sb = new StringBuilder(); - #if DEBUG - if(response.Reserved1 != 0) sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); - if(response.Reserved2 != 0) sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); - #endif + #if DEBUG + if(response.Reserved1 != 0) + sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); + + if(response.Reserved2 != 0) + sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); + #endif foreach(CDTextPack descriptor in response.DataPacks) if((descriptor.HeaderID1 & 0x80) != 0x80) { // Ignore NOPs if((descriptor.HeaderID1 & 0x80) != 0) - sb.AppendFormat("Incorrect CD-Text pack type {0}, not decoding", descriptor.HeaderID1) - .AppendLine(); + sb.AppendFormat("Incorrect CD-Text pack type {0}, not decoding", descriptor.HeaderID1). + AppendLine(); } else { @@ -256,71 +139,98 @@ namespace DiscImageChef.Decoders.CD case 0x80: { sb.Append("CD-Text pack contains title for "); - if(descriptor.HeaderID2 == 0x00) sb.AppendLine("album"); - else sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine(); + + if(descriptor.HeaderID2 == 0x00) + sb.AppendLine("album"); + else + sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine(); + break; } case 0x81: { sb.Append("CD-Text pack contains performer for "); - if(descriptor.HeaderID2 == 0x00) sb.AppendLine("album"); - else sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine(); + + if(descriptor.HeaderID2 == 0x00) + sb.AppendLine("album"); + else + sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine(); + break; } case 0x82: { sb.Append("CD-Text pack contains songwriter for "); - if(descriptor.HeaderID2 == 0x00) sb.AppendLine("album"); - else sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine(); + + if(descriptor.HeaderID2 == 0x00) + sb.AppendLine("album"); + else + sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine(); + break; } case 0x83: { - if(descriptor.HeaderID2 == 0x00) sb.AppendLine("album"); - else sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine(); + if(descriptor.HeaderID2 == 0x00) + sb.AppendLine("album"); + else + sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine(); + break; } case 0x84: { sb.Append("CD-Text pack contains arranger for "); - if(descriptor.HeaderID2 == 0x00) sb.AppendLine("album"); - else sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine(); + + if(descriptor.HeaderID2 == 0x00) + sb.AppendLine("album"); + else + sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine(); + break; } case 0x85: { sb.Append("CD-Text pack contains content provider's message for "); - if(descriptor.HeaderID2 == 0x00) sb.AppendLine("album"); - else sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine(); + + if(descriptor.HeaderID2 == 0x00) + sb.AppendLine("album"); + else + sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine(); + break; } case 0x86: { sb.AppendLine("CD-Text pack contains disc identification information"); + break; } case 0x87: { sb.AppendLine("CD-Text pack contains genre identification information"); + break; } case 0x88: { sb.AppendLine("CD-Text pack contains table of contents information"); + break; } case 0x89: { sb.AppendLine("CD-Text pack contains second table of contents information"); + break; } @@ -329,25 +239,31 @@ namespace DiscImageChef.Decoders.CD case 0x8C: { sb.AppendLine("CD-Text pack contains reserved data"); + break; } case 0x8D: { sb.AppendLine("CD-Text pack contains data reserved for content provider only"); + break; } case 0x8E: { - if(descriptor.HeaderID2 == 0x00) sb.AppendLine("CD-Text pack contains UPC"); - else sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine(); + if(descriptor.HeaderID2 == 0x00) + sb.AppendLine("CD-Text pack contains UPC"); + else + sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine(); + break; } case 0x8F: { sb.AppendLine("CD-Text pack contains size block information"); + break; } } @@ -364,20 +280,25 @@ namespace DiscImageChef.Decoders.CD case 0x87: case 0x8E: { - if(descriptor.DBCC) sb.AppendLine("Double Byte Character Code is used"); + if(descriptor.DBCC) + sb.AppendLine("Double Byte Character Code is used"); + sb.AppendFormat("Block number {0}", descriptor.BlockNumber).AppendLine(); sb.AppendFormat("Character position {0}", descriptor.CharacterPosition).AppendLine(); + sb.AppendFormat("Text field: \"{0}\"", StringHandlers.CToString(descriptor.TextDataField, Encoding.GetEncoding("iso-8859-1"))).AppendLine(); + break; } default: { sb.AppendFormat("Binary contents: {0}", - PrintHex.ByteArrayToHexArrayString(descriptor.TextDataField, 28)) - .AppendLine(); + PrintHex.ByteArrayToHexArrayString(descriptor.TextDataField, 28)). + AppendLine(); + break; } } @@ -391,7 +312,40 @@ namespace DiscImageChef.Decoders.CD public static string Prettify(byte[] CDTextResponse) { CDText? decoded = Decode(CDTextResponse); + return Prettify(decoded); } + + public struct CDText + { + /// Total size of returned CD-Text information minus this field + public ushort DataLength; + /// Reserved + public byte Reserved1; + /// Reserved + public byte Reserved2; + /// CD-Text data packs + public CDTextPack[] DataPacks; + } + + public struct CDTextPack + { + /// Byte 0 Pack ID1 (Pack Type) + public byte HeaderID1; + /// Byte 1 Pack ID2 (Track number) + public byte HeaderID2; + /// Byte 2 Pack ID3 + public byte HeaderID3; + /// Byte 3, bit 7 Double Byte Character Code + public bool DBCC; + /// Byte 3, bits 6 to 4 Block number + public byte BlockNumber; + /// Byte 3, bits 3 to 0 Character position + public byte CharacterPosition; + /// Bytes 4 to 15 Text data + public byte[] TextDataField; + /// Bytes 16 to 17 CRC16 + public ushort CRC; + } } } \ No newline at end of file diff --git a/CD/Enums.cs b/CD/Enums.cs index 0890f81..1664765 100644 --- a/CD/Enums.cs +++ b/CD/Enums.cs @@ -37,65 +37,25 @@ namespace DiscImageChef.Decoders.CD [SuppressMessage("ReSharper", "MemberCanBeInternal")] public enum TocAdr : byte { - /// - /// Q Sub-channel mode information not supplied - /// - NoInformation = 0x00, - /// - /// Q Sub-channel encodes current position data - /// - CurrentPosition = 0x01, - /// - /// Q Sub-channel encodes the media catalog number - /// - MediaCatalogNumber = 0x02, - /// - /// Q Sub-channel encodes the ISRC - /// - ISRC = 0x03, - /// - /// Q Sub-channel encodes the start of an audio/data track (if found in TOC) - /// - TrackPointer = 0x01, - /// - /// Q Sub-channel encodes the start of a video track (if found in TOC) for CD-V - /// + /// Q Sub-channel mode information not supplied + NoInformation = 0x00, /// Q Sub-channel encodes current position data + CurrentPosition = 0x01, /// Q Sub-channel encodes the media catalog number + MediaCatalogNumber = 0x02, /// Q Sub-channel encodes the ISRC + ISRC = 0x03, /// Q Sub-channel encodes the start of an audio/data track (if found in TOC) + TrackPointer = 0x01, /// Q Sub-channel encodes the start of a video track (if found in TOC) for CD-V VideoTrackPointer = 0x04 } public enum TocControl : byte { - /// - /// Stereo audio, no pre-emphasis - /// - TwoChanNoPreEmph = 0x00, - /// - /// Stereo audio with pre-emphasis - /// - TwoChanPreEmph = 0x01, - /// - /// If mask applied, track can be copied - /// - CopyPermissionMask = 0x02, - /// - /// Data track, recorded uninterrumpted - /// - DataTrack = 0x04, - /// - /// Data track, recorded incrementally - /// - DataTrackIncremental = 0x05, - /// - /// Quadraphonic audio, no pre-emphasis - /// - FourChanNoPreEmph = 0x08, - /// - /// Quadraphonic audio with pre-emphasis - /// - FourChanPreEmph = 0x09, - /// - /// Reserved mask - /// + /// Stereo audio, no pre-emphasis + TwoChanNoPreEmph = 0x00, /// Stereo audio with pre-emphasis + TwoChanPreEmph = 0x01, /// If mask applied, track can be copied + CopyPermissionMask = 0x02, /// Data track, recorded uninterrumpted + DataTrack = 0x04, /// Data track, recorded incrementally + DataTrackIncremental = 0x05, /// Quadraphonic audio, no pre-emphasis + FourChanNoPreEmph = 0x08, /// Quadraphonic audio with pre-emphasis + FourChanPreEmph = 0x09, /// Reserved mask ReservedMask = 0x0C } } \ No newline at end of file diff --git a/CD/FullTOC.cs b/CD/FullTOC.cs index 6440f49..503031f 100644 --- a/CD/FullTOC.cs +++ b/CD/FullTOC.cs @@ -37,25 +37,13 @@ using DiscImageChef.Console; namespace DiscImageChef.Decoders.CD { /// - /// Information from the following standards: - /// ANSI X3.304-1997 - /// T10/1048-D revision 9.0 - /// T10/1048-D revision 10a - /// T10/1228-D revision 7.0c - /// T10/1228-D revision 11a - /// T10/1363-D revision 10g - /// T10/1545-D revision 1d - /// T10/1545-D revision 5 - /// T10/1545-D revision 5a - /// T10/1675-D revision 2c - /// T10/1675-D revision 4 - /// T10/1836-D revision 2g - /// ISO/IEC 61104: Compact disc video system - 12 cm CD-V - /// ISO/IEC 60908: Audio recording - Compact disc digital audio system + /// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a + /// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision + /// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g ISO/IEC 61104: Compact + /// disc video system - 12 cm CD-V ISO/IEC 60908: Audio recording - Compact disc digital audio system /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static class FullTOC { const string StereoNoPre = "Stereo audio track with no pre-emphasis"; @@ -65,98 +53,15 @@ namespace DiscImageChef.Decoders.CD const string DataUnintrp = "Data track, recorded uninterrupted"; const string DataIncrtly = "Data track, recorded incrementally"; - public struct CDFullTOC - { - /// - /// Total size of returned session information minus this field - /// - public ushort DataLength; - /// - /// First complete session number in hex - /// - public byte FirstCompleteSession; - /// - /// Last complete session number in hex - /// - public byte LastCompleteSession; - /// - /// Track descriptors - /// - public TrackDataDescriptor[] TrackDescriptors; - } - - public struct TrackDataDescriptor - { - /// - /// Byte 0 - /// Session number in hex - /// - public byte SessionNumber; - /// - /// Byte 1, bits 7 to 4 - /// Type of information in Q subchannel of block where this TOC entry was found - /// - public byte ADR; - /// - /// Byte 1, bits 3 to 0 - /// Track attributes - /// - public byte CONTROL; - /// - /// Byte 2 - /// - public byte TNO; - /// - /// Byte 3 - /// - public byte POINT; - /// - /// Byte 4 - /// - public byte Min; - /// - /// Byte 5 - /// - public byte Sec; - /// - /// Byte 6 - /// - public byte Frame; - /// - /// Byte 7, CD only - /// - public byte Zero; - /// - /// Byte 7, bits 7 to 4, DDCD only - /// - public byte HOUR; - /// - /// Byte 7, bits 3 to 0, DDCD only - /// - public byte PHOUR; - /// - /// Byte 8 - /// - public byte PMIN; - /// - /// Byte 9 - /// - public byte PSEC; - /// - /// Byte 10 - /// - public byte PFRAME; - } - public static CDFullTOC? Decode(byte[] CDFullTOCResponse) { - if(CDFullTOCResponse == null) return null; + if(CDFullTOCResponse == null) + return null; - CDFullTOC decoded = new CDFullTOC + var decoded = new CDFullTOC { DataLength = BigEndianBitConverter.ToUInt16(CDFullTOCResponse, 0), - FirstCompleteSession = CDFullTOCResponse[2], - LastCompleteSession = CDFullTOCResponse[3] + FirstCompleteSession = CDFullTOCResponse[2], LastCompleteSession = CDFullTOCResponse[3] }; decoded.TrackDescriptors = new TrackDataDescriptor[(decoded.DataLength - 2) / 11]; @@ -166,6 +71,7 @@ namespace DiscImageChef.Decoders.CD DicConsole.DebugWriteLine("CD full TOC decoder", "Expected CDFullTOC size ({0} bytes) is not received size ({1} bytes), not decoding", decoded.DataLength + 2, CDFullTOCResponse.Length); + return null; } @@ -192,16 +98,18 @@ namespace DiscImageChef.Decoders.CD public static string Prettify(CDFullTOC? CDFullTOCResponse) { - if(CDFullTOCResponse == null) return null; + if(CDFullTOCResponse == null) + return null; CDFullTOC response = CDFullTOCResponse.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); int lastSession = 0; sb.AppendFormat("First complete session number: {0}", response.FirstCompleteSession).AppendLine(); sb.AppendFormat("Last complete session number: {0}", response.LastCompleteSession).AppendLine(); + foreach(TrackDataDescriptor descriptor in response.TrackDescriptors) if((descriptor.CONTROL & 0x08) == 0x08 || descriptor.ADR != 1 && descriptor.ADR != 5 && descriptor.ADR != 4 && descriptor.ADR != 6 || @@ -240,31 +148,40 @@ namespace DiscImageChef.Decoders.CD case 0xA0 when descriptor.ADR == 4: { sb.AppendFormat("First video track number: {0}", descriptor.PMIN).AppendLine(); + switch(descriptor.PSEC) { case 0x10: sb.AppendLine("CD-V single in NTSC format with digital stereo sound"); + break; case 0x11: sb.AppendLine("CD-V single in NTSC format with digital bilingual sound"); + break; case 0x12: sb.AppendLine("CD-V disc in NTSC format with digital stereo sound"); + break; case 0x13: sb.AppendLine("CD-V disc in NTSC format with digital bilingual sound"); + break; case 0x20: sb.AppendLine("CD-V single in PAL format with digital stereo sound"); + break; case 0x21: sb.AppendLine("CD-V single in PAL format with digital bilingual sound"); + break; case 0x22: sb.AppendLine("CD-V disc in PAL format with digital stereo sound"); + break; case 0x23: sb.AppendLine("CD-V disc in PAL format with digital bilingual sound"); + break; } @@ -274,63 +191,80 @@ namespace DiscImageChef.Decoders.CD case 0xA0 when descriptor.ADR == 1: { sb.AppendFormat("First track number: {0} (", descriptor.PMIN); + switch((TocControl)(descriptor.CONTROL & 0x0D)) { case TocControl.TwoChanNoPreEmph: sb.Append(StereoNoPre); + break; case TocControl.TwoChanPreEmph: sb.Append(StereoPreEm); + break; case TocControl.FourChanNoPreEmph: sb.Append(QuadNoPreEm); + break; case TocControl.FourChanPreEmph: sb.Append(QuadPreEmph); + break; case TocControl.DataTrack: sb.Append(DataUnintrp); + break; case TocControl.DataTrackIncremental: sb.Append(DataIncrtly); + break; } sb.AppendLine(")"); sb.AppendFormat("Disc type: {0}", descriptor.PSEC).AppendLine(); + //sb.AppendFormat("Absolute time: {3:D2}:{0:D2}:{1:D2}:{2:D2}", descriptor.Min, descriptor.Sec, descriptor.Frame, descriptor.HOUR).AppendLine(); break; } case 0xA1 when descriptor.ADR == 4: sb.AppendFormat("Last video track number: {0}", descriptor.PMIN).AppendLine(); + break; case 0xA1 when descriptor.ADR == 1: { sb.AppendFormat("Last track number: {0} (", descriptor.PMIN); + switch((TocControl)(descriptor.CONTROL & 0x0D)) { case TocControl.TwoChanNoPreEmph: sb.Append(StereoNoPre); + break; case TocControl.TwoChanPreEmph: sb.Append(StereoPreEm); + break; case TocControl.FourChanNoPreEmph: sb.Append(QuadNoPreEm); + break; case TocControl.FourChanPreEmph: sb.Append(QuadPreEmph); + break; case TocControl.DataTrack: sb.Append(DataUnintrp); + break; case TocControl.DataTrackIncremental: sb.Append(DataIncrtly); + break; } sb.AppendLine(")"); + //sb.AppendFormat("Absolute time: {3:D2}:{0:D2}:{1:D2}:{2:D2}", descriptor.Min, descriptor.Sec, descriptor.Frame, descriptor.HOUR).AppendLine(); break; } @@ -343,8 +277,9 @@ namespace DiscImageChef.Decoders.CD descriptor.PHOUR).AppendLine(); else sb.AppendFormat("Lead-out start position: {0:D2}:{1:D2}:{2:D2}", - descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME) - .AppendLine(); + descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME). + AppendLine(); + //sb.AppendFormat("Absolute time: {3:D2}:{0:D2}:{1:D2}:{2:D2}", descriptor.Min, descriptor.Sec, descriptor.Frame, descriptor.HOUR).AppendLine(); switch((TocControl)(descriptor.CONTROL & 0x0D)) @@ -354,10 +289,12 @@ namespace DiscImageChef.Decoders.CD case TocControl.FourChanNoPreEmph: case TocControl.FourChanPreEmph: sb.AppendLine("Lead-out is audio type"); + break; case TocControl.DataTrack: case TocControl.DataTrackIncremental: sb.AppendLine("Lead-out is data type"); + break; } @@ -366,21 +303,24 @@ namespace DiscImageChef.Decoders.CD case 0xF0: { - sb.AppendFormat("Book type: 0x{0:X2}", descriptor.PMIN); - sb.AppendFormat("Material type: 0x{0:X2}", descriptor.PSEC); + sb.AppendFormat("Book type: 0x{0:X2}", descriptor.PMIN); + sb.AppendFormat("Material type: 0x{0:X2}", descriptor.PSEC); sb.AppendFormat("Moment of inertia: 0x{0:X2}", descriptor.PFRAME); + if(descriptor.PHOUR > 0) sb.AppendFormat("Absolute time: {3:D2}:{0:D2}:{1:D2}:{2:D2}", descriptor.Min, descriptor.Sec, descriptor.Frame, descriptor.HOUR).AppendLine(); else sb.AppendFormat("Absolute time: {0:D2}:{1:D2}:{2:D2}", descriptor.Min, descriptor.Sec, descriptor.Frame).AppendLine(); + break; } default: { - if(descriptor.POINT >= 0x01 && descriptor.POINT <= 0x63) + if(descriptor.POINT >= 0x01 && + descriptor.POINT <= 0x63) if(descriptor.ADR == 4) sb.AppendFormat("Video track {3} starts at: {0:D2}:{1:D2}:{2:D2}", descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME, @@ -391,7 +331,8 @@ namespace DiscImageChef.Decoders.CD if((TocControl)(descriptor.CONTROL & 0x0D) == TocControl.DataTrack || (TocControl)(descriptor.CONTROL & 0x0D) == - TocControl.DataTrackIncremental) type = "Data"; + TocControl.DataTrackIncremental) + type = "Data"; if(descriptor.PHOUR > 0) sb.AppendFormat("{5} track {3} starts at: {4:D2}:{0:D2}:{1:D2}:{2:D2} (", @@ -406,21 +347,27 @@ namespace DiscImageChef.Decoders.CD { case TocControl.TwoChanNoPreEmph: sb.Append(StereoNoPre); + break; case TocControl.TwoChanPreEmph: sb.Append(StereoPreEm); + break; case TocControl.FourChanNoPreEmph: sb.Append(QuadNoPreEm); + break; case TocControl.FourChanPreEmph: sb.Append(QuadPreEmph); + break; case TocControl.DataTrack: sb.Append(DataUnintrp); + break; case TocControl.DataTrackIncremental: sb.Append(DataIncrtly); + break; } @@ -457,24 +404,26 @@ namespace DiscImageChef.Decoders.CD { if(descriptor.PHOUR > 0) { - sb - .AppendFormat("Start of next possible program in the recordable area of the disc: {3:D2}:{0:D2}:{1:D2}:{2:D2}", + sb. + AppendFormat("Start of next possible program in the recordable area of the disc: {3:D2}:{0:D2}:{1:D2}:{2:D2}", descriptor.Min, descriptor.Sec, descriptor.Frame, descriptor.HOUR).AppendLine(); - sb - .AppendFormat("Maximum start of outermost Lead-out in the recordable area of the disc: {3:D2}:{0:D2}:{1:D2}:{2:D2}", + + sb. + AppendFormat("Maximum start of outermost Lead-out in the recordable area of the disc: {3:D2}:{0:D2}:{1:D2}:{2:D2}", descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME, descriptor.PHOUR).AppendLine(); } else { - sb - .AppendFormat("Start of next possible program in the recordable area of the disc: {0:D2}:{1:D2}:{2:D2}", + sb. + AppendFormat("Start of next possible program in the recordable area of the disc: {0:D2}:{1:D2}:{2:D2}", descriptor.Min, descriptor.Sec, descriptor.Frame).AppendLine(); - sb - .AppendFormat("Maximum start of outermost Lead-out in the recordable area of the disc: {0:D2}:{1:D2}:{2:D2}", - descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME) - .AppendLine(); + + sb. + AppendFormat("Maximum start of outermost Lead-out in the recordable area of the disc: {0:D2}:{1:D2}:{2:D2}", + descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME). + AppendLine(); } break; @@ -482,9 +431,11 @@ namespace DiscImageChef.Decoders.CD case 0xB1: { - sb.AppendFormat("Number of skip interval pointers: {0}", descriptor.PMIN) - .AppendLine(); + sb.AppendFormat("Number of skip interval pointers: {0}", descriptor.PMIN). + AppendLine(); + sb.AppendFormat("Number of skip track pointers: {0}", descriptor.PSEC).AppendLine(); + break; } @@ -499,22 +450,25 @@ namespace DiscImageChef.Decoders.CD sb.AppendFormat("Skip track {0}", descriptor.PMIN).AppendLine(); sb.AppendFormat("Skip track {0}", descriptor.PSEC).AppendLine(); sb.AppendFormat("Skip track {0}", descriptor.PFRAME).AppendLine(); + break; } case 0xC0: { sb.AppendFormat("Optimum recording power: 0x{0:X2}", descriptor.Min).AppendLine(); + if(descriptor.PHOUR > 0) - sb - .AppendFormat("Start time of the first Lead-in area in the disc: {3:D2}:{0:D2}:{1:D2}:{2:D2}", + sb. + AppendFormat("Start time of the first Lead-in area in the disc: {3:D2}:{0:D2}:{1:D2}:{2:D2}", descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME, descriptor.PHOUR).AppendLine(); else - sb - .AppendFormat("Start time of the first Lead-in area in the disc: {0:D2}:{1:D2}:{2:D2}", - descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME) - .AppendLine(); + sb. + AppendFormat("Start time of the first Lead-in area in the disc: {0:D2}:{1:D2}:{2:D2}", + descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME). + AppendLine(); + break; } @@ -528,6 +482,7 @@ namespace DiscImageChef.Decoders.CD sb.AppendFormat("PMIN = {0}", descriptor.PMIN).AppendLine(); sb.AppendFormat("PSEC = {0}", descriptor.PSEC).AppendLine(); sb.AppendFormat("PFRAME = {0}", descriptor.PFRAME).AppendLine(); + break; } @@ -535,23 +490,25 @@ namespace DiscImageChef.Decoders.CD { if(descriptor.PHOUR > 0) { - sb - .AppendFormat("Start position of outer part lead-in area: {3:D2}:{0:D2}:{1:D2}:{2:D2}", + sb. + AppendFormat("Start position of outer part lead-in area: {3:D2}:{0:D2}:{1:D2}:{2:D2}", descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME, descriptor.PHOUR).AppendLine(); - sb - .AppendFormat("Stop position of inner part lead-out area: {3:D2}:{0:D2}:{1:D2}:{2:D2}", + + sb. + AppendFormat("Stop position of inner part lead-out area: {3:D2}:{0:D2}:{1:D2}:{2:D2}", descriptor.Min, descriptor.Sec, descriptor.Frame, descriptor.HOUR).AppendLine(); } else { - sb - .AppendFormat("Start position of outer part lead-in area: {0:D2}:{1:D2}:{2:D2}", - descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME) - .AppendLine(); - sb - .AppendFormat("Stop position of inner part lead-out area: {0:D2}:{1:D2}:{2:D2}", + sb. + AppendFormat("Start position of outer part lead-in area: {0:D2}:{1:D2}:{2:D2}", + descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME). + AppendLine(); + + sb. + AppendFormat("Stop position of inner part lead-out area: {0:D2}:{1:D2}:{2:D2}", descriptor.Min, descriptor.Sec, descriptor.Frame).AppendLine(); } @@ -560,14 +517,16 @@ namespace DiscImageChef.Decoders.CD default: { - if(descriptor.POINT >= 0x01 && descriptor.POINT <= 0x40) + if(descriptor.POINT >= 0x01 && + descriptor.POINT <= 0x40) { - sb - .AppendFormat("Start time for interval that should be skipped: {0:D2}:{1:D2}:{2:D2}", - descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME) - .AppendLine(); - sb - .AppendFormat("Ending time for interval that should be skipped: {0:D2}:{1:D2}:{2:D2}", + sb. + AppendFormat("Start time for interval that should be skipped: {0:D2}:{1:D2}:{2:D2}", + descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME). + AppendLine(); + + sb. + AppendFormat("Ending time for interval that should be skipped: {0:D2}:{1:D2}:{2:D2}", descriptor.Min, descriptor.Sec, descriptor.Frame).AppendLine(); } else @@ -597,6 +556,7 @@ namespace DiscImageChef.Decoders.CD { uint id = (uint)((descriptor.Min << 16) + (descriptor.Sec << 8) + descriptor.Frame); sb.AppendFormat("Disc ID: {0:X6}", id & 0x00FFFFFF).AppendLine(); + break; } } @@ -608,7 +568,52 @@ namespace DiscImageChef.Decoders.CD public static string Prettify(byte[] CDFullTOCResponse) { CDFullTOC? decoded = Decode(CDFullTOCResponse); + return Prettify(decoded); } + + public struct CDFullTOC + { + /// Total size of returned session information minus this field + public ushort DataLength; + /// First complete session number in hex + public byte FirstCompleteSession; + /// Last complete session number in hex + public byte LastCompleteSession; + /// Track descriptors + public TrackDataDescriptor[] TrackDescriptors; + } + + public struct TrackDataDescriptor + { + /// Byte 0 Session number in hex + public byte SessionNumber; + /// Byte 1, bits 7 to 4 Type of information in Q subchannel of block where this TOC entry was found + public byte ADR; + /// Byte 1, bits 3 to 0 Track attributes + public byte CONTROL; + /// Byte 2 + public byte TNO; + /// Byte 3 + public byte POINT; + /// Byte 4 + public byte Min; + /// Byte 5 + public byte Sec; + /// Byte 6 + public byte Frame; + /// Byte 7, CD only + public byte Zero; + /// Byte 7, bits 7 to 4, DDCD only + public byte HOUR; + /// Byte 7, bits 3 to 0, DDCD only + public byte PHOUR; + /// Byte 8 + public byte PMIN; + /// Byte 9 + public byte PSEC; + /// Byte 10 + public byte PFRAME; + } } } \ No newline at end of file diff --git a/CD/PMA.cs b/CD/PMA.cs index 7fd4980..339e2a4 100644 --- a/CD/PMA.cs +++ b/CD/PMA.cs @@ -37,112 +37,22 @@ using DiscImageChef.Console; namespace DiscImageChef.Decoders.CD { /// - /// Information from the following standards: - /// ANSI X3.304-1997 - /// T10/1048-D revision 9.0 - /// T10/1048-D revision 10a - /// T10/1228-D revision 7.0c - /// T10/1228-D revision 11a - /// T10/1363-D revision 10g - /// T10/1545-D revision 1d - /// T10/1545-D revision 5 - /// T10/1545-D revision 5a - /// T10/1675-D revision 2c - /// T10/1675-D revision 4 - /// T10/1836-D revision 2g + /// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a + /// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision + /// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static class PMA { - public struct CDPMA - { - /// - /// Total size of returned session information minus this field - /// - public ushort DataLength; - /// - /// Reserved - /// - public byte Reserved1; - /// - /// Reserved - /// - public byte Reserved2; - /// - /// Track descriptors - /// - public CDPMADescriptors[] PMADescriptors; - } - - public struct CDPMADescriptors - { - /// - /// Byte 0 - /// Reserved - /// - public byte Reserved; - /// - /// Byte 1, bits 7 to 4 - /// Type of information in Q subchannel of block where this TOC entry was found - /// - public byte ADR; - /// - /// Byte 1, bits 3 to 0 - /// Track attributes - /// - public byte CONTROL; - /// - /// Byte 2 - /// - public byte TNO; - /// - /// Byte 3 - /// - public byte POINT; - /// - /// Byte 4 - /// - public byte Min; - /// - /// Byte 5 - /// - public byte Sec; - /// - /// Byte 6 - /// - public byte Frame; - /// - /// Byte 7, bits 7 to 4 - /// - public byte HOUR; - /// - /// Byte 7, bits 3 to 0 - /// - public byte PHOUR; - /// - /// Byte 8 - /// - public byte PMIN; - /// - /// Byte 9 - /// - public byte PSEC; - /// - /// Byte 10 - /// - public byte PFRAME; - } - public static CDPMA? Decode(byte[] CDPMAResponse) { - if(CDPMAResponse == null) return null; + if(CDPMAResponse == null) + return null; - CDPMA decoded = new CDPMA + var decoded = new CDPMA { - DataLength = BigEndianBitConverter.ToUInt16(CDPMAResponse, 0), - Reserved1 = CDPMAResponse[2], + DataLength = BigEndianBitConverter.ToUInt16(CDPMAResponse, 0), Reserved1 = CDPMAResponse[2], Reserved2 = CDPMAResponse[3] }; @@ -153,6 +63,7 @@ namespace DiscImageChef.Decoders.CD DicConsole.DebugWriteLine("CD PMA decoder", "Expected CDPMA size ({0} bytes) is not received size ({1} bytes), not decoding", decoded.DataLength + 2, CDPMAResponse.Length); + return null; } @@ -178,22 +89,27 @@ namespace DiscImageChef.Decoders.CD public static string Prettify(CDPMA? CDPMAResponse) { - if(CDPMAResponse == null) return null; + if(CDPMAResponse == null) + return null; CDPMA response = CDPMAResponse.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); - #if DEBUG - if(response.Reserved1 != 0) sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); - if(response.Reserved2 != 0) sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); - #endif + #if DEBUG + if(response.Reserved1 != 0) + sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); + + if(response.Reserved2 != 0) + sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); + #endif foreach(CDPMADescriptors descriptor in response.PMADescriptors) { - #if DEBUG - if(descriptor.Reserved != 0) sb.AppendFormat("Reserved = 0x{0:X2}", descriptor.Reserved).AppendLine(); - #endif + #if DEBUG + if(descriptor.Reserved != 0) + sb.AppendFormat("Reserved = 0x{0:X2}", descriptor.Reserved).AppendLine(); + #endif switch(descriptor.ADR) { @@ -201,25 +117,32 @@ namespace DiscImageChef.Decoders.CD if(descriptor.POINT > 0) { sb.AppendFormat("Track {0}", descriptor.POINT); + switch((TocControl)(descriptor.CONTROL & 0x0D)) { case TocControl.TwoChanNoPreEmph: sb.Append(" (Stereo audio track with no pre-emphasis)"); + break; case TocControl.TwoChanPreEmph: sb.Append(" (Stereo audio track with 50/15 μs pre-emphasis)"); + break; case TocControl.FourChanNoPreEmph: sb.Append(" (Quadraphonic audio track with no pre-emphasis)"); + break; case TocControl.FourChanPreEmph: sb.Append(" (Quadraphonic audio track with 50/15 μs pre-emphasis)"); + break; case TocControl.DataTrack: sb.Append(" (Data track, recorded uninterrupted)"); + break; case TocControl.DataTrackIncremental: sb.Append(" (Data track, recorded incrementally)"); + break; } @@ -229,6 +152,7 @@ namespace DiscImageChef.Decoders.CD else sb.AppendFormat(" starts at {0:D2}:{1:D2}:{2:D2}", descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME); + if(descriptor.PHOUR > 0) sb.AppendFormat(" and ends at {3}:{0:D2}:{1:D2}:{2:D2}", descriptor.Min, descriptor.Sec, descriptor.Frame, descriptor.HOUR); @@ -238,60 +162,100 @@ namespace DiscImageChef.Decoders.CD sb.AppendLine(); } - else goto default; + else + goto default; break; case 2: uint id = (uint)((descriptor.Min << 16) + (descriptor.Sec << 8) + descriptor.Frame); sb.AppendFormat("Disc ID: {0:X6}", id & 0x00FFFFFF).AppendLine(); + break; case 3: sb.AppendFormat("Skip track assignment {0} says that tracks ", descriptor.POINT); - if(descriptor.Min > 0) sb.AppendFormat("{0} ", descriptor.Min); - if(descriptor.Sec > 0) sb.AppendFormat("{0} ", descriptor.Sec); - if(descriptor.Frame > 0) sb.AppendFormat("{0} ", descriptor.Frame); - if(descriptor.PMIN > 0) sb.AppendFormat("{0} ", descriptor.PMIN); - if(descriptor.PSEC > 0) sb.AppendFormat("{0} ", descriptor.PSEC); - if(descriptor.PFRAME > 0) sb.AppendFormat("{0} ", descriptor.PFRAME); + + if(descriptor.Min > 0) + sb.AppendFormat("{0} ", descriptor.Min); + + if(descriptor.Sec > 0) + sb.AppendFormat("{0} ", descriptor.Sec); + + if(descriptor.Frame > 0) + sb.AppendFormat("{0} ", descriptor.Frame); + + if(descriptor.PMIN > 0) + sb.AppendFormat("{0} ", descriptor.PMIN); + + if(descriptor.PSEC > 0) + sb.AppendFormat("{0} ", descriptor.PSEC); + + if(descriptor.PFRAME > 0) + sb.AppendFormat("{0} ", descriptor.PFRAME); + sb.AppendLine("should be skipped"); + break; case 4: sb.AppendFormat("Unskip track assignment {0} says that tracks ", descriptor.POINT); - if(descriptor.Min > 0) sb.AppendFormat("{0} ", descriptor.Min); - if(descriptor.Sec > 0) sb.AppendFormat("{0} ", descriptor.Sec); - if(descriptor.Frame > 0) sb.AppendFormat("{0} ", descriptor.Frame); - if(descriptor.PMIN > 0) sb.AppendFormat("{0} ", descriptor.PMIN); - if(descriptor.PSEC > 0) sb.AppendFormat("{0} ", descriptor.PSEC); - if(descriptor.PFRAME > 0) sb.AppendFormat("{0} ", descriptor.PFRAME); + + if(descriptor.Min > 0) + sb.AppendFormat("{0} ", descriptor.Min); + + if(descriptor.Sec > 0) + sb.AppendFormat("{0} ", descriptor.Sec); + + if(descriptor.Frame > 0) + sb.AppendFormat("{0} ", descriptor.Frame); + + if(descriptor.PMIN > 0) + sb.AppendFormat("{0} ", descriptor.PMIN); + + if(descriptor.PSEC > 0) + sb.AppendFormat("{0} ", descriptor.PSEC); + + if(descriptor.PFRAME > 0) + sb.AppendFormat("{0} ", descriptor.PFRAME); + sb.AppendLine("should not be skipped"); + break; case 5: sb.AppendFormat("Skip time interval assignment {0} says that from ", descriptor.POINT); + if(descriptor.PHOUR > 0) sb.AppendFormat("{3}:{0:D2}:{1:D2}:{2:D2} to ", descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME, descriptor.PHOUR); else sb.AppendFormat("{0:D2}:{1:D2}:{2:D2} to ", descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME); + if(descriptor.PHOUR > 0) sb.AppendFormat("{3}:{0:D2}:{1:D2}:{2:D2} ", descriptor.Min, descriptor.Sec, descriptor.Frame, descriptor.HOUR); - else sb.AppendFormat("{0:D2}:{1:D2}:{2:D2} ", descriptor.Min, descriptor.Sec, descriptor.Frame); + else + sb.AppendFormat("{0:D2}:{1:D2}:{2:D2} ", descriptor.Min, descriptor.Sec, descriptor.Frame); + sb.AppendLine("should be skipped"); + break; case 6: sb.AppendFormat("Unskip time interval assignment {0} says that from ", descriptor.POINT); + if(descriptor.PHOUR > 0) sb.AppendFormat("{3}:{0:D2}:{1:D2}:{2:D2} to ", descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME, descriptor.PHOUR); else sb.AppendFormat("{0:D2}:{1:D2}:{2:D2} to ", descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME); + if(descriptor.PHOUR > 0) sb.AppendFormat("{3}:{0:D2}:{1:D2}:{2:D2} ", descriptor.Min, descriptor.Sec, descriptor.Frame, descriptor.HOUR); - else sb.AppendFormat("{0:D2}:{1:D2}:{2:D2} ", descriptor.Min, descriptor.Sec, descriptor.Frame); + else + sb.AppendFormat("{0:D2}:{1:D2}:{2:D2} ", descriptor.Min, descriptor.Sec, descriptor.Frame); + sb.AppendLine("should not be skipped"); + break; default: @@ -307,6 +271,7 @@ namespace DiscImageChef.Decoders.CD sb.AppendFormat("PMIN = {0}", descriptor.PMIN).AppendLine(); sb.AppendFormat("PSEC = {0}", descriptor.PSEC).AppendLine(); sb.AppendFormat("PFRAME = {0}", descriptor.PFRAME).AppendLine(); + break; } } @@ -317,7 +282,50 @@ namespace DiscImageChef.Decoders.CD public static string Prettify(byte[] CDPMAResponse) { CDPMA? decoded = Decode(CDPMAResponse); + return Prettify(decoded); } + + public struct CDPMA + { + /// Total size of returned session information minus this field + public ushort DataLength; + /// Reserved + public byte Reserved1; + /// Reserved + public byte Reserved2; + /// Track descriptors + public CDPMADescriptors[] PMADescriptors; + } + + public struct CDPMADescriptors + { + /// Byte 0 Reserved + public byte Reserved; + /// Byte 1, bits 7 to 4 Type of information in Q subchannel of block where this TOC entry was found + public byte ADR; + /// Byte 1, bits 3 to 0 Track attributes + public byte CONTROL; + /// Byte 2 + public byte TNO; + /// Byte 3 + public byte POINT; + /// Byte 4 + public byte Min; + /// Byte 5 + public byte Sec; + /// Byte 6 + public byte Frame; + /// Byte 7, bits 7 to 4 + public byte HOUR; + /// Byte 7, bits 3 to 0 + public byte PHOUR; + /// Byte 8 + public byte PMIN; + /// Byte 9 + public byte PSEC; + /// Byte 10 + public byte PFRAME; + } } } \ No newline at end of file diff --git a/CD/Sector.cs b/CD/Sector.cs index 7d7326b..ddf4858 100644 --- a/CD/Sector.cs +++ b/CD/Sector.cs @@ -36,152 +36,143 @@ using System.Linq; namespace DiscImageChef.Decoders.CD { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static class Sector { public static readonly byte[] ScrambleTable = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x60, 0x00, - 0x28, 0x00, 0x1E, 0x80, 0x08, 0x60, 0x06, 0xA8, 0x02, 0xFE, 0x81, 0x80, 0x60, 0x60, 0x28, 0x28, 0x1E, - 0x9E, 0x88, 0x68, 0x66, 0xAE, 0xAA, 0xFC, 0x7F, 0x01, 0xE0, 0x00, 0x48, 0x00, 0x36, 0x80, 0x16, 0xE0, - 0x0E, 0xC8, 0x04, 0x56, 0x83, 0x7E, 0xE1, 0xE0, 0x48, 0x48, 0x36, 0xB6, 0x96, 0xF6, 0xEE, 0xC6, 0xCC, - 0x52, 0xD5, 0xFD, 0x9F, 0x01, 0xA8, 0x00, 0x7E, 0x80, 0x20, 0x60, 0x18, 0x28, 0x0A, 0x9E, 0x87, 0x28, - 0x62, 0x9E, 0xA9, 0xA8, 0x7E, 0xFE, 0xA0, 0x40, 0x78, 0x30, 0x22, 0x94, 0x19, 0xAF, 0x4A, 0xFC, 0x37, - 0x01, 0xD6, 0x80, 0x5E, 0xE0, 0x38, 0x48, 0x12, 0xB6, 0x8D, 0xB6, 0xE5, 0xB6, 0xCB, 0x36, 0xD7, 0x56, - 0xDE, 0xBE, 0xD8, 0x70, 0x5A, 0xA4, 0x3B, 0x3B, 0x53, 0x53, 0x7D, 0xFD, 0xE1, 0x81, 0x88, 0x60, 0x66, - 0xA8, 0x2A, 0xFE, 0x9F, 0x00, 0x68, 0x00, 0x2E, 0x80, 0x1C, 0x60, 0x09, 0xE8, 0x06, 0xCE, 0x82, 0xD4, - 0x61, 0x9F, 0x68, 0x68, 0x2E, 0xAE, 0x9C, 0x7C, 0x69, 0xE1, 0xEE, 0xC8, 0x4C, 0x56, 0xB5, 0xFE, 0xF7, - 0x00, 0x46, 0x80, 0x32, 0xE0, 0x15, 0x88, 0x0F, 0x26, 0x84, 0x1A, 0xE3, 0x4B, 0x09, 0xF7, 0x46, 0xC6, - 0xB2, 0xD2, 0xF5, 0x9D, 0x87, 0x29, 0xA2, 0x9E, 0xF9, 0xA8, 0x42, 0xFE, 0xB1, 0x80, 0x74, 0x60, 0x27, - 0x68, 0x1A, 0xAE, 0x8B, 0x3C, 0x67, 0x51, 0xEA, 0xBC, 0x4F, 0x31, 0xF4, 0x14, 0x47, 0x4F, 0x72, 0xB4, - 0x25, 0xB7, 0x5B, 0x36, 0xBB, 0x56, 0xF3, 0x7E, 0xC5, 0xE0, 0x53, 0x08, 0x3D, 0xC6, 0x91, 0x92, 0xEC, - 0x6D, 0x8D, 0xED, 0xA5, 0x8D, 0xBB, 0x25, 0xB3, 0x5B, 0x35, 0xFB, 0x57, 0x03, 0x7E, 0x81, 0xE0, 0x60, - 0x48, 0x28, 0x36, 0x9E, 0x96, 0xE8, 0x6E, 0xCE, 0xAC, 0x54, 0x7D, 0xFF, 0x61, 0x80, 0x28, 0x60, 0x1E, - 0xA8, 0x08, 0x7E, 0x86, 0xA0, 0x62, 0xF8, 0x29, 0x82, 0x9E, 0xE1, 0xA8, 0x48, 0x7E, 0xB6, 0xA0, 0x76, - 0xF8, 0x26, 0xC2, 0x9A, 0xD1, 0xAB, 0x1C, 0x7F, 0x49, 0xE0, 0x36, 0xC8, 0x16, 0xD6, 0x8E, 0xDE, 0xE4, - 0x58, 0x4B, 0x7A, 0xB7, 0x63, 0x36, 0xA9, 0xD6, 0xFE, 0xDE, 0xC0, 0x58, 0x50, 0x3A, 0xBC, 0x13, 0x31, - 0xCD, 0xD4, 0x55, 0x9F, 0x7F, 0x28, 0x20, 0x1E, 0x98, 0x08, 0x6A, 0x86, 0xAF, 0x22, 0xFC, 0x19, 0x81, - 0xCA, 0xE0, 0x57, 0x08, 0x3E, 0x86, 0x90, 0x62, 0xEC, 0x29, 0x8D, 0xDE, 0xE5, 0x98, 0x4B, 0x2A, 0xB7, - 0x5F, 0x36, 0xB8, 0x16, 0xF2, 0x8E, 0xC5, 0xA4, 0x53, 0x3B, 0x7D, 0xD3, 0x61, 0x9D, 0xE8, 0x69, 0x8E, - 0xAE, 0xE4, 0x7C, 0x4B, 0x61, 0xF7, 0x68, 0x46, 0xAE, 0xB2, 0xFC, 0x75, 0x81, 0xE7, 0x20, 0x4A, 0x98, - 0x37, 0x2A, 0x96, 0x9F, 0x2E, 0xE8, 0x1C, 0x4E, 0x89, 0xF4, 0x66, 0xC7, 0x6A, 0xD2, 0xAF, 0x1D, 0xBC, - 0x09, 0xB1, 0xC6, 0xF4, 0x52, 0xC7, 0x7D, 0x92, 0xA1, 0xAD, 0xB8, 0x7D, 0xB2, 0xA1, 0xB5, 0xB8, 0x77, - 0x32, 0xA6, 0x95, 0xBA, 0xEF, 0x33, 0x0C, 0x15, 0xC5, 0xCF, 0x13, 0x14, 0x0D, 0xCF, 0x45, 0x94, 0x33, - 0x2F, 0x55, 0xDC, 0x3F, 0x19, 0xD0, 0x0A, 0xDC, 0x07, 0x19, 0xC2, 0x8A, 0xD1, 0xA7, 0x1C, 0x7A, 0x89, - 0xE3, 0x26, 0xC9, 0xDA, 0xD6, 0xDB, 0x1E, 0xDB, 0x48, 0x5B, 0x76, 0xBB, 0x66, 0xF3, 0x6A, 0xC5, 0xEF, - 0x13, 0x0C, 0x0D, 0xC5, 0xC5, 0x93, 0x13, 0x2D, 0xCD, 0xDD, 0x95, 0x99, 0xAF, 0x2A, 0xFC, 0x1F, 0x01, - 0xC8, 0x00, 0x56, 0x80, 0x3E, 0xE0, 0x10, 0x48, 0x0C, 0x36, 0x85, 0xD6, 0xE3, 0x1E, 0xC9, 0xC8, 0x56, - 0xD6, 0xBE, 0xDE, 0xF0, 0x58, 0x44, 0x3A, 0xB3, 0x53, 0x35, 0xFD, 0xD7, 0x01, 0x9E, 0x80, 0x68, 0x60, - 0x2E, 0xA8, 0x1C, 0x7E, 0x89, 0xE0, 0x66, 0xC8, 0x2A, 0xD6, 0x9F, 0x1E, 0xE8, 0x08, 0x4E, 0x86, 0xB4, - 0x62, 0xF7, 0x69, 0x86, 0xAE, 0xE2, 0xFC, 0x49, 0x81, 0xF6, 0xE0, 0x46, 0xC8, 0x32, 0xD6, 0x95, 0x9E, - 0xEF, 0x28, 0x4C, 0x1E, 0xB5, 0xC8, 0x77, 0x16, 0xA6, 0x8E, 0xFA, 0xE4, 0x43, 0x0B, 0x71, 0xC7, 0x64, - 0x52, 0xAB, 0x7D, 0xBF, 0x61, 0xB0, 0x28, 0x74, 0x1E, 0xA7, 0x48, 0x7A, 0xB6, 0xA3, 0x36, 0xF9, 0xD6, - 0xC2, 0xDE, 0xD1, 0x98, 0x5C, 0x6A, 0xB9, 0xEF, 0x32, 0xCC, 0x15, 0x95, 0xCF, 0x2F, 0x14, 0x1C, 0x0F, - 0x49, 0xC4, 0x36, 0xD3, 0x56, 0xDD, 0xFE, 0xD9, 0x80, 0x5A, 0xE0, 0x3B, 0x08, 0x13, 0x46, 0x8D, 0xF2, - 0xE5, 0x85, 0x8B, 0x23, 0x27, 0x59, 0xDA, 0xBA, 0xDB, 0x33, 0x1B, 0x55, 0xCB, 0x7F, 0x17, 0x60, 0x0E, - 0xA8, 0x04, 0x7E, 0x83, 0x60, 0x61, 0xE8, 0x28, 0x4E, 0x9E, 0xB4, 0x68, 0x77, 0x6E, 0xA6, 0xAC, 0x7A, - 0xFD, 0xE3, 0x01, 0x89, 0xC0, 0x66, 0xD0, 0x2A, 0xDC, 0x1F, 0x19, 0xC8, 0x0A, 0xD6, 0x87, 0x1E, 0xE2, - 0x88, 0x49, 0xA6, 0xB6, 0xFA, 0xF6, 0xC3, 0x06, 0xD1, 0xC2, 0xDC, 0x51, 0x99, 0xFC, 0x6A, 0xC1, 0xEF, - 0x10, 0x4C, 0x0C, 0x35, 0xC5, 0xD7, 0x13, 0x1E, 0x8D, 0xC8, 0x65, 0x96, 0xAB, 0x2E, 0xFF, 0x5C, 0x40, - 0x39, 0xF0, 0x12, 0xC4, 0x0D, 0x93, 0x45, 0xAD, 0xF3, 0x3D, 0x85, 0xD1, 0xA3, 0x1C, 0x79, 0xC9, 0xE2, - 0xD6, 0xC9, 0x9E, 0xD6, 0xE8, 0x5E, 0xCE, 0xB8, 0x54, 0x72, 0xBF, 0x65, 0xB0, 0x2B, 0x34, 0x1F, 0x57, - 0x48, 0x3E, 0xB6, 0x90, 0x76, 0xEC, 0x26, 0xCD, 0xDA, 0xD5, 0x9B, 0x1F, 0x2B, 0x48, 0x1F, 0x76, 0x88, - 0x26, 0xE6, 0x9A, 0xCA, 0xEB, 0x17, 0x0F, 0x4E, 0x84, 0x34, 0x63, 0x57, 0x69, 0xFE, 0xAE, 0xC0, 0x7C, - 0x50, 0x21, 0xFC, 0x18, 0x41, 0xCA, 0xB0, 0x57, 0x34, 0x3E, 0x97, 0x50, 0x6E, 0xBC, 0x2C, 0x71, 0xDD, - 0xE4, 0x59, 0x8B, 0x7A, 0xE7, 0x63, 0x0A, 0xA9, 0xC7, 0x3E, 0xD2, 0x90, 0x5D, 0xAC, 0x39, 0xBD, 0xD2, - 0xF1, 0x9D, 0x84, 0x69, 0xA3, 0x6E, 0xF9, 0xEC, 0x42, 0xCD, 0xF1, 0x95, 0x84, 0x6F, 0x23, 0x6C, 0x19, - 0xED, 0xCA, 0xCD, 0x97, 0x15, 0xAE, 0x8F, 0x3C, 0x64, 0x11, 0xEB, 0x4C, 0x4F, 0x75, 0xF4, 0x27, 0x07, - 0x5A, 0x82, 0xBB, 0x21, 0xB3, 0x58, 0x75, 0xFA, 0xA7, 0x03, 0x3A, 0x81, 0xD3, 0x20, 0x5D, 0xD8, 0x39, - 0x9A, 0x92, 0xEB, 0x2D, 0x8F, 0x5D, 0xA4, 0x39, 0xBB, 0x52, 0xF3, 0x7D, 0x85, 0xE1, 0xA3, 0x08, 0x79, - 0xC6, 0xA2, 0xD2, 0xF9, 0x9D, 0x82, 0xE9, 0xA1, 0x8E, 0xF8, 0x64, 0x42, 0xAB, 0x71, 0xBF, 0x64, 0x70, - 0x2B, 0x64, 0x1F, 0x6B, 0x48, 0x2F, 0x76, 0x9C, 0x26, 0xE9, 0xDA, 0xCE, 0xDB, 0x14, 0x5B, 0x4F, 0x7B, - 0x74, 0x23, 0x67, 0x59, 0xEA, 0xBA, 0xCF, 0x33, 0x14, 0x15, 0xCF, 0x4F, 0x14, 0x34, 0x0F, 0x57, 0x44, - 0x3E, 0xB3, 0x50, 0x75, 0xFC, 0x27, 0x01, 0xDA, 0x80, 0x5B, 0x20, 0x3B, 0x58, 0x13, 0x7A, 0x8D, 0xE3, - 0x25, 0x89, 0xDB, 0x26, 0xDB, 0x5A, 0xDB, 0x7B, 0x1B, 0x63, 0x4B, 0x69, 0xF7, 0x6E, 0xC6, 0xAC, 0x52, - 0xFD, 0xFD, 0x81, 0x81, 0xA0, 0x60, 0x78, 0x28, 0x22, 0x9E, 0x99, 0xA8, 0x6A, 0xFE, 0xAF, 0x00, 0x7C, - 0x00, 0x21, 0xC0, 0x18, 0x50, 0x0A, 0xBC, 0x07, 0x31, 0xC2, 0x94, 0x51, 0xAF, 0x7C, 0x7C, 0x21, 0xE1, - 0xD8, 0x48, 0x5A, 0xB6, 0xBB, 0x36, 0xF3, 0x56, 0xC5, 0xFE, 0xD3, 0x00, 0x5D, 0xC0, 0x39, 0x90, 0x12, - 0xEC, 0x0D, 0x8D, 0xC5, 0xA5, 0x93, 0x3B, 0x2D, 0xD3, 0x5D, 0x9D, 0xF9, 0xA9, 0x82, 0xFE, 0xE1, 0x80, - 0x48, 0x60, 0x36, 0xA8, 0x16, 0xFE, 0x8E, 0xC0, 0x64, 0x50, 0x2B, 0x7C, 0x1F, 0x61, 0xC8, 0x28, 0x56, - 0x9E, 0xBE, 0xE8, 0x70, 0x4E, 0xA4, 0x34, 0x7B, 0x57, 0x63, 0x7E, 0xA9, 0xE0, 0x7E, 0xC8, 0x20, 0x56, - 0x98, 0x3E, 0xEA, 0x90, 0x4F, 0x2C, 0x34, 0x1D, 0xD7, 0x49, 0x9E, 0xB6, 0xE8, 0x76, 0xCE, 0xA6, 0xD4, - 0x7A, 0xDF, 0x63, 0x18, 0x29, 0xCA, 0x9E, 0xD7, 0x28, 0x5E, 0x9E, 0xB8, 0x68, 0x72, 0xAE, 0xA5, 0xBC, - 0x7B, 0x31, 0xE3, 0x54, 0x49, 0xFF, 0x76, 0xC0, 0x26, 0xD0, 0x1A, 0xDC, 0x0B, 0x19, 0xC7, 0x4A, 0xD2, - 0xB7, 0x1D, 0xB6, 0x89, 0xB6, 0xE6, 0xF6, 0xCA, 0xC6, 0xD7, 0x12, 0xDE, 0x8D, 0x98, 0x65, 0xAA, 0xAB, - 0x3F, 0x3F, 0x50, 0x10, 0x3C, 0x0C, 0x11, 0xC5, 0xCC, 0x53, 0x15, 0xFD, 0xCF, 0x01, 0x94, 0x00, 0x6F, - 0x40, 0x2C, 0x30, 0x1D, 0xD4, 0x09, 0x9F, 0x46, 0xE8, 0x32, 0xCE, 0x95, 0x94, 0x6F, 0x2F, 0x6C, 0x1C, - 0x2D, 0xC9, 0xDD, 0x96, 0xD9, 0xAE, 0xDA, 0xFC, 0x5B, 0x01, 0xFB, 0x40, 0x43, 0x70, 0x31, 0xE4, 0x14, - 0x4B, 0x4F, 0x77, 0x74, 0x26, 0xA7, 0x5A, 0xFA, 0xBB, 0x03, 0x33, 0x41, 0xD5, 0xF0, 0x5F, 0x04, 0x38, - 0x03, 0x52, 0x81, 0xFD, 0xA0, 0x41, 0xB8, 0x30, 0x72, 0x94, 0x25, 0xAF, 0x5B, 0x3C, 0x3B, 0x51, 0xD3, - 0x7C, 0x5D, 0xE1, 0xF9, 0x88, 0x42, 0xE6, 0xB1, 0x8A, 0xF4, 0x67, 0x07, 0x6A, 0x82, 0xAF, 0x21, 0xBC, - 0x18, 0x71, 0xCA, 0xA4, 0x57, 0x3B, 0x7E, 0x93, 0x60, 0x6D, 0xE8, 0x2D, 0x8E, 0x9D, 0xA4, 0x69, 0xBB, - 0x6E, 0xF3, 0x6C, 0x45, 0xED, 0xF3, 0x0D, 0x85, 0xC5, 0xA3, 0x13, 0x39, 0xCD, 0xD2, 0xD5, 0x9D, 0x9F, - 0x29, 0xA8, 0x1E, 0xFE, 0x88, 0x40, 0x66, 0xB0, 0x2A, 0xF4, 0x1F, 0x07, 0x48, 0x02, 0xB6, 0x81, 0xB6, - 0xE0, 0x76, 0xC8, 0x26, 0xD6, 0x9A, 0xDE, 0xEB, 0x18, 0x4F, 0x4A, 0xB4, 0x37, 0x37, 0x56, 0x96, 0xBE, - 0xEE, 0xF0, 0x4C, 0x44, 0x35, 0xF3, 0x57, 0x05, 0xFE, 0x83, 0x00, 0x61, 0xC0, 0x28, 0x50, 0x1E, 0xBC, - 0x08, 0x71, 0xC6, 0xA4, 0x52, 0xFB, 0x7D, 0x83, 0x61, 0xA1, 0xE8, 0x78, 0x4E, 0xA2, 0xB4, 0x79, 0xB7, - 0x62, 0xF6, 0xA9, 0x86, 0xFE, 0xE2, 0xC0, 0x49, 0x90, 0x36, 0xEC, 0x16, 0xCD, 0xCE, 0xD5, 0x94, 0x5F, - 0x2F, 0x78, 0x1C, 0x22, 0x89, 0xD9, 0xA6, 0xDA, 0xFA, 0xDB, 0x03, 0x1B, 0x41, 0xCB, 0x70, 0x57, 0x64, - 0x3E, 0xAB, 0x50, 0x7F, 0x7C, 0x20, 0x21, 0xD8, 0x18, 0x5A, 0x8A, 0xBB, 0x27, 0x33, 0x5A, 0x95, 0xFB, - 0x2F, 0x03, 0x5C, 0x01, 0xF9, 0xC0, 0x42, 0xD0, 0x31, 0x9C, 0x14, 0x69, 0xCF, 0x6E, 0xD4, 0x2C, 0x5F, - 0x5D, 0xF8, 0x39, 0x82, 0x92, 0xE1, 0xAD, 0x88, 0x7D, 0xA6, 0xA1, 0xBA, 0xF8, 0x73, 0x02, 0xA5, 0xC1, - 0xBB, 0x10, 0x73, 0x4C, 0x25, 0xF5, 0xDB, 0x07, 0x1B, 0x42, 0x8B, 0x71, 0xA7, 0x64, 0x7A, 0xAB, 0x63, - 0x3F, 0x69, 0xD0, 0x2E, 0xDC, 0x1C, 0x59, 0xC9, 0xFA, 0xD6, 0xC3, 0x1E, 0xD1, 0xC8, 0x5C, 0x56, 0xB9, - 0xFE, 0xF2, 0xC0, 0x45, 0x90, 0x33, 0x2C, 0x15, 0xDD, 0xCF, 0x19, 0x94, 0x0A, 0xEF, 0x47, 0x0C, 0x32, - 0x85, 0xD5, 0xA3, 0x1F, 0x39, 0xC8, 0x12, 0xD6, 0x8D, 0x9E, 0xE5, 0xA8, 0x4B, 0x3E, 0xB7, 0x50, 0x76, - 0xBC, 0x26, 0xF1, 0xDA, 0xC4, 0x5B, 0x13, 0x7B, 0x4D, 0xE3, 0x75, 0x89, 0xE7, 0x26, 0xCA, 0x9A, 0xD7, - 0x2B, 0x1E, 0x9F, 0x48, 0x68, 0x36, 0xAE, 0x96, 0xFC, 0x6E, 0xC1, 0xEC, 0x50, 0x4D, 0xFC, 0x35, 0x81, - 0xD7, 0x20, 0x5E, 0x98, 0x38, 0x6A, 0x92, 0xAF, 0x2D, 0xBC, 0x1D, 0xB1, 0xC9, 0xB4, 0x56, 0xF7, 0x7E, - 0xC6, 0xA0, 0x52, 0xF8, 0x3D, 0x82, 0x91, 0xA1, 0xAC, 0x78, 0x7D, 0xE2, 0xA1, 0x89, 0xB8, 0x66, 0xF2, - 0xAA, 0xC5, 0xBF, 0x13, 0x30, 0x0D, 0xD4, 0x05, 0x9F, 0x43, 0x28, 0x31, 0xDE, 0x94, 0x58, 0x6F, 0x7A, - 0xAC, 0x23, 0x3D, 0xD9, 0xD1, 0x9A, 0xDC, 0x6B, 0x19, 0xEF, 0x4A, 0xCC, 0x37, 0x15, 0xD6, 0x8F, 0x1E, - 0xE4, 0x08, 0x4B, 0x46, 0xB7, 0x72, 0xF6, 0xA5, 0x86, 0xFB, 0x22, 0xC3, 0x59, 0x91, 0xFA, 0xEC, 0x43, - 0x0D, 0xF1, 0xC5, 0x84, 0x53, 0x23, 0x7D, 0xD9, 0xE1, 0x9A, 0xC8, 0x6B, 0x16, 0xAF, 0x4E, 0xFC, 0x34, - 0x41, 0xD7, 0x70, 0x5E, 0xA4, 0x38, 0x7B, 0x52, 0xA3, 0x7D, 0xB9, 0xE1, 0xB2, 0xC8, 0x75, 0x96, 0xA7, - 0x2E, 0xFA, 0x9C, 0x43, 0x29, 0xF1, 0xDE, 0xC4, 0x58, 0x53, 0x7A, 0xBD, 0xE3, 0x31, 0x89, 0xD4, 0x66, - 0xDF, 0x6A, 0xD8, 0x2F, 0x1A, 0x9C, 0x0B, 0x29, 0xC7, 0x5E, 0xD2, 0xB8, 0x5D, 0xB2, 0xB9, 0xB5, 0xB2, - 0xF7, 0x35, 0x86, 0x97, 0x22, 0xEE, 0x99, 0x8C, 0x6A, 0xE5, 0xEF, 0x0B, 0x0C, 0x07, 0x45, 0xC2, 0xB3, - 0x11, 0xB5, 0xCC, 0x77, 0x15, 0xE6, 0x8F, 0x0A, 0xE4, 0x07, 0x0B, 0x42, 0x87, 0x71, 0xA2, 0xA4, 0x79, - 0xBB, 0x62, 0xF3, 0x69, 0x85, 0xEE, 0xE3, 0x0C, 0x49, 0xC5, 0xF6, 0xD3, 0x06, 0xDD, 0xC2, 0xD9, 0x91, - 0x9A, 0xEC, 0x6B, 0x0D, 0xEF, 0x45, 0x8C, 0x33, 0x25, 0xD5, 0xDB, 0x1F, 0x1B, 0x48, 0x0B, 0x76, 0x87, - 0x66, 0xE2, 0xAA, 0xC9, 0xBF, 0x16, 0xF0, 0x0E, 0xC4, 0x04, 0x53, 0x43, 0x7D, 0xF1, 0xE1, 0x84, 0x48, - 0x63, 0x76, 0xA9, 0xE6, 0xFE, 0xCA, 0xC0, 0x57, 0x10, 0x3E, 0x8C, 0x10, 0x65, 0xCC, 0x2B, 0x15, 0xDF, - 0x4F, 0x18, 0x34, 0x0A, 0x97, 0x47, 0x2E, 0xB2, 0x9C, 0x75, 0xA9, 0xE7, 0x3E, 0xCA, 0x90, 0x57, 0x2C, - 0x3E, 0x9D, 0xD0, 0x69, 0x9C, 0x2E, 0xE9, 0xDC, 0x4E, 0xD9, 0xF4, 0x5A, 0xC7, 0x7B, 0x12, 0xA3, 0x4D, - 0xB9, 0xF5, 0xB2, 0xC7, 0x35, 0x92, 0x97, 0x2D, 0xAE, 0x9D, 0xBC, 0x69, 0xB1, 0xEE, 0xF4, 0x4C, 0x47, - 0x75, 0xF2, 0xA7, 0x05, 0xBA, 0x83, 0x33, 0x21, 0xD5, 0xD8, 0x5F, 0x1A, 0xB8, 0x0B, 0x32, 0x87, 0x55, - 0xA2, 0xBF, 0x39, 0xB0, 0x12, 0xF4, 0x0D, 0x87, 0x45, 0xA2, 0xB3, 0x39, 0xB5, 0xD2, 0xF7, 0x1D, 0x86, - 0x89, 0xA2, 0xE6, 0xF9, 0x8A, 0xC2, 0xE7, 0x11, 0x8A, 0x8C, 0x67, 0x25, 0xEA, 0x9B, 0x0F, 0x2B, 0x44, - 0x1F, 0x73, 0x48, 0x25, 0xF6, 0x9B, 0x06, 0xEB, 0x42, 0xCF, 0x71, 0x94, 0x24, 0x6F, 0x5B, 0x6C, 0x3B, - 0x6D, 0xD3, 0x6D, 0x9D, 0xED, 0xA9, 0x8D, 0xBE, 0xE5, 0xB0, 0x4B, 0x34, 0x37, 0x57, 0x56, 0xBE, 0xBE, - 0xF0, 0x70, 0x44, 0x24, 0x33, 0x5B, 0x55, 0xFB, 0x7F, 0x03, 0x60, 0x01, 0xE8, 0x00, 0x4E, 0x80, 0x34, - 0x60, 0x17, 0x68, 0x0E, 0xAE, 0x84, 0x7C, 0x63, 0x61, 0xE9, 0xE8, 0x4E, 0xCE, 0xB4, 0x54, 0x77, 0x7F, - 0x66, 0xA0, 0x2A, 0xF8, 0x1F, 0x02, 0x88, 0x01, 0xA6, 0x80, 0x7A, 0xE0, 0x23, 0x08, 0x19, 0xC6, 0x8A, - 0xD2, 0xE7, 0x1D, 0x8A, 0x89, 0xA7, 0x26, 0xFA, 0x9A, 0xC3, 0x2B, 0x11, 0xDF, 0x4C, 0x58, 0x35, 0xFA, - 0x97, 0x03, 0x2E, 0x81, 0xDC, 0x60, 0x59, 0xE8, 0x3A, 0xCE, 0x93, 0x14, 0x6D, 0xCF, 0x6D, 0x94, 0x2D, - 0xAF, 0x5D, 0xBC, 0x39, 0xB1, 0xD2, 0xF4, 0x5D, 0x87, 0x79, 0xA2, 0xA2, 0xF9, 0xB9, 0x82, 0xF2, 0xE1, - 0x85, 0x88, 0x63, 0x26, 0xA9, 0xDA, 0xFE, 0xDB, 0x00, 0x5B, 0x40, 0x3B, 0x70, 0x13, 0x64, 0x0D, 0xEB, - 0x45, 0x8F, 0x73, 0x24, 0x25, 0xDB, 0x5B, 0x1B, 0x7B, 0x4B, 0x63, 0x77, 0x69, 0xE6, 0xAE, 0xCA, 0xFC, - 0x57, 0x01, 0xFE, 0x80, 0x40, 0x60, 0x30, 0x28, 0x14, 0x1E, 0x8F, 0x48, 0x64, 0x36, 0xAB, 0x56, 0xFF, - 0x7E, 0xC0, 0x20, 0x50, 0x18, 0x3C, 0x0A, 0x91, 0xC7, 0x2C, 0x52, 0x9D, 0xFD, 0xA9, 0x81, 0xBE, 0xE0, - 0x70, 0x48, 0x24, 0x36, 0x9B, 0x56, 0xEB, 0x7E, 0xCF, 0x60, 0x54, 0x28, 0x3F, 0x5E, 0x90, 0x38, 0x6C, - 0x12, 0xAD, 0xCD, 0xBD, 0x95, 0xB1, 0xAF, 0x34, 0x7C, 0x17, 0x61, 0xCE, 0xA8, 0x54, 0x7E, 0xBF, 0x60, - 0x70, 0x28, 0x24, 0x1E, 0x9B, 0x48, 0x6B, 0x76, 0xAF, 0x66, 0xFC, 0x2A, 0xC1, 0xDF, 0x10, 0x58, 0x0C, - 0x3A, 0x85, 0xD3, 0x23, 0x1D, 0xD9, 0xC9, 0x9A, 0xD6, 0xEB, 0x1E, 0xCF, 0x48, 0x54, 0x36, 0xBF, 0x56, - 0xF0, 0x3E, 0xC4, 0x10, 0x53, 0x4C, 0x3D, 0xF5, 0xD1, 0x87, 0x1C, 0x62, 0x89, 0xE9, 0xA6, 0xCE, 0xFA, - 0xD4, 0x43, 0x1F, 0x71, 0xC8, 0x24, 0x56, 0x9B, 0x7E, 0xEB, 0x60, 0x4F, 0x68, 0x34, 0x2E, 0x97, 0x5C, - 0x6E, 0xB9, 0xEC, 0x72, 0xCD, 0xE5, 0x95, 0x8B, 0x2F, 0x27, 0x5C, 0x1A, 0xB9, 0xCB, 0x32, 0xD7, 0x55, - 0x9E, 0xBF, 0x28, 0x70, 0x1E, 0xA4, 0x08, 0x7B, 0x46, 0xA3, 0x72, 0xF9, 0xE5, 0x82, 0xCB, 0x21, 0x97, - 0x58, 0x6E, 0xBA, 0xAC, 0x73, 0x3D, 0xE5, 0xD1, 0x8B, 0x1C, 0x67, 0x49, 0xEA, 0xB6, 0xCF, 0x36, 0xD4, - 0x16, 0xDF, 0x4E, 0xD8, 0x34, 0x5A, 0x97, 0x7B, 0x2E, 0xA3, 0x5C, 0x79, 0xF9, 0xE2, 0xC2, 0xC9, 0x91, - 0x96, 0xEC, 0x6E, 0xCD, 0xEC, 0x55, 0x8D, 0xFF, 0x25, 0x80, 0x1B, 0x20, 0x0B, 0x58, 0x07, 0x7A, 0x82, - 0xA3, 0x21, 0xB9, 0xD8, 0x72, 0xDA, 0xA5, 0x9B, 0x3B, 0x2B, 0x53, 0x5F, 0x7D, 0xF8, 0x21, 0x82, 0x98, - 0x61, 0xAA, 0xA8, 0x7F, 0x3E, 0xA0, 0x10, 0x78, 0x0C, 0x22, 0x85, 0xD9, 0xA3, 0x1A, 0xF9, 0xCB, 0x02, - 0xD7, 0x41, 0x9E, 0xB0, 0x68, 0x74, 0x2E, 0xA7, 0x5C, 0x7A, 0xB9, 0xE3, 0x32, 0xC9, 0xD5, 0x96, 0xDF, - 0x2E, 0xD8, 0x1C, 0x5A, 0x89, 0xFB, 0x26, 0xC3, 0x5A, 0xD1, 0xFB, 0x1C, 0x43, 0x49, 0xF1, 0xF6, 0xC4, - 0x46, 0xD3, 0x72, 0xDD, 0xE5, 0x99 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x60, 0x00, 0x28, + 0x00, 0x1E, 0x80, 0x08, 0x60, 0x06, 0xA8, 0x02, 0xFE, 0x81, 0x80, 0x60, 0x60, 0x28, 0x28, 0x1E, 0x9E, 0x88, + 0x68, 0x66, 0xAE, 0xAA, 0xFC, 0x7F, 0x01, 0xE0, 0x00, 0x48, 0x00, 0x36, 0x80, 0x16, 0xE0, 0x0E, 0xC8, 0x04, + 0x56, 0x83, 0x7E, 0xE1, 0xE0, 0x48, 0x48, 0x36, 0xB6, 0x96, 0xF6, 0xEE, 0xC6, 0xCC, 0x52, 0xD5, 0xFD, 0x9F, + 0x01, 0xA8, 0x00, 0x7E, 0x80, 0x20, 0x60, 0x18, 0x28, 0x0A, 0x9E, 0x87, 0x28, 0x62, 0x9E, 0xA9, 0xA8, 0x7E, + 0xFE, 0xA0, 0x40, 0x78, 0x30, 0x22, 0x94, 0x19, 0xAF, 0x4A, 0xFC, 0x37, 0x01, 0xD6, 0x80, 0x5E, 0xE0, 0x38, + 0x48, 0x12, 0xB6, 0x8D, 0xB6, 0xE5, 0xB6, 0xCB, 0x36, 0xD7, 0x56, 0xDE, 0xBE, 0xD8, 0x70, 0x5A, 0xA4, 0x3B, + 0x3B, 0x53, 0x53, 0x7D, 0xFD, 0xE1, 0x81, 0x88, 0x60, 0x66, 0xA8, 0x2A, 0xFE, 0x9F, 0x00, 0x68, 0x00, 0x2E, + 0x80, 0x1C, 0x60, 0x09, 0xE8, 0x06, 0xCE, 0x82, 0xD4, 0x61, 0x9F, 0x68, 0x68, 0x2E, 0xAE, 0x9C, 0x7C, 0x69, + 0xE1, 0xEE, 0xC8, 0x4C, 0x56, 0xB5, 0xFE, 0xF7, 0x00, 0x46, 0x80, 0x32, 0xE0, 0x15, 0x88, 0x0F, 0x26, 0x84, + 0x1A, 0xE3, 0x4B, 0x09, 0xF7, 0x46, 0xC6, 0xB2, 0xD2, 0xF5, 0x9D, 0x87, 0x29, 0xA2, 0x9E, 0xF9, 0xA8, 0x42, + 0xFE, 0xB1, 0x80, 0x74, 0x60, 0x27, 0x68, 0x1A, 0xAE, 0x8B, 0x3C, 0x67, 0x51, 0xEA, 0xBC, 0x4F, 0x31, 0xF4, + 0x14, 0x47, 0x4F, 0x72, 0xB4, 0x25, 0xB7, 0x5B, 0x36, 0xBB, 0x56, 0xF3, 0x7E, 0xC5, 0xE0, 0x53, 0x08, 0x3D, + 0xC6, 0x91, 0x92, 0xEC, 0x6D, 0x8D, 0xED, 0xA5, 0x8D, 0xBB, 0x25, 0xB3, 0x5B, 0x35, 0xFB, 0x57, 0x03, 0x7E, + 0x81, 0xE0, 0x60, 0x48, 0x28, 0x36, 0x9E, 0x96, 0xE8, 0x6E, 0xCE, 0xAC, 0x54, 0x7D, 0xFF, 0x61, 0x80, 0x28, + 0x60, 0x1E, 0xA8, 0x08, 0x7E, 0x86, 0xA0, 0x62, 0xF8, 0x29, 0x82, 0x9E, 0xE1, 0xA8, 0x48, 0x7E, 0xB6, 0xA0, + 0x76, 0xF8, 0x26, 0xC2, 0x9A, 0xD1, 0xAB, 0x1C, 0x7F, 0x49, 0xE0, 0x36, 0xC8, 0x16, 0xD6, 0x8E, 0xDE, 0xE4, + 0x58, 0x4B, 0x7A, 0xB7, 0x63, 0x36, 0xA9, 0xD6, 0xFE, 0xDE, 0xC0, 0x58, 0x50, 0x3A, 0xBC, 0x13, 0x31, 0xCD, + 0xD4, 0x55, 0x9F, 0x7F, 0x28, 0x20, 0x1E, 0x98, 0x08, 0x6A, 0x86, 0xAF, 0x22, 0xFC, 0x19, 0x81, 0xCA, 0xE0, + 0x57, 0x08, 0x3E, 0x86, 0x90, 0x62, 0xEC, 0x29, 0x8D, 0xDE, 0xE5, 0x98, 0x4B, 0x2A, 0xB7, 0x5F, 0x36, 0xB8, + 0x16, 0xF2, 0x8E, 0xC5, 0xA4, 0x53, 0x3B, 0x7D, 0xD3, 0x61, 0x9D, 0xE8, 0x69, 0x8E, 0xAE, 0xE4, 0x7C, 0x4B, + 0x61, 0xF7, 0x68, 0x46, 0xAE, 0xB2, 0xFC, 0x75, 0x81, 0xE7, 0x20, 0x4A, 0x98, 0x37, 0x2A, 0x96, 0x9F, 0x2E, + 0xE8, 0x1C, 0x4E, 0x89, 0xF4, 0x66, 0xC7, 0x6A, 0xD2, 0xAF, 0x1D, 0xBC, 0x09, 0xB1, 0xC6, 0xF4, 0x52, 0xC7, + 0x7D, 0x92, 0xA1, 0xAD, 0xB8, 0x7D, 0xB2, 0xA1, 0xB5, 0xB8, 0x77, 0x32, 0xA6, 0x95, 0xBA, 0xEF, 0x33, 0x0C, + 0x15, 0xC5, 0xCF, 0x13, 0x14, 0x0D, 0xCF, 0x45, 0x94, 0x33, 0x2F, 0x55, 0xDC, 0x3F, 0x19, 0xD0, 0x0A, 0xDC, + 0x07, 0x19, 0xC2, 0x8A, 0xD1, 0xA7, 0x1C, 0x7A, 0x89, 0xE3, 0x26, 0xC9, 0xDA, 0xD6, 0xDB, 0x1E, 0xDB, 0x48, + 0x5B, 0x76, 0xBB, 0x66, 0xF3, 0x6A, 0xC5, 0xEF, 0x13, 0x0C, 0x0D, 0xC5, 0xC5, 0x93, 0x13, 0x2D, 0xCD, 0xDD, + 0x95, 0x99, 0xAF, 0x2A, 0xFC, 0x1F, 0x01, 0xC8, 0x00, 0x56, 0x80, 0x3E, 0xE0, 0x10, 0x48, 0x0C, 0x36, 0x85, + 0xD6, 0xE3, 0x1E, 0xC9, 0xC8, 0x56, 0xD6, 0xBE, 0xDE, 0xF0, 0x58, 0x44, 0x3A, 0xB3, 0x53, 0x35, 0xFD, 0xD7, + 0x01, 0x9E, 0x80, 0x68, 0x60, 0x2E, 0xA8, 0x1C, 0x7E, 0x89, 0xE0, 0x66, 0xC8, 0x2A, 0xD6, 0x9F, 0x1E, 0xE8, + 0x08, 0x4E, 0x86, 0xB4, 0x62, 0xF7, 0x69, 0x86, 0xAE, 0xE2, 0xFC, 0x49, 0x81, 0xF6, 0xE0, 0x46, 0xC8, 0x32, + 0xD6, 0x95, 0x9E, 0xEF, 0x28, 0x4C, 0x1E, 0xB5, 0xC8, 0x77, 0x16, 0xA6, 0x8E, 0xFA, 0xE4, 0x43, 0x0B, 0x71, + 0xC7, 0x64, 0x52, 0xAB, 0x7D, 0xBF, 0x61, 0xB0, 0x28, 0x74, 0x1E, 0xA7, 0x48, 0x7A, 0xB6, 0xA3, 0x36, 0xF9, + 0xD6, 0xC2, 0xDE, 0xD1, 0x98, 0x5C, 0x6A, 0xB9, 0xEF, 0x32, 0xCC, 0x15, 0x95, 0xCF, 0x2F, 0x14, 0x1C, 0x0F, + 0x49, 0xC4, 0x36, 0xD3, 0x56, 0xDD, 0xFE, 0xD9, 0x80, 0x5A, 0xE0, 0x3B, 0x08, 0x13, 0x46, 0x8D, 0xF2, 0xE5, + 0x85, 0x8B, 0x23, 0x27, 0x59, 0xDA, 0xBA, 0xDB, 0x33, 0x1B, 0x55, 0xCB, 0x7F, 0x17, 0x60, 0x0E, 0xA8, 0x04, + 0x7E, 0x83, 0x60, 0x61, 0xE8, 0x28, 0x4E, 0x9E, 0xB4, 0x68, 0x77, 0x6E, 0xA6, 0xAC, 0x7A, 0xFD, 0xE3, 0x01, + 0x89, 0xC0, 0x66, 0xD0, 0x2A, 0xDC, 0x1F, 0x19, 0xC8, 0x0A, 0xD6, 0x87, 0x1E, 0xE2, 0x88, 0x49, 0xA6, 0xB6, + 0xFA, 0xF6, 0xC3, 0x06, 0xD1, 0xC2, 0xDC, 0x51, 0x99, 0xFC, 0x6A, 0xC1, 0xEF, 0x10, 0x4C, 0x0C, 0x35, 0xC5, + 0xD7, 0x13, 0x1E, 0x8D, 0xC8, 0x65, 0x96, 0xAB, 0x2E, 0xFF, 0x5C, 0x40, 0x39, 0xF0, 0x12, 0xC4, 0x0D, 0x93, + 0x45, 0xAD, 0xF3, 0x3D, 0x85, 0xD1, 0xA3, 0x1C, 0x79, 0xC9, 0xE2, 0xD6, 0xC9, 0x9E, 0xD6, 0xE8, 0x5E, 0xCE, + 0xB8, 0x54, 0x72, 0xBF, 0x65, 0xB0, 0x2B, 0x34, 0x1F, 0x57, 0x48, 0x3E, 0xB6, 0x90, 0x76, 0xEC, 0x26, 0xCD, + 0xDA, 0xD5, 0x9B, 0x1F, 0x2B, 0x48, 0x1F, 0x76, 0x88, 0x26, 0xE6, 0x9A, 0xCA, 0xEB, 0x17, 0x0F, 0x4E, 0x84, + 0x34, 0x63, 0x57, 0x69, 0xFE, 0xAE, 0xC0, 0x7C, 0x50, 0x21, 0xFC, 0x18, 0x41, 0xCA, 0xB0, 0x57, 0x34, 0x3E, + 0x97, 0x50, 0x6E, 0xBC, 0x2C, 0x71, 0xDD, 0xE4, 0x59, 0x8B, 0x7A, 0xE7, 0x63, 0x0A, 0xA9, 0xC7, 0x3E, 0xD2, + 0x90, 0x5D, 0xAC, 0x39, 0xBD, 0xD2, 0xF1, 0x9D, 0x84, 0x69, 0xA3, 0x6E, 0xF9, 0xEC, 0x42, 0xCD, 0xF1, 0x95, + 0x84, 0x6F, 0x23, 0x6C, 0x19, 0xED, 0xCA, 0xCD, 0x97, 0x15, 0xAE, 0x8F, 0x3C, 0x64, 0x11, 0xEB, 0x4C, 0x4F, + 0x75, 0xF4, 0x27, 0x07, 0x5A, 0x82, 0xBB, 0x21, 0xB3, 0x58, 0x75, 0xFA, 0xA7, 0x03, 0x3A, 0x81, 0xD3, 0x20, + 0x5D, 0xD8, 0x39, 0x9A, 0x92, 0xEB, 0x2D, 0x8F, 0x5D, 0xA4, 0x39, 0xBB, 0x52, 0xF3, 0x7D, 0x85, 0xE1, 0xA3, + 0x08, 0x79, 0xC6, 0xA2, 0xD2, 0xF9, 0x9D, 0x82, 0xE9, 0xA1, 0x8E, 0xF8, 0x64, 0x42, 0xAB, 0x71, 0xBF, 0x64, + 0x70, 0x2B, 0x64, 0x1F, 0x6B, 0x48, 0x2F, 0x76, 0x9C, 0x26, 0xE9, 0xDA, 0xCE, 0xDB, 0x14, 0x5B, 0x4F, 0x7B, + 0x74, 0x23, 0x67, 0x59, 0xEA, 0xBA, 0xCF, 0x33, 0x14, 0x15, 0xCF, 0x4F, 0x14, 0x34, 0x0F, 0x57, 0x44, 0x3E, + 0xB3, 0x50, 0x75, 0xFC, 0x27, 0x01, 0xDA, 0x80, 0x5B, 0x20, 0x3B, 0x58, 0x13, 0x7A, 0x8D, 0xE3, 0x25, 0x89, + 0xDB, 0x26, 0xDB, 0x5A, 0xDB, 0x7B, 0x1B, 0x63, 0x4B, 0x69, 0xF7, 0x6E, 0xC6, 0xAC, 0x52, 0xFD, 0xFD, 0x81, + 0x81, 0xA0, 0x60, 0x78, 0x28, 0x22, 0x9E, 0x99, 0xA8, 0x6A, 0xFE, 0xAF, 0x00, 0x7C, 0x00, 0x21, 0xC0, 0x18, + 0x50, 0x0A, 0xBC, 0x07, 0x31, 0xC2, 0x94, 0x51, 0xAF, 0x7C, 0x7C, 0x21, 0xE1, 0xD8, 0x48, 0x5A, 0xB6, 0xBB, + 0x36, 0xF3, 0x56, 0xC5, 0xFE, 0xD3, 0x00, 0x5D, 0xC0, 0x39, 0x90, 0x12, 0xEC, 0x0D, 0x8D, 0xC5, 0xA5, 0x93, + 0x3B, 0x2D, 0xD3, 0x5D, 0x9D, 0xF9, 0xA9, 0x82, 0xFE, 0xE1, 0x80, 0x48, 0x60, 0x36, 0xA8, 0x16, 0xFE, 0x8E, + 0xC0, 0x64, 0x50, 0x2B, 0x7C, 0x1F, 0x61, 0xC8, 0x28, 0x56, 0x9E, 0xBE, 0xE8, 0x70, 0x4E, 0xA4, 0x34, 0x7B, + 0x57, 0x63, 0x7E, 0xA9, 0xE0, 0x7E, 0xC8, 0x20, 0x56, 0x98, 0x3E, 0xEA, 0x90, 0x4F, 0x2C, 0x34, 0x1D, 0xD7, + 0x49, 0x9E, 0xB6, 0xE8, 0x76, 0xCE, 0xA6, 0xD4, 0x7A, 0xDF, 0x63, 0x18, 0x29, 0xCA, 0x9E, 0xD7, 0x28, 0x5E, + 0x9E, 0xB8, 0x68, 0x72, 0xAE, 0xA5, 0xBC, 0x7B, 0x31, 0xE3, 0x54, 0x49, 0xFF, 0x76, 0xC0, 0x26, 0xD0, 0x1A, + 0xDC, 0x0B, 0x19, 0xC7, 0x4A, 0xD2, 0xB7, 0x1D, 0xB6, 0x89, 0xB6, 0xE6, 0xF6, 0xCA, 0xC6, 0xD7, 0x12, 0xDE, + 0x8D, 0x98, 0x65, 0xAA, 0xAB, 0x3F, 0x3F, 0x50, 0x10, 0x3C, 0x0C, 0x11, 0xC5, 0xCC, 0x53, 0x15, 0xFD, 0xCF, + 0x01, 0x94, 0x00, 0x6F, 0x40, 0x2C, 0x30, 0x1D, 0xD4, 0x09, 0x9F, 0x46, 0xE8, 0x32, 0xCE, 0x95, 0x94, 0x6F, + 0x2F, 0x6C, 0x1C, 0x2D, 0xC9, 0xDD, 0x96, 0xD9, 0xAE, 0xDA, 0xFC, 0x5B, 0x01, 0xFB, 0x40, 0x43, 0x70, 0x31, + 0xE4, 0x14, 0x4B, 0x4F, 0x77, 0x74, 0x26, 0xA7, 0x5A, 0xFA, 0xBB, 0x03, 0x33, 0x41, 0xD5, 0xF0, 0x5F, 0x04, + 0x38, 0x03, 0x52, 0x81, 0xFD, 0xA0, 0x41, 0xB8, 0x30, 0x72, 0x94, 0x25, 0xAF, 0x5B, 0x3C, 0x3B, 0x51, 0xD3, + 0x7C, 0x5D, 0xE1, 0xF9, 0x88, 0x42, 0xE6, 0xB1, 0x8A, 0xF4, 0x67, 0x07, 0x6A, 0x82, 0xAF, 0x21, 0xBC, 0x18, + 0x71, 0xCA, 0xA4, 0x57, 0x3B, 0x7E, 0x93, 0x60, 0x6D, 0xE8, 0x2D, 0x8E, 0x9D, 0xA4, 0x69, 0xBB, 0x6E, 0xF3, + 0x6C, 0x45, 0xED, 0xF3, 0x0D, 0x85, 0xC5, 0xA3, 0x13, 0x39, 0xCD, 0xD2, 0xD5, 0x9D, 0x9F, 0x29, 0xA8, 0x1E, + 0xFE, 0x88, 0x40, 0x66, 0xB0, 0x2A, 0xF4, 0x1F, 0x07, 0x48, 0x02, 0xB6, 0x81, 0xB6, 0xE0, 0x76, 0xC8, 0x26, + 0xD6, 0x9A, 0xDE, 0xEB, 0x18, 0x4F, 0x4A, 0xB4, 0x37, 0x37, 0x56, 0x96, 0xBE, 0xEE, 0xF0, 0x4C, 0x44, 0x35, + 0xF3, 0x57, 0x05, 0xFE, 0x83, 0x00, 0x61, 0xC0, 0x28, 0x50, 0x1E, 0xBC, 0x08, 0x71, 0xC6, 0xA4, 0x52, 0xFB, + 0x7D, 0x83, 0x61, 0xA1, 0xE8, 0x78, 0x4E, 0xA2, 0xB4, 0x79, 0xB7, 0x62, 0xF6, 0xA9, 0x86, 0xFE, 0xE2, 0xC0, + 0x49, 0x90, 0x36, 0xEC, 0x16, 0xCD, 0xCE, 0xD5, 0x94, 0x5F, 0x2F, 0x78, 0x1C, 0x22, 0x89, 0xD9, 0xA6, 0xDA, + 0xFA, 0xDB, 0x03, 0x1B, 0x41, 0xCB, 0x70, 0x57, 0x64, 0x3E, 0xAB, 0x50, 0x7F, 0x7C, 0x20, 0x21, 0xD8, 0x18, + 0x5A, 0x8A, 0xBB, 0x27, 0x33, 0x5A, 0x95, 0xFB, 0x2F, 0x03, 0x5C, 0x01, 0xF9, 0xC0, 0x42, 0xD0, 0x31, 0x9C, + 0x14, 0x69, 0xCF, 0x6E, 0xD4, 0x2C, 0x5F, 0x5D, 0xF8, 0x39, 0x82, 0x92, 0xE1, 0xAD, 0x88, 0x7D, 0xA6, 0xA1, + 0xBA, 0xF8, 0x73, 0x02, 0xA5, 0xC1, 0xBB, 0x10, 0x73, 0x4C, 0x25, 0xF5, 0xDB, 0x07, 0x1B, 0x42, 0x8B, 0x71, + 0xA7, 0x64, 0x7A, 0xAB, 0x63, 0x3F, 0x69, 0xD0, 0x2E, 0xDC, 0x1C, 0x59, 0xC9, 0xFA, 0xD6, 0xC3, 0x1E, 0xD1, + 0xC8, 0x5C, 0x56, 0xB9, 0xFE, 0xF2, 0xC0, 0x45, 0x90, 0x33, 0x2C, 0x15, 0xDD, 0xCF, 0x19, 0x94, 0x0A, 0xEF, + 0x47, 0x0C, 0x32, 0x85, 0xD5, 0xA3, 0x1F, 0x39, 0xC8, 0x12, 0xD6, 0x8D, 0x9E, 0xE5, 0xA8, 0x4B, 0x3E, 0xB7, + 0x50, 0x76, 0xBC, 0x26, 0xF1, 0xDA, 0xC4, 0x5B, 0x13, 0x7B, 0x4D, 0xE3, 0x75, 0x89, 0xE7, 0x26, 0xCA, 0x9A, + 0xD7, 0x2B, 0x1E, 0x9F, 0x48, 0x68, 0x36, 0xAE, 0x96, 0xFC, 0x6E, 0xC1, 0xEC, 0x50, 0x4D, 0xFC, 0x35, 0x81, + 0xD7, 0x20, 0x5E, 0x98, 0x38, 0x6A, 0x92, 0xAF, 0x2D, 0xBC, 0x1D, 0xB1, 0xC9, 0xB4, 0x56, 0xF7, 0x7E, 0xC6, + 0xA0, 0x52, 0xF8, 0x3D, 0x82, 0x91, 0xA1, 0xAC, 0x78, 0x7D, 0xE2, 0xA1, 0x89, 0xB8, 0x66, 0xF2, 0xAA, 0xC5, + 0xBF, 0x13, 0x30, 0x0D, 0xD4, 0x05, 0x9F, 0x43, 0x28, 0x31, 0xDE, 0x94, 0x58, 0x6F, 0x7A, 0xAC, 0x23, 0x3D, + 0xD9, 0xD1, 0x9A, 0xDC, 0x6B, 0x19, 0xEF, 0x4A, 0xCC, 0x37, 0x15, 0xD6, 0x8F, 0x1E, 0xE4, 0x08, 0x4B, 0x46, + 0xB7, 0x72, 0xF6, 0xA5, 0x86, 0xFB, 0x22, 0xC3, 0x59, 0x91, 0xFA, 0xEC, 0x43, 0x0D, 0xF1, 0xC5, 0x84, 0x53, + 0x23, 0x7D, 0xD9, 0xE1, 0x9A, 0xC8, 0x6B, 0x16, 0xAF, 0x4E, 0xFC, 0x34, 0x41, 0xD7, 0x70, 0x5E, 0xA4, 0x38, + 0x7B, 0x52, 0xA3, 0x7D, 0xB9, 0xE1, 0xB2, 0xC8, 0x75, 0x96, 0xA7, 0x2E, 0xFA, 0x9C, 0x43, 0x29, 0xF1, 0xDE, + 0xC4, 0x58, 0x53, 0x7A, 0xBD, 0xE3, 0x31, 0x89, 0xD4, 0x66, 0xDF, 0x6A, 0xD8, 0x2F, 0x1A, 0x9C, 0x0B, 0x29, + 0xC7, 0x5E, 0xD2, 0xB8, 0x5D, 0xB2, 0xB9, 0xB5, 0xB2, 0xF7, 0x35, 0x86, 0x97, 0x22, 0xEE, 0x99, 0x8C, 0x6A, + 0xE5, 0xEF, 0x0B, 0x0C, 0x07, 0x45, 0xC2, 0xB3, 0x11, 0xB5, 0xCC, 0x77, 0x15, 0xE6, 0x8F, 0x0A, 0xE4, 0x07, + 0x0B, 0x42, 0x87, 0x71, 0xA2, 0xA4, 0x79, 0xBB, 0x62, 0xF3, 0x69, 0x85, 0xEE, 0xE3, 0x0C, 0x49, 0xC5, 0xF6, + 0xD3, 0x06, 0xDD, 0xC2, 0xD9, 0x91, 0x9A, 0xEC, 0x6B, 0x0D, 0xEF, 0x45, 0x8C, 0x33, 0x25, 0xD5, 0xDB, 0x1F, + 0x1B, 0x48, 0x0B, 0x76, 0x87, 0x66, 0xE2, 0xAA, 0xC9, 0xBF, 0x16, 0xF0, 0x0E, 0xC4, 0x04, 0x53, 0x43, 0x7D, + 0xF1, 0xE1, 0x84, 0x48, 0x63, 0x76, 0xA9, 0xE6, 0xFE, 0xCA, 0xC0, 0x57, 0x10, 0x3E, 0x8C, 0x10, 0x65, 0xCC, + 0x2B, 0x15, 0xDF, 0x4F, 0x18, 0x34, 0x0A, 0x97, 0x47, 0x2E, 0xB2, 0x9C, 0x75, 0xA9, 0xE7, 0x3E, 0xCA, 0x90, + 0x57, 0x2C, 0x3E, 0x9D, 0xD0, 0x69, 0x9C, 0x2E, 0xE9, 0xDC, 0x4E, 0xD9, 0xF4, 0x5A, 0xC7, 0x7B, 0x12, 0xA3, + 0x4D, 0xB9, 0xF5, 0xB2, 0xC7, 0x35, 0x92, 0x97, 0x2D, 0xAE, 0x9D, 0xBC, 0x69, 0xB1, 0xEE, 0xF4, 0x4C, 0x47, + 0x75, 0xF2, 0xA7, 0x05, 0xBA, 0x83, 0x33, 0x21, 0xD5, 0xD8, 0x5F, 0x1A, 0xB8, 0x0B, 0x32, 0x87, 0x55, 0xA2, + 0xBF, 0x39, 0xB0, 0x12, 0xF4, 0x0D, 0x87, 0x45, 0xA2, 0xB3, 0x39, 0xB5, 0xD2, 0xF7, 0x1D, 0x86, 0x89, 0xA2, + 0xE6, 0xF9, 0x8A, 0xC2, 0xE7, 0x11, 0x8A, 0x8C, 0x67, 0x25, 0xEA, 0x9B, 0x0F, 0x2B, 0x44, 0x1F, 0x73, 0x48, + 0x25, 0xF6, 0x9B, 0x06, 0xEB, 0x42, 0xCF, 0x71, 0x94, 0x24, 0x6F, 0x5B, 0x6C, 0x3B, 0x6D, 0xD3, 0x6D, 0x9D, + 0xED, 0xA9, 0x8D, 0xBE, 0xE5, 0xB0, 0x4B, 0x34, 0x37, 0x57, 0x56, 0xBE, 0xBE, 0xF0, 0x70, 0x44, 0x24, 0x33, + 0x5B, 0x55, 0xFB, 0x7F, 0x03, 0x60, 0x01, 0xE8, 0x00, 0x4E, 0x80, 0x34, 0x60, 0x17, 0x68, 0x0E, 0xAE, 0x84, + 0x7C, 0x63, 0x61, 0xE9, 0xE8, 0x4E, 0xCE, 0xB4, 0x54, 0x77, 0x7F, 0x66, 0xA0, 0x2A, 0xF8, 0x1F, 0x02, 0x88, + 0x01, 0xA6, 0x80, 0x7A, 0xE0, 0x23, 0x08, 0x19, 0xC6, 0x8A, 0xD2, 0xE7, 0x1D, 0x8A, 0x89, 0xA7, 0x26, 0xFA, + 0x9A, 0xC3, 0x2B, 0x11, 0xDF, 0x4C, 0x58, 0x35, 0xFA, 0x97, 0x03, 0x2E, 0x81, 0xDC, 0x60, 0x59, 0xE8, 0x3A, + 0xCE, 0x93, 0x14, 0x6D, 0xCF, 0x6D, 0x94, 0x2D, 0xAF, 0x5D, 0xBC, 0x39, 0xB1, 0xD2, 0xF4, 0x5D, 0x87, 0x79, + 0xA2, 0xA2, 0xF9, 0xB9, 0x82, 0xF2, 0xE1, 0x85, 0x88, 0x63, 0x26, 0xA9, 0xDA, 0xFE, 0xDB, 0x00, 0x5B, 0x40, + 0x3B, 0x70, 0x13, 0x64, 0x0D, 0xEB, 0x45, 0x8F, 0x73, 0x24, 0x25, 0xDB, 0x5B, 0x1B, 0x7B, 0x4B, 0x63, 0x77, + 0x69, 0xE6, 0xAE, 0xCA, 0xFC, 0x57, 0x01, 0xFE, 0x80, 0x40, 0x60, 0x30, 0x28, 0x14, 0x1E, 0x8F, 0x48, 0x64, + 0x36, 0xAB, 0x56, 0xFF, 0x7E, 0xC0, 0x20, 0x50, 0x18, 0x3C, 0x0A, 0x91, 0xC7, 0x2C, 0x52, 0x9D, 0xFD, 0xA9, + 0x81, 0xBE, 0xE0, 0x70, 0x48, 0x24, 0x36, 0x9B, 0x56, 0xEB, 0x7E, 0xCF, 0x60, 0x54, 0x28, 0x3F, 0x5E, 0x90, + 0x38, 0x6C, 0x12, 0xAD, 0xCD, 0xBD, 0x95, 0xB1, 0xAF, 0x34, 0x7C, 0x17, 0x61, 0xCE, 0xA8, 0x54, 0x7E, 0xBF, + 0x60, 0x70, 0x28, 0x24, 0x1E, 0x9B, 0x48, 0x6B, 0x76, 0xAF, 0x66, 0xFC, 0x2A, 0xC1, 0xDF, 0x10, 0x58, 0x0C, + 0x3A, 0x85, 0xD3, 0x23, 0x1D, 0xD9, 0xC9, 0x9A, 0xD6, 0xEB, 0x1E, 0xCF, 0x48, 0x54, 0x36, 0xBF, 0x56, 0xF0, + 0x3E, 0xC4, 0x10, 0x53, 0x4C, 0x3D, 0xF5, 0xD1, 0x87, 0x1C, 0x62, 0x89, 0xE9, 0xA6, 0xCE, 0xFA, 0xD4, 0x43, + 0x1F, 0x71, 0xC8, 0x24, 0x56, 0x9B, 0x7E, 0xEB, 0x60, 0x4F, 0x68, 0x34, 0x2E, 0x97, 0x5C, 0x6E, 0xB9, 0xEC, + 0x72, 0xCD, 0xE5, 0x95, 0x8B, 0x2F, 0x27, 0x5C, 0x1A, 0xB9, 0xCB, 0x32, 0xD7, 0x55, 0x9E, 0xBF, 0x28, 0x70, + 0x1E, 0xA4, 0x08, 0x7B, 0x46, 0xA3, 0x72, 0xF9, 0xE5, 0x82, 0xCB, 0x21, 0x97, 0x58, 0x6E, 0xBA, 0xAC, 0x73, + 0x3D, 0xE5, 0xD1, 0x8B, 0x1C, 0x67, 0x49, 0xEA, 0xB6, 0xCF, 0x36, 0xD4, 0x16, 0xDF, 0x4E, 0xD8, 0x34, 0x5A, + 0x97, 0x7B, 0x2E, 0xA3, 0x5C, 0x79, 0xF9, 0xE2, 0xC2, 0xC9, 0x91, 0x96, 0xEC, 0x6E, 0xCD, 0xEC, 0x55, 0x8D, + 0xFF, 0x25, 0x80, 0x1B, 0x20, 0x0B, 0x58, 0x07, 0x7A, 0x82, 0xA3, 0x21, 0xB9, 0xD8, 0x72, 0xDA, 0xA5, 0x9B, + 0x3B, 0x2B, 0x53, 0x5F, 0x7D, 0xF8, 0x21, 0x82, 0x98, 0x61, 0xAA, 0xA8, 0x7F, 0x3E, 0xA0, 0x10, 0x78, 0x0C, + 0x22, 0x85, 0xD9, 0xA3, 0x1A, 0xF9, 0xCB, 0x02, 0xD7, 0x41, 0x9E, 0xB0, 0x68, 0x74, 0x2E, 0xA7, 0x5C, 0x7A, + 0xB9, 0xE3, 0x32, 0xC9, 0xD5, 0x96, 0xDF, 0x2E, 0xD8, 0x1C, 0x5A, 0x89, 0xFB, 0x26, 0xC3, 0x5A, 0xD1, 0xFB, + 0x1C, 0x43, 0x49, 0xF1, 0xF6, 0xC4, 0x46, 0xD3, 0x72, 0xDD, 0xE5, 0x99 }; public static readonly byte[] SyncMark = @@ -191,19 +182,26 @@ namespace DiscImageChef.Decoders.CD public static byte[] Scramble(byte[] sector) { - if(sector == null || sector.Length < 2352) return sector; + if(sector == null || + sector.Length < 2352) + return sector; byte[] sync = new byte[12]; Array.Copy(sector, 0, sync, 0, 12); - if(!SyncMark.SequenceEqual(sync)) return sector; + if(!SyncMark.SequenceEqual(sync)) + return sector; - byte[] scrambled = new byte[sector.Length]; - for(int i = 0; i < 2352; i++) scrambled[i] = (byte)(sector[i] ^ ScrambleTable[i]); + byte[] scrambled = new byte[sector.Length]; - if(sector.Length <= 2352) return scrambled; + for(int i = 0; i < 2352; i++) + scrambled[i] = (byte)(sector[i] ^ ScrambleTable[i]); - for(int i = 2352; i < sector.Length; i++) scrambled[i] = sector[i]; + if(sector.Length <= 2352) + return scrambled; + + for(int i = 2352; i < sector.Length; i++) + scrambled[i] = sector[i]; return scrambled; } diff --git a/CD/Session.cs b/CD/Session.cs index 97846f4..5a7d0e8 100644 --- a/CD/Session.cs +++ b/CD/Session.cs @@ -37,88 +37,23 @@ using DiscImageChef.Console; namespace DiscImageChef.Decoders.CD { /// - /// Information from the following standards: - /// ANSI X3.304-1997 - /// T10/1048-D revision 9.0 - /// T10/1048-D revision 10a - /// T10/1228-D revision 7.0c - /// T10/1228-D revision 11a - /// T10/1363-D revision 10g - /// T10/1545-D revision 1d - /// T10/1545-D revision 5 - /// T10/1545-D revision 5a - /// T10/1675-D revision 2c - /// T10/1675-D revision 4 - /// T10/1836-D revision 2g + /// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a + /// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision + /// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static class Session { - public struct CDSessionInfo - { - /// - /// Total size of returned session information minus this field - /// - public ushort DataLength; - /// - /// First track number in hex - /// - public byte FirstCompleteSession; - /// - /// Last track number in hex - /// - public byte LastCompleteSession; - /// - /// Track descriptors - /// - public TrackDataDescriptor[] TrackDescriptors; - } - - public struct TrackDataDescriptor - { - /// - /// Byte 0 - /// Reserved - /// - public byte Reserved1; - /// - /// Byte 1, bits 7 to 4 - /// Type of information in Q subchannel of block where this TOC entry was found - /// - public byte ADR; - /// - /// Byte 1, bits 3 to 0 - /// Track attributes - /// - public byte CONTROL; - /// - /// Byte 2 - /// First track number in last complete session - /// - public byte TrackNumber; - /// - /// Byte 3 - /// Reserved - /// - public byte Reserved2; - /// - /// Bytes 4 to 7 - /// First track number in last complete session start address in LBA or in MSF - /// - public uint TrackStartAddress; - } - public static CDSessionInfo? Decode(byte[] CDSessionInfoResponse) { - if(CDSessionInfoResponse == null) return null; + if(CDSessionInfoResponse == null) + return null; - CDSessionInfo decoded = new CDSessionInfo + var decoded = new CDSessionInfo { DataLength = BigEndianBitConverter.ToUInt16(CDSessionInfoResponse, 0), - FirstCompleteSession = CDSessionInfoResponse[2], - LastCompleteSession = CDSessionInfoResponse[3] + FirstCompleteSession = CDSessionInfoResponse[2], LastCompleteSession = CDSessionInfoResponse[3] }; decoded.TrackDescriptors = new TrackDataDescriptor[(decoded.DataLength - 2) / 8]; @@ -128,6 +63,7 @@ namespace DiscImageChef.Decoders.CD DicConsole.DebugWriteLine("CD Session Info decoder", "Expected CDSessionInfo size ({0} bytes) is not received size ({1} bytes), not decoding", decoded.DataLength + 2, CDSessionInfoResponse.Length); + return null; } @@ -138,6 +74,7 @@ namespace DiscImageChef.Decoders.CD decoded.TrackDescriptors[i].CONTROL = (byte)(CDSessionInfoResponse[1 + i * 8 + 4] & 0x0F); decoded.TrackDescriptors[i].TrackNumber = CDSessionInfoResponse[2 + i * 8 + 4]; decoded.TrackDescriptors[i].Reserved2 = CDSessionInfoResponse[3 + i * 8 + 4]; + decoded.TrackDescriptors[i].TrackStartAddress = BigEndianBitConverter.ToUInt32(CDSessionInfoResponse, 4 + i * 8 + 4); } @@ -147,18 +84,21 @@ namespace DiscImageChef.Decoders.CD public static string Prettify(CDSessionInfo? CDSessionInfoResponse) { - if(CDSessionInfoResponse == null) return null; + if(CDSessionInfoResponse == null) + return null; CDSessionInfo response = CDSessionInfoResponse.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendFormat("First complete session number: {0}", response.FirstCompleteSession).AppendLine(); sb.AppendFormat("Last complete session number: {0}", response.LastCompleteSession).AppendLine(); + foreach(TrackDataDescriptor descriptor in response.TrackDescriptors) { - sb.AppendFormat("First track number in last complete session: {0}", descriptor.TrackNumber) - .AppendLine(); + sb.AppendFormat("First track number in last complete session: {0}", descriptor.TrackNumber). + AppendLine(); + sb.AppendFormat("Track starts at LBA {0}, or MSF {1:X2}:{2:X2}:{3:X2}", descriptor.TrackStartAddress, (descriptor.TrackStartAddress & 0x0000FF00) >> 8, (descriptor.TrackStartAddress & 0x00FF0000) >> 16, @@ -168,15 +108,19 @@ namespace DiscImageChef.Decoders.CD { case TocAdr.NoInformation: sb.AppendLine("Q subchannel mode not given"); + break; case TocAdr.CurrentPosition: sb.AppendLine("Q subchannel stores current position"); + break; case TocAdr.ISRC: sb.AppendLine("Q subchannel stores ISRC"); + break; case TocAdr.MediaCatalogNumber: sb.AppendLine("Q subchannel stores media catalog number"); + break; } @@ -188,35 +132,41 @@ namespace DiscImageChef.Decoders.CD { case TocControl.TwoChanNoPreEmph: sb.AppendLine("Stereo audio track with no pre-emphasis"); + break; case TocControl.TwoChanPreEmph: sb.AppendLine("Stereo audio track with 50/15 μs pre-emphasis"); + break; case TocControl.FourChanNoPreEmph: sb.AppendLine("Quadraphonic audio track with no pre-emphasis"); + break; case TocControl.FourChanPreEmph: sb.AppendLine("Stereo audio track with 50/15 μs pre-emphasis"); + break; case TocControl.DataTrack: sb.AppendLine("Data track, recorded uninterrupted"); + break; case TocControl.DataTrackIncremental: sb.AppendLine("Data track, recorded incrementally"); + break; } sb.AppendLine((descriptor.CONTROL & (byte)TocControl.CopyPermissionMask) == - (byte)TocControl.CopyPermissionMask - ? "Digital copy of track is permitted" + (byte)TocControl.CopyPermissionMask ? "Digital copy of track is permitted" : "Digital copy of track is prohibited"); - #if DEBUG + #if DEBUG if(descriptor.Reserved1 != 0) sb.AppendFormat("Reserved1 = 0x{0:X2}", descriptor.Reserved1).AppendLine(); + if(descriptor.Reserved2 != 0) sb.AppendFormat("Reserved2 = 0x{0:X2}", descriptor.Reserved2).AppendLine(); - #endif + #endif sb.AppendLine(); } @@ -228,7 +178,36 @@ namespace DiscImageChef.Decoders.CD public static string Prettify(byte[] CDSessionInfoResponse) { CDSessionInfo? decoded = Decode(CDSessionInfoResponse); + return Prettify(decoded); } + + public struct CDSessionInfo + { + /// Total size of returned session information minus this field + public ushort DataLength; + /// First track number in hex + public byte FirstCompleteSession; + /// Last track number in hex + public byte LastCompleteSession; + /// Track descriptors + public TrackDataDescriptor[] TrackDescriptors; + } + + public struct TrackDataDescriptor + { + /// Byte 0 Reserved + public byte Reserved1; + /// Byte 1, bits 7 to 4 Type of information in Q subchannel of block where this TOC entry was found + public byte ADR; + /// Byte 1, bits 3 to 0 Track attributes + public byte CONTROL; + /// Byte 2 First track number in last complete session + public byte TrackNumber; + /// Byte 3 Reserved + public byte Reserved2; + /// Bytes 4 to 7 First track number in last complete session start address in LBA or in MSF + public uint TrackStartAddress; + } } } \ No newline at end of file diff --git a/CD/TOC.cs b/CD/TOC.cs index 622c9b4..e71141c 100644 --- a/CD/TOC.cs +++ b/CD/TOC.cs @@ -37,89 +37,23 @@ using DiscImageChef.Console; namespace DiscImageChef.Decoders.CD { /// - /// Information from the following standards: - /// ANSI X3.304-1997 - /// T10/1048-D revision 9.0 - /// T10/1048-D revision 10a - /// T10/1228-D revision 7.0c - /// T10/1228-D revision 11a - /// T10/1363-D revision 10g - /// T10/1545-D revision 1d - /// T10/1545-D revision 5 - /// T10/1545-D revision 5a - /// T10/1675-D revision 2c - /// T10/1675-D revision 4 - /// T10/1836-D revision 2g - /// ISO/IEC 61104: Compact disc video system - 12 cm CD-V - /// ISO/IEC 60908: Audio recording - Compact disc digital audio system + /// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a + /// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision + /// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g ISO/IEC 61104: Compact + /// disc video system - 12 cm CD-V ISO/IEC 60908: Audio recording - Compact disc digital audio system /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static class TOC { - public struct CDTOC - { - /// - /// Total size of returned TOC minus this field - /// - public ushort DataLength; - /// - /// First track number in hex - /// - public byte FirstTrack; - /// - /// Last track number in hex - /// - public byte LastTrack; - /// - /// Track descriptors - /// - public CDTOCTrackDataDescriptor[] TrackDescriptors; - } - - public struct CDTOCTrackDataDescriptor - { - /// - /// Byte 0 - /// Reserved - /// - public byte Reserved1; - /// - /// Byte 1, bits 7 to 4 - /// Type of information in Q subchannel of block where this TOC entry was found - /// - public byte ADR; - /// - /// Byte 1, bits 3 to 0 - /// Track attributes - /// - public byte CONTROL; - /// - /// Byte 2 - /// Track number - /// - public byte TrackNumber; - /// - /// Byte 3 - /// Reserved - /// - public byte Reserved2; - /// - /// Bytes 4 to 7 - /// The track start address in LBA or in MSF - /// - public uint TrackStartAddress; - } - public static CDTOC? Decode(byte[] CDTOCResponse) { - if(CDTOCResponse == null) return null; + if(CDTOCResponse == null) + return null; - CDTOC decoded = new CDTOC + var decoded = new CDTOC { - DataLength = BigEndianBitConverter.ToUInt16(CDTOCResponse, 0), - FirstTrack = CDTOCResponse[2], + DataLength = BigEndianBitConverter.ToUInt16(CDTOCResponse, 0), FirstTrack = CDTOCResponse[2], LastTrack = CDTOCResponse[3] }; @@ -130,6 +64,7 @@ namespace DiscImageChef.Decoders.CD DicConsole.DebugWriteLine("CD TOC decoder", "Expected CDTOC size ({0} bytes) is not received size ({1} bytes), not decoding", decoded.DataLength + 2, CDTOCResponse.Length); + return null; } @@ -140,6 +75,7 @@ namespace DiscImageChef.Decoders.CD decoded.TrackDescriptors[i].CONTROL = (byte)(CDTOCResponse[1 + i * 8 + 4] & 0x0F); decoded.TrackDescriptors[i].TrackNumber = CDTOCResponse[2 + i * 8 + 4]; decoded.TrackDescriptors[i].Reserved2 = CDTOCResponse[3 + i * 8 + 4]; + decoded.TrackDescriptors[i].TrackStartAddress = BigEndianBitConverter.ToUInt32(CDTOCResponse, 4 + i * 8 + 4); } @@ -149,18 +85,23 @@ namespace DiscImageChef.Decoders.CD public static string Prettify(CDTOC? CDTOCResponse) { - if(CDTOCResponse == null) return null; + if(CDTOCResponse == null) + return null; CDTOC response = CDTOCResponse.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendFormat("First track number in first complete session: {0}", response.FirstTrack).AppendLine(); sb.AppendFormat("Last track number in last complete session: {0}", response.LastTrack).AppendLine(); + foreach(CDTOCTrackDataDescriptor descriptor in response.TrackDescriptors) { - if(descriptor.TrackNumber == 0xAA) sb.AppendLine("Track number: Lead-Out"); - else sb.AppendFormat("Track number: {0}", descriptor.TrackNumber).AppendLine(); + if(descriptor.TrackNumber == 0xAA) + sb.AppendLine("Track number: Lead-Out"); + else + sb.AppendFormat("Track number: {0}", descriptor.TrackNumber).AppendLine(); + sb.AppendFormat("Track starts at LBA {0}, or MSF {1:X2}:{2:X2}:{3:X2}", descriptor.TrackStartAddress, (descriptor.TrackStartAddress & 0x0000FF00) >> 8, (descriptor.TrackStartAddress & 0x00FF0000) >> 16, @@ -170,21 +111,27 @@ namespace DiscImageChef.Decoders.CD { case TocAdr.NoInformation: sb.AppendLine("Q subchannel mode not given"); + break; case TocAdr.TrackPointer: sb.AppendLine("Q subchannel stores track pointer"); + break; case TocAdr.VideoTrackPointer: sb.AppendLine("Q subchannel stores video track pointer"); + break; case TocAdr.ISRC: sb.AppendLine("Q subchannel stores ISRC"); + break; case TocAdr.MediaCatalogNumber: sb.AppendLine("Q subchannel stores media catalog number"); + break; default: sb.AppendFormat("Q subchannel mode {0}", descriptor.ADR).AppendLine(); + break; } @@ -196,35 +143,41 @@ namespace DiscImageChef.Decoders.CD { case TocControl.TwoChanNoPreEmph: sb.AppendLine("Stereo audio track with no pre-emphasis"); + break; case TocControl.TwoChanPreEmph: sb.AppendLine("Stereo audio track with 50/15 μs pre-emphasis"); + break; case TocControl.FourChanNoPreEmph: sb.AppendLine("Quadraphonic audio track with no pre-emphasis"); + break; case TocControl.FourChanPreEmph: sb.AppendLine("Quadraphonic audio track with 50/15 μs pre-emphasis"); + break; case TocControl.DataTrack: sb.AppendLine("Data track, recorded uninterrupted"); + break; case TocControl.DataTrackIncremental: sb.AppendLine("Data track, recorded incrementally"); + break; } sb.AppendLine((descriptor.CONTROL & (byte)TocControl.CopyPermissionMask) == - (byte)TocControl.CopyPermissionMask - ? "Digital copy of track is permitted" + (byte)TocControl.CopyPermissionMask ? "Digital copy of track is permitted" : "Digital copy of track is prohibited"); - #if DEBUG + #if DEBUG if(descriptor.Reserved1 != 0) sb.AppendFormat("Reserved1 = 0x{0:X2}", descriptor.Reserved1).AppendLine(); + if(descriptor.Reserved2 != 0) sb.AppendFormat("Reserved2 = 0x{0:X2}", descriptor.Reserved2).AppendLine(); - #endif + #endif sb.AppendLine(); } @@ -236,7 +189,36 @@ namespace DiscImageChef.Decoders.CD public static string Prettify(byte[] CDTOCResponse) { CDTOC? decoded = Decode(CDTOCResponse); + return Prettify(decoded); } + + public struct CDTOC + { + /// Total size of returned TOC minus this field + public ushort DataLength; + /// First track number in hex + public byte FirstTrack; + /// Last track number in hex + public byte LastTrack; + /// Track descriptors + public CDTOCTrackDataDescriptor[] TrackDescriptors; + } + + public struct CDTOCTrackDataDescriptor + { + /// Byte 0 Reserved + public byte Reserved1; + /// Byte 1, bits 7 to 4 Type of information in Q subchannel of block where this TOC entry was found + public byte ADR; + /// Byte 1, bits 3 to 0 Track attributes + public byte CONTROL; + /// Byte 2 Track number + public byte TrackNumber; + /// Byte 3 Reserved + public byte Reserved2; + /// Bytes 4 to 7 The track start address in LBA or in MSF + public uint TrackStartAddress; + } } } \ No newline at end of file diff --git a/DVD/AACS.cs b/DVD/AACS.cs index 47bd319..c11ec52 100644 --- a/DVD/AACS.cs +++ b/DVD/AACS.cs @@ -35,47 +35,23 @@ using System.Diagnostics.CodeAnalysis; namespace DiscImageChef.Decoders.DVD { /// - /// Information from the following standards: - /// ANSI X3.304-1997 - /// T10/1048-D revision 9.0 - /// T10/1048-D revision 10a - /// T10/1228-D revision 7.0c - /// T10/1228-D revision 11a - /// T10/1363-D revision 10g - /// T10/1545-D revision 1d - /// T10/1545-D revision 5 - /// T10/1545-D revision 5a - /// T10/1675-D revision 2c - /// T10/1675-D revision 4 - /// T10/1836-D revision 2g - /// ECMA 365 + /// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a + /// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision + /// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g ECMA 365 /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static class AACS { public struct HDLeadInCopyright { - /// - /// Bytes 0 to 1 - /// Data length - /// + /// Bytes 0 to 1 Data length public ushort DataLength; - /// - /// Byte 2 - /// Reserved - /// + /// Byte 2 Reserved public byte Reserved1; - /// - /// Byte 3 - /// Reserved - /// + /// Byte 3 Reserved public byte Reserved2; - /// - /// Bytes 4 to 2052 - /// HD DVD Lead-In Copyright Information - /// + /// Bytes 4 to 2052 HD DVD Lead-In Copyright Information public byte[] CopyrightInformation; } } diff --git a/DVD/ADIP.cs b/DVD/ADIP.cs index d970c66..6680ec8 100644 --- a/DVD/ADIP.cs +++ b/DVD/ADIP.cs @@ -35,47 +35,23 @@ using System.Diagnostics.CodeAnalysis; namespace DiscImageChef.Decoders.DVD { /// - /// Information from the following standards: - /// ANSI X3.304-1997 - /// T10/1048-D revision 9.0 - /// T10/1048-D revision 10a - /// T10/1228-D revision 7.0c - /// T10/1228-D revision 11a - /// T10/1363-D revision 10g - /// T10/1545-D revision 1d - /// T10/1545-D revision 5 - /// T10/1545-D revision 5a - /// T10/1675-D revision 2c - /// T10/1675-D revision 4 - /// T10/1836-D revision 2g - /// ECMA 365 + /// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a + /// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision + /// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g ECMA 365 /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static class ADIP { public struct ADIPInformation { - /// - /// Bytes 0 to 1 - /// Data length - /// + /// Bytes 0 to 1 Data length public ushort DataLength; - /// - /// Byte 2 - /// Reserved - /// + /// Byte 2 Reserved public byte Reserved1; - /// - /// Byte 3 - /// Reserved - /// + /// Byte 3 Reserved public byte Reserved2; - /// - /// Bytes 4 to 259 - /// ADIP, defined in DVD standards - /// + /// Bytes 4 to 259 ADIP, defined in DVD standards public byte[] ADIP; } } diff --git a/DVD/BCA.cs b/DVD/BCA.cs index 9eef594..8444240 100644 --- a/DVD/BCA.cs +++ b/DVD/BCA.cs @@ -35,47 +35,23 @@ using System.Diagnostics.CodeAnalysis; namespace DiscImageChef.Decoders.DVD { /// - /// Information from the following standards: - /// ANSI X3.304-1997 - /// T10/1048-D revision 9.0 - /// T10/1048-D revision 10a - /// T10/1228-D revision 7.0c - /// T10/1228-D revision 11a - /// T10/1363-D revision 10g - /// T10/1545-D revision 1d - /// T10/1545-D revision 5 - /// T10/1545-D revision 5a - /// T10/1675-D revision 2c - /// T10/1675-D revision 4 - /// T10/1836-D revision 2g - /// ECMA 365 + /// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a + /// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision + /// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g ECMA 365 /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static class BCA { public struct BurstCuttingArea { - /// - /// Bytes 0 to 1 - /// Data length - /// + /// Bytes 0 to 1 Data length public ushort DataLength; - /// - /// Byte 2 - /// Reserved - /// + /// Byte 2 Reserved public byte Reserved1; - /// - /// Byte 3 - /// Reserved - /// + /// Byte 3 Reserved public byte Reserved2; - /// - /// Bytes 4 to end - /// Burst cutting area contents, 12 to 188 bytes - /// + /// Bytes 4 to end Burst cutting area contents, 12 to 188 bytes public byte[] BCA; } } diff --git a/DVD/CPRM.cs b/DVD/CPRM.cs index b3e957f..71ad73f 100644 --- a/DVD/CPRM.cs +++ b/DVD/CPRM.cs @@ -35,71 +35,35 @@ using System.Diagnostics.CodeAnalysis; namespace DiscImageChef.Decoders.DVD { /// - /// Information from the following standards: - /// ANSI X3.304-1997 - /// T10/1048-D revision 9.0 - /// T10/1048-D revision 10a - /// T10/1228-D revision 7.0c - /// T10/1228-D revision 11a - /// T10/1363-D revision 10g - /// T10/1545-D revision 1d - /// T10/1545-D revision 5 - /// T10/1545-D revision 5a - /// T10/1675-D revision 2c - /// T10/1675-D revision 4 - /// T10/1836-D revision 2g - /// ECMA 365 + /// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a + /// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision + /// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g ECMA 365 /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static class CPRM { public struct DiscMediaIdentifier { - /// - /// Bytes 0 to 1 - /// Data length - /// + /// Bytes 0 to 1 Data length public ushort DataLength; - /// - /// Byte 2 - /// Reserved - /// + /// Byte 2 Reserved public byte Reserved1; - /// - /// Byte 3 - /// Reserved - /// + /// Byte 3 Reserved public byte Reserved2; - /// - /// Bytes 4 to end - /// Disc Media Identifier for CPRM - /// + /// Bytes 4 to end Disc Media Identifier for CPRM public byte[] MediaIdentifier; } public struct DiscMediaKeyBlock { - /// - /// Bytes 0 to 1 - /// Data length - /// + /// Bytes 0 to 1 Data length public ushort DataLength; - /// - /// Byte 2 - /// Reserved - /// + /// Byte 2 Reserved public byte Reserved1; - /// - /// Byte 3 - /// Reserved - /// + /// Byte 3 Reserved public byte Reserved2; - /// - /// Bytes 4 to end - /// Disc Media Key Block for CPRM - /// + /// Bytes 4 to end Disc Media Key Block for CPRM public byte[] MediaKeyBlock; } } diff --git a/DVD/CSS&CPRM.cs b/DVD/CSS&CPRM.cs index 1a6b52d..fb3da87 100644 --- a/DVD/CSS&CPRM.cs +++ b/DVD/CSS&CPRM.cs @@ -36,147 +36,94 @@ using System.Text; namespace DiscImageChef.Decoders.DVD { /// - /// Information from the following standards: - /// ANSI X3.304-1997 - /// T10/1048-D revision 9.0 - /// T10/1048-D revision 10a - /// T10/1228-D revision 7.0c - /// T10/1228-D revision 11a - /// T10/1363-D revision 10g - /// T10/1545-D revision 1d - /// T10/1545-D revision 5 - /// T10/1545-D revision 5a - /// T10/1675-D revision 2c - /// T10/1675-D revision 4 - /// T10/1836-D revision 2g - /// ECMA 365 + /// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a + /// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision + /// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g ECMA 365 /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] public static class CSS_CPRM { - public struct LeadInCopyright - { - /// - /// Bytes 0 to 1 - /// Data length - /// - public ushort DataLength; - /// - /// Byte 2 - /// Reserved - /// - public byte Reserved1; - /// - /// Byte 3 - /// Reserved - /// - public byte Reserved2; - /// - /// Byte 4 - /// Copy protection system type - /// - public CopyrightType CopyrightType; - /// - /// Byte 5 - /// Bitmask of regions where this disc is playable - /// - public byte RegionInformation; - /// - /// Byte 6 - /// Reserved - /// - public byte Reserved3; - /// - /// Byte 7 - /// Reserved - /// - public byte Reserved4; - } - - public struct DiscKey - { - /// - /// Bytes 0 to 1 - /// Data length - /// - public ushort DataLength; - /// - /// Byte 2 - /// Reserved - /// - public byte Reserved1; - /// - /// Byte 3 - /// Reserved - /// - public byte Reserved2; - /// - /// Bytes 4 to 2052 - /// Disc key for CSS, Album Identifier for CPPM - /// - public byte[] Key; - } - public static LeadInCopyright? DecodeLeadInCopyright(byte[] response) { - if(response?.Length != 8) return null; + if(response?.Length != 8) + return null; return new LeadInCopyright { - DataLength = (ushort)((response[0] << 8) + response[1]), - Reserved1 = response[2], - Reserved2 = response[3], - CopyrightType = (CopyrightType)response[4], + DataLength = (ushort)((response[0] << 8) + response[1]), Reserved1 = response[2], + Reserved2 = response[3], CopyrightType = (CopyrightType)response[4], RegionInformation = response[5], - Reserved3 = response[6], - Reserved4 = response[7] + Reserved3 = response[6], Reserved4 = response[7] }; } public static string PrettifyLeadInCopyright(LeadInCopyright? cmi) { - if(cmi == null) return null; + if(cmi == null) + return null; LeadInCopyright decoded = cmi.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); switch(decoded.CopyrightType) { case CopyrightType.NoProtection: sb.AppendLine("Disc has no encryption."); + break; case CopyrightType.CSS: sb.AppendLine("Disc is encrypted using CSS or CPPM."); + break; case CopyrightType.CPRM: sb.AppendLine("Disc is encrypted using CPRM."); + break; case CopyrightType.AACS: sb.AppendLine("Disc is encrypted using AACS."); + break; default: sb.AppendFormat("Disc is encrypted using unknown algorithm with ID {0}.", decoded.CopyrightType); + break; } - if(decoded.CopyrightType == 0) return sb.ToString(); + if(decoded.CopyrightType == 0) + return sb.ToString(); - if(decoded.RegionInformation == 0xFF) sb.AppendLine("Disc cannot be played in any region at all."); - else if(decoded.RegionInformation == 0x00) sb.AppendLine("Disc can be played in any region."); + if(decoded.RegionInformation == 0xFF) + sb.AppendLine("Disc cannot be played in any region at all."); + else if(decoded.RegionInformation == 0x00) + sb.AppendLine("Disc can be played in any region."); else { sb.Append("Disc can be played in the following regions:"); - if((decoded.RegionInformation & 0x01) != 0x01) sb.Append(" 0"); - if((decoded.RegionInformation & 0x02) != 0x02) sb.Append(" 1"); - if((decoded.RegionInformation & 0x04) != 0x04) sb.Append(" 2"); - if((decoded.RegionInformation & 0x08) != 0x08) sb.Append(" 3"); - if((decoded.RegionInformation & 0x10) != 0x10) sb.Append(" 4"); - if((decoded.RegionInformation & 0x20) != 0x20) sb.Append(" 5"); - if((decoded.RegionInformation & 0x40) != 0x40) sb.Append(" 6"); - if((decoded.RegionInformation & 0x80) != 0x80) sb.Append(" 7"); + + if((decoded.RegionInformation & 0x01) != 0x01) + sb.Append(" 0"); + + if((decoded.RegionInformation & 0x02) != 0x02) + sb.Append(" 1"); + + if((decoded.RegionInformation & 0x04) != 0x04) + sb.Append(" 2"); + + if((decoded.RegionInformation & 0x08) != 0x08) + sb.Append(" 3"); + + if((decoded.RegionInformation & 0x10) != 0x10) + sb.Append(" 4"); + + if((decoded.RegionInformation & 0x20) != 0x20) + sb.Append(" 5"); + + if((decoded.RegionInformation & 0x40) != 0x40) + sb.Append(" 6"); + + if((decoded.RegionInformation & 0x80) != 0x80) + sb.Append(" 7"); } return sb.ToString(); @@ -184,5 +131,35 @@ namespace DiscImageChef.Decoders.DVD public static string PrettifyLeadInCopyright(byte[] response) => PrettifyLeadInCopyright(DecodeLeadInCopyright(response)); + + public struct LeadInCopyright + { + /// Bytes 0 to 1 Data length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Byte 4 Copy protection system type + public CopyrightType CopyrightType; + /// Byte 5 Bitmask of regions where this disc is playable + public byte RegionInformation; + /// Byte 6 Reserved + public byte Reserved3; + /// Byte 7 Reserved + public byte Reserved4; + } + + public struct DiscKey + { + /// Bytes 0 to 1 Data length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Bytes 4 to 2052 Disc key for CSS, Album Identifier for CPPM + public byte[] Key; + } } } \ No newline at end of file diff --git a/DVD/Cartridge.cs b/DVD/Cartridge.cs index 1e7cedb..34b8821 100644 --- a/DVD/Cartridge.cs +++ b/DVD/Cartridge.cs @@ -36,159 +36,88 @@ using System.Text; namespace DiscImageChef.Decoders.DVD { /// - /// Information from the following standards: - /// ANSI X3.304-1997 - /// T10/1048-D revision 9.0 - /// T10/1048-D revision 10a - /// T10/1228-D revision 7.0c - /// T10/1228-D revision 11a - /// T10/1363-D revision 10g - /// T10/1545-D revision 1d - /// T10/1545-D revision 5 - /// T10/1545-D revision 5a - /// T10/1675-D revision 2c - /// T10/1675-D revision 4 - /// T10/1836-D revision 2g + /// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a + /// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision + /// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] public static class Cartridge { - public struct MediumStatus - { - /// - /// Bytes 0 to 1 - /// Data length - /// - public ushort DataLength; - /// - /// Byte 2 - /// Reserved - /// - public byte Reserved1; - /// - /// Byte 3 - /// Reserved - /// - public byte Reserved2; - /// - /// Byte 4, bit 7 - /// Medium is in a cartridge - /// - public bool Cartridge; - /// - /// Byte 4, bit 6 - /// Medium has been taken out/inserted in a cartridge - /// - public bool OUT; - /// - /// Byte 4, bits 5 to 4 - /// Reserved - /// - public byte Reserved3; - /// - /// Byte 4, bit 3 - /// Media is write protected by reason stablished in RAMSWI - /// - public bool MSWI; - /// - /// Byte 4, bit 2 - /// Media is write protected by cartridge - /// - public bool CWP; - /// - /// Byte 4, bit 1 - /// Media is persistently write protected - /// - public bool PWP; - /// - /// Byte 4, bit 0 - /// Reserved - /// - public bool Reserved4; - /// - /// Byte 5 - /// Writable status depending on cartridge - /// - public byte DiscType; - /// - /// Byte 6 - /// Reserved - /// - public byte Reserved5; - /// - /// Byte 7 - /// Reason of specific write protection, only defined 0x01 as "bare disc wp", and 0xFF as unspecified. Rest reserved. - /// - public byte RAMSWI; - } - public static MediumStatus? Decode(byte[] response) { - if(response?.Length != 8) return null; + if(response?.Length != 8) + return null; return new MediumStatus { - DataLength = (ushort)((response[0] << 8) + response[1]), - Reserved1 = response[2], - Reserved2 = response[3], - Cartridge = (response[4] & 0x80) == 0x80, - OUT = (response[4] & 0x40) == 0x40, - Reserved3 = (byte)((response[4] & 0x30) >> 4), - MSWI = (response[4] & 0x08) == 0x08, - CWP = (response[4] & 0x04) == 0x04, - PWP = (response[4] & 0x02) == 0x02, - Reserved4 = (response[4] & 0x01) == 0x01, - DiscType = response[5], - Reserved5 = response[6], + DataLength = (ushort)((response[0] << 8) + response[1]), Reserved1 = response[2], + Reserved2 = response[3], Cartridge = (response[4] & 0x80) == 0x80, + OUT = (response[4] & 0x40) == 0x40, + Reserved3 = (byte)((response[4] & 0x30) >> 4), MSWI = (response[4] & 0x08) == 0x08, + CWP = (response[4] & 0x04) == 0x04, + PWP = (response[4] & 0x02) == 0x02, + Reserved4 = (response[4] & 0x01) == 0x01, + DiscType = response[5], Reserved5 = response[6], RAMSWI = response[7] }; } public static string Prettify(MediumStatus? status) { - if(status == null) return null; + if(status == null) + return null; - MediumStatus decoded = status.Value; - StringBuilder sb = new StringBuilder(); + MediumStatus decoded = status.Value; + var sb = new StringBuilder(); - if(decoded.PWP) sb.AppendLine("Disc surface is set to write protected status"); + if(decoded.PWP) + sb.AppendLine("Disc surface is set to write protected status"); if(decoded.Cartridge) { sb.AppendLine("Disc comes in a cartridge"); - if(decoded.OUT) sb.AppendLine("Disc has been extracted from the cartridge"); - if(decoded.CWP) sb.AppendLine("Cartridge is set to write protected"); + + if(decoded.OUT) + sb.AppendLine("Disc has been extracted from the cartridge"); + + if(decoded.CWP) + sb.AppendLine("Cartridge is set to write protected"); } switch(decoded.DiscType) { case 0: sb.AppendLine("Disc shall not be written without a cartridge"); + break; case 0x10: sb.AppendLine("Disc may be written without a cartridge"); + break; default: sb.AppendFormat("Unknown disc type id {0}", decoded.DiscType).AppendLine(); + break; } - if(!decoded.MSWI) return sb.ToString(); + if(!decoded.MSWI) + return sb.ToString(); switch(decoded.RAMSWI) { case 0: break; case 1: sb.AppendLine("Disc is write inhibited because it has been extracted from the cartridge"); + break; case 0xFF: sb.AppendLine("Disc is write inhibited for an unspecified reason"); + break; default: sb.AppendFormat("Disc has unknown reason {0} for write inhibition", decoded.RAMSWI).AppendLine(); + break; } @@ -196,5 +125,38 @@ namespace DiscImageChef.Decoders.DVD } public static string Prettify(byte[] response) => Prettify(Decode(response)); + + public struct MediumStatus + { + /// Bytes 0 to 1 Data length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Byte 4, bit 7 Medium is in a cartridge + public bool Cartridge; + /// Byte 4, bit 6 Medium has been taken out/inserted in a cartridge + public bool OUT; + /// Byte 4, bits 5 to 4 Reserved + public byte Reserved3; + /// Byte 4, bit 3 Media is write protected by reason stablished in RAMSWI + public bool MSWI; + /// Byte 4, bit 2 Media is write protected by cartridge + public bool CWP; + /// Byte 4, bit 1 Media is persistently write protected + public bool PWP; + /// Byte 4, bit 0 Reserved + public bool Reserved4; + /// Byte 5 Writable status depending on cartridge + public byte DiscType; + /// Byte 6 Reserved + public byte Reserved5; + /// + /// Byte 7 Reason of specific write protection, only defined 0x01 as "bare disc wp", and 0xFF as unspecified. Rest + /// reserved. + /// + public byte RAMSWI; + } } } \ No newline at end of file diff --git a/DVD/DDS.cs b/DVD/DDS.cs index 61e1d97..0fdb75a 100644 --- a/DVD/DDS.cs +++ b/DVD/DDS.cs @@ -37,176 +37,28 @@ using System.Text; namespace DiscImageChef.Decoders.DVD { /// - /// Information from the following standards: - /// ANSI X3.304-1997 - /// T10/1048-D revision 9.0 - /// T10/1048-D revision 10a - /// T10/1228-D revision 7.0c - /// T10/1228-D revision 11a - /// T10/1363-D revision 10g - /// T10/1545-D revision 1d - /// T10/1545-D revision 5 - /// T10/1545-D revision 5a - /// T10/1675-D revision 2c - /// T10/1675-D revision 4 - /// T10/1836-D revision 2g - /// ECMA 272: 120 mm DVD Rewritable Disk (DVD-RAM) - /// ECMA 330: 120 mm (4,7 Gbytes per side) and 80 mm (1,46 Gbytes per side) DVD Rewritable Disk (DVD-RAM) + /// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a + /// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision + /// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g ECMA 272: 120 mm DVD + /// Rewritable Disk (DVD-RAM) ECMA 330: 120 mm (4,7 Gbytes per side) and 80 mm (1,46 Gbytes per side) DVD Rewritable + /// Disk (DVD-RAM) /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] public static class DDS { - public struct DiscDefinitionStructure - { - /// - /// Bytes 0 to 1 - /// Data length - /// - public ushort DataLength; - /// - /// Byte 2 - /// Reserved - /// - public byte Reserved1; - /// - /// Byte 3 - /// Reserved - /// - public byte Reserved2; - - /// - /// Bytes 4 to 5 - /// DDS Identifier = 0x0A0A - /// - public ushort Identifier; - /// - /// Byte 6 - /// Reserved - /// - public byte Reserved3; - /// - /// Byte 7, bit 7 - /// If set, formatting is in process - /// - public bool InProcess; - /// - /// Byte 7, bit 6 - /// If set, formatting is using partial certification - /// Only in ECMA-272 - /// - public bool PartialCertification; - /// - /// Byte 7, bit 5 - /// If set, only a group is being formatted - /// Only in ECMA-272 - /// - public bool FormattingOnlyAGroup; - /// - /// Byte 7, bits 4 to 2 - /// Reserved - /// - public byte Reserved4; - /// - /// Byte 7, bit 1 - /// If set, disk has been certified by a user - /// - public bool UserCertification; - /// - /// Byte 7, bit 0 - /// If set, disk has been certified by a manufacturer - /// - public bool ManufacturerCertification; - /// - /// Bytes 8 to 11 - /// How many times the DDS has been updated - /// - public uint UpdateCount; - /// - /// Bytes 12 to 13 - /// How many groups the disk has - /// 24 for ECMA-272 - /// 1 for ECMA-330 - /// - public ushort Groups; - /// - /// Bytes 14 to 15 - /// How many zones the disk has - /// Only in ECMA-330 - /// - public ushort Zones; - /// - /// Bytes 14 to 19 in ECMA-272 - /// Bytes 16 to 83 in ECMA-330 - /// Reserved - /// - public byte[] Reserved; - /// - /// Bytes 20 to 43 - /// Group certification flags - /// - public GroupCertificationFlag[] GroupCertificationFlags; - - /// - /// Bytes 85 to 87 - /// Location of first sector in the Primary Spare Area - /// - public uint SpareAreaFirstPSN; - /// - /// Bytes 89 to 91 - /// Location of first sector in the Primary Spare Area - /// - public uint SpareAreaLastPSN; - /// - /// Bytes 93 to 95 - /// PSN for LSN 0 - /// - public uint LSN0Location; - /// - /// The starting LSN of each zone - /// - public uint[] StartLSNForZone; - } - - public struct GroupCertificationFlag - { - /// - /// Bit 7 - /// If set, formatting of this group is in process - /// - public bool InProcess; - /// - /// Bit 6 - /// If set, formatting is using partial certification - /// - public bool PartialCertification; - /// - /// Bits 5 to 2 - /// Reserved - /// - public byte Reserved1; - /// - /// Bit 1 - /// If set, this group has been certified by user - /// - public bool UserCertification; - /// - /// Bit 0 - /// Reserved - /// - public bool Reserved2; - } - public static DiscDefinitionStructure? Decode(byte[] response) { - if(response?.Length != 2052) return null; + if(response?.Length != 2052) + return null; - DiscDefinitionStructure dds = - new DiscDefinitionStructure {Identifier = (ushort)((response[4] << 8) + response[5])}; + var dds = new DiscDefinitionStructure + { + Identifier = (ushort)((response[4] << 8) + response[5]) + }; - if(dds.Identifier != 0x0A0A) return null; + if(dds.Identifier != 0x0A0A) + return null; // Common to both DVD-RAM versions dds.DataLength = (ushort)((response[0] << 8) + response[1]); @@ -216,8 +68,10 @@ namespace DiscImageChef.Decoders.DVD dds.InProcess |= (response[7] & 0x80) == 0x80; dds.UserCertification |= (response[7] & 0x02) == 0x02; dds.ManufacturerCertification |= (response[7] & 0x01) == 0x01; + dds.UpdateCount = (uint)((response[8] << 24) + (response[9] << 16) + (response[10] << 8) + response[11]); + dds.Groups = (ushort)((response[12] << 8) + response[13]); @@ -230,6 +84,7 @@ namespace DiscImageChef.Decoders.DVD dds.Reserved = new byte[6]; Array.Copy(response, 14, dds.Reserved, 0, 6); dds.GroupCertificationFlags = new GroupCertificationFlag[24]; + for(int i = 0; i < 24; i++) { dds.GroupCertificationFlags[i].InProcess |= (response[20 + i] & 0x80) == 0x80; @@ -241,7 +96,8 @@ namespace DiscImageChef.Decoders.DVD } // ECMA-330 - if(dds.Groups != 1) return dds; + if(dds.Groups != 1) + return dds; { dds.Reserved4 = (byte)((response[7] & 0x7C) >> 2); @@ -263,23 +119,31 @@ namespace DiscImageChef.Decoders.DVD public static string Prettify(DiscDefinitionStructure? dds) { - if(dds == null) return null; + if(dds == null) + return null; DiscDefinitionStructure decoded = dds.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); if(decoded.InProcess) { sb.AppendLine("Formatting in progress."); + if(decoded.Groups == 24) { - if(decoded.PartialCertification) sb.AppendLine("Formatting is only using partial certification"); - if(decoded.FormattingOnlyAGroup) sb.AppendLine("Only a group is being formatted"); + if(decoded.PartialCertification) + sb.AppendLine("Formatting is only using partial certification"); + + if(decoded.FormattingOnlyAGroup) + sb.AppendLine("Only a group is being formatted"); } } - if(decoded.UserCertification) sb.AppendLine("Disc has been certified by an user"); - if(decoded.ManufacturerCertification) sb.AppendLine("Disc has been certified by a manufacturer"); + if(decoded.UserCertification) + sb.AppendLine("Disc has been certified by an user"); + + if(decoded.ManufacturerCertification) + sb.AppendLine("Disc has been certified by a manufacturer"); sb.AppendFormat("DDS has been updated {0} times", decoded.UpdateCount).AppendLine(); @@ -289,6 +153,7 @@ namespace DiscImageChef.Decoders.DVD if(decoded.GroupCertificationFlags[i].InProcess) { sb.AppendFormat("Group {0} is being formatted", i).AppendLine(); + if(decoded.GroupCertificationFlags[i].PartialCertification) sb.AppendFormat("Group {0} is being certified partially", i).AppendLine(); } @@ -297,12 +162,15 @@ namespace DiscImageChef.Decoders.DVD sb.AppendFormat("Group {0} has been certified by an user", i).AppendLine(); } - if(decoded.Groups != 1) return sb.ToString(); + if(decoded.Groups != 1) + return sb.ToString(); { sb.AppendFormat("Disc has {0} zones", decoded.Zones).AppendLine(); + sb.AppendFormat("Primary Spare Area stats at PSN {0:X}h and ends at PSN {1:X}h, inclusively", decoded.SpareAreaFirstPSN, decoded.SpareAreaLastPSN).AppendLine(); + sb.AppendFormat("LSN 0 is at PSN {0:X}h", decoded.LSN0Location).AppendLine(); for(int i = 0; i < decoded.StartLSNForZone.Length; i++) @@ -313,5 +181,65 @@ namespace DiscImageChef.Decoders.DVD } public static string Prettify(byte[] response) => Prettify(Decode(response)); + + public struct DiscDefinitionStructure + { + /// Bytes 0 to 1 Data length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + + /// Bytes 4 to 5 DDS Identifier = 0x0A0A + public ushort Identifier; + /// Byte 6 Reserved + public byte Reserved3; + /// Byte 7, bit 7 If set, formatting is in process + public bool InProcess; + /// Byte 7, bit 6 If set, formatting is using partial certification Only in ECMA-272 + public bool PartialCertification; + /// Byte 7, bit 5 If set, only a group is being formatted Only in ECMA-272 + public bool FormattingOnlyAGroup; + /// Byte 7, bits 4 to 2 Reserved + public byte Reserved4; + /// Byte 7, bit 1 If set, disk has been certified by a user + public bool UserCertification; + /// Byte 7, bit 0 If set, disk has been certified by a manufacturer + public bool ManufacturerCertification; + /// Bytes 8 to 11 How many times the DDS has been updated + public uint UpdateCount; + /// Bytes 12 to 13 How many groups the disk has 24 for ECMA-272 1 for ECMA-330 + public ushort Groups; + /// Bytes 14 to 15 How many zones the disk has Only in ECMA-330 + public ushort Zones; + /// Bytes 14 to 19 in ECMA-272 Bytes 16 to 83 in ECMA-330 Reserved + public byte[] Reserved; + /// Bytes 20 to 43 Group certification flags + public GroupCertificationFlag[] GroupCertificationFlags; + + /// Bytes 85 to 87 Location of first sector in the Primary Spare Area + public uint SpareAreaFirstPSN; + /// Bytes 89 to 91 Location of first sector in the Primary Spare Area + public uint SpareAreaLastPSN; + /// Bytes 93 to 95 PSN for LSN 0 + public uint LSN0Location; + /// The starting LSN of each zone + public uint[] StartLSNForZone; + } + + public struct GroupCertificationFlag + { + /// Bit 7 If set, formatting of this group is in process + public bool InProcess; + /// Bit 6 If set, formatting is using partial certification + public bool PartialCertification; + /// Bits 5 to 2 Reserved + public byte Reserved1; + /// Bit 1 If set, this group has been certified by user + public bool UserCertification; + /// Bit 0 Reserved + public bool Reserved2; + } } } \ No newline at end of file diff --git a/DVD/DMI.cs b/DVD/DMI.cs index 2b4a50c..b0c7c9a 100644 --- a/DVD/DMI.cs +++ b/DVD/DMI.cs @@ -35,47 +35,23 @@ using System.Diagnostics.CodeAnalysis; namespace DiscImageChef.Decoders.DVD { /// - /// Information from the following standards: - /// ANSI X3.304-1997 - /// T10/1048-D revision 9.0 - /// T10/1048-D revision 10a - /// T10/1228-D revision 7.0c - /// T10/1228-D revision 11a - /// T10/1363-D revision 10g - /// T10/1545-D revision 1d - /// T10/1545-D revision 5 - /// T10/1545-D revision 5a - /// T10/1675-D revision 2c - /// T10/1675-D revision 4 - /// T10/1836-D revision 2g - /// ECMA 365 + /// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a + /// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision + /// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g ECMA 365 /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static class DMI { public struct DiscManufacturingInformation { - /// - /// Bytes 0 to 1 - /// Data length - /// + /// Bytes 0 to 1 Data length public ushort DataLength; - /// - /// Byte 2 - /// Reserved - /// + /// Byte 2 Reserved public byte Reserved1; - /// - /// Byte 3 - /// Reserved - /// + /// Byte 3 Reserved public byte Reserved2; - /// - /// Bytes 4 to 2052 - /// Disc Manufacturing Information - /// + /// Bytes 4 to 2052 Disc Manufacturing Information public byte[] DMI; } } diff --git a/DVD/Enums.cs b/DVD/Enums.cs index 40cf4f3..5e05112 100644 --- a/DVD/Enums.cs +++ b/DVD/Enums.cs @@ -38,238 +38,111 @@ namespace DiscImageChef.Decoders.DVD [SuppressMessage("ReSharper", "InconsistentNaming")] public enum DiskCategory : byte { - /// - /// DVD-ROM. Version 1 is ECMA-267 and ECMA-268. - /// - DVDROM = 0, - /// - /// DVD-RAM. Version 1 is ECMA-272. Version 6 is ECMA-330. - /// - DVDRAM = 1, - /// - /// DVD-R. Version 1 is ECMA-279. Version 5 is ECMA-359. Version 6 is ECMA-382. - /// - DVDR = 2, - /// - /// DVD-RW. Version 2 is ECMA-338. Version 3 is ECMA-384. - /// - DVDRW = 3, - /// - /// HD DVD-ROM - /// - HDDVDROM = 4, - /// - /// HD DVD-RAM - /// - HDDVDRAM = 5, - /// - /// HD DVD-R - /// - HDDVDR = 6, - /// - /// HD DVD-RW - /// - HDDVDRW = 7, - /// - /// UMD. Version 0 is ECMA-365. - /// - UMD = 8, - /// - /// DVD+RW. Version 1 is ECMA-274. Version 2 is ECMA-337. Version 3 is ECMA-371. - /// - DVDPRW = 9, - /// - /// DVD+R. Version 1 is ECMA-349. - /// - DVDPR = 10, - /// - /// DVD+RW DL. Version 1 is ECMA-374. - /// - DVDPRWDL = 13, - /// - /// DVD+R DL. Version 1 is ECMA-364. - /// - DVDPRDL = 14, - /// - /// According to standards this value is reserved. - /// It's used by Nintendo GODs and WODs. - /// + /// DVD-ROM. Version 1 is ECMA-267 and ECMA-268. + DVDROM = 0, /// DVD-RAM. Version 1 is ECMA-272. Version 6 is ECMA-330. + DVDRAM = 1, /// DVD-R. Version 1 is ECMA-279. Version 5 is ECMA-359. Version 6 is ECMA-382. + DVDR = 2, /// DVD-RW. Version 2 is ECMA-338. Version 3 is ECMA-384. + DVDRW = 3, /// HD DVD-ROM + HDDVDROM = 4, /// HD DVD-RAM + HDDVDRAM = 5, /// HD DVD-R + HDDVDR = 6, /// HD DVD-RW + HDDVDRW = 7, /// UMD. Version 0 is ECMA-365. + UMD = 8, /// DVD+RW. Version 1 is ECMA-274. Version 2 is ECMA-337. Version 3 is ECMA-371. + DVDPRW = 9, /// DVD+R. Version 1 is ECMA-349. + DVDPR = 10, /// DVD+RW DL. Version 1 is ECMA-374. + DVDPRWDL = 13, /// DVD+R DL. Version 1 is ECMA-364. + DVDPRDL = 14, /// According to standards this value is reserved. It's used by Nintendo GODs and WODs. Nintendo = 15 } [SuppressMessage("ReSharper", "InconsistentNaming")] public enum MaximumRateField : byte { - /// - /// 2.52 Mbps - /// - TwoMbps = 0x00, - /// - /// 5.04 Mbps - /// - FiveMbps = 0x01, - /// - /// 10.08 Mbps - /// - TenMbps = 0x02, - /// - /// 20.16 Mbps - /// - TwentyMbps = 0x03, - /// - /// 30.24 Mbps - /// - ThirtyMbps = 0x04, - Unspecified = 0x0F + /// 2.52 Mbps + TwoMbps = 0x00, /// 5.04 Mbps + FiveMbps = 0x01, /// 10.08 Mbps + TenMbps = 0x02, /// 20.16 Mbps + TwentyMbps = 0x03, /// 30.24 Mbps + ThirtyMbps = 0x04, Unspecified = 0x0F } [SuppressMessage("ReSharper", "InconsistentNaming")] public enum LayerTypeFieldMask : byte { - Embossed = 0x01, - Recordable = 0x02, - Rewritable = 0x04, - Reserved = 0x08 + Embossed = 0x01, Recordable = 0x02, Rewritable = 0x04, + Reserved = 0x08 } [SuppressMessage("ReSharper", "InconsistentNaming")] public enum LinearDensityField : byte { - /// - /// 0.267 μm/bit - /// - TwoSix = 0x00, - /// - /// 0.293 μm/bit - /// - TwoNine = 0x01, - /// - /// 0.409 to 0.435 μm/bit - /// - FourZero = 0x02, - /// - /// 0.280 to 0.291 μm/bit - /// - TwoEight = 0x04, - /// - /// 0.153 μm/bit - /// - OneFive = 0x05, - /// - /// 0.130 to 0.140 μm/bit - /// - OneThree = 0x06, - /// - /// 0.353 μm/bit - /// + /// 0.267 μm/bit + TwoSix = 0x00, /// 0.293 μm/bit + TwoNine = 0x01, /// 0.409 to 0.435 μm/bit + FourZero = 0x02, /// 0.280 to 0.291 μm/bit + TwoEight = 0x04, /// 0.153 μm/bit + OneFive = 0x05, /// 0.130 to 0.140 μm/bit + OneThree = 0x06, /// 0.353 μm/bit ThreeFive = 0x08 } [SuppressMessage("ReSharper", "InconsistentNaming")] public enum TrackDensityField : byte { - /// - /// 0.74 μm/track - /// - Seven = 0x00, - /// - /// 0.80 μm/track - /// - Eight = 0x01, - /// - /// 0.615 μm/track - /// - Six = 0x02, - /// - /// 0.40 μm/track - /// - Four = 0x03, - /// - /// 0.34 μm/track - /// + /// 0.74 μm/track + Seven = 0x00, /// 0.80 μm/track + Eight = 0x01, /// 0.615 μm/track + Six = 0x02, /// 0.40 μm/track + Four = 0x03, /// 0.34 μm/track Three = 0x04 } [SuppressMessage("ReSharper", "InconsistentNaming")] public enum CopyrightType : byte { - /// - /// There is no copy protection - /// - NoProtection = 0x00, - /// - /// Copy protection is CSS/CPPM - /// - CSS = 0x01, - /// - /// Copy protection is CPRM - /// - CPRM = 0x02, - /// - /// Copy protection is AACS - /// + /// There is no copy protection + NoProtection = 0x00, /// Copy protection is CSS/CPPM + CSS = 0x01, /// Copy protection is CPRM + CPRM = 0x02, /// Copy protection is AACS AACS = 0x10 } [SuppressMessage("ReSharper", "InconsistentNaming")] public enum WPDiscTypes : byte { - /// - /// Should not write without a cartridge - /// - DoNotWrite = 0x00, - /// - /// Can write without a cartridge - /// - CanWrite = 0x01, - Reserved1 = 0x02, - Reserved2 = 0x03 + /// Should not write without a cartridge + DoNotWrite = 0x00, /// Can write without a cartridge + CanWrite = 0x01, Reserved1 = 0x02, Reserved2 = 0x03 } [SuppressMessage("ReSharper", "InconsistentNaming")] public enum DVDSize { - /// - /// 120 mm - /// - OneTwenty = 0, - /// - /// 80 mm - /// + /// 120 mm + OneTwenty = 0, /// 80 mm Eighty = 1 } [SuppressMessage("ReSharper", "InconsistentNaming")] public enum DVDRAMDiscType { - /// - /// Shall not be recorded without a case - /// - Cased = 0, - /// - /// May be recorded without a case or within one - /// + /// Shall not be recorded without a case + Cased = 0, /// May be recorded without a case or within one Uncased = 1 } [SuppressMessage("ReSharper", "InconsistentNaming")] public enum DVDLayerStructure { - Unspecified = 0, - InvertedStack = 1, - TwoP = 2, - Reserved = 3 + Unspecified = 0, InvertedStack = 1, TwoP = 2, + Reserved = 3 } [SuppressMessage("ReSharper", "InconsistentNaming")] public enum DVDRecordingSpeed { - None = 0, - Two = 0, - Four = 0x10, - Six = 0x20, - Eight = 0x30, - Ten = 0x40, + None = 0, Two = 0, Four = 0x10, + Six = 0x20, Eight = 0x30, Ten = 0x40, Twelve = 0x50 } #endregion diff --git a/DVD/Layers.cs b/DVD/Layers.cs index 503cb04..1be6922 100644 --- a/DVD/Layers.cs +++ b/DVD/Layers.cs @@ -35,209 +35,95 @@ using System.Diagnostics.CodeAnalysis; namespace DiscImageChef.Decoders.DVD { /// - /// Information from the following standards: - /// ANSI X3.304-1997 - /// T10/1048-D revision 9.0 - /// T10/1048-D revision 10a - /// T10/1228-D revision 7.0c - /// T10/1228-D revision 11a - /// T10/1363-D revision 10g - /// T10/1545-D revision 1d - /// T10/1545-D revision 5 - /// T10/1545-D revision 5a - /// T10/1675-D revision 2c - /// T10/1675-D revision 4 - /// T10/1836-D revision 2g - /// ECMA 365 + /// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a + /// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision + /// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g ECMA 365 /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static class Layers { public struct LayerCapacity { - /// - /// Bytes 0 to 1 - /// Data length - /// + /// Bytes 0 to 1 Data length public ushort DataLength; - /// - /// Byte 2 - /// Reserved - /// + /// Byte 2 Reserved public byte Reserved1; - /// - /// Byte 3 - /// Reserved - /// + /// Byte 3 Reserved public byte Reserved2; - /// - /// Byte 4, bit 7 - /// If set, L0 capacity is immutable - /// + /// Byte 4, bit 7 If set, L0 capacity is immutable public bool InitStatus; - /// - /// Byte 4, bits 6 to 0 - /// Reserved - /// + /// Byte 4, bits 6 to 0 Reserved public byte Reserved3; - /// - /// Byte 5 - /// Reserved - /// + /// Byte 5 Reserved public byte Reserved4; - /// - /// Byte 6 - /// Reserved - /// + /// Byte 6 Reserved public byte Reserved5; - /// - /// Byte 7 - /// Reserved - /// + /// Byte 7 Reserved public byte Reserved6; - /// - /// Byte 8 to 11 - /// L0 Data Area Capacity - /// + /// Byte 8 to 11 L0 Data Area Capacity public uint Capacity; } public struct MiddleZoneStartAddress { - /// - /// Bytes 0 to 1 - /// Data length = 10 - /// + /// Bytes 0 to 1 Data length = 10 public ushort DataLength; - /// - /// Byte 2 - /// Reserved - /// + /// Byte 2 Reserved public byte Reserved1; - /// - /// Byte 3 - /// Reserved - /// + /// Byte 3 Reserved public byte Reserved2; - /// - /// Byte 4, bit 7 - /// If set, L0 shifter middle area is immutable - /// + /// Byte 4, bit 7 If set, L0 shifter middle area is immutable public bool InitStatus; - /// - /// Byte 4, bits 6 to 0 - /// Reserved - /// + /// Byte 4, bits 6 to 0 Reserved public byte Reserved3; - /// - /// Byte 5 - /// Reserved - /// + /// Byte 5 Reserved public byte Reserved4; - /// - /// Byte 6 - /// Reserved - /// + /// Byte 6 Reserved public byte Reserved5; - /// - /// Byte 7 - /// Reserved - /// + /// Byte 7 Reserved public byte Reserved6; - /// - /// Byte 8 to 11 - /// Start LBA of Shifted Middle Area on L0 - /// + /// Byte 8 to 11 Start LBA of Shifted Middle Area on L0 public uint ShiftedMiddleAreaStartAddress; } public struct JumpIntervalSize { - /// - /// Bytes 0 to 1 - /// Data length = 10 - /// + /// Bytes 0 to 1 Data length = 10 public ushort DataLength; - /// - /// Byte 2 - /// Reserved - /// + /// Byte 2 Reserved public byte Reserved1; - /// - /// Byte 3 - /// Reserved - /// + /// Byte 3 Reserved public byte Reserved2; - /// - /// Byte 4 - /// Reserved - /// + /// Byte 4 Reserved public byte Reserved3; - /// - /// Byte 5 - /// Reserved - /// + /// Byte 5 Reserved public byte Reserved4; - /// - /// Byte 6 - /// Reserved - /// + /// Byte 6 Reserved public byte Reserved5; - /// - /// Byte 7 - /// Reserved - /// + /// Byte 7 Reserved public byte Reserved6; - /// - /// Byte 8 to 11 - /// Jump Interval size for the Regular Interval Layer Jump - /// + /// Byte 8 to 11 Jump Interval size for the Regular Interval Layer Jump public uint Size; } public struct ManualLayerJumpAddress { - /// - /// Bytes 0 to 1 - /// Data length = 10 - /// + /// Bytes 0 to 1 Data length = 10 public ushort DataLength; - /// - /// Byte 2 - /// Reserved - /// + /// Byte 2 Reserved public byte Reserved1; - /// - /// Byte 3 - /// Reserved - /// + /// Byte 3 Reserved public byte Reserved2; - /// - /// Byte 4 - /// Reserved - /// + /// Byte 4 Reserved public byte Reserved3; - /// - /// Byte 5 - /// Reserved - /// + /// Byte 5 Reserved public byte Reserved4; - /// - /// Byte 6 - /// Reserved - /// + /// Byte 6 Reserved public byte Reserved5; - /// - /// Byte 7 - /// Reserved - /// + /// Byte 7 Reserved public byte Reserved6; - /// - /// Byte 8 to 11 - /// LBA for the manual layer jump - /// + /// Byte 8 to 11 LBA for the manual layer jump public uint LBA; } } diff --git a/DVD/PFI.cs b/DVD/PFI.cs index c61660f..4549fe4 100644 --- a/DVD/PFI.cs +++ b/DVD/PFI.cs @@ -37,1032 +37,32 @@ using System.Text; namespace DiscImageChef.Decoders.DVD { /// - /// Information from the following standards: - /// ANSI X3.304-1997 - /// T10/1048-D revision 9.0 - /// T10/1048-D revision 10a - /// T10/1228-D revision 7.0c - /// T10/1228-D revision 11a - /// T10/1363-D revision 10g - /// T10/1545-D revision 1d - /// T10/1545-D revision 5 - /// T10/1545-D revision 5a - /// T10/1675-D revision 2c - /// T10/1675-D revision 4 - /// T10/1836-D revision 2g - /// ECMA 267: 120 mm DVD - Read-Only Disk - /// ECMA 268: 80 mm DVD - Read-Only Disk - /// ECMA 272: 120 mm DVD Rewritable Disk (DVD-RAM) - /// ECMA 274: Data Interchange on 120 mm Optical Disk using +RW Format - Capacity: 3,0 Gbytes and 6,0 Gbytes - /// ECMA 279: 80 mm (1,23 Gbytes per side) and 120 mm (3,95 Gbytes per side) DVD-Recordable Disk (DVD-R) - /// ECMA 330: 120 mm (4,7 Gbytes per side) and 80 mm (1,46 Gbytes per side) DVD Rewritable Disk (DVD-RAM) - /// ECMA 337: Data Interchange on 120 mm and 80 mm Optical Disk using +RW Format - Capacity: 4,7 and 1,46 Gbytes per - /// Side - /// ECMA 338: 80 mm (1,46 Gbytes per side) and 120 mm (4,70 Gbytes per side) DVD Re-recordable Disk (DVD-RW) - /// ECMA 349: Data Interchange on 120 mm and 80 mm Optical Disk using +R Format - Capacity: 4,7 and 1,46 Gbytes per - /// Side - /// ECMA 359: 80 mm (1,46 Gbytes per side) and 120 mm (4,70 Gbytes per side) DVD Recordable Disk (DVD-R) - /// ECMA 364: Data Interchange on 120 mm and 80 mm Optical Disk using +R DL Format - Capacity 8,55 and 2,66 Gbytes per - /// Side - /// ECMA 365: Data Interchange on 60 mm Read-Only ODC - Capacity: 1,8 Gbytes (UMD™) - /// ECMA 371: Data Interchange on 120 mm and 80 mm Optical Disk using +RW HS Format - Capacity 4,7 and 1,46 Gbytes per - /// side - /// ECMA 374: Data Interchange on 120 mm and 80 mm Optical Disk using +RW DL Format - Capacity 8,55 and 2,66 Gbytes per - /// side - /// ECMA 382: 120 mm (8,54 Gbytes per side) and 80 mm (2,66 Gbytes per side) DVD Recordable Disk for Dual Layer (DVD-R - /// for DL) - /// ECMA 384: 120 mm (8,54 Gbytes per side) and 80 mm (2,66 Gbytes per side) DVD Re-recordable Disk for Dual Layer - /// (DVD-RW for DL) + /// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a + /// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision + /// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g ECMA 267: 120 mm DVD - + /// Read-Only Disk ECMA 268: 80 mm DVD - Read-Only Disk ECMA 272: 120 mm DVD Rewritable Disk (DVD-RAM) ECMA 274: Data + /// Interchange on 120 mm Optical Disk using +RW Format - Capacity: 3,0 Gbytes and 6,0 Gbytes ECMA 279: 80 mm (1,23 + /// Gbytes per side) and 120 mm (3,95 Gbytes per side) DVD-Recordable Disk (DVD-R) ECMA 330: 120 mm (4,7 Gbytes per + /// side) and 80 mm (1,46 Gbytes per side) DVD Rewritable Disk (DVD-RAM) ECMA 337: Data Interchange on 120 mm and 80 mm + /// Optical Disk using +RW Format - Capacity: 4,7 and 1,46 Gbytes per Side ECMA 338: 80 mm (1,46 Gbytes per side) and + /// 120 mm (4,70 Gbytes per side) DVD Re-recordable Disk (DVD-RW) ECMA 349: Data Interchange on 120 mm and 80 mm + /// Optical Disk using +R Format - Capacity: 4,7 and 1,46 Gbytes per Side ECMA 359: 80 mm (1,46 Gbytes per side) and + /// 120 mm (4,70 Gbytes per side) DVD Recordable Disk (DVD-R) ECMA 364: Data Interchange on 120 mm and 80 mm Optical + /// Disk using +R DL Format - Capacity 8,55 and 2,66 Gbytes per Side ECMA 365: Data Interchange on 60 mm Read-Only ODC + /// - Capacity: 1,8 Gbytes (UMD™) ECMA 371: Data Interchange on 120 mm and 80 mm Optical Disk using +RW HS Format - + /// Capacity 4,7 and 1,46 Gbytes per side ECMA 374: Data Interchange on 120 mm and 80 mm Optical Disk using +RW DL + /// Format - Capacity 8,55 and 2,66 Gbytes per side ECMA 382: 120 mm (8,54 Gbytes per side) and 80 mm (2,66 Gbytes per + /// side) DVD Recordable Disk for Dual Layer (DVD-R for DL) ECMA 384: 120 mm (8,54 Gbytes per side) and 80 mm (2,66 + /// Gbytes per side) DVD Re-recordable Disk for Dual Layer (DVD-RW for DL) /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] public static class PFI { - public struct PhysicalFormatInformation - { - /// - /// Bytes 0 to 1 - /// Data length - /// - public ushort DataLength; - /// - /// Byte 2 - /// Reserved - /// - public byte Reserved1; - /// - /// Byte 3 - /// Reserved - /// - public byte Reserved2; - - #region PFI common to all - /// - /// Byte 4, bits 7 to 4 - /// Disk category field - /// - public DiskCategory DiskCategory; - /// - /// Byte 4, bits 3 to 0 - /// Media version - /// - public byte PartVersion; - /// - /// Byte 5, bits 7 to 4 - /// 120mm if 0, 80mm if 1. If UMD (60mm) 0 also. Reserved rest of values - /// - public DVDSize DiscSize; - /// - /// Byte 5, bits 3 to 0 - /// Maximum data rate - /// - public MaximumRateField MaximumRate; - /// - /// Byte 6, bit 7 - /// Reserved - /// - public bool Reserved3; - /// - /// Byte 6, bits 6 to 5 - /// Number of layers - /// - public byte Layers; - /// - /// Byte 6, bit 4 - /// Track path - /// - public bool TrackPath; - /// - /// Byte 6, bits 3 to 0 - /// Layer type - /// - public LayerTypeFieldMask LayerType; - /// - /// Byte 7, bits 7 to 4 - /// Linear density field - /// - public LinearDensityField LinearDensity; - /// - /// Byte 7, bits 3 to 0 - /// Track density field - /// - public TrackDensityField TrackDensity; - /// - /// Bytes 8 to 11 - /// PSN where Data Area starts - /// - public uint DataAreaStartPSN; - /// - /// Bytes 12 to 15 - /// PSN where Data Area ends - /// - public uint DataAreaEndPSN; - /// - /// Bytes 16 to 19 - /// PSN where Data Area ends in Layer 0 - /// - public uint Layer0EndPSN; - /// - /// Byte 20, bit 7 - /// True if BCA exists. GC/Wii discs do not have this bit set, but there is a BCA, making it unreadable in normal DVD - /// drives - /// - public bool BCA; - /// - /// Byte 20, bits 6 to 0 - /// Reserved - /// - public byte Reserved4; - #endregion PFI common to all - - #region UMD PFI - /// - /// Bytes 21 to 22 - /// UMD only, media attribute, application-defined, part of media specific in rest of discs - /// - public ushort MediaAttribute; - #endregion UMD PFI - - #region DVD-RAM PFI - /// - /// Byte 36 - /// Disc type, respecting case recordability - /// - public DVDRAMDiscType DiscType; - #endregion DVD-RAM PFI - - #region DVD-RAM PFI, Version 0001b - /// - /// Byte 52 - /// Byte 504 in Version 0110b - /// Linear velocity, in tenths of m/s - /// - public byte Velocity; - /// - /// Byte 53 - /// Byte 505 in Version 0110b - /// Read power on disk surface, tenths of mW - /// - public byte ReadPower; - /// - /// Byte 54 - /// Byte 507 in Version 0110b - /// Peak power on disk surface for recording land tracks - /// - public byte PeakPower; - /// - /// Byte 55 - /// Bias power on disk surface for recording land tracks - /// - public byte BiasPower; - /// - /// Byte 56 - /// First pulse starting time for recording on land tracks, ns - /// - public byte FirstPulseStart; - /// - /// Byte 57 - /// Byte 515 in Version 0110b - /// First pulse ending time for recording on land tracks - /// - public byte FirstPulseEnd; - /// - /// Byte 58 - /// Byte 518 in Version 0110b - /// Multiple-pulse duration time for recording on land tracks - /// - public byte MultiplePulseDuration; - /// - /// Byte 59 - /// Byte 519 in Version 0110b - /// Last pulse starting time for recording on land tracks - /// - public byte LastPulseStart; - /// - /// Byte 60 - /// Las pulse ending time for recording on land tracks - /// - public byte LastPulseEnd; - /// - /// Byte 61 - /// Bias power duration for recording on land tracks - /// - public byte BiasPowerDuration; - /// - /// Byte 62 - /// Byte 511 on Version 0110b - /// Peak power for recording on groove tracks - /// - public byte PeakPowerGroove; - /// - /// Byte 63 - /// Bias power for recording on groove tracks - /// - public byte BiasPowerGroove; - /// - /// Byte 64 - /// First pulse starting time on groove tracks - /// - public byte FirstPulseStartGroove; - /// - /// Byte 65 - /// First pulse ending time on groove tracks - /// - public byte FirstPulseEndGroove; - /// - /// Byte 66 - /// Multiple-pulse duration time on groove tracks - /// - public byte MultiplePulseDurationGroove; - /// - /// Byte 67 - /// Last pulse starting time on groove tracks - /// - public byte LastPulseStartGroove; - /// - /// Byte 68 - /// Last pulse ending time on groove tracks - /// - public byte LastPulseEndGroove; - /// - /// Byte 69 - /// Bias power duration for recording on groove tracks - /// - public byte BiasPowerDurationGroove; - #endregion DVD-RAM PFI, Version 0001b - - #region DVD-R PFI, DVD-RW PFI - /// - /// Bytes 36 to 39 - /// Sector number of the first sector of the current Border Out - /// - public uint CurrentBorderOutSector; - /// - /// Bytes 40 to 43 - /// Sector number of the first sector of the next Border In - /// - public uint NextBorderInSector; - #endregion DVD-R PFI, DVD-RW PFI - - #region DVD+RW PFI - /// - /// Byte 36 - /// Linear velocities - /// 0 = CLV from 4,90 m/s to 6,25 m/s - /// 1 = CAV from 3,02 m/s to 7,35 m/s - /// - public byte RecordingVelocity; - /// - /// Byte 37 - /// Maximum read power in milliwatts at maximum velocity - /// mW = 20 * (value - 1) - /// - public byte ReadPowerMaxVelocity; - /// - /// Byte 38 - /// Indicative value of Ptarget in mW at maximum velocity - /// - public byte PIndMaxVelocity; - /// - /// Byte 39 - /// Peak power multiplication factor at maximum velocity - /// - public byte PMaxVelocity; - /// - /// Byte 40 - /// Bias1/write power ration at maximum velocity - /// - public byte E1MaxVelocity; - /// - /// Byte 41 - /// Bias2/write power ration at maximum velocity - /// - public byte E2MaxVelocity; - /// - /// Byte 42 - /// Target value for γ, γtarget at the maximum velocity - /// - public byte YTargetMaxVelocity; - /// - /// Byte 43 - /// Maximum read power in milliwatts at reference velocity (4,90 m/s) - /// mW = 20 * (value - 1) - /// - public byte ReadPowerRefVelocity; - /// - /// Byte 44 - /// Indicative value of Ptarget in mW at reference velocity (4,90 m/s) - /// - public byte PIndRefVelocity; - /// - /// Byte 45 - /// Peak power multiplication factor at reference velocity (4,90 m/s) - /// - public byte PRefVelocity; - /// - /// Byte 46 - /// Bias1/write power ration at reference velocity (4,90 m/s) - /// - public byte E1RefVelocity; - /// - /// Byte 47 - /// Bias2/write power ration at reference velocity (4,90 m/s) - /// - public byte E2RefVelocity; - /// - /// Byte 48 - /// Target value for γ, γtarget at the reference velocity (4,90 m/s) - /// - public byte YTargetRefVelocity; - /// - /// Byte 49 - /// Maximum read power in milliwatts at minimum velocity - /// mW = 20 * (value - 1) - /// - public byte ReadPowerMinVelocity; - /// - /// Byte 50 - /// Indicative value of Ptarget in mW at minimum velocity - /// - public byte PIndMinVelocity; - /// - /// Byte 51 - /// Peak power multiplication factor at minimum velocity - /// - public byte PMinVelocity; - /// - /// Byte 52 - /// Bias1/write power ration at minimum velocity - /// - public byte E1MinVelocity; - /// - /// Byte 53 - /// Bias2/write power ration at minimum velocity - /// - public byte E2MinVelocity; - /// - /// Byte 54 - /// Target value for γ, γtarget at the minimum velocity - /// - public byte YTargetMinVelocity; - #endregion DVD+RW PFI - - #region DVD-RAM PFI, version 0110b - /// - /// Byte 506, bit 7 - /// Mode of adaptative write pulse control - /// - public bool AdaptativeWritePulseControlFlag; - /// - /// Byte 508 - /// Bias power 1 on disk surface for recording land tracks - /// - public byte BiasPower1; - /// - /// Byte 509 - /// Bias power 2 on disk surface for recording land tracks - /// - public byte BiasPower2; - /// - /// Byte 510 - /// Bias power 3 on disk surface for recording land tracks - /// - public byte BiasPower3; - /// - /// Byte 512 - /// Bias power 1 on disk surface for recording groove tracks - /// - public byte BiasPower1Groove; - /// - /// Byte 513 - /// Bias power 2 on disk surface for recording groove tracks - /// - public byte BiasPower2Groove; - /// - /// Byte 514 - /// Bias power 3 on disk surface for recording groove tracks - /// - public byte BiasPower3Groove; - /// - /// Byte 516 - /// First pulse duration - /// - public byte FirstPulseDuration; - /// - /// Byte 520 - /// Bias power 2 duration on land tracks at Velocity 1 - /// - public byte BiasPower2Duration; - /// - /// Byte 521 - /// First pulse start time, at Mark 3T and Leading Space 3T - /// - public byte FirstPulseStart3TSpace3T; - /// - /// Byte 522 - /// First pulse start time, at Mark 4T and Leading Space 3T - /// - public byte FirstPulseStart4TSpace3T; - /// - /// Byte 523 - /// First pulse start time, at Mark 5T and Leading Space 3T - /// - public byte FirstPulseStart5TSpace3T; - /// - /// Byte 524 - /// First pulse start time, at Mark >5T and Leading Space 3T - /// - public byte FirstPulseStartSpace3T; - /// - /// Byte 525 - /// First pulse start time, at Mark 3T and Leading Space 4T - /// - public byte FirstPulseStart3TSpace4T; - /// - /// Byte 526 - /// First pulse start time, at Mark 4T and Leading Space 4T - /// - public byte FirstPulseStart4TSpace4T; - /// - /// Byte 527 - /// First pulse start time, at Mark 5T and Leading Space 4T - /// - public byte FirstPulseStart5TSpace4T; - /// - /// Byte 528 - /// First pulse start time, at Mark >5T and Leading Space 4T - /// - public byte FirstPulseStartSpace4T; - /// - /// Byte 529 - /// First pulse start time, at Mark 3T and Leading Space 5T - /// - public byte FirstPulseStart3TSpace5T; - /// - /// Byte 530 - /// First pulse start time, at Mark 4T and Leading Space 5T - /// - public byte FirstPulseStart4TSpace5T; - /// - /// Byte 531 - /// First pulse start time, at Mark 5T and Leading Space 5T - /// - public byte FirstPulseStart5TSpace5T; - /// - /// Byte 532 - /// First pulse start time, at Mark >5T and Leading Space 5T - /// - public byte FirstPulseStartSpace5T; - /// - /// Byte 533 - /// First pulse start time, at Mark 3T and Leading Space >5T - /// - public byte FirstPulseStart3TSpace; - /// - /// Byte 534 - /// First pulse start time, at Mark 4T and Leading Space >5T - /// - public byte FirstPulseStart4TSpace; - /// - /// Byte 535 - /// First pulse start time, at Mark 5T and Leading Space >5T - /// - public byte FirstPulseStart5TSpace; - /// - /// Byte 536 - /// First pulse start time, at Mark >5T and Leading Space >5T - /// - public byte FirstPulseStartSpace; - /// - /// Byte 537 - /// First pulse start time, at Mark 3T and Trailing Space 3T - /// - public byte FirstPulse3TStartTSpace3T; - /// - /// Byte 538 - /// First pulse start time, at Mark 4T and Trailing Space 3T - /// - public byte FirstPulse4TStartTSpace3T; - /// - /// Byte 539 - /// First pulse start time, at Mark 5T and Trailing Space 3T - /// - public byte FirstPulse5TStartTSpace3T; - /// - /// Byte 540 - /// First pulse start time, at Mark >5T and Trailing Space 3T - /// - public byte FirstPulseStartTSpace3T; - /// - /// Byte 541 - /// First pulse start time, at Mark 3T and Trailing Space 4T - /// - public byte FirstPulse3TStartTSpace4T; - /// - /// Byte 542 - /// First pulse start time, at Mark 4T and Trailing Space 4T - /// - public byte FirstPulse4TStartTSpace4T; - /// - /// Byte 543 - /// First pulse start time, at Mark 5T and Trailing Space 4T - /// - public byte FirstPulse5TStartTSpace4T; - /// - /// Byte 544 - /// First pulse start time, at Mark >5T and Trailing Space 4T - /// - public byte FirstPulseStartTSpace4T; - /// - /// Byte 545 - /// First pulse start time, at Mark 3T and Trailing Space 5T - /// - public byte FirstPulse3TStartTSpace5T; - /// - /// Byte 546 - /// First pulse start time, at Mark 4T and Trailing Space 5T - /// - public byte FirstPulse4TStartTSpace5T; - /// - /// Byte 547 - /// First pulse start time, at Mark 5T and Trailing Space 5T - /// - public byte FirstPulse5TStartTSpace5T; - /// - /// Byte 548 - /// First pulse start time, at Mark >5T and Trailing Space 5T - /// - public byte FirstPulseStartTSpace5T; - /// - /// Byte 549 - /// First pulse start time, at Mark 3T and Trailing Space >5T - /// - public byte FirstPulse3TStartTSpace; - /// - /// Byte 550 - /// First pulse start time, at Mark 4T and Trailing Space >5T - /// - public byte FirstPulse4TStartTSpace; - /// - /// Byte 551 - /// First pulse start time, at Mark 5T and Trailing Space >5T - /// - public byte FirstPulse5TStartTSpace; - /// - /// Byte 552 - /// First pulse start time, at Mark >5T and Trailing Space >5T - /// - public byte FirstPulseStartTSpace; - /// - /// Bytes 553 to 600 - /// Disk manufacturer's name, space-padded - /// - public string DiskManufacturer; - /// - /// Bytes 601 to 616 - /// Disk manufacturer's supplementary information - /// - public string DiskManufacturerSupplementary; - /// - /// Bytes 617 to 627 - /// Write power control parameters - /// - public byte[] WritePowerControlParams; - /// - /// Byte 619 - /// Ratio of peak power for land tracks to threshold peak power for land tracks - /// - public byte PowerRatioLandThreshold; - /// - /// Byte 620 - /// Target asymmetry - /// - public byte TargetAsymmetry; - /// - /// Byte 621 - /// Temporary peak power - /// - public byte TemporaryPeakPower; - /// - /// Byte 622 - /// Temporary bias power 1 - /// - public byte TemporaryBiasPower1; - /// - /// Byte 623 - /// Temporary bias power 2 - /// - public byte TemporaryBiasPower2; - /// - /// Byte 624 - /// Temporary bias power 3 - /// - public byte TemporaryBiasPower3; - /// - /// Byte 625 - /// Ratio of peak power for groove tracks to threshold peak power for groove tracks - /// - public byte PowerRatioGrooveThreshold; - /// - /// Byte 626 - /// Ratio of peak power for land tracks to threshold 6T peak power for land tracks - /// - public byte PowerRatioLandThreshold6T; - /// - /// Byte 627 - /// Ratio of peak power for groove tracks to threshold 6T peak power for groove tracks - /// - public byte PowerRatioGrooveThreshold6T; - #endregion DVD-RAM PFI, version 0110b - - #region DVD+RW PFI, DVD+R PFI, DVD+R DL PFI and DVD+RW DL PFI - /// - /// Byte 20, bit 6 - /// If set indicates data zone contains extended information for VCPS - /// - public bool VCPS; - /// - /// Byte 21 - /// Indicates restricted usage disk - /// - public byte ApplicationCode; - /// - /// Byte 22 - /// Bitmap of extended information block presence - /// - public byte ExtendedInformation; - /// - /// Bytes 23 to 30 - /// Disk manufacturer ID, null-padded - /// - public string DiskManufacturerID; - /// - /// Bytes 31 to 33 - /// Media type ID, null-padded - /// - public string MediaTypeID; - /// - /// Byte 34 - /// Product revision number - /// - public byte ProductRevision; - /// - /// Byte 35 - /// Indicates how many bytes, up to 63, are used in ADIP's PFI - /// - public byte PFIUsedInADIP; - #endregion DVD+RW PFI, DVD+R PFI, DVD+R DL PFI and DVD+RW DL PFI - - #region DVD+RW PFI, version 0010b - /// - /// Byte 55 - /// Ttop first pulse duration - /// - public byte TopFirstPulseDuration; - /// - /// Byte 56 - /// Tmp multi pulse duration - /// - public byte MultiPulseDuration; - /// - /// Byte 57 - /// dTtop first pulse lead time - /// - public byte FirstPulseLeadTime; - /// - /// Byte 58 - /// dTera erase lead time at reference velocity - /// - public byte EraseLeadTimeRefVelocity; - /// - /// Byte 59 - /// dTera erase lead time at upper velocity - /// - public byte EraseLeadTimeUppVelocity; - #endregion DVD+RW PFI, version 0010b - - #region DVD+R PFI version 0001b and DVD+R DL PFI version 0001b - /// - /// Byte 36 - /// Primary recording velocity for the basic write strategy - /// - public byte PrimaryVelocity; - /// - /// Byte 37 - /// Upper recording velocity for the basic write strategy - /// - public byte UpperVelocity; - /// - /// Byte 38 - /// Wavelength λIND - /// - public byte Wavelength; - /// - /// Byte 39 - /// Normalized write power dependency on wavelength (dP/dλ)/(PIND/λIND) - /// - public byte NormalizedPowerDependency; - /// - /// Byte 40 - /// Maximum read power at primary velocity - /// - public byte MaximumPowerAtPrimaryVelocity; - /// - /// Byte 41 - /// Pind at primary velocity - /// - public byte PindAtPrimaryVelocity; - /// - /// Byte 42 - /// βtarget at primary velocity - /// - public byte BtargetAtPrimaryVelocity; - /// - /// Byte 43 - /// Maximum read power at upper velocity - /// - public byte MaximumPowerAtUpperVelocity; - /// - /// Byte 44 - /// Pind at primary velocity - /// - public byte PindAtUpperVelocity; - /// - /// Byte 45 - /// βtarget at upper velocity - /// - public byte BtargetAtUpperVelocity; - /// - /// Byte 46 - /// Ttop (≥4T) first pulse duration for cm∗ ≥4T at Primary velocity - /// - public byte FirstPulseDuration4TPrimaryVelocity; - /// - /// Byte 47 - /// Ttop (=3T) first pulse duration for cm∗ =3T at Primary velocity - /// - public byte FirstPulseDuration3TPrimaryVelocity; - /// - /// Byte 48 - /// Tmp multi pulse duration at Primary velocity - /// - public byte MultiPulseDurationPrimaryVelocity; - /// - /// Byte 49 - /// Tlp last pulse duration at Primary velocity - /// - public byte LastPulseDurationPrimaryVelocity; - /// - /// Byte 50 - /// dTtop (≥4T) first pulse lead time for cm∗ ≥4T at Primary velocity - /// - public byte FirstPulseLeadTime4TPrimaryVelocity; - /// - /// Byte 51 - /// dTtop (=3T) first pulse lead time for cm∗ =3T at Primary velocity - /// - public byte FirstPulseLeadTime3TPrimaryVelocity; - /// - /// Byte 52 - /// dTle first pulse leading edge shift for ps∗ =3T at Primary velocity - /// - public byte FirstPulseLeadingEdgePrimaryVelocity; - /// - /// Byte 53 - /// Ttop (≥4T) first pulse duration for cm∗ ≥4T at Upper velocity - /// - public byte FirstPulseDuration4TUpperVelocity; - /// - /// Byte 54 - /// Ttop (=3T) first pulse duration for cm∗ =3T at Upper velocity - /// - public byte FirstPulseDuration3TUpperVelocity; - /// - /// Byte 55 - /// Tmp multi pulse duration at Upper velocity - /// - public byte MultiPulseDurationUpperVelocity; - /// - /// Byte 56 - /// Tlp last pulse duration at Upper velocity - /// - public byte LastPulseDurationUpperVelocity; - /// - /// Byte 57 - /// dTtop (≥4T) first pulse lead time for cm∗ ≥4T at Upper velocity - /// - public byte FirstPulseLeadTime4TUpperVelocity; - /// - /// Byte 58 - /// dTtop (=3T) first pulse lead time for cm∗ =3T at Upper velocity - /// - public byte FirstPulseLeadTime3TUpperVelocity; - /// - /// Byte 59 - /// dTle first pulse leading edge shift for ps∗ =3T at Upper velocity - /// - public byte FirstPulseLeadingEdgeUpperVelocity; - #endregion DVD+R PFI version 0001b and DVD+R DL PFI version 0001b - - #region DVD+R DL PFI version 0001b - /// - /// Byte 34, bits 7 to 6 - /// - public DVDLayerStructure LayerStructure; - #endregion DVD+R DL PFI version 0001b - - #region DVD+RW DL PFI - /// - /// Byte 36 - /// Primary recording velocity for the basic write strategy - /// - public byte BasicPrimaryVelocity; - /// - /// Byte 37 - /// Maximum read power at Primary velocity - /// - public byte MaxReadPowerPrimaryVelocity; - /// - /// Byte 38 - /// PIND at Primary velocity - /// - public byte PindPrimaryVelocity; - /// - /// Byte 39 - /// ρ at Primary velocity - /// - public byte PPrimaryVelocity; - /// - /// Byte 40 - /// ε1 at Primary velocity - /// - public byte E1PrimaryVelocity; - /// - /// Byte 41 - /// ε2 at Primary velocity - /// - public byte E2PrimaryVelocity; - /// - /// Byte 42 - /// γtarget at Primary velocity - /// - public byte YtargetPrimaryVelocity; - /// - /// Byte 43 - /// β optimum at Primary velocity - /// - public byte BOptimumPrimaryVelocity; - /// - /// Byte 46 - /// Ttop first pulse duration - /// - public byte TFirstPulseDuration; - /// - /// Byte 47 - /// Tmp multi pulse duration - /// - public byte TMultiPulseDuration; - /// - /// Byte 48 - /// dTtop first pulse lead/lag time for any runlength ≥ 4T - /// - public byte FirstPulseLeadTimeAnyRun; - /// - /// Byte 49 - /// dTtop,3 first pulse lead/lag time for runlengths = 3T - /// - public byte FirstPulseLeadTimeRun3T; - /// - /// Byte 50 - /// dTlp last pulse lead/lag time for any runlength ≥ 5T - /// - public byte LastPulseLeadTimeAnyRun; - /// - /// Byte 51 - /// dTlp,3 last pulse lead/lag time for runlengths = 3T - /// - public byte LastPulseLeadTime3T; - /// - /// Byte 52 - /// dTlp,4 last pulse lead/lag time for runlengths = 4T - /// - public byte LastPulseLeadTime4T; - /// - /// Byte 53 - /// dTera erase lead/lag time when preceding mark length ≥ 5T - /// - public byte ErasePulseLeadTimeAny; - /// - /// Byte 54 - /// dTera,3 erase lead/lag time when preceding mark length = 3T - /// - public byte ErasePulseLeadTime3T; - /// - /// Byte 55 - /// dTera,4 erase lead/lag time when preceding mark length = 4T - /// - public byte ErasePulseLeadTime4T; - #endregion DVD+RW DL PFI - - #region DVD-R DL PFI and DVD-RW DL PFI - /// - /// Byte 21 - /// Maximum recording speed - /// - public DVDRecordingSpeed MaxRecordingSpeed; - /// - /// Byte 22 - /// Minimum recording speed - /// - public DVDRecordingSpeed MinRecordingSpeed; - /// - /// Byte 23 - /// Another recording speed - /// - public DVDRecordingSpeed RecordingSpeed1; - /// - /// Byte 24 - /// Another recording speed - /// - public DVDRecordingSpeed RecordingSpeed2; - /// - /// Byte 25 - /// Another recording speed - /// - public DVDRecordingSpeed RecordingSpeed3; - /// - /// Byte 26 - /// Another recording speed - /// - public DVDRecordingSpeed RecordingSpeed4; - /// - /// Byte 27 - /// Another recording speed - /// - public DVDRecordingSpeed RecordingSpeed5; - /// - /// Byte 28 - /// Another recording speed - /// - public DVDRecordingSpeed RecordingSpeed6; - /// - /// Byte 29 - /// Another recording speed - /// - public DVDRecordingSpeed RecordingSpeed7; - /// - /// Byte 30 - /// Class - /// - public byte Class; - /// - /// Byte 31 - /// Extended version. 0x30 = ECMA-382, 0x20 = ECMA-384 - /// - public byte ExtendedVersion; - /// - /// Byte 36 - /// Start sector number of current RMD in Extra Border Zone - /// - public uint CurrentRMDExtraBorderPSN; - /// - /// Byte 40 - /// Start sector number of Physical Format Information blocks in Extra Border Zone - /// - public uint PFIExtraBorderPSN; - /// - /// Byte 44, bit 0 - /// If NOT set, Control Data Zone is pre-recorded - /// - public bool PreRecordedControlDataInv; - /// - /// Byte 44 bit 1 - /// Lead-in Zone is pre-recorded - /// - public bool PreRecordedLeadIn; - /// - /// Byte 44 bit 3 - /// Lead-out Zone is pre-recorded - /// - public bool PreRecordedLeadOut; - /// - /// Byte 45 bits 0 to 3 - /// AR characteristic of LPP on Layer 1 - /// - public byte ARCharLayer1; - /// - /// Byte 45 bits 4 to 7 - /// Tracking polarity on Layer 1 - /// - public byte TrackPolarityLayer1; - #endregion DVD-R DL PFI and DVD-RW DL PFI - } - public static PhysicalFormatInformation? Decode(byte[] response) { - if(response == null) return null; + if(response == null) + return null; if(response.Length == 2048) { @@ -1071,10 +71,11 @@ namespace DiscImageChef.Decoders.DVD response = tmp2; } - if(response.Length < 2052) return null; + if(response.Length < 2052) + return null; - PhysicalFormatInformation pfi = new PhysicalFormatInformation(); - byte[] tmp; + var pfi = new PhysicalFormatInformation(); + byte[] tmp; pfi.DataLength = (ushort)((response[0] << 8) + response[1]); pfi.Reserved1 = response[2]; @@ -1091,12 +92,16 @@ namespace DiscImageChef.Decoders.DVD pfi.LayerType = (LayerTypeFieldMask)(response[6] & 0x07); pfi.LinearDensity = (LinearDensityField)((response[7] & 0xF0) >> 4); pfi.TrackDensity = (TrackDensityField)(response[7] & 0x0F); + pfi.DataAreaStartPSN = (uint)((response[8] << 24) + (response[9] << 16) + (response[10] << 8) + response[11]); + pfi.DataAreaEndPSN = (uint)((response[12] << 24) + (response[13] << 16) + (response[14] << 8) + response[15]); + pfi.Layer0EndPSN = (uint)((response[16] << 24) + (response[17] << 16) + (response[18] << 8) + response[19]); + pfi.BCA |= (response[20] & 0x80) == 0x80; switch(pfi.DiskCategory) @@ -1104,7 +109,9 @@ namespace DiscImageChef.Decoders.DVD // UMD case DiskCategory.UMD: pfi.MediaAttribute = (ushort)((response[21] << 8) + response[22]); + break; + // DVD-RAM case DiskCategory.DVDRAM: pfi.DiscType = (DVDRAMDiscType)response[36]; @@ -1201,14 +208,18 @@ namespace DiscImageChef.Decoders.DVD } break; + // DVD-R and DVD-RW case DiskCategory.DVDR when pfi.PartVersion < 6: case DiskCategory.DVDRW when pfi.PartVersion < 3: pfi.CurrentBorderOutSector = (uint)((response[36] << 24) + (response[37] << 16) + (response[38] << 8) + response[39]); + pfi.NextBorderInSector = (uint)((response[40] << 24) + (response[41] << 16) + (response[42] << 8) + response[43]); + break; + // DVD+RW case DiskCategory.DVDPRW: pfi.RecordingVelocity = response[36]; @@ -1230,12 +241,15 @@ namespace DiscImageChef.Decoders.DVD pfi.E1MinVelocity = response[52]; pfi.E2MinVelocity = response[53]; pfi.YTargetMinVelocity = response[54]; + break; } // DVD+R, DVD+RW, DVD+R DL and DVD+RW DL - if(pfi.DiskCategory == DiskCategory.DVDPR || pfi.DiskCategory == DiskCategory.DVDPRW || - pfi.DiskCategory == DiskCategory.DVDPRDL || pfi.DiskCategory == DiskCategory.DVDPRWDL) + if(pfi.DiskCategory == DiskCategory.DVDPR || + pfi.DiskCategory == DiskCategory.DVDPRW || + pfi.DiskCategory == DiskCategory.DVDPRDL || + pfi.DiskCategory == DiskCategory.DVDPRWDL) { pfi.VCPS |= (response[20] & 0x40) == 0x40; pfi.ApplicationCode = response[21]; @@ -1246,8 +260,10 @@ namespace DiscImageChef.Decoders.DVD tmp = new byte[3]; Array.Copy(response, 31, tmp, 0, 3); pfi.MediaTypeID = StringHandlers.CToString(tmp); - pfi.ProductRevision = - pfi.DiskCategory == DiskCategory.DVDPRDL ? (byte)(response[34] & 0x3F) : response[34]; + + pfi.ProductRevision = pfi.DiskCategory == DiskCategory.DVDPRDL ? (byte)(response[34] & 0x3F) + : response[34]; + pfi.PFIUsedInADIP = response[35]; } @@ -1260,7 +276,9 @@ namespace DiscImageChef.Decoders.DVD pfi.FirstPulseLeadTime = response[57]; pfi.EraseLeadTimeRefVelocity = response[58]; pfi.EraseLeadTimeUppVelocity = response[59]; + break; + // DVD+R and DVD+R DL case DiskCategory.DVDPR: case DiskCategory.DVDPRDL: @@ -1288,6 +306,7 @@ namespace DiscImageChef.Decoders.DVD pfi.FirstPulseLeadTime4TUpperVelocity = response[57]; pfi.FirstPulseLeadTime3TUpperVelocity = response[58]; pfi.FirstPulseLeadingEdgeUpperVelocity = response[59]; + break; } @@ -1296,7 +315,9 @@ namespace DiscImageChef.Decoders.DVD // DVD+R DL case DiskCategory.DVDPRDL: pfi.LayerStructure = (DVDLayerStructure)((response[34] & 0xC0) >> 6); + break; + // DVD+RW DL case DiskCategory.DVDPRWDL: pfi.BasicPrimaryVelocity = response[36]; @@ -1317,7 +338,9 @@ namespace DiscImageChef.Decoders.DVD pfi.ErasePulseLeadTimeAny = response[53]; pfi.ErasePulseLeadTime3T = response[54]; pfi.ErasePulseLeadTime4T = response[55]; + break; + // DVD-R DL and DVD-RW DL case DiskCategory.DVDR when pfi.PartVersion == 6: case DiskCategory.DVDRW when pfi.PartVersion == 3: @@ -1332,15 +355,19 @@ namespace DiscImageChef.Decoders.DVD pfi.RecordingSpeed7 = (DVDRecordingSpeed)response[29]; pfi.Class = response[30]; pfi.ExtendedVersion = response[31]; + pfi.CurrentBorderOutSector = (uint)((response[36] << 24) + (response[37] << 16) + (response[38] << 8) + response[39]); + pfi.NextBorderInSector = (uint)((response[40] << 24) + (response[41] << 16) + (response[42] << 8) + response[43]); + pfi.PreRecordedControlDataInv |= (response[44] & 0x01) == 0x01; pfi.PreRecordedLeadIn |= (response[44] & 0x02) == 0x02; pfi.PreRecordedLeadOut |= (response[44] & 0x08) == 0x08; pfi.ARCharLayer1 = (byte)(response[45] & 0x0F); pfi.TrackPolarityLayer1 = (byte)((response[45] & 0xF0) >> 4); + break; } @@ -1349,22 +376,27 @@ namespace DiscImageChef.Decoders.DVD public static string Prettify(PhysicalFormatInformation? pfi) { - if(pfi == null) return null; + if(pfi == null) + return null; PhysicalFormatInformation decoded = pfi.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); string sizeString; + switch(decoded.DiscSize) { case DVDSize.Eighty: sizeString = "80mm"; + break; case DVDSize.OneTwenty: sizeString = "120mm"; + break; default: sizeString = $"unknown size identifier {decoded.DiscSize}"; + break; } @@ -1374,26 +406,32 @@ namespace DiscImageChef.Decoders.DVD { case DiskCategory.DVDROM: sb.AppendFormat(categorySentence, sizeString, "DVD-ROM", decoded.PartVersion).AppendLine(); + switch(decoded.DiscSize) { case DVDSize.OneTwenty when decoded.PartVersion == 1: sb.AppendLine("Disc claims conformation to ECMA-267"); + break; case DVDSize.Eighty when decoded.PartVersion == 1: sb.AppendLine("Disc claims conformation to ECMA-268"); + break; } break; case DiskCategory.DVDRAM: sb.AppendFormat(categorySentence, sizeString, "DVD-RAM", decoded.PartVersion).AppendLine(); + switch(decoded.PartVersion) { case 1: sb.AppendLine("Disc claims conformation to ECMA-272"); + break; case 6: sb.AppendLine("Disc claims conformation to ECMA-330"); + break; } @@ -1401,17 +439,22 @@ namespace DiscImageChef.Decoders.DVD case DiskCategory.DVDR: if(decoded.PartVersion >= 6) sb.AppendFormat(categorySentence, sizeString, "DVD-R DL", decoded.PartVersion).AppendLine(); - else sb.AppendFormat(categorySentence, sizeString, "DVD-R", decoded.PartVersion).AppendLine(); + else + sb.AppendFormat(categorySentence, sizeString, "DVD-R", decoded.PartVersion).AppendLine(); + switch(decoded.PartVersion) { case 1: sb.AppendLine("Disc claims conformation to ECMA-279"); + break; case 5: sb.AppendLine("Disc claims conformation to ECMA-359"); + break; case 6: sb.AppendLine("Disc claims conformation to ECMA-382"); + break; } @@ -1419,14 +462,18 @@ namespace DiscImageChef.Decoders.DVD case DiskCategory.DVDRW: if(decoded.PartVersion >= 3) sb.AppendFormat(categorySentence, sizeString, "DVD-RW DL", decoded.PartVersion).AppendLine(); - else sb.AppendFormat(categorySentence, sizeString, "DVD-RW", decoded.PartVersion).AppendLine(); + else + sb.AppendFormat(categorySentence, sizeString, "DVD-RW", decoded.PartVersion).AppendLine(); + switch(decoded.PartVersion) { case 2: sb.AppendLine("Disc claims conformation to ECMA-338"); + break; case 3: sb.AppendLine("Disc claims conformation to ECMA-384"); + break; } @@ -1434,57 +481,70 @@ namespace DiscImageChef.Decoders.DVD case DiskCategory.UMD: if(decoded.DiscSize == DVDSize.OneTwenty) sb.AppendFormat(categorySentence, "60mm", "UMD", decoded.PartVersion).AppendLine(); - else sb.AppendFormat(categorySentence, "invalid size", "UMD", decoded.PartVersion).AppendLine(); + else + sb.AppendFormat(categorySentence, "invalid size", "UMD", decoded.PartVersion).AppendLine(); + switch(decoded.PartVersion) { case 0: sb.AppendLine("Disc claims conformation to ECMA-365"); + break; } break; case DiskCategory.DVDPRW: sb.AppendFormat(categorySentence, sizeString, "DVD+RW", decoded.PartVersion).AppendLine(); + switch(decoded.PartVersion) { case 1: sb.AppendLine("Disc claims conformation to ECMA-274"); + break; case 2: sb.AppendLine("Disc claims conformation to ECMA-337"); + break; case 3: sb.AppendLine("Disc claims conformation to ECMA-371"); + break; } break; case DiskCategory.DVDPR: sb.AppendFormat(categorySentence, sizeString, "DVD+R", decoded.PartVersion).AppendLine(); + switch(decoded.PartVersion) { case 1: sb.AppendLine("Disc claims conformation to ECMA-349"); + break; } break; case DiskCategory.DVDPRWDL: sb.AppendFormat(categorySentence, sizeString, "DVD+RW DL", decoded.PartVersion).AppendLine(); + switch(decoded.PartVersion) { case 1: sb.AppendLine("Disc claims conformation to ECMA-374"); + break; } break; case DiskCategory.DVDPRDL: sb.AppendFormat(categorySentence, sizeString, "DVD+R DL", decoded.PartVersion).AppendLine(); + switch(decoded.PartVersion) { case 1: sb.AppendLine("Disc claims conformation to ECMA-364"); + break; } @@ -1495,24 +555,32 @@ namespace DiscImageChef.Decoders.DVD sb.AppendLine("Disc is a Nintendo Gamecube Optical Disc (GOD)"); else if(decoded.DiscSize == DVDSize.OneTwenty) sb.AppendLine("Disc is a Nintendo Wii Optical Disc (WOD)"); - else goto default; - else goto default; + else + goto default; + else + goto default; + break; case DiskCategory.HDDVDROM: sb.AppendFormat(categorySentence, sizeString, "HD DVD-ROM", decoded.PartVersion).AppendLine(); + break; case DiskCategory.HDDVDRAM: sb.AppendFormat(categorySentence, sizeString, "HD DVD-RAM", decoded.PartVersion).AppendLine(); + break; case DiskCategory.HDDVDR: sb.AppendFormat(categorySentence, sizeString, "HD DVD-R", decoded.PartVersion).AppendLine(); + break; case DiskCategory.HDDVDRW: sb.AppendFormat(categorySentence, sizeString, "HD DVD-RW", decoded.PartVersion).AppendLine(); + break; default: - sb.AppendFormat(categorySentence, sizeString, "unknown disc type", decoded.PartVersion) - .AppendLine(); + sb.AppendFormat(categorySentence, sizeString, "unknown disc type", decoded.PartVersion). + AppendLine(); + break; } @@ -1520,57 +588,77 @@ namespace DiscImageChef.Decoders.DVD { case MaximumRateField.TwoMbps: sb.AppendLine("Disc maximum transfer rate is 2,52 Mbit/sec."); + break; case MaximumRateField.FiveMbps: sb.AppendLine("Disc maximum transfer rate is 5,04 Mbit/sec."); + break; case MaximumRateField.TenMbps: sb.AppendLine("Disc maximum transfer rate is 10,08 Mbit/sec."); + break; case MaximumRateField.TwentyMbps: sb.AppendLine("Disc maximum transfer rate is 20,16 Mbit/sec."); + break; case MaximumRateField.ThirtyMbps: sb.AppendLine("Disc maximum transfer rate is 30,24 Mbit/sec."); + break; case MaximumRateField.Unspecified: sb.AppendLine("Disc maximum transfer rate is unspecified."); + break; default: - sb.AppendFormat("Disc maximum transfer rate is specified by unknown key {0}", decoded.MaximumRate) - .AppendLine(); + sb.AppendFormat("Disc maximum transfer rate is specified by unknown key {0}", decoded.MaximumRate). + AppendLine(); + break; } sb.AppendFormat("Disc has {0} layers", decoded.Layers + 1).AppendLine(); - if(decoded.TrackPath && decoded.Layers == 1) sb.AppendLine("Layers are in parallel track path"); - else if(!decoded.TrackPath && decoded.Layers == 1) sb.AppendLine("Layers are in opposite track path"); + + if(decoded.TrackPath && + decoded.Layers == 1) + sb.AppendLine("Layers are in parallel track path"); + else if(!decoded.TrackPath && + decoded.Layers == 1) + sb.AppendLine("Layers are in opposite track path"); switch(decoded.LinearDensity) { case LinearDensityField.TwoSix: sb.AppendLine("Pitch size is 0,267 μm/bit"); + break; case LinearDensityField.TwoNine: sb.AppendLine("Pitch size is 0,147 μm/bit"); + break; case LinearDensityField.FourZero: sb.AppendLine("Pitch size is between 0,409 μm/bit and 0,435 μm/bit"); + break; case LinearDensityField.TwoEight: sb.AppendLine("Pitch size is between 0,140 μm/bit and 0,148 μm/bit"); + break; case LinearDensityField.OneFive: sb.AppendLine("Pitch size is 0,153 μm/bit"); + break; case LinearDensityField.OneThree: sb.AppendLine("Pitch size is between 0,130 μm/bit and 0,140 μm/bit"); + break; case LinearDensityField.ThreeFive: sb.AppendLine("Pitch size is 0,353 μm/bit"); + break; default: sb.AppendFormat("Unknown pitch size key {0}", decoded.LinearDensity).AppendLine(); + break; } @@ -1578,21 +666,27 @@ namespace DiscImageChef.Decoders.DVD { case TrackDensityField.Seven: sb.AppendLine("Track size is 0,74 μm"); + break; case TrackDensityField.Eight: sb.AppendLine("Track size is 0,80 μm"); + break; case TrackDensityField.Six: sb.AppendLine("Track size is 0,615 μm"); + break; case TrackDensityField.Four: sb.AppendLine("Track size is 0,40 μm"); + break; case TrackDensityField.Three: sb.AppendLine("Track size is 0,34 μm"); + break; default: sb.AppendFormat("Unknown track size key {0}", decoded.LinearDensity).AppendLine(); + break; } @@ -1601,37 +695,46 @@ namespace DiscImageChef.Decoders.DVD { sb.AppendFormat("Data area starts at PSN {0:X}h", decoded.DataAreaStartPSN).AppendLine(); sb.AppendFormat("Data area ends at PSN {0:X}h", decoded.DataAreaEndPSN).AppendLine(); - if(decoded.Layers == 1 && !decoded.TrackPath) + + if(decoded.Layers == 1 && + !decoded.TrackPath) sb.AppendFormat("Layer 0 ends at PSN {0:X}h", decoded.Layer0EndPSN).AppendLine(); } else sb.AppendLine("Disc is empty"); - else sb.AppendLine("Disc is empty"); + else + sb.AppendLine("Disc is empty"); - if(decoded.BCA) sb.AppendLine("Disc has a burst cutting area"); + if(decoded.BCA) + sb.AppendLine("Disc has a burst cutting area"); switch(decoded.DiskCategory) { case DiskCategory.UMD: sb.AppendFormat("Media attribute is {0}", decoded.MediaAttribute).AppendLine(); + break; case DiskCategory.DVDRAM: switch(decoded.DiscType) { case DVDRAMDiscType.Cased: sb.AppendLine("Disc shall be recorded with a case"); + break; case DVDRAMDiscType.Uncased: sb.AppendLine("Disc can be recorded with or without a case"); + break; default: sb.AppendFormat("Unknown DVD-RAM case type key {0}", decoded.DiscType).AppendLine(); + break; } if(decoded.PartVersion == 6) { sb.AppendFormat("Disc manufacturer is {0}", decoded.DiskManufacturer).AppendLine(); + sb.AppendFormat("Disc manufacturer supplementary information is {0}", decoded.DiskManufacturerSupplementary).AppendLine(); } @@ -1639,36 +742,465 @@ namespace DiscImageChef.Decoders.DVD break; case DiskCategory.DVDR when decoded.PartVersion < 6: case DiskCategory.DVDRW when decoded.PartVersion < 3: - sb.AppendFormat("Current Border-Out first sector is PSN {0:X}h", decoded.CurrentBorderOutSector) - .AppendLine(); - sb.AppendFormat("Next Border-In first sector is PSN {0:X}h", decoded.NextBorderInSector) - .AppendLine(); + sb.AppendFormat("Current Border-Out first sector is PSN {0:X}h", decoded.CurrentBorderOutSector). + AppendLine(); + + sb.AppendFormat("Next Border-In first sector is PSN {0:X}h", decoded.NextBorderInSector). + AppendLine(); + break; case DiskCategory.DVDPR: case DiskCategory.DVDPRW: case DiskCategory.DVDPRDL: case DiskCategory.DVDPRWDL: - if(decoded.VCPS) sb.AppendLine("Disc contains extended information for VCPS"); + if(decoded.VCPS) + sb.AppendLine("Disc contains extended information for VCPS"); + sb.AppendFormat("Disc application code is {0}", decoded.ApplicationCode).AppendLine(); sb.AppendFormat("Disc manufacturer is {0}", decoded.DiskManufacturerID).AppendLine(); sb.AppendFormat("Disc media type is {0}", decoded.MediaTypeID).AppendLine(); sb.AppendFormat("Disc product revision is {0}", decoded.ProductRevision).AppendLine(); + break; } if((decoded.DiskCategory != DiskCategory.DVDR || decoded.PartVersion < 6) && - (decoded.DiskCategory != DiskCategory.DVDRW || decoded.PartVersion < 3)) return sb.ToString(); + (decoded.DiskCategory != DiskCategory.DVDRW || decoded.PartVersion < 3)) + return sb.ToString(); + + sb.AppendFormat("Current RMD in extra Border zone starts at PSN {0:X}h", decoded.CurrentRMDExtraBorderPSN). + AppendLine(); - sb.AppendFormat("Current RMD in extra Border zone starts at PSN {0:X}h", decoded.CurrentRMDExtraBorderPSN) - .AppendLine(); sb.AppendFormat("PFI in extra Border zone starts at PSN {0:X}h", decoded.PFIExtraBorderPSN).AppendLine(); - if(!decoded.PreRecordedControlDataInv) sb.AppendLine("Control Data Zone is pre-recorded"); - if(decoded.PreRecordedLeadIn) sb.AppendLine("Lead-In is pre-recorded"); - if(decoded.PreRecordedLeadOut) sb.AppendLine("Lead-Out is pre-recorded"); + + if(!decoded.PreRecordedControlDataInv) + sb.AppendLine("Control Data Zone is pre-recorded"); + + if(decoded.PreRecordedLeadIn) + sb.AppendLine("Lead-In is pre-recorded"); + + if(decoded.PreRecordedLeadOut) + sb.AppendLine("Lead-Out is pre-recorded"); return sb.ToString(); } public static string Prettify(byte[] response) => Prettify(Decode(response)); + + public struct PhysicalFormatInformation + { + /// Bytes 0 to 1 Data length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + + #region PFI common to all + /// Byte 4, bits 7 to 4 Disk category field + public DiskCategory DiskCategory; + /// Byte 4, bits 3 to 0 Media version + public byte PartVersion; + /// Byte 5, bits 7 to 4 120mm if 0, 80mm if 1. If UMD (60mm) 0 also. Reserved rest of values + public DVDSize DiscSize; + /// Byte 5, bits 3 to 0 Maximum data rate + public MaximumRateField MaximumRate; + /// Byte 6, bit 7 Reserved + public bool Reserved3; + /// Byte 6, bits 6 to 5 Number of layers + public byte Layers; + /// Byte 6, bit 4 Track path + public bool TrackPath; + /// Byte 6, bits 3 to 0 Layer type + public LayerTypeFieldMask LayerType; + /// Byte 7, bits 7 to 4 Linear density field + public LinearDensityField LinearDensity; + /// Byte 7, bits 3 to 0 Track density field + public TrackDensityField TrackDensity; + /// Bytes 8 to 11 PSN where Data Area starts + public uint DataAreaStartPSN; + /// Bytes 12 to 15 PSN where Data Area ends + public uint DataAreaEndPSN; + /// Bytes 16 to 19 PSN where Data Area ends in Layer 0 + public uint Layer0EndPSN; + /// + /// Byte 20, bit 7 True if BCA exists. GC/Wii discs do not have this bit set, but there is a BCA, making it + /// unreadable in normal DVD drives + /// + public bool BCA; + /// Byte 20, bits 6 to 0 Reserved + public byte Reserved4; + #endregion PFI common to all + + #region UMD PFI + /// Bytes 21 to 22 UMD only, media attribute, application-defined, part of media specific in rest of discs + public ushort MediaAttribute; + #endregion UMD PFI + + #region DVD-RAM PFI + /// Byte 36 Disc type, respecting case recordability + public DVDRAMDiscType DiscType; + #endregion DVD-RAM PFI + + #region DVD-RAM PFI, Version 0001b + /// Byte 52 Byte 504 in Version 0110b Linear velocity, in tenths of m/s + public byte Velocity; + /// Byte 53 Byte 505 in Version 0110b Read power on disk surface, tenths of mW + public byte ReadPower; + /// Byte 54 Byte 507 in Version 0110b Peak power on disk surface for recording land tracks + public byte PeakPower; + /// Byte 55 Bias power on disk surface for recording land tracks + public byte BiasPower; + /// Byte 56 First pulse starting time for recording on land tracks, ns + public byte FirstPulseStart; + /// Byte 57 Byte 515 in Version 0110b First pulse ending time for recording on land tracks + public byte FirstPulseEnd; + /// Byte 58 Byte 518 in Version 0110b Multiple-pulse duration time for recording on land tracks + public byte MultiplePulseDuration; + /// Byte 59 Byte 519 in Version 0110b Last pulse starting time for recording on land tracks + public byte LastPulseStart; + /// Byte 60 Las pulse ending time for recording on land tracks + public byte LastPulseEnd; + /// Byte 61 Bias power duration for recording on land tracks + public byte BiasPowerDuration; + /// Byte 62 Byte 511 on Version 0110b Peak power for recording on groove tracks + public byte PeakPowerGroove; + /// Byte 63 Bias power for recording on groove tracks + public byte BiasPowerGroove; + /// Byte 64 First pulse starting time on groove tracks + public byte FirstPulseStartGroove; + /// Byte 65 First pulse ending time on groove tracks + public byte FirstPulseEndGroove; + /// Byte 66 Multiple-pulse duration time on groove tracks + public byte MultiplePulseDurationGroove; + /// Byte 67 Last pulse starting time on groove tracks + public byte LastPulseStartGroove; + /// Byte 68 Last pulse ending time on groove tracks + public byte LastPulseEndGroove; + /// Byte 69 Bias power duration for recording on groove tracks + public byte BiasPowerDurationGroove; + #endregion DVD-RAM PFI, Version 0001b + + #region DVD-R PFI, DVD-RW PFI + /// Bytes 36 to 39 Sector number of the first sector of the current Border Out + public uint CurrentBorderOutSector; + /// Bytes 40 to 43 Sector number of the first sector of the next Border In + public uint NextBorderInSector; + #endregion DVD-R PFI, DVD-RW PFI + + #region DVD+RW PFI + /// Byte 36 Linear velocities 0 = CLV from 4,90 m/s to 6,25 m/s 1 = CAV from 3,02 m/s to 7,35 m/s + public byte RecordingVelocity; + /// Byte 37 Maximum read power in milliwatts at maximum velocity mW = 20 * (value - 1) + public byte ReadPowerMaxVelocity; + /// Byte 38 Indicative value of Ptarget in mW at maximum velocity + public byte PIndMaxVelocity; + /// Byte 39 Peak power multiplication factor at maximum velocity + public byte PMaxVelocity; + /// Byte 40 Bias1/write power ration at maximum velocity + public byte E1MaxVelocity; + /// Byte 41 Bias2/write power ration at maximum velocity + public byte E2MaxVelocity; + /// Byte 42 Target value for γ, γtarget at the maximum velocity + public byte YTargetMaxVelocity; + /// Byte 43 Maximum read power in milliwatts at reference velocity (4,90 m/s) mW = 20 * (value - 1) + public byte ReadPowerRefVelocity; + /// Byte 44 Indicative value of Ptarget in mW at reference velocity (4,90 m/s) + public byte PIndRefVelocity; + /// Byte 45 Peak power multiplication factor at reference velocity (4,90 m/s) + public byte PRefVelocity; + /// Byte 46 Bias1/write power ration at reference velocity (4,90 m/s) + public byte E1RefVelocity; + /// Byte 47 Bias2/write power ration at reference velocity (4,90 m/s) + public byte E2RefVelocity; + /// Byte 48 Target value for γ, γtarget at the reference velocity (4,90 m/s) + public byte YTargetRefVelocity; + /// Byte 49 Maximum read power in milliwatts at minimum velocity mW = 20 * (value - 1) + public byte ReadPowerMinVelocity; + /// Byte 50 Indicative value of Ptarget in mW at minimum velocity + public byte PIndMinVelocity; + /// Byte 51 Peak power multiplication factor at minimum velocity + public byte PMinVelocity; + /// Byte 52 Bias1/write power ration at minimum velocity + public byte E1MinVelocity; + /// Byte 53 Bias2/write power ration at minimum velocity + public byte E2MinVelocity; + /// Byte 54 Target value for γ, γtarget at the minimum velocity + public byte YTargetMinVelocity; + #endregion DVD+RW PFI + + #region DVD-RAM PFI, version 0110b + /// Byte 506, bit 7 Mode of adaptative write pulse control + public bool AdaptativeWritePulseControlFlag; + /// Byte 508 Bias power 1 on disk surface for recording land tracks + public byte BiasPower1; + /// Byte 509 Bias power 2 on disk surface for recording land tracks + public byte BiasPower2; + /// Byte 510 Bias power 3 on disk surface for recording land tracks + public byte BiasPower3; + /// Byte 512 Bias power 1 on disk surface for recording groove tracks + public byte BiasPower1Groove; + /// Byte 513 Bias power 2 on disk surface for recording groove tracks + public byte BiasPower2Groove; + /// Byte 514 Bias power 3 on disk surface for recording groove tracks + public byte BiasPower3Groove; + /// Byte 516 First pulse duration + public byte FirstPulseDuration; + /// Byte 520 Bias power 2 duration on land tracks at Velocity 1 + public byte BiasPower2Duration; + /// Byte 521 First pulse start time, at Mark 3T and Leading Space 3T + public byte FirstPulseStart3TSpace3T; + /// Byte 522 First pulse start time, at Mark 4T and Leading Space 3T + public byte FirstPulseStart4TSpace3T; + /// Byte 523 First pulse start time, at Mark 5T and Leading Space 3T + public byte FirstPulseStart5TSpace3T; + /// Byte 524 First pulse start time, at Mark >5T and Leading Space 3T + public byte FirstPulseStartSpace3T; + /// Byte 525 First pulse start time, at Mark 3T and Leading Space 4T + public byte FirstPulseStart3TSpace4T; + /// Byte 526 First pulse start time, at Mark 4T and Leading Space 4T + public byte FirstPulseStart4TSpace4T; + /// Byte 527 First pulse start time, at Mark 5T and Leading Space 4T + public byte FirstPulseStart5TSpace4T; + /// Byte 528 First pulse start time, at Mark >5T and Leading Space 4T + public byte FirstPulseStartSpace4T; + /// Byte 529 First pulse start time, at Mark 3T and Leading Space 5T + public byte FirstPulseStart3TSpace5T; + /// Byte 530 First pulse start time, at Mark 4T and Leading Space 5T + public byte FirstPulseStart4TSpace5T; + /// Byte 531 First pulse start time, at Mark 5T and Leading Space 5T + public byte FirstPulseStart5TSpace5T; + /// Byte 532 First pulse start time, at Mark >5T and Leading Space 5T + public byte FirstPulseStartSpace5T; + /// Byte 533 First pulse start time, at Mark 3T and Leading Space >5T + public byte FirstPulseStart3TSpace; + /// Byte 534 First pulse start time, at Mark 4T and Leading Space >5T + public byte FirstPulseStart4TSpace; + /// Byte 535 First pulse start time, at Mark 5T and Leading Space >5T + public byte FirstPulseStart5TSpace; + /// Byte 536 First pulse start time, at Mark >5T and Leading Space >5T + public byte FirstPulseStartSpace; + /// Byte 537 First pulse start time, at Mark 3T and Trailing Space 3T + public byte FirstPulse3TStartTSpace3T; + /// Byte 538 First pulse start time, at Mark 4T and Trailing Space 3T + public byte FirstPulse4TStartTSpace3T; + /// Byte 539 First pulse start time, at Mark 5T and Trailing Space 3T + public byte FirstPulse5TStartTSpace3T; + /// Byte 540 First pulse start time, at Mark >5T and Trailing Space 3T + public byte FirstPulseStartTSpace3T; + /// Byte 541 First pulse start time, at Mark 3T and Trailing Space 4T + public byte FirstPulse3TStartTSpace4T; + /// Byte 542 First pulse start time, at Mark 4T and Trailing Space 4T + public byte FirstPulse4TStartTSpace4T; + /// Byte 543 First pulse start time, at Mark 5T and Trailing Space 4T + public byte FirstPulse5TStartTSpace4T; + /// Byte 544 First pulse start time, at Mark >5T and Trailing Space 4T + public byte FirstPulseStartTSpace4T; + /// Byte 545 First pulse start time, at Mark 3T and Trailing Space 5T + public byte FirstPulse3TStartTSpace5T; + /// Byte 546 First pulse start time, at Mark 4T and Trailing Space 5T + public byte FirstPulse4TStartTSpace5T; + /// Byte 547 First pulse start time, at Mark 5T and Trailing Space 5T + public byte FirstPulse5TStartTSpace5T; + /// Byte 548 First pulse start time, at Mark >5T and Trailing Space 5T + public byte FirstPulseStartTSpace5T; + /// Byte 549 First pulse start time, at Mark 3T and Trailing Space >5T + public byte FirstPulse3TStartTSpace; + /// Byte 550 First pulse start time, at Mark 4T and Trailing Space >5T + public byte FirstPulse4TStartTSpace; + /// Byte 551 First pulse start time, at Mark 5T and Trailing Space >5T + public byte FirstPulse5TStartTSpace; + /// Byte 552 First pulse start time, at Mark >5T and Trailing Space >5T + public byte FirstPulseStartTSpace; + /// Bytes 553 to 600 Disk manufacturer's name, space-padded + public string DiskManufacturer; + /// Bytes 601 to 616 Disk manufacturer's supplementary information + public string DiskManufacturerSupplementary; + /// Bytes 617 to 627 Write power control parameters + public byte[] WritePowerControlParams; + /// Byte 619 Ratio of peak power for land tracks to threshold peak power for land tracks + public byte PowerRatioLandThreshold; + /// Byte 620 Target asymmetry + public byte TargetAsymmetry; + /// Byte 621 Temporary peak power + public byte TemporaryPeakPower; + /// Byte 622 Temporary bias power 1 + public byte TemporaryBiasPower1; + /// Byte 623 Temporary bias power 2 + public byte TemporaryBiasPower2; + /// Byte 624 Temporary bias power 3 + public byte TemporaryBiasPower3; + /// Byte 625 Ratio of peak power for groove tracks to threshold peak power for groove tracks + public byte PowerRatioGrooveThreshold; + /// Byte 626 Ratio of peak power for land tracks to threshold 6T peak power for land tracks + public byte PowerRatioLandThreshold6T; + /// Byte 627 Ratio of peak power for groove tracks to threshold 6T peak power for groove tracks + public byte PowerRatioGrooveThreshold6T; + #endregion DVD-RAM PFI, version 0110b + + #region DVD+RW PFI, DVD+R PFI, DVD+R DL PFI and DVD+RW DL PFI + /// Byte 20, bit 6 If set indicates data zone contains extended information for VCPS + public bool VCPS; + /// Byte 21 Indicates restricted usage disk + public byte ApplicationCode; + /// Byte 22 Bitmap of extended information block presence + public byte ExtendedInformation; + /// Bytes 23 to 30 Disk manufacturer ID, null-padded + public string DiskManufacturerID; + /// Bytes 31 to 33 Media type ID, null-padded + public string MediaTypeID; + /// Byte 34 Product revision number + public byte ProductRevision; + /// Byte 35 Indicates how many bytes, up to 63, are used in ADIP's PFI + public byte PFIUsedInADIP; + #endregion DVD+RW PFI, DVD+R PFI, DVD+R DL PFI and DVD+RW DL PFI + + #region DVD+RW PFI, version 0010b + /// Byte 55 Ttop first pulse duration + public byte TopFirstPulseDuration; + /// Byte 56 Tmp multi pulse duration + public byte MultiPulseDuration; + /// Byte 57 dTtop first pulse lead time + public byte FirstPulseLeadTime; + /// Byte 58 dTera erase lead time at reference velocity + public byte EraseLeadTimeRefVelocity; + /// Byte 59 dTera erase lead time at upper velocity + public byte EraseLeadTimeUppVelocity; + #endregion DVD+RW PFI, version 0010b + + #region DVD+R PFI version 0001b and DVD+R DL PFI version 0001b + /// Byte 36 Primary recording velocity for the basic write strategy + public byte PrimaryVelocity; + /// Byte 37 Upper recording velocity for the basic write strategy + public byte UpperVelocity; + /// Byte 38 Wavelength λIND + public byte Wavelength; + /// Byte 39 Normalized write power dependency on wavelength (dP/dλ)/(PIND/λIND) + public byte NormalizedPowerDependency; + /// Byte 40 Maximum read power at primary velocity + public byte MaximumPowerAtPrimaryVelocity; + /// Byte 41 Pind at primary velocity + public byte PindAtPrimaryVelocity; + /// Byte 42 βtarget at primary velocity + public byte BtargetAtPrimaryVelocity; + /// Byte 43 Maximum read power at upper velocity + public byte MaximumPowerAtUpperVelocity; + /// Byte 44 Pind at primary velocity + public byte PindAtUpperVelocity; + /// Byte 45 βtarget at upper velocity + public byte BtargetAtUpperVelocity; + /// Byte 46 Ttop (≥4T) first pulse duration for cm∗ ≥4T at Primary velocity + public byte FirstPulseDuration4TPrimaryVelocity; + /// Byte 47 Ttop (=3T) first pulse duration for cm∗ =3T at Primary velocity + public byte FirstPulseDuration3TPrimaryVelocity; + /// Byte 48 Tmp multi pulse duration at Primary velocity + public byte MultiPulseDurationPrimaryVelocity; + /// Byte 49 Tlp last pulse duration at Primary velocity + public byte LastPulseDurationPrimaryVelocity; + /// Byte 50 dTtop (≥4T) first pulse lead time for cm∗ ≥4T at Primary velocity + public byte FirstPulseLeadTime4TPrimaryVelocity; + /// Byte 51 dTtop (=3T) first pulse lead time for cm∗ =3T at Primary velocity + public byte FirstPulseLeadTime3TPrimaryVelocity; + /// Byte 52 dTle first pulse leading edge shift for ps∗ =3T at Primary velocity + public byte FirstPulseLeadingEdgePrimaryVelocity; + /// Byte 53 Ttop (≥4T) first pulse duration for cm∗ ≥4T at Upper velocity + public byte FirstPulseDuration4TUpperVelocity; + /// Byte 54 Ttop (=3T) first pulse duration for cm∗ =3T at Upper velocity + public byte FirstPulseDuration3TUpperVelocity; + /// Byte 55 Tmp multi pulse duration at Upper velocity + public byte MultiPulseDurationUpperVelocity; + /// Byte 56 Tlp last pulse duration at Upper velocity + public byte LastPulseDurationUpperVelocity; + /// Byte 57 dTtop (≥4T) first pulse lead time for cm∗ ≥4T at Upper velocity + public byte FirstPulseLeadTime4TUpperVelocity; + /// Byte 58 dTtop (=3T) first pulse lead time for cm∗ =3T at Upper velocity + public byte FirstPulseLeadTime3TUpperVelocity; + /// Byte 59 dTle first pulse leading edge shift for ps∗ =3T at Upper velocity + public byte FirstPulseLeadingEdgeUpperVelocity; + #endregion DVD+R PFI version 0001b and DVD+R DL PFI version 0001b + + #region DVD+R DL PFI version 0001b + /// Byte 34, bits 7 to 6 + public DVDLayerStructure LayerStructure; + #endregion DVD+R DL PFI version 0001b + + #region DVD+RW DL PFI + /// Byte 36 Primary recording velocity for the basic write strategy + public byte BasicPrimaryVelocity; + /// Byte 37 Maximum read power at Primary velocity + public byte MaxReadPowerPrimaryVelocity; + /// Byte 38 PIND at Primary velocity + public byte PindPrimaryVelocity; + /// Byte 39 ρ at Primary velocity + public byte PPrimaryVelocity; + /// Byte 40 ε1 at Primary velocity + public byte E1PrimaryVelocity; + /// Byte 41 ε2 at Primary velocity + public byte E2PrimaryVelocity; + /// Byte 42 γtarget at Primary velocity + public byte YtargetPrimaryVelocity; + /// Byte 43 β optimum at Primary velocity + public byte BOptimumPrimaryVelocity; + /// Byte 46 Ttop first pulse duration + public byte TFirstPulseDuration; + /// Byte 47 Tmp multi pulse duration + public byte TMultiPulseDuration; + /// Byte 48 dTtop first pulse lead/lag time for any runlength ≥ 4T + public byte FirstPulseLeadTimeAnyRun; + /// Byte 49 dTtop,3 first pulse lead/lag time for runlengths = 3T + public byte FirstPulseLeadTimeRun3T; + /// Byte 50 dTlp last pulse lead/lag time for any runlength ≥ 5T + public byte LastPulseLeadTimeAnyRun; + /// Byte 51 dTlp,3 last pulse lead/lag time for runlengths = 3T + public byte LastPulseLeadTime3T; + /// Byte 52 dTlp,4 last pulse lead/lag time for runlengths = 4T + public byte LastPulseLeadTime4T; + /// Byte 53 dTera erase lead/lag time when preceding mark length ≥ 5T + public byte ErasePulseLeadTimeAny; + /// Byte 54 dTera,3 erase lead/lag time when preceding mark length = 3T + public byte ErasePulseLeadTime3T; + /// Byte 55 dTera,4 erase lead/lag time when preceding mark length = 4T + public byte ErasePulseLeadTime4T; + #endregion DVD+RW DL PFI + + #region DVD-R DL PFI and DVD-RW DL PFI + /// Byte 21 Maximum recording speed + public DVDRecordingSpeed MaxRecordingSpeed; + /// Byte 22 Minimum recording speed + public DVDRecordingSpeed MinRecordingSpeed; + /// Byte 23 Another recording speed + public DVDRecordingSpeed RecordingSpeed1; + /// Byte 24 Another recording speed + public DVDRecordingSpeed RecordingSpeed2; + /// Byte 25 Another recording speed + public DVDRecordingSpeed RecordingSpeed3; + /// Byte 26 Another recording speed + public DVDRecordingSpeed RecordingSpeed4; + /// Byte 27 Another recording speed + public DVDRecordingSpeed RecordingSpeed5; + /// Byte 28 Another recording speed + public DVDRecordingSpeed RecordingSpeed6; + /// Byte 29 Another recording speed + public DVDRecordingSpeed RecordingSpeed7; + /// Byte 30 Class + public byte Class; + /// Byte 31 Extended version. 0x30 = ECMA-382, 0x20 = ECMA-384 + public byte ExtendedVersion; + /// Byte 36 Start sector number of current RMD in Extra Border Zone + public uint CurrentRMDExtraBorderPSN; + /// Byte 40 Start sector number of Physical Format Information blocks in Extra Border Zone + public uint PFIExtraBorderPSN; + /// Byte 44, bit 0 If NOT set, Control Data Zone is pre-recorded + public bool PreRecordedControlDataInv; + /// Byte 44 bit 1 Lead-in Zone is pre-recorded + public bool PreRecordedLeadIn; + /// Byte 44 bit 3 Lead-out Zone is pre-recorded + public bool PreRecordedLeadOut; + /// Byte 45 bits 0 to 3 AR characteristic of LPP on Layer 1 + public byte ARCharLayer1; + /// Byte 45 bits 4 to 7 Tracking polarity on Layer 1 + public byte TrackPolarityLayer1; + #endregion DVD-R DL PFI and DVD-RW DL PFI + } } } \ No newline at end of file diff --git a/DVD/PRI.cs b/DVD/PRI.cs index 14cd109..52965d2 100644 --- a/DVD/PRI.cs +++ b/DVD/PRI.cs @@ -35,47 +35,23 @@ using System.Diagnostics.CodeAnalysis; namespace DiscImageChef.Decoders.DVD { /// - /// Information from the following standards: - /// ANSI X3.304-1997 - /// T10/1048-D revision 9.0 - /// T10/1048-D revision 10a - /// T10/1228-D revision 7.0c - /// T10/1228-D revision 11a - /// T10/1363-D revision 10g - /// T10/1545-D revision 1d - /// T10/1545-D revision 5 - /// T10/1545-D revision 5a - /// T10/1675-D revision 2c - /// T10/1675-D revision 4 - /// T10/1836-D revision 2g - /// ECMA 365 + /// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a + /// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision + /// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g ECMA 365 /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static class PRI { public struct PreRecordedInformation { - /// - /// Bytes 0 to 1 - /// Data length - /// + /// Bytes 0 to 1 Data length public ushort DataLength; - /// - /// Byte 2 - /// Reserved - /// + /// Byte 2 Reserved public byte Reserved1; - /// - /// Byte 3 - /// Reserved - /// + /// Byte 3 Reserved public byte Reserved2; - /// - /// Bytes 4 to end - /// Pre-recorded Information in Lead-in for writable media - /// + /// Bytes 4 to end Pre-recorded Information in Lead-in for writable media public byte[] PRI; } } diff --git a/DVD/RMD.cs b/DVD/RMD.cs index b20b35a..81108ed 100644 --- a/DVD/RMD.cs +++ b/DVD/RMD.cs @@ -35,86 +35,41 @@ using System.Diagnostics.CodeAnalysis; namespace DiscImageChef.Decoders.DVD { /// - /// Information from the following standards: - /// ANSI X3.304-1997 - /// T10/1048-D revision 9.0 - /// T10/1048-D revision 10a - /// T10/1228-D revision 7.0c - /// T10/1228-D revision 11a - /// T10/1363-D revision 10g - /// T10/1545-D revision 1d - /// T10/1545-D revision 5 - /// T10/1545-D revision 5a - /// T10/1675-D revision 2c - /// T10/1675-D revision 4 - /// T10/1836-D revision 2g - /// ECMA 365 + /// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a + /// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision + /// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g ECMA 365 /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static class RMD { public struct LastBorderOutRMD { - /// - /// Bytes 0 to 1 - /// Data length - /// + /// Bytes 0 to 1 Data length public ushort DataLength; - /// - /// Byte 2 - /// Reserved - /// + /// Byte 2 Reserved public byte Reserved1; - /// - /// Byte 3 - /// Reserved - /// + /// Byte 3 Reserved public byte Reserved2; - /// - /// Bytes 4 to end - /// RMD in last recorded Border-out - /// + /// Bytes 4 to end RMD in last recorded Border-out public byte[] RMD; } public struct HDMediumStatus { - /// - /// Bytes 0 to 1 - /// Data length - /// + /// Bytes 0 to 1 Data length public ushort DataLength; - /// - /// Byte 2 - /// Reserved - /// + /// Byte 2 Reserved public byte Reserved1; - /// - /// Byte 3 - /// Reserved - /// + /// Byte 3 Reserved public byte Reserved2; - /// - /// Byte 4, bits 7 to 1 - /// Reserved - /// + /// Byte 4, bits 7 to 1 Reserved public byte Reserved3; - /// - /// Byte 4, bit 0 - /// Test Zone has been extended - /// + /// Byte 4, bit 0 Test Zone has been extended public bool ExtendedTestZone; - /// - /// Byte 5 - /// Number of remaining RMDs in RDZ - /// + /// Byte 5 Number of remaining RMDs in RDZ public byte RemainingRMDs; - /// - /// Bytes 6 to 7 - /// Number of remaining RMDs in current RMZ - /// + /// Bytes 6 to 7 Number of remaining RMDs in current RMZ public ushort CurrentRemainingRMDs; } } diff --git a/DVD/Spare.cs b/DVD/Spare.cs index ca9bfa6..675667c 100644 --- a/DVD/Spare.cs +++ b/DVD/Spare.cs @@ -36,68 +36,22 @@ using System.Text; namespace DiscImageChef.Decoders.DVD { /// - /// Information from the following standards: - /// ANSI X3.304-1997 - /// T10/1048-D revision 9.0 - /// T10/1048-D revision 10a - /// T10/1228-D revision 7.0c - /// T10/1228-D revision 11a - /// T10/1363-D revision 10g - /// T10/1545-D revision 1d - /// T10/1545-D revision 5 - /// T10/1545-D revision 5a - /// T10/1675-D revision 2c - /// T10/1675-D revision 4 - /// T10/1836-D revision 2g + /// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a + /// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision + /// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] public static class Spare { - public struct SpareAreaInformation - { - /// - /// Bytes 0 to 1 - /// Data length - /// - public ushort DataLength; - /// - /// Byte 2 - /// Reserved - /// - public byte Reserved1; - /// - /// Byte 3 - /// Reserved - /// - public byte Reserved2; - /// - /// Bytes 4 to 7 - /// Data length - /// - public uint UnusedPrimaryBlocks; - /// - /// Bytes 8 to 11 - /// Data length - /// - public uint UnusedSupplementaryBlocks; - /// - /// Bytes 12 to 15 - /// Data length - /// - public uint AllocatedSupplementaryBlocks; - } - public static SpareAreaInformation? Decode(byte[] response) { - if(response?.Length != 16) return null; + if(response?.Length != 16) + return null; return new SpareAreaInformation { - DataLength = (ushort)((response[0] << 8) + response[1]), - Reserved1 = response[2], + DataLength = (ushort)((response[0] << 8) + response[1]), Reserved1 = response[2], Reserved2 = response[3], UnusedPrimaryBlocks = (uint)((response[4] << 24) + (response[5] << 16) + (response[6] << 8) + response[7]), @@ -110,19 +64,37 @@ namespace DiscImageChef.Decoders.DVD public static string Prettify(SpareAreaInformation? sai) { - if(sai == null) return null; + if(sai == null) + return null; SpareAreaInformation decoded = sai.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendFormat("{0} unused primary spare blocks", decoded.UnusedPrimaryBlocks).AppendLine(); sb.AppendFormat("{0} unused supplementary spare blocks", decoded.UnusedSupplementaryBlocks).AppendLine(); - sb.AppendFormat("{0} allocated supplementary spare blocks", decoded.AllocatedSupplementaryBlocks) - .AppendLine(); + + sb.AppendFormat("{0} allocated supplementary spare blocks", decoded.AllocatedSupplementaryBlocks). + AppendLine(); return sb.ToString(); } public static string Prettify(byte[] response) => Prettify(Decode(response)); + + public struct SpareAreaInformation + { + /// Bytes 0 to 1 Data length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Bytes 4 to 7 Data length + public uint UnusedPrimaryBlocks; + /// Bytes 8 to 11 Data length + public uint UnusedSupplementaryBlocks; + /// Bytes 12 to 15 Data length + public uint AllocatedSupplementaryBlocks; + } } } \ No newline at end of file diff --git a/DVD/UDI.cs b/DVD/UDI.cs index 3bf26e2..adbfad8 100644 --- a/DVD/UDI.cs +++ b/DVD/UDI.cs @@ -35,87 +35,39 @@ using System.Diagnostics.CodeAnalysis; namespace DiscImageChef.Decoders.DVD { /// - /// Information from the following standards: - /// ANSI X3.304-1997 - /// T10/1048-D revision 9.0 - /// T10/1048-D revision 10a - /// T10/1228-D revision 7.0c - /// T10/1228-D revision 11a - /// T10/1363-D revision 10g - /// T10/1545-D revision 1d - /// T10/1545-D revision 5 - /// T10/1545-D revision 5a - /// T10/1675-D revision 2c - /// T10/1675-D revision 4 - /// T10/1836-D revision 2g - /// ECMA 365 + /// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a + /// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision + /// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g ECMA 365 /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static class UDI { public struct UniqueDiscIdentifier { - /// - /// Bytes 0 to 1 - /// Data length - /// + /// Bytes 0 to 1 Data length public ushort DataLength; - /// - /// Byte 2 - /// Reserved - /// + /// Byte 2 Reserved public byte Reserved1; - /// - /// Byte 3 - /// Reserved - /// + /// Byte 3 Reserved public byte Reserved2; - /// - /// Byte 4 - /// Reserved - /// + /// Byte 4 Reserved public byte Reserved3; - /// - /// Byte 5 - /// Reserved - /// + /// Byte 5 Reserved public byte Reserved4; - /// - /// Bytes 6 to 7 - /// Random number - /// + /// Bytes 6 to 7 Random number public ushort RandomNumber; - /// - /// Byte 8 to 11 - /// Year - /// + /// Byte 8 to 11 Year public uint Year; - /// - /// Byte 12 to 13 - /// Month - /// + /// Byte 12 to 13 Month public ushort Month; - /// - /// Byte 14 to 15 - /// Day - /// + /// Byte 14 to 15 Day public ushort Day; - /// - /// Byte 16 to 17 - /// Hour - /// + /// Byte 16 to 17 Hour public ushort Hour; - /// - /// Byte 18 to 19 - /// Minute - /// + /// Byte 18 to 19 Minute public ushort Minute; - /// - /// Byte 20 to 21 - /// Second - /// + /// Byte 20 to 21 Second public ushort Second; } } diff --git a/Floppy/Amiga.cs b/Floppy/Amiga.cs index 0b2aada..3eb0d5c 100644 --- a/Floppy/Amiga.cs +++ b/Floppy/Amiga.cs @@ -35,54 +35,33 @@ using System.Runtime.InteropServices; namespace DiscImageChef.Decoders.Floppy { - /// - /// Methods and structures for Commodore Amiga decoding - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + /// Methods and structures for Commodore Amiga decoding + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static class Amiga { public struct Sector { - /// - /// Set to 0x00 - /// + /// Set to 0x00 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public byte[] zero; - /// - /// Set to 0xA1 - /// + /// Set to 0xA1 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public byte[] sync; - /// - /// Set to 0xFF - /// + /// Set to 0xFF public byte amiga; - /// - /// Track number - /// + /// Track number public byte track; - /// - /// Sector number - /// + /// Sector number public byte sector; - /// - /// Remaining sectors til end of writing - /// + /// Remaining sectors til end of writing public byte remaining; - /// - /// OS dependent tag - /// + /// OS dependent tag [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] label; - /// - /// Checksum from to - /// + /// Checksum from to public uint headerChecksum; - /// - /// Checksum from - /// + /// Checksum from public uint dataChecksum; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)] public byte[] data; diff --git a/Floppy/Apple2.cs b/Floppy/Apple2.cs index 3304c4e..4fe8e3f 100644 --- a/Floppy/Apple2.cs +++ b/Floppy/Apple2.cs @@ -40,150 +40,58 @@ using DiscImageChef.Console; namespace DiscImageChef.Decoders.Floppy { - /// - /// Methods and structures for Apple ][ floppy decoding - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + /// Methods and structures for Apple ][ floppy decoding + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static class Apple2 { - /// - /// GCR-encoded Apple ][ GCR floppy track - /// - public class RawTrack - { - /// - /// Track preamble, set to self-sync 0xFF, between 40 and 95 bytes - /// - public byte[] gap; - public RawSector[] sectors; - } - - /// - /// GCR-encoded Apple ][ GCR floppy sector - /// - public class RawSector - { - /// - /// Address field - /// - public RawAddressField addressField; - /// - /// Data field - /// - public RawDataField dataField; - /// - /// Track preamble, set to self-sync 0xFF, between 14 and 24 bytes - /// - public byte[] gap; - /// - /// Track preamble, set to self-sync 0xFF, between 5 and 10 bytes - /// - public byte[] innerGap; - } - - /// - /// GCR-encoded Apple ][ GCR floppy sector address field - /// - public class RawAddressField - { - /// - /// decodedChecksum = decodedVolume ^ decodedTrack ^ decodedSector - /// checksum[0] = (decodedChecksum >> 1) | 0xAA - /// checksum[1] = decodedChecksum | 0xAA - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] - public byte[] checksum; - /// - /// Always 0xDE, 0xAA, 0xEB - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] - public byte[] epilogue; - /// - /// Always 0xD5, 0xAA, 0x96 - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] - public byte[] prologue; - /// - /// Sector number encoded as: - /// sector[0] = (decodedSector >> 1) | 0xAA - /// sector[1] = decodedSector | 0xAA - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] - public byte[] sector; - /// - /// Track number encoded as: - /// track[0] = (decodedTrack >> 1) | 0xAA - /// track[1] = decodedTrack | 0xAA - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] - public byte[] track; - /// - /// Volume number encoded as: - /// volume[0] = (decodedVolume >> 1) | 0xAA - /// volume[1] = decodedVolume | 0xAA - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] - public byte[] volume; - } - - /// - /// GCR-encoded Apple ][ GCR floppy sector data field - /// - public class RawDataField - { - public byte checksum; - /// - /// Encoded data bytes. - /// 410 bytes for 5to3 (aka DOS 3.2) format - /// 342 bytes for 6to2 (aka DOS 3.3) format - /// - public byte[] data; - /// - /// Always 0xDE, 0xAA, 0xEB - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] - public byte[] epilogue; - /// - /// Always 0xD5, 0xAA, 0xAD - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] - public byte[] prologue; - } - static readonly byte[] ReadTable5and3 = { // 00h 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + // 10h 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + // 20h 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + // 30h 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + // 40h 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + // 50h 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + // 60h 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + // 70h 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + // 80h 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + // 90h 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + // A0h 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0x01, 0x02, 0x03, + // B0h 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x04, 0x05, 0x06, 0xFF, 0xFF, 0x07, 0x08, 0xFF, 0x09, 0x0A, 0x0B, + // C0h 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + // D0h 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0C, 0x0D, 0xFF, 0xFF, 0x0E, 0x0F, 0xFF, 0x10, 0x11, 0x12, + // E0h 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x13, 0x14, 0xFF, 0x15, 0x16, 0x17, + // F0h 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x18, 0x19, 0x1A, 0xFF, 0xFF, 0x1B, 0x1C, 0xFF, 0x1D, 0x1E, 0x1F }; @@ -192,48 +100,64 @@ namespace DiscImageChef.Decoders.Floppy { // 00h 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + // 10h 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + // 20h 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + // 30h 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + // 40h 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + // 50h 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + // 60h 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + // 70h 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + // 80h 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + // 90h 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x02, 0x03, 0xFF, 0x04, 0x05, 0x06, + // A0h 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x08, 0xFF, 0xFF, 0xFF, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, + // B0h 0xFF, 0xFF, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0xFF, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, + // C0h 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1B, 0xFF, 0x1C, 0x1D, 0x1E, + // D0h 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0x20, 0x21, 0xFF, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, + // E0h 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x29, 0x2A, 0x2B, 0xFF, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, + // F0h 0xFF, 0xFF, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0xFF, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F }; - /// - /// Decodes the 5and3 encoded data - /// + /// Decodes the 5and3 encoded data /// 5and3 encoded data. public static byte[] Decode5and3(byte[] data) { - if(data == null || data.Length != 410) return null; + if(data == null || + data.Length != 410) + return null; byte[] buffer = new byte[data.Length]; byte carry = 0; + for(int i = 0; i < data.Length; i++) { carry ^= ReadTable5and3[data[i]]; @@ -241,6 +165,7 @@ namespace DiscImageChef.Decoders.Floppy } byte[] output = new byte[256]; + for(int i = 0; i < 51; i++) { byte b1 = buffer[51 * 3 - i]; @@ -260,16 +185,17 @@ namespace DiscImageChef.Decoders.Floppy return output; } - /// - /// Decodes the 6and2 encoded data - /// + /// Decodes the 6and2 encoded data /// 6and2 encoded data. public static byte[] Decode6and2(byte[] data) { - if(data == null || data.Length != 342) return null; + if(data == null || + data.Length != 342) + return null; byte[] buffer = new byte[data.Length]; byte carry = 0; + for(int i = 0; i < data.Length; i++) { carry ^= ReadTable6and2[data[i]]; @@ -277,6 +203,7 @@ namespace DiscImageChef.Decoders.Floppy } byte[] output = new byte[256]; + for(uint i = 0; i < 256; i++) { output[i] = (byte)((buffer[86 + i] << 2) & 0xFF); @@ -303,13 +230,17 @@ namespace DiscImageChef.Decoders.Floppy public static byte[] DecodeSector(RawSector sector) { - if(sector.addressField.prologue[0] != 0xD5 || sector.addressField.prologue[1] != 0xAA) return null; + if(sector.addressField.prologue[0] != 0xD5 || + sector.addressField.prologue[1] != 0xAA) + return null; // Pre DOS 3.3 - if(sector.addressField.prologue[2] == 0xB5) return Decode5and3(sector.dataField.data); + if(sector.addressField.prologue[2] == 0xB5) + return Decode5and3(sector.dataField.data); // DOS 3.3 return sector.addressField.prologue[2] == 0x96 ? Decode6and2(sector.dataField.data) : null; + // Unknown // Not Apple ][ GCR? @@ -322,7 +253,9 @@ namespace DiscImageChef.Decoders.Floppy endOffset = offset; // Not an Apple ][ GCR sector - if(data == null || data.Length < 363) return null; + if(data == null || + data.Length < 363) + return null; int position = offset; @@ -331,49 +264,71 @@ namespace DiscImageChef.Decoders.Floppy while(position < data.Length) { // Prologue found - if(data[position] == 0xD5 && data[position + 1] == 0xAA) + if(data[position] == 0xD5 && + data[position + 1] == 0xAA) { DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Prologue found at {0}", position); // Epilogue not in correct position - if(data[position + 11] != 0xDE || data[position + 12] != 0xAA) return null; + if(data[position + 11] != 0xDE || + data[position + 12] != 0xAA) + return null; - RawSector sector = new RawSector + var sector = new RawSector { addressField = new RawAddressField { - prologue = new[] {data[position], data[position + 1], data[position + 2]}, - volume = new[] {data[position + 3], data[position + 4]}, - track = new[] {data[position + 5], data[position + 6]}, - sector = new[] {data[position + 7], data[position + 8]}, - checksum = new[] {data[position + 9], data[position + 10]}, + prologue = new[] + { + data[position], data[position + 1], data[position + 2] + }, + volume = new[] + { + data[position + 3], data[position + 4] + }, + track = new[] + { + data[position + 5], data[position + 6] + }, + sector = new[] + { + data[position + 7], data[position + 8] + }, + checksum = new[] + { + data[position + 9], data[position + 10] + }, epilogue = new[] - { - data[position + 11], data[position + 12], data[position + 13] - } + { + data[position + 11], data[position + 12], data[position + 13] + } } }; DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Volume {0}", (((sector.addressField.volume[0] & 0x55) << 1) | (sector.addressField.volume[1] & 0x55)) & 0xFF); + DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Track {0}", (((sector.addressField.track[0] & 0x55) << 1) | (sector.addressField.track[1] & 0x55)) & 0xFF); + DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Sector {0}", (((sector.addressField.sector[0] & 0x55) << 1) | (sector.addressField.sector[1] & 0x55)) & 0xFF); + DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Checksum {0}", (((sector.addressField.checksum[0] & 0x55) << 1) | (sector.addressField.checksum[1] & 0x55)) & 0xFF); + DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Epilogue {0:X2}{1:X2}{2:X2}", sector.addressField.epilogue[0], sector.addressField.epilogue[1], sector.addressField.epilogue[2]); position += 14; - int syncCount = 0; - bool onSync = false; - MemoryStream gaps = new MemoryStream(); + int syncCount = 0; + bool onSync = false; + var gaps = new MemoryStream(); while(data[position] == 0xFF) { @@ -384,16 +339,20 @@ namespace DiscImageChef.Decoders.Floppy } // Lost sync - if(!onSync) return null; + if(!onSync) + return null; // Prologue not found - if(data[position] != 0xD5 || data[position + 1] != 0xAA) return null; + if(data[position] != 0xD5 || + data[position + 1] != 0xAA) + return null; sector.innerGap = gaps.ToArray(); sector.dataField = new RawDataField(); DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Inner gap has {0} bytes", sector.innerGap.Length); + DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Prologue found at {0}", position); sector.dataField.prologue = new byte[3]; sector.dataField.prologue[0] = data[position]; @@ -402,19 +361,24 @@ namespace DiscImageChef.Decoders.Floppy position += 3; gaps = new MemoryStream(); + // Read data until epilogue is found - while(data[position + 1] != 0xDE || data[position + 2] != 0xAA) + while(data[position + 1] != 0xDE || + data[position + 2] != 0xAA) { gaps.WriteByte(data[position]); position++; // No space left for epilogue - if(position + 4 > data.Length) return null; + if(position + 4 > data.Length) + return null; } sector.dataField.data = gaps.ToArray(); + DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Data has {0} bytes", sector.dataField.data.Length); + sector.dataField.checksum = data[position]; sector.dataField.epilogue = new byte[3]; sector.dataField.epilogue[0] = data[position + 1]; @@ -423,8 +387,10 @@ namespace DiscImageChef.Decoders.Floppy position += 4; gaps = new MemoryStream(); + // Read gap, if any - while(position < data.Length && data[position] == 0xFF) + while(position < data.Length && + data[position] == 0xFF) { gaps.WriteByte(data[position]); position++; @@ -438,32 +404,41 @@ namespace DiscImageChef.Decoders.Floppy } sector.gap = gaps.ToArray(); + // Return current position to be able to read separate sectors endOffset = position; - DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Got {0} bytes of gap", sector.gap.Length); + DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Got {0} bytes of gap", sector.gap.Length); DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Finished sector at {0}", position); + return sector; } - if(data[position] == 0xFF) position++; + if(data[position] == 0xFF) + position++; + // Found data that is not sync or a prologue - else return null; + else + return null; } } - catch(IndexOutOfRangeException) { return null; } + catch(IndexOutOfRangeException) + { + return null; + } return null; } public static byte[] MarshalAddressField(RawAddressField addressField) { - if(addressField == null) return null; + if(addressField == null) + return null; - MemoryStream raw = new MemoryStream(); + var raw = new MemoryStream(); raw.Write(addressField.prologue, 0, addressField.prologue.Length); - raw.Write(addressField.volume, 0, addressField.volume.Length); - raw.Write(addressField.track, 0, addressField.track.Length); - raw.Write(addressField.sector, 0, addressField.sector.Length); + raw.Write(addressField.volume, 0, addressField.volume.Length); + raw.Write(addressField.track, 0, addressField.track.Length); + raw.Write(addressField.sector, 0, addressField.sector.Length); raw.Write(addressField.checksum, 0, addressField.checksum.Length); raw.Write(addressField.epilogue, 0, addressField.epilogue.Length); @@ -472,21 +447,22 @@ namespace DiscImageChef.Decoders.Floppy public static byte[] MarshalSector(RawSector sector) { - if(sector == null) return null; + if(sector == null) + return null; - MemoryStream raw = new MemoryStream(); + var raw = new MemoryStream(); raw.Write(sector.addressField.prologue, 0, sector.addressField.prologue.Length); - raw.Write(sector.addressField.volume, 0, sector.addressField.volume.Length); - raw.Write(sector.addressField.track, 0, sector.addressField.track.Length); - raw.Write(sector.addressField.sector, 0, sector.addressField.sector.Length); + raw.Write(sector.addressField.volume, 0, sector.addressField.volume.Length); + raw.Write(sector.addressField.track, 0, sector.addressField.track.Length); + raw.Write(sector.addressField.sector, 0, sector.addressField.sector.Length); raw.Write(sector.addressField.checksum, 0, sector.addressField.checksum.Length); raw.Write(sector.addressField.epilogue, 0, sector.addressField.epilogue.Length); - raw.Write(sector.innerGap, 0, sector.innerGap.Length); - raw.Write(sector.dataField.prologue, 0, sector.dataField.prologue.Length); - raw.Write(sector.dataField.data, 0, sector.dataField.data.Length); + raw.Write(sector.innerGap, 0, sector.innerGap.Length); + raw.Write(sector.dataField.prologue, 0, sector.dataField.prologue.Length); + raw.Write(sector.dataField.data, 0, sector.dataField.data.Length); raw.WriteByte(sector.dataField.checksum); raw.Write(sector.dataField.epilogue, 0, sector.dataField.epilogue.Length); - raw.Write(sector.gap, 0, sector.gap.Length); + raw.Write(sector.gap, 0, sector.gap.Length); return raw.ToArray(); } @@ -498,13 +474,14 @@ namespace DiscImageChef.Decoders.Floppy int position = offset; bool firstSector = true; bool onSync = false; - MemoryStream gaps = new MemoryStream(); + var gaps = new MemoryStream(); int count = 0; List sectors = new List(); byte[] trackNumber = new byte[2]; endOffset = offset; - while(position < data.Length && data[position] == 0xFF) + while(position < data.Length && + data[position] == 0xFF) { gaps.WriteByte(data[position]); count++; @@ -512,15 +489,19 @@ namespace DiscImageChef.Decoders.Floppy onSync = count >= 5; } - if(position >= data.Length) return null; + if(position >= data.Length) + return null; - if(!onSync) return null; + if(!onSync) + return null; while(position < data.Length) { int oldPosition = position; RawSector sector = MarshalSector(data, out position, position); - if(sector == null) break; + + if(sector == null) + break; if(firstSector) { @@ -529,9 +510,11 @@ namespace DiscImageChef.Decoders.Floppy firstSector = false; } - if(sector.addressField.track[0] != trackNumber[0] || sector.addressField.track[1] != trackNumber[1]) + if(sector.addressField.track[0] != trackNumber[0] || + sector.addressField.track[1] != trackNumber[1]) { position = oldPosition; + break; } @@ -540,23 +523,33 @@ namespace DiscImageChef.Decoders.Floppy (sector.addressField.sector[1] & 0x55)) & 0xFF, (((sector.addressField.track[0] & 0x55) << 1) | (sector.addressField.track[1] & 0x55)) & 0xFF); + sectors.Add(sector); } - if(sectors.Count == 0) return null; + if(sectors.Count == 0) + return null; + + var track = new RawTrack + { + gap = gaps.ToArray(), sectors = sectors.ToArray() + }; - RawTrack track = new RawTrack {gap = gaps.ToArray(), sectors = sectors.ToArray()}; endOffset = position; + return track; } public static byte[] MarshalTrack(RawTrack track) { - if(track == null) return null; + if(track == null) + return null; - MemoryStream raw = new MemoryStream(); + var raw = new MemoryStream(); raw.Write(track.gap, 0, track.gap.Length); - foreach(byte[] rawSector in track.sectors.Select(MarshalSector)) raw.Write(rawSector, 0, rawSector.Length); + + foreach(byte[] rawSector in track.sectors.Select(MarshalSector)) + raw.Write(rawSector, 0, rawSector.Length); return raw.ToArray(); } @@ -570,15 +563,18 @@ namespace DiscImageChef.Decoders.Floppy int position = offset; RawTrack track = MarshalTrack(data, out position, position); + while(track != null) { tracks.Add(track); track = MarshalTrack(data, out position, position); } - if(tracks.Count == 0) return null; + if(tracks.Count == 0) + return null; endOffset = position; + return tracks; } @@ -586,10 +582,13 @@ namespace DiscImageChef.Decoders.Floppy public static byte[] MarshalDisk(RawTrack[] disk) { - if(disk == null) return null; + if(disk == null) + return null; - MemoryStream raw = new MemoryStream(); - foreach(byte[] rawTrack in disk.Select(MarshalTrack)) raw.Write(rawTrack, 0, rawTrack.Length); + var raw = new MemoryStream(); + + foreach(byte[] rawTrack in disk.Select(MarshalTrack)) + raw.Write(rawTrack, 0, rawTrack.Length); return raw.ToArray(); } @@ -600,5 +599,66 @@ namespace DiscImageChef.Decoders.Floppy return sector != null && position != 0; } + + /// GCR-encoded Apple ][ GCR floppy track + public class RawTrack + { + /// Track preamble, set to self-sync 0xFF, between 40 and 95 bytes + public byte[] gap; + public RawSector[] sectors; + } + + /// GCR-encoded Apple ][ GCR floppy sector + public class RawSector + { + /// Address field + public RawAddressField addressField; + /// Data field + public RawDataField dataField; + /// Track preamble, set to self-sync 0xFF, between 14 and 24 bytes + public byte[] gap; + /// Track preamble, set to self-sync 0xFF, between 5 and 10 bytes + public byte[] innerGap; + } + + /// GCR-encoded Apple ][ GCR floppy sector address field + public class RawAddressField + { + /// + /// decodedChecksum = decodedVolume ^ decodedTrack ^ decodedSector checksum[0] = (decodedChecksum >> 1) | 0xAA + /// checksum[1] = decodedChecksum | 0xAA + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public byte[] checksum; + /// Always 0xDE, 0xAA, 0xEB + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public byte[] epilogue; + /// Always 0xD5, 0xAA, 0x96 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public byte[] prologue; + /// Sector number encoded as: sector[0] = (decodedSector >> 1) | 0xAA sector[1] = decodedSector | 0xAA + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public byte[] sector; + /// Track number encoded as: track[0] = (decodedTrack >> 1) | 0xAA track[1] = decodedTrack | 0xAA + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public byte[] track; + /// Volume number encoded as: volume[0] = (decodedVolume >> 1) | 0xAA volume[1] = decodedVolume | 0xAA + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public byte[] volume; + } + + /// GCR-encoded Apple ][ GCR floppy sector data field + public class RawDataField + { + public byte checksum; + /// Encoded data bytes. 410 bytes for 5to3 (aka DOS 3.2) format 342 bytes for 6to2 (aka DOS 3.3) format + public byte[] data; + /// Always 0xDE, 0xAA, 0xEB + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public byte[] epilogue; + /// Always 0xD5, 0xAA, 0xAD + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public byte[] prologue; + } } } \ No newline at end of file diff --git a/Floppy/AppleSony.cs b/Floppy/AppleSony.cs index c7b8899..2b0cf5b 100644 --- a/Floppy/AppleSony.cs +++ b/Floppy/AppleSony.cs @@ -42,138 +42,35 @@ namespace DiscImageChef.Decoders.Floppy // Information from: // Inside Macintosh, Volume II, ISBN 0-201-17732-3 - /// - /// Methods and structures for Apple Sony GCR floppy decoding - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// Methods and structures for Apple Sony GCR floppy decoding + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] public static class AppleSony { - /// - /// GCR-encoded Apple Sony GCR floppy track - /// - public class RawTrack - { - /// - /// Track preamble, set to self-sync 0xFF, 36 bytes - /// - public byte[] gap; - public RawSector[] sectors; - } - - /// - /// GCR-encoded Apple Sony GCR floppy sector - /// - public class RawSector - { - /// - /// Address field - /// - public RawAddressField addressField; - /// - /// Data field - /// - public RawDataField dataField; - /// - /// Track preamble, set to self-sync 0xFF, unknown size - /// - public byte[] gap; - /// - /// Track preamble, set to self-sync 0xFF, 6 bytes - /// - public byte[] innerGap; - } - - /// - /// GCR-encoded Apple Sony GCR floppy sector address field - /// - public class RawAddressField - { - /// - /// Checksum - /// - public byte checksum; - /// - /// Always 0xDE, 0xAA - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] - public byte[] epilogue; - /// - /// Disk format - /// - public AppleEncodedFormat format; - /// - /// Always 0xD5, 0xAA, 0x96 - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] - public byte[] prologue; - /// - /// Encoded sector number - /// - public byte sector; - /// - /// Encoded side number - /// - public byte side; - /// - /// Encoded (decodedTrack & 0x3F) - /// - public byte track; - } - - /// - /// GCR-encoded Apple ][ GCR floppy sector data field - /// - public class RawDataField - { - /// - /// Checksum - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] - public byte[] checksum; - /// - /// Encoded data bytes. - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 698)] - public byte[] data; - /// - /// Always 0xDE, 0xAA - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] - public byte[] epilogue; - /// - /// Always 0xD5, 0xAA, 0xAD - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] - public byte[] prologue; - /// - /// Spare, usually - /// - public byte spare; - } - public static byte[] DecodeSector(RawSector sector) { - if(sector.addressField.prologue[0] != 0xD5 || sector.addressField.prologue[1] != 0xAA || - sector.addressField.prologue[2] != 0x96) return null; + if(sector.addressField.prologue[0] != 0xD5 || + sector.addressField.prologue[1] != 0xAA || + sector.addressField.prologue[2] != 0x96) + return null; - byte[] bf1 = new byte[175]; - byte[] bf2 = new byte[175]; - byte[] bf3 = new byte[175]; - byte[] nib_data = sector.dataField.data; - MemoryStream ms = new MemoryStream(); + byte[] bf1 = new byte[175]; + byte[] bf2 = new byte[175]; + byte[] bf3 = new byte[175]; + byte[] nib_data = sector.dataField.data; + var ms = new MemoryStream(); int j = 0; byte w3 = 0; + for(int i = 0; i <= 174; i++) { byte w4 = nib_data[j++]; byte w1 = nib_data[j++]; byte w2 = nib_data[j++]; - if(i != 174) w3 = nib_data[j++]; + if(i != 174) + w3 = nib_data[j++]; bf1[i] = (byte)(((w1 & 0x3F) | ((w4 << 2) & 0xC0)) & 0x0F); bf2[i] = (byte)(((w2 & 0x3F) | ((w4 << 4) & 0xC0)) & 0x0F); @@ -184,13 +81,17 @@ namespace DiscImageChef.Decoders.Floppy uint ck1 = 0; uint ck2 = 0; uint ck3 = 0; + while(true) { ck1 = (ck1 & 0xFF) << 1; - if((ck1 & 0x0100) > 0) ck1++; + + if((ck1 & 0x0100) > 0) + ck1++; byte carry = (byte)((bf1[j] ^ ck1) & 0xFF); ck3 += carry; + if((ck1 & 0x0100) > 0) { ck3++; @@ -201,6 +102,7 @@ namespace DiscImageChef.Decoders.Floppy carry = (byte)((bf2[j] ^ ck3) & 0xFF); ck2 += carry; + if(ck3 > 0xFF) { ck2++; @@ -209,10 +111,12 @@ namespace DiscImageChef.Decoders.Floppy ms.WriteByte(carry); - if(ms.Length == 524) break; + if(ms.Length == 524) + break; carry = (byte)((bf3[j] ^ ck2) & 0xFF); ck1 += carry; + if(ck2 > 0xFF) { ck1++; @@ -235,7 +139,9 @@ namespace DiscImageChef.Decoders.Floppy endOffset = offset; // Not an Apple ][ GCR sector - if(data == null || data.Length < 363) return null; + if(data == null || + data.Length < 363) + return null; int position = offset; @@ -244,29 +150,37 @@ namespace DiscImageChef.Decoders.Floppy while(position < data.Length) { // Prologue found - if(data[position] == 0xD5 && data[position + 1] == 0xAA && data[position + 2] == 0x96) + if(data[position] == 0xD5 && + data[position + 1] == 0xAA && + data[position + 2] == 0x96) { // Epilogue not in correct position - if(data[position + 8] != 0xDE || data[position + 9] != 0xAA) return null; + if(data[position + 8] != 0xDE || + data[position + 9] != 0xAA) + return null; - RawSector sector = new RawSector + var sector = new RawSector { addressField = new RawAddressField { - prologue = new[] {data[position], data[position + 1], data[position + 2]}, - track = data[position + 3], - sector = data[position + 4], - side = data[position + 5], - format = (AppleEncodedFormat)data[position + 6], - checksum = data[position + 7], - epilogue = new[] {data[position + 8], data[position + 9]} + prologue = new[] + { + data[position], data[position + 1], data[position + 2] + }, + track = data[position + 3], sector = data[position + 4], + side = data[position + 5], + format = (AppleEncodedFormat)data[position + 6], checksum = data[position + 7], + epilogue = new[] + { + data[position + 8], data[position + 9] + } } }; position += 10; - int syncCount = 0; - bool onSync = false; - MemoryStream gaps = new MemoryStream(); + int syncCount = 0; + bool onSync = false; + var gaps = new MemoryStream(); while(data[position] == 0xFF) { @@ -277,29 +191,40 @@ namespace DiscImageChef.Decoders.Floppy } // Lost sync - if(!onSync) return null; + if(!onSync) + return null; // Prologue not found - if(data[position] != 0xDE || data[position + 1] != 0xAA || data[position + 2] != 0xAD) + if(data[position] != 0xDE || + data[position + 1] != 0xAA || + data[position + 2] != 0xAD) return null; sector.innerGap = gaps.ToArray(); + sector.dataField = new RawDataField { - prologue = new[] {data[position], data[position + 1], data[position + 2]}, - spare = data[position + 3] + prologue = new[] + { + data[position], data[position + 1], data[position + 2] + }, + spare = data[position + 3] }; + position += 4; gaps = new MemoryStream(); + // Read data until epilogue is found - while(data[position + 4] != 0xD5 || data[position + 5] != 0xAA) + while(data[position + 4] != 0xD5 || + data[position + 5] != 0xAA) { gaps.WriteByte(data[position]); position++; // No space left for epilogue - if(position + 7 > data.Length) return null; + if(position + 7 > data.Length) + return null; } sector.dataField.data = gaps.ToArray(); @@ -314,8 +239,10 @@ namespace DiscImageChef.Decoders.Floppy position += 7; gaps = new MemoryStream(); + // Read gap, if any - while(position < data.Length && data[position] == 0xFF) + while(position < data.Length && + data[position] == 0xFF) { gaps.WriteByte(data[position]); position++; @@ -329,26 +256,35 @@ namespace DiscImageChef.Decoders.Floppy } sector.gap = gaps.ToArray(); + // Return current position to be able to read separate sectors endOffset = position; + return sector; } - if(data[position] == 0xFF) position++; + if(data[position] == 0xFF) + position++; + // Found data that is not sync or a prologue - else return null; + else + return null; } } - catch(IndexOutOfRangeException) { return null; } + catch(IndexOutOfRangeException) + { + return null; + } return null; } public static byte[] MarshalAddressField(RawAddressField addressField) { - if(addressField == null) return null; + if(addressField == null) + return null; - MemoryStream raw = new MemoryStream(); + var raw = new MemoryStream(); raw.Write(addressField.prologue, 0, addressField.prologue.Length); raw.WriteByte(addressField.track); raw.WriteByte(addressField.sector); @@ -361,22 +297,23 @@ namespace DiscImageChef.Decoders.Floppy public static byte[] MarshalSector(RawSector sector) { - if(sector == null) return null; + if(sector == null) + return null; - MemoryStream raw = new MemoryStream(); + var raw = new MemoryStream(); raw.Write(sector.addressField.prologue, 0, sector.addressField.prologue.Length); raw.WriteByte(sector.addressField.track); raw.WriteByte(sector.addressField.sector); raw.WriteByte(sector.addressField.side); raw.WriteByte((byte)sector.addressField.format); raw.WriteByte(sector.addressField.checksum); - raw.Write(sector.innerGap, 0, sector.innerGap.Length); + raw.Write(sector.innerGap, 0, sector.innerGap.Length); raw.Write(sector.dataField.prologue, 0, sector.dataField.prologue.Length); raw.WriteByte(sector.dataField.spare); - raw.Write(sector.dataField.data, 0, sector.dataField.data.Length); + raw.Write(sector.dataField.data, 0, sector.dataField.data.Length); raw.Write(sector.dataField.checksum, 0, sector.dataField.checksum.Length); raw.Write(sector.dataField.epilogue, 0, sector.dataField.epilogue.Length); - raw.Write(sector.gap, 0, sector.gap.Length); + raw.Write(sector.gap, 0, sector.gap.Length); return raw.ToArray(); } @@ -388,14 +325,15 @@ namespace DiscImageChef.Decoders.Floppy int position = offset; bool firstSector = true; bool onSync = false; - MemoryStream gaps = new MemoryStream(); + var gaps = new MemoryStream(); int count = 0; List sectors = new List(); byte trackNumber = 0; byte sideNumber = 0; endOffset = offset; - while(position < data.Length && data[position] == 0xFF) + while(position < data.Length && + data[position] == 0xFF) { gaps.WriteByte(data[position]); count++; @@ -403,15 +341,19 @@ namespace DiscImageChef.Decoders.Floppy onSync = count >= 5; } - if(position >= data.Length) return null; + if(position >= data.Length) + return null; - if(!onSync) return null; + if(!onSync) + return null; while(position < data.Length) { int oldPosition = position; RawSector sector = MarshalSector(data, out position, position); - if(sector == null) break; + + if(sector == null) + break; if(firstSector) { @@ -420,29 +362,40 @@ namespace DiscImageChef.Decoders.Floppy firstSector = false; } - if(sector.addressField.track != trackNumber || sector.addressField.side != sideNumber) + if(sector.addressField.track != trackNumber || + sector.addressField.side != sideNumber) { position = oldPosition; + break; } sectors.Add(sector); } - if(sectors.Count == 0) return null; + if(sectors.Count == 0) + return null; + + var track = new RawTrack + { + gap = gaps.ToArray(), sectors = sectors.ToArray() + }; - RawTrack track = new RawTrack {gap = gaps.ToArray(), sectors = sectors.ToArray()}; endOffset = position; + return track; } public static byte[] MarshalTrack(RawTrack track) { - if(track == null) return null; + if(track == null) + return null; - MemoryStream raw = new MemoryStream(); + var raw = new MemoryStream(); raw.Write(track.gap, 0, track.gap.Length); - foreach(byte[] rawSector in track.sectors.Select(MarshalSector)) raw.Write(rawSector, 0, rawSector.Length); + + foreach(byte[] rawSector in track.sectors.Select(MarshalSector)) + raw.Write(rawSector, 0, rawSector.Length); return raw.ToArray(); } @@ -456,15 +409,18 @@ namespace DiscImageChef.Decoders.Floppy int position = offset; RawTrack track = MarshalTrack(data, out position, position); + while(track != null) { tracks.Add(track); track = MarshalTrack(data, out position, position); } - if(tracks.Count == 0) return null; + if(tracks.Count == 0) + return null; endOffset = position; + return tracks; } @@ -472,10 +428,13 @@ namespace DiscImageChef.Decoders.Floppy public static byte[] MarshalDisk(RawTrack[] disk) { - if(disk == null) return null; + if(disk == null) + return null; - MemoryStream raw = new MemoryStream(); - foreach(byte[] rawTrack in disk.Select(MarshalTrack)) raw.Write(rawTrack, 0, rawTrack.Length); + var raw = new MemoryStream(); + + foreach(byte[] rawTrack in disk.Select(MarshalTrack)) + raw.Write(rawTrack, 0, rawTrack.Length); return raw.ToArray(); } @@ -486,5 +445,66 @@ namespace DiscImageChef.Decoders.Floppy return sector != null && position != 0; } + + /// GCR-encoded Apple Sony GCR floppy track + public class RawTrack + { + /// Track preamble, set to self-sync 0xFF, 36 bytes + public byte[] gap; + public RawSector[] sectors; + } + + /// GCR-encoded Apple Sony GCR floppy sector + public class RawSector + { + /// Address field + public RawAddressField addressField; + /// Data field + public RawDataField dataField; + /// Track preamble, set to self-sync 0xFF, unknown size + public byte[] gap; + /// Track preamble, set to self-sync 0xFF, 6 bytes + public byte[] innerGap; + } + + /// GCR-encoded Apple Sony GCR floppy sector address field + public class RawAddressField + { + /// Checksum + public byte checksum; + /// Always 0xDE, 0xAA + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public byte[] epilogue; + /// Disk format + public AppleEncodedFormat format; + /// Always 0xD5, 0xAA, 0x96 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public byte[] prologue; + /// Encoded sector number + public byte sector; + /// Encoded side number + public byte side; + /// Encoded (decodedTrack & 0x3F) + public byte track; + } + + /// GCR-encoded Apple ][ GCR floppy sector data field + public class RawDataField + { + /// Checksum + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public byte[] checksum; + /// Encoded data bytes. + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 698)] + public byte[] data; + /// Always 0xDE, 0xAA + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public byte[] epilogue; + /// Always 0xD5, 0xAA, 0xAD + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public byte[] prologue; + /// Spare, usually + public byte spare; + } } } \ No newline at end of file diff --git a/Floppy/Commodore.cs b/Floppy/Commodore.cs index a6f5faa..ee08454 100644 --- a/Floppy/Commodore.cs +++ b/Floppy/Commodore.cs @@ -35,66 +35,39 @@ using System.Runtime.InteropServices; namespace DiscImageChef.Decoders.Floppy { - /// - /// Methods and structures for Commodore GCR floppy decoding - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + /// Methods and structures for Commodore GCR floppy decoding + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static class Commodore { - /// - /// Decoded Commodore GCR sector header - /// + /// Decoded Commodore GCR sector header public struct SectorHeader { - /// - /// Always 0x08 - /// + /// Always 0x08 public byte id; - /// - /// XOR of following fields - /// + /// XOR of following fields public byte checksum; - /// - /// Sector number - /// + /// Sector number public byte sector; - /// - /// Track number - /// + /// Track number public byte track; - /// - /// Format ID, unknown meaning - /// + /// Format ID, unknown meaning public ushort format; - /// - /// Filled with 0x0F - /// + /// Filled with 0x0F public ushort fill; } - /// - /// Decoded Commodore GCR sector data - /// + /// Decoded Commodore GCR sector data public struct SectorData { - /// - /// Always 0x07 - /// + /// Always 0x07 public byte id; - /// - /// User data - /// + /// User data [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)] public byte data; - /// - /// XOR of - /// + /// XOR of public byte checksum; - /// - /// Filled with 0x0F - /// + /// Filled with 0x0F public ushort fill; } } diff --git a/Floppy/Enums.cs b/Floppy/Enums.cs index efb3326..6c3d2f8 100644 --- a/Floppy/Enums.cs +++ b/Floppy/Enums.cs @@ -34,73 +34,35 @@ using System.Diagnostics.CodeAnalysis; namespace DiscImageChef.Decoders.Floppy { - /// - /// In-sector code for sector size - /// + /// In-sector code for sector size [SuppressMessage("ReSharper", "InconsistentNaming")] public enum IBMSectorSizeCode : byte { - /// - /// 128 bytes/sector - /// - EighthKilo = 0, - /// - /// 256 bytes/sector - /// - QuarterKilo = 1, - /// - /// 512 bytes/sector - /// - HalfKilo = 2, - /// - /// 1024 bytes/sector - /// - Kilo = 3, - /// - /// 2048 bytes/sector - /// - TwiceKilo = 4, - /// - /// 4096 bytes/sector - /// - FriceKilo = 5, - /// - /// 8192 bytes/sector - /// - TwiceFriceKilo = 6, - /// - /// 16384 bytes/sector - /// + /// 128 bytes/sector + EighthKilo = 0, /// 256 bytes/sector + QuarterKilo = 1, /// 512 bytes/sector + HalfKilo = 2, /// 1024 bytes/sector + Kilo = 3, /// 2048 bytes/sector + TwiceKilo = 4, /// 4096 bytes/sector + FriceKilo = 5, /// 8192 bytes/sector + TwiceFriceKilo = 6, /// 16384 bytes/sector FricelyFriceKilo = 7 } [SuppressMessage("ReSharper", "InconsistentNaming")] public enum IBMIdType : byte { - IndexMark = 0xFC, - AddressMark = 0xFE, - DataMark = 0xFB, + IndexMark = 0xFC, AddressMark = 0xFE, DataMark = 0xFB, DeletedDataMark = 0xF8 } [SuppressMessage("ReSharper", "InconsistentNaming")] public enum AppleEncodedFormat : byte { - /// - /// Disk is an Apple II 3.5" disk - /// - AppleII = 0x96, - /// - /// Disk is an Apple Lisa 3.5" disk - /// - Lisa = 0x97, - /// - /// Disk is an Apple Macintosh single-sided 3.5" disk - /// - MacSingleSide = 0x9A, - /// - /// Disk is an Apple Macintosh double-sided 3.5" disk - /// + /// Disk is an Apple II 3.5" disk + AppleII = 0x96, /// Disk is an Apple Lisa 3.5" disk + Lisa = 0x97, /// Disk is an Apple Macintosh single-sided 3.5" disk + MacSingleSide = 0x9A, /// Disk is an Apple Macintosh double-sided 3.5" disk MacDoubleSide = 0xD9 } } \ No newline at end of file diff --git a/Floppy/ISO.cs b/Floppy/ISO.cs index 9e6caef..d311ec2 100644 --- a/Floppy/ISO.cs +++ b/Floppy/ISO.cs @@ -45,125 +45,76 @@ namespace DiscImageChef.Decoders.Floppy // ECMA-147 // ECMA-100 - /// - /// Methods and structures for ISO floppy decoding (also used by Atari ST and others) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + /// Methods and structures for ISO floppy decoding (also used by Atari ST and others) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static class ISO { - /// - /// ISO floppy track, also used by Atari ST and others - /// + /// ISO floppy track, also used by Atari ST and others public struct Track { - /// - /// Start of track, 32 bytes set to 0x4E - /// + /// Start of track, 32 bytes set to 0x4E [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public byte[] innerGap; - /// - /// Track sectors - /// + /// Track sectors public Sector[] sectors; - /// - /// Undefined size - /// + /// Undefined size public byte[] gap; } - /// - /// Raw demodulated format for IBM System 34 floppies - /// + /// Raw demodulated format for IBM System 34 floppies public struct Sector { - /// - /// Sector address mark - /// + /// Sector address mark public AddressMark addressMark; - /// - /// 22 bytes set to 0x4E, set to 0x22 on Commodore 1581 - /// + /// 22 bytes set to 0x4E, set to 0x22 on Commodore 1581 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 22)] public byte[] innerGap; - /// - /// Sector data block - /// + /// Sector data block public DataBlock dataBlock; - /// - /// Variable bytes set to 0x4E, ECMA defines 54 - /// + /// Variable bytes set to 0x4E, ECMA defines 54 public byte[] outerGap; } - /// - /// Sector address mark for IBM System 34 floppies, contains sync word - /// + /// Sector address mark for IBM System 34 floppies, contains sync word public struct AddressMark { - /// - /// 12 bytes set to 0 - /// + /// 12 bytes set to 0 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] public byte[] zero; - /// - /// 3 bytes set to 0xA1 - /// + /// 3 bytes set to 0xA1 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] aone; - /// - /// Set to - /// + /// Set to public IBMIdType type; - /// - /// Track number - /// + /// Track number public byte track; - /// - /// Side number - /// + /// Side number public byte side; - /// - /// Sector number - /// + /// Sector number public byte sector; /// /// /// public IBMSectorSizeCode sectorSize; - /// - /// CRC16 from to end of - /// + /// CRC16 from to end of public ushort crc; } - /// - /// Sector data block for IBM System 34 floppies - /// + /// Sector data block for IBM System 34 floppies public struct DataBlock { - /// - /// 12 bytes set to 0 - /// + /// 12 bytes set to 0 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] public byte[] zero; - /// - /// 3 bytes set to 0xA1 - /// + /// 3 bytes set to 0xA1 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] aone; - /// - /// Set to or to - /// + /// Set to or to public IBMIdType type; - /// - /// User data - /// + /// User data public byte[] data; - /// - /// CRC16 from to end of - /// + /// CRC16 from to end of public ushort crc; } } diff --git a/Floppy/Perpendicular.cs b/Floppy/Perpendicular.cs index 1ca02fe..baf2c43 100644 --- a/Floppy/Perpendicular.cs +++ b/Floppy/Perpendicular.cs @@ -45,156 +45,94 @@ namespace DiscImageChef.Decoders.Floppy // ECMA-147 // ECMA-100 - /// - /// Methods and structures for perpendicular MFM floppy decoding - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + /// Methods and structures for perpendicular MFM floppy decoding + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static class Perpendicular { - /// - /// Perpendicular floppy track - /// + /// Perpendicular floppy track public struct Track { - /// - /// Start of track - /// + /// Start of track public TrackPreamble trackStart; - /// - /// Track sectors - /// + /// Track sectors public Sector[] sectors; - /// - /// Undefined size - /// + /// Undefined size public byte[] gap; } - /// - /// Raw demodulated format for perpendicular floppies - /// + /// Raw demodulated format for perpendicular floppies public struct Sector { - /// - /// Sector address mark - /// + /// Sector address mark public AddressMark addressMark; - /// - /// 41 bytes set to 0x4E - /// + /// 41 bytes set to 0x4E [MarshalAs(UnmanagedType.ByValArray, SizeConst = 41)] public byte[] innerGap; - /// - /// Sector data block - /// + /// Sector data block public DataBlock dataBlock; - /// - /// Variable-sized inter-sector gap, ECMA defines 83 bytes - /// + /// Variable-sized inter-sector gap, ECMA defines 83 bytes public byte[] outerGap; } - /// - /// Start of IBM PC MFM floppy track - /// Used by IBM PC, Apple Macintosh (high-density only), and a lot others - /// + /// Start of IBM PC MFM floppy track Used by IBM PC, Apple Macintosh (high-density only), and a lot others public struct TrackPreamble { - /// - /// Gap from index pulse, 80 bytes set to 0x4E - /// + /// Gap from index pulse, 80 bytes set to 0x4E [MarshalAs(UnmanagedType.ByValArray, SizeConst = 80)] public byte[] gap; - /// - /// 12 bytes set to 0x00 - /// + /// 12 bytes set to 0x00 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] public byte[] zero; - /// - /// 3 bytes set to 0xC2 - /// + /// 3 bytes set to 0xC2 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] ctwo; - /// - /// Set to - /// + /// Set to public IBMIdType type; - /// - /// Gap until first sector, 50 bytes to 0x4E - /// + /// Gap until first sector, 50 bytes to 0x4E [MarshalAs(UnmanagedType.ByValArray, SizeConst = 50)] public byte[] gap1; } - /// - /// Sector address mark for IBM System 34 floppies, contains sync word - /// + /// Sector address mark for IBM System 34 floppies, contains sync word public struct AddressMark { - /// - /// 12 bytes set to 0 - /// + /// 12 bytes set to 0 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] public byte[] zero; - /// - /// 3 bytes set to 0xA1 - /// + /// 3 bytes set to 0xA1 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] aone; - /// - /// Set to - /// + /// Set to public IBMIdType type; - /// - /// Track number - /// + /// Track number public byte track; - /// - /// Side number - /// + /// Side number public byte side; - /// - /// Sector number - /// + /// Sector number public byte sector; /// /// /// public IBMSectorSizeCode sectorSize; - /// - /// CRC16 from to end of - /// + /// CRC16 from to end of public ushort crc; } - /// - /// Sector data block for IBM System 34 floppies - /// + /// Sector data block for IBM System 34 floppies public struct DataBlock { - /// - /// 12 bytes set to 0 - /// + /// 12 bytes set to 0 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] public byte[] zero; - /// - /// 3 bytes set to 0xA1 - /// + /// 3 bytes set to 0xA1 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] aone; - /// - /// Set to or to - /// + /// Set to or to public IBMIdType type; - /// - /// User data - /// + /// User data public byte[] data; - /// - /// CRC16 from to end of - /// + /// CRC16 from to end of public ushort crc; } } diff --git a/Floppy/System34.cs b/Floppy/System34.cs index bb8529a..21fbee4 100644 --- a/Floppy/System34.cs +++ b/Floppy/System34.cs @@ -45,157 +45,94 @@ namespace DiscImageChef.Decoders.Floppy // ECMA-147 // ECMA-100 - /// - /// Methods and structures for IBM System 34 floppy decoding - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + /// Methods and structures for IBM System 34 floppy decoding + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static class System34 { - /// - /// Track format for IBM System 34 floppy - /// Used by IBM PC, Apple Macintosh (high-density only), and a lot others - /// + /// Track format for IBM System 34 floppy Used by IBM PC, Apple Macintosh (high-density only), and a lot others public struct Track { - /// - /// Start of track - /// + /// Start of track public TrackPreamble trackStart; - /// - /// Track sectors - /// + /// Track sectors public Sector[] sectors; - /// - /// Undefined size - /// + /// Undefined size public byte[] gap; } - /// - /// Start of IBM PC MFM floppy track - /// Used by IBM PC, Apple Macintosh (high-density only), and a lot others - /// + /// Start of IBM PC MFM floppy track Used by IBM PC, Apple Macintosh (high-density only), and a lot others public struct TrackPreamble { - /// - /// Gap from index pulse, 80 bytes set to 0x4E - /// + /// Gap from index pulse, 80 bytes set to 0x4E [MarshalAs(UnmanagedType.ByValArray, SizeConst = 80)] public byte[] gap; - /// - /// 12 bytes set to 0x00 - /// + /// 12 bytes set to 0x00 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] public byte[] zero; - /// - /// 3 bytes set to 0xC2 - /// + /// 3 bytes set to 0xC2 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] ctwo; - /// - /// Set to - /// + /// Set to public IBMIdType type; - /// - /// Gap until first sector, 50 bytes to 0x4E - /// + /// Gap until first sector, 50 bytes to 0x4E [MarshalAs(UnmanagedType.ByValArray, SizeConst = 50)] public byte[] gap1; } - /// - /// Raw demodulated format for IBM System 34 floppies - /// + /// Raw demodulated format for IBM System 34 floppies public struct Sector { - /// - /// Sector address mark - /// + /// Sector address mark public AddressMark addressMark; - /// - /// 22 bytes set to 0x4E, set to 0x22 on Commodore 1581 - /// + /// 22 bytes set to 0x4E, set to 0x22 on Commodore 1581 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 22)] public byte[] innerGap; - /// - /// Sector data block - /// + /// Sector data block public DataBlock dataBlock; - /// - /// Variable bytes set to 0x4E, ECMA defines 54 - /// + /// Variable bytes set to 0x4E, ECMA defines 54 public byte[] outerGap; } - /// - /// Sector address mark for IBM System 34 floppies, contains sync word - /// + /// Sector address mark for IBM System 34 floppies, contains sync word public struct AddressMark { - /// - /// 12 bytes set to 0 - /// + /// 12 bytes set to 0 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] public byte[] zero; - /// - /// 3 bytes set to 0xA1 - /// + /// 3 bytes set to 0xA1 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] aone; - /// - /// Set to - /// + /// Set to public IBMIdType type; - /// - /// Track number - /// + /// Track number public byte track; - /// - /// Side number - /// + /// Side number public byte side; - /// - /// Sector number - /// + /// Sector number public byte sector; /// /// /// public IBMSectorSizeCode sectorSize; - /// - /// CRC16 from to end of - /// + /// CRC16 from to end of public ushort crc; } - /// - /// Sector data block for IBM System 34 floppies - /// + /// Sector data block for IBM System 34 floppies public struct DataBlock { - /// - /// 12 bytes set to 0 - /// + /// 12 bytes set to 0 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] public byte[] zero; - /// - /// 3 bytes set to 0xA1 - /// + /// 3 bytes set to 0xA1 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] aone; - /// - /// Set to or to - /// + /// Set to or to public IBMIdType type; - /// - /// User data - /// + /// User data public byte[] data; - /// - /// CRC16 from to end of - /// + /// CRC16 from to end of public ushort crc; } } diff --git a/Floppy/System3740.cs b/Floppy/System3740.cs index de719c6..a53fe2e 100644 --- a/Floppy/System3740.cs +++ b/Floppy/System3740.cs @@ -45,140 +45,85 @@ namespace DiscImageChef.Decoders.Floppy // ECMA-147 // ECMA-100 - /// - /// Methods and structures for IBM System 3740 floppy decoding - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + /// Methods and structures for IBM System 3740 floppy decoding + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static class System3740 { - /// - /// Track format for IBM System 3740 floppy - /// + /// Track format for IBM System 3740 floppy public struct Track { - /// - /// Start of track - /// + /// Start of track public TrackPreamble trackStart; - /// - /// Track sectors - /// + /// Track sectors public Sector[] sectors; - /// - /// Undefined size - /// + /// Undefined size public byte[] gap; } - /// - /// Start of IBM PC FM floppy track - /// + /// Start of IBM PC FM floppy track public struct TrackPreamble { - /// - /// Gap from index pulse, 80 bytes set to 0xFF - /// + /// Gap from index pulse, 80 bytes set to 0xFF [MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)] public byte[] gap; - /// - /// 6 bytes set to 0x00 - /// + /// 6 bytes set to 0x00 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] public byte[] zero; - /// - /// Set to - /// + /// Set to public IBMIdType type; - /// - /// Gap until first sector, 26 bytes to 0xFF - /// + /// Gap until first sector, 26 bytes to 0xFF [MarshalAs(UnmanagedType.ByValArray, SizeConst = 26)] public byte[] gap1; } - /// - /// Raw demodulated format for IBM System 3740 floppies - /// + /// Raw demodulated format for IBM System 3740 floppies public struct Sector { - /// - /// Sector address mark - /// + /// Sector address mark public AddressMark addressMark; - /// - /// 11 bytes set to 0xFF - /// + /// 11 bytes set to 0xFF [MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] public byte[] innerGap; - /// - /// Sector data block - /// + /// Sector data block public DataBlock dataBlock; - /// - /// Variable bytes set to 0xFF - /// + /// Variable bytes set to 0xFF public byte[] outerGap; } - /// - /// Sector address mark for IBM System 3740 floppies, contains sync word - /// + /// Sector address mark for IBM System 3740 floppies, contains sync word public struct AddressMark { - /// - /// 6 bytes set to 0 - /// + /// 6 bytes set to 0 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] public byte[] zero; - /// - /// Set to - /// + /// Set to public IBMIdType type; - /// - /// Track number - /// + /// Track number public byte track; - /// - /// Side number - /// + /// Side number public byte side; - /// - /// Sector number - /// + /// Sector number public byte sector; /// /// /// public IBMSectorSizeCode sectorSize; - /// - /// CRC16 from to end of - /// + /// CRC16 from to end of public ushort crc; } - /// - /// Sector data block for IBM System 3740 floppies - /// + /// Sector data block for IBM System 3740 floppies public struct DataBlock { - /// - /// 12 bytes set to 0 - /// + /// 12 bytes set to 0 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] public byte[] zero; - /// - /// Set to or to - /// + /// Set to or to public IBMIdType type; - /// - /// User data - /// + /// User data public byte[] data; - /// - /// CRC16 from to end of - /// + /// CRC16 from to end of public ushort crc; } } diff --git a/LisaTag.cs b/LisaTag.cs index 0ca471a..cd49ec4 100644 --- a/LisaTag.cs +++ b/LisaTag.cs @@ -35,352 +35,20 @@ using System.Diagnostics.CodeAnalysis; namespace DiscImageChef.Decoders { - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "MemberCanBeInternal"), SuppressMessage("ReSharper", "NotAccessedField.Global"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static class LisaTag { - /// - /// LisaOS tag as stored on Apple Profile and FileWare disks (20 bytes) - /// - public struct ProfileTag - { - /// 0x00, Lisa OS version number - public ushort Version; - /// 0x02 bits 7 to 6, kind of info in this block - public byte Kind; - /// 0x02 bits 5 to 0, reserved - public byte Reserved; - /// 0x03, disk volume number - public byte Volume; - /// 0x04, file ID - public short FileId; - /// - /// 0x06 bit 7, checksum valid? - /// - public bool ValidChk; - /// - /// 0x06 bits 6 to 0, used bytes in block - /// - public ushort UsedBytes; - /// - /// 0x08, 3 bytes, absolute page number - /// - public uint AbsPage; - /// - /// 0x0B, checksum of data - /// - public byte Checksum; - /// - /// 0x0C, relative page number - /// - public ushort RelPage; - /// - /// 0x0E, 3 bytes, next block, 0xFFFFFF if it's last block - /// - public uint NextBlock; - /// - /// 0x11, 3 bytes, previous block, 0xFFFFFF if it's first block - /// - public uint PrevBlock; - - /// On-memory value for easy first block search. - public bool IsFirst; - /// On-memory value for easy last block search. - public bool IsLast; - - /// - /// Converts this tag to Priam DataTower format - /// - public PriamTag ToPriam() => - new PriamTag - { - AbsPage = AbsPage, - Checksum = Checksum, - FileId = FileId, - IsFirst = IsFirst, - IsLast = IsLast, - Kind = Kind, - NextBlock = IsLast ? 0xFFFFFF : NextBlock & 0xFFFFFF, - PrevBlock = IsFirst ? 0xFFFFFF : PrevBlock & 0xFFFFFF, - RelPage = RelPage, - UsedBytes = UsedBytes, - ValidChk = ValidChk, - Version = Version, - Volume = Volume - }; - - /// - /// Converts this tag to Sony format - /// - public SonyTag ToSony() => - new SonyTag - { - FileId = FileId, - IsFirst = IsFirst, - IsLast = IsLast, - Kind = Kind, - NextBlock = (ushort)NextBlock, - PrevBlock = (ushort)PrevBlock, - RelPage = RelPage, - Version = Version, - Volume = Volume - }; - - /// - /// Gets a byte array representation of this tag - /// - public byte[] GetBytes() - { - byte[] tagBytes = new byte[20]; - - byte[] tmp = BigEndianBitConverter.GetBytes(Version); - Array.Copy(tmp, 0, tagBytes, 0, 2); - tagBytes[2] = (byte)(Kind << 6); - tagBytes[3] = Volume; - tmp = BigEndianBitConverter.GetBytes(FileId); - Array.Copy(tmp, 0, tagBytes, 4, 2); - tmp = BigEndianBitConverter.GetBytes((ushort)(UsedBytes & 0x7FFF)); - Array.Copy(tmp, 0, tagBytes, 6, 2); - if(ValidChk) tagBytes[6] += 0x80; - tmp = BigEndianBitConverter.GetBytes(AbsPage); - Array.Copy(tmp, 1, tagBytes, 8, 3); - tagBytes[11] = Checksum; - tmp = BigEndianBitConverter.GetBytes(RelPage); - Array.Copy(tmp, 0, tagBytes, 12, 2); - tmp = BigEndianBitConverter.GetBytes(IsLast ? 0xFFFFFF : NextBlock); - Array.Copy(tmp, 1, tagBytes, 14, 3); - tmp = BigEndianBitConverter.GetBytes(IsFirst ? 0xFFFFFF : PrevBlock); - Array.Copy(tmp, 1, tagBytes, 17, 3); - - return tagBytes; - } - } - - /// - /// LisaOS tag as stored on Priam DataTower disks (24 bytes) - /// - public struct PriamTag - { - /// 0x00, Lisa OS version number - public ushort Version; - /// 0x02 bits 7 to 6, kind of info in this block - public byte Kind; - /// 0x02 bits 5 to 0, reserved - public byte Reserved; - /// 0x03, disk volume number - public byte Volume; - /// 0x04, file ID - public short FileId; - /// - /// 0x06 bit 7, checksum valid? - /// - public bool ValidChk; - /// - /// 0x06 bits 6 to 0, used bytes in block - /// - public ushort UsedBytes; - /// - /// 0x08, 3 bytes, absolute page number - /// - public uint AbsPage; - /// - /// 0x0B, checksum of data - /// - public byte Checksum; - /// - /// 0x0C, relative page number - /// - public ushort RelPage; - /// - /// 0x0E, 3 bytes, next block, 0xFFFFFF if it's last block - /// - public uint NextBlock; - /// - /// 0x11, 3 bytes, previous block, 0xFFFFFF if it's first block - /// - public uint PrevBlock; - /// - /// 0x14, disk size - /// - public uint DiskSize; - - /// On-memory value for easy first block search. - public bool IsFirst; - /// On-memory value for easy last block search. - public bool IsLast; - - /// - /// Converts this tag to Apple Profile format - /// - public ProfileTag ToProfile() => - new ProfileTag - { - AbsPage = AbsPage, - Checksum = Checksum, - FileId = FileId, - IsFirst = IsFirst, - IsLast = IsLast, - Kind = Kind, - NextBlock = IsLast ? 0xFFFFFF : NextBlock & 0xFFFFFF, - PrevBlock = IsFirst ? 0xFFFFFF : PrevBlock & 0xFFFFFF, - RelPage = RelPage, - UsedBytes = UsedBytes, - ValidChk = ValidChk, - Version = Version, - Volume = Volume - }; - - /// - /// Converts this tag to Sony format - /// - public SonyTag ToSony() => - new SonyTag - { - FileId = FileId, - IsFirst = IsFirst, - IsLast = IsLast, - Kind = Kind, - NextBlock = (ushort)(IsLast ? 0x7FF : NextBlock & 0x7FF), - PrevBlock = (ushort)(IsFirst ? 0x7FF : PrevBlock & 0x7FF), - RelPage = RelPage, - Version = Version, - Volume = Volume - }; - - /// - /// Gets a byte array representation of this tag - /// - public byte[] GetBytes() - { - byte[] tagBytes = new byte[24]; - - byte[] tmp = BigEndianBitConverter.GetBytes(Version); - Array.Copy(tmp, 0, tagBytes, 0, 2); - tagBytes[2] = (byte)(Kind << 6); - tagBytes[3] = Volume; - tmp = BigEndianBitConverter.GetBytes(FileId); - Array.Copy(tmp, 0, tagBytes, 4, 2); - tmp = BigEndianBitConverter.GetBytes((ushort)(UsedBytes & 0x7FFF)); - Array.Copy(tmp, 0, tagBytes, 6, 2); - if(ValidChk) tagBytes[6] += 0x80; - tmp = BigEndianBitConverter.GetBytes(AbsPage); - Array.Copy(tmp, 1, tagBytes, 8, 3); - tagBytes[11] = Checksum; - tmp = BigEndianBitConverter.GetBytes(RelPage); - Array.Copy(tmp, 0, tagBytes, 12, 2); - tmp = BigEndianBitConverter.GetBytes(IsLast ? 0xFFFFFF : NextBlock); - Array.Copy(tmp, 1, tagBytes, 14, 3); - tmp = BigEndianBitConverter.GetBytes(IsFirst ? 0xFFFFFF : PrevBlock); - Array.Copy(tmp, 1, tagBytes, 17, 3); - tmp = BigEndianBitConverter.GetBytes(DiskSize); - Array.Copy(tmp, 0, tagBytes, 20, 4); - - return tagBytes; - } - } - - /// - /// LisaOS tag as stored on Apple Sony disks (12 bytes) - /// - public struct SonyTag - { - /// 0x00, Lisa OS version number - public ushort Version; - /// 0x02 bits 7 to 6, kind of info in this block - public byte Kind; - /// 0x02 bits 5 to 0, reserved - public byte Reserved; - /// 0x03, disk volume number - public byte Volume; - /// 0x04, file ID - public short FileId; - /// - /// 0x06, relative page number - /// - public ushort RelPage; - /// - /// 0x08, 3 bytes, next block, 0x7FF if it's last block, 0x8000 set if block is valid - /// - public ushort NextBlock; - /// - /// 0x0A, 3 bytes, previous block, 0x7FF if it's first block - /// - public ushort PrevBlock; - - /// On-memory value for easy first block search. - public bool IsFirst; - /// On-memory value for easy last block search. - public bool IsLast; - - /// - /// Converts this tag to Apple Profile format - /// - public ProfileTag ToProfile() => - new ProfileTag - { - FileId = FileId, - IsFirst = IsFirst, - IsLast = IsLast, - Kind = Kind, - NextBlock = (uint)(IsLast ? 0xFFFFFF : NextBlock & 0xFFFFFF), - PrevBlock = (uint)(IsFirst ? 0xFFFFFF : PrevBlock & 0xFFFFFF), - RelPage = RelPage, - Version = Version, - Volume = Volume - }; - - /// - /// Converts this tag to Priam DataTower format - /// - public PriamTag ToPriam() => - new PriamTag - { - FileId = FileId, - IsFirst = IsFirst, - IsLast = IsLast, - Kind = Kind, - NextBlock = (uint)(IsLast ? 0xFFFFFF : NextBlock & 0xFFFFFF), - PrevBlock = (uint)(IsFirst ? 0xFFFFFF : PrevBlock & 0xFFFFFF), - RelPage = RelPage, - Version = Version, - Volume = Volume - }; - - /// - /// Gets a byte array representation of this tag - /// - public byte[] GetBytes() - { - byte[] tagBytes = new byte[12]; - - byte[] tmp = BigEndianBitConverter.GetBytes(Version); - Array.Copy(tmp, 0, tagBytes, 0, 2); - tagBytes[2] = (byte)(Kind << 6); - tagBytes[3] = Volume; - tmp = BigEndianBitConverter.GetBytes(FileId); - Array.Copy(tmp, 0, tagBytes, 4, 2); - tmp = BigEndianBitConverter.GetBytes(RelPage); - Array.Copy(tmp, 0, tagBytes, 6, 2); - tmp = BigEndianBitConverter.GetBytes(IsLast ? 0x7FF : NextBlock); - Array.Copy(tmp, 1, tagBytes, 8, 2); - tmp = BigEndianBitConverter.GetBytes(IsFirst ? 0x7FF : PrevBlock); - Array.Copy(tmp, 1, tagBytes, 10, 2); - - return tagBytes; - } - } - public static SonyTag? DecodeSonyTag(byte[] tag) { - if(tag == null || tag.Length != 12) return null; + if(tag == null || + tag.Length != 12) + return null; - SonyTag snTag = new SonyTag + var snTag = new SonyTag { - Version = BigEndianBitConverter.ToUInt16(tag, 0), - Kind = (byte)((tag[2] & 0xC0) >> 6), - Reserved = (byte)(tag[2] & 0x3F), - Volume = tag[3], + Version = BigEndianBitConverter.ToUInt16(tag, 0), Kind = (byte)((tag[2] & 0xC0) >> 6), + Reserved = (byte)(tag[2] & 0x3F), Volume = tag[3], FileId = BigEndianBitConverter.ToInt16(tag, 4), RelPage = BigEndianBitConverter.ToUInt16(tag, 6), NextBlock = (ushort)(BigEndianBitConverter.ToUInt16(tag, 8) & 0x7FF), @@ -395,9 +63,11 @@ namespace DiscImageChef.Decoders public static ProfileTag? DecodeProfileTag(byte[] tag) { - if(tag == null || tag.Length != 20) return null; + if(tag == null || + tag.Length != 20) + return null; - ProfileTag phTag = new ProfileTag(); + var phTag = new ProfileTag(); byte[] tmp = new byte[4]; @@ -438,9 +108,11 @@ namespace DiscImageChef.Decoders public static PriamTag? DecodePriamTag(byte[] tag) { - if(tag == null || tag.Length != 24) return null; + if(tag == null || + tag.Length != 24) + return null; - PriamTag pmTag = new PriamTag(); + var pmTag = new PriamTag(); byte[] tmp = new byte[4]; @@ -483,7 +155,8 @@ namespace DiscImageChef.Decoders public static PriamTag? DecodeTag(byte[] tag) { - if(tag == null) return null; + if(tag == null) + return null; PriamTag pmTag; @@ -492,7 +165,8 @@ namespace DiscImageChef.Decoders case 12: SonyTag? snTag = DecodeSonyTag(tag); - if(snTag == null) return null; + if(snTag == null) + return null; pmTag = new PriamTag(); pmTag.AbsPage = 0; @@ -515,7 +189,8 @@ namespace DiscImageChef.Decoders case 20: ProfileTag? phTag = DecodeProfileTag(tag); - if(phTag == null) return null; + if(phTag == null) + return null; pmTag = new PriamTag(); pmTag.AbsPage = phTag.Value.AbsPage; @@ -539,5 +214,243 @@ namespace DiscImageChef.Decoders default: return null; } } + + /// LisaOS tag as stored on Apple Profile and FileWare disks (20 bytes) + public struct ProfileTag + { + /// 0x00, Lisa OS version number + public ushort Version; + /// 0x02 bits 7 to 6, kind of info in this block + public byte Kind; + /// 0x02 bits 5 to 0, reserved + public byte Reserved; + /// 0x03, disk volume number + public byte Volume; + /// 0x04, file ID + public short FileId; + /// 0x06 bit 7, checksum valid? + public bool ValidChk; + /// 0x06 bits 6 to 0, used bytes in block + public ushort UsedBytes; + /// 0x08, 3 bytes, absolute page number + public uint AbsPage; + /// 0x0B, checksum of data + public byte Checksum; + /// 0x0C, relative page number + public ushort RelPage; + /// 0x0E, 3 bytes, next block, 0xFFFFFF if it's last block + public uint NextBlock; + /// 0x11, 3 bytes, previous block, 0xFFFFFF if it's first block + public uint PrevBlock; + + /// On-memory value for easy first block search. + public bool IsFirst; + /// On-memory value for easy last block search. + public bool IsLast; + + /// Converts this tag to Priam DataTower format + public PriamTag ToPriam() => new PriamTag + { + AbsPage = AbsPage, Checksum = Checksum, FileId = FileId, IsFirst = IsFirst, + IsLast = IsLast, Kind = Kind, NextBlock = IsLast ? 0xFFFFFF : NextBlock & 0xFFFFFF, + PrevBlock = IsFirst ? 0xFFFFFF : PrevBlock & 0xFFFFFF, + RelPage = RelPage, UsedBytes = UsedBytes, + ValidChk = ValidChk, + Version = Version, + Volume = Volume + }; + + /// Converts this tag to Sony format + public SonyTag ToSony() => new SonyTag + { + FileId = FileId, IsFirst = IsFirst, IsLast = IsLast, Kind = Kind, + NextBlock = (ushort)NextBlock, PrevBlock = (ushort)PrevBlock, RelPage = RelPage, Version = Version, + Volume = Volume + }; + + /// Gets a byte array representation of this tag + public byte[] GetBytes() + { + byte[] tagBytes = new byte[20]; + + byte[] tmp = BigEndianBitConverter.GetBytes(Version); + Array.Copy(tmp, 0, tagBytes, 0, 2); + tagBytes[2] = (byte)(Kind << 6); + tagBytes[3] = Volume; + tmp = BigEndianBitConverter.GetBytes(FileId); + Array.Copy(tmp, 0, tagBytes, 4, 2); + tmp = BigEndianBitConverter.GetBytes((ushort)(UsedBytes & 0x7FFF)); + Array.Copy(tmp, 0, tagBytes, 6, 2); + + if(ValidChk) + tagBytes[6] += 0x80; + + tmp = BigEndianBitConverter.GetBytes(AbsPage); + Array.Copy(tmp, 1, tagBytes, 8, 3); + tagBytes[11] = Checksum; + tmp = BigEndianBitConverter.GetBytes(RelPage); + Array.Copy(tmp, 0, tagBytes, 12, 2); + tmp = BigEndianBitConverter.GetBytes(IsLast ? 0xFFFFFF : NextBlock); + Array.Copy(tmp, 1, tagBytes, 14, 3); + tmp = BigEndianBitConverter.GetBytes(IsFirst ? 0xFFFFFF : PrevBlock); + Array.Copy(tmp, 1, tagBytes, 17, 3); + + return tagBytes; + } + } + + /// LisaOS tag as stored on Priam DataTower disks (24 bytes) + public struct PriamTag + { + /// 0x00, Lisa OS version number + public ushort Version; + /// 0x02 bits 7 to 6, kind of info in this block + public byte Kind; + /// 0x02 bits 5 to 0, reserved + public byte Reserved; + /// 0x03, disk volume number + public byte Volume; + /// 0x04, file ID + public short FileId; + /// 0x06 bit 7, checksum valid? + public bool ValidChk; + /// 0x06 bits 6 to 0, used bytes in block + public ushort UsedBytes; + /// 0x08, 3 bytes, absolute page number + public uint AbsPage; + /// 0x0B, checksum of data + public byte Checksum; + /// 0x0C, relative page number + public ushort RelPage; + /// 0x0E, 3 bytes, next block, 0xFFFFFF if it's last block + public uint NextBlock; + /// 0x11, 3 bytes, previous block, 0xFFFFFF if it's first block + public uint PrevBlock; + /// 0x14, disk size + public uint DiskSize; + + /// On-memory value for easy first block search. + public bool IsFirst; + /// On-memory value for easy last block search. + public bool IsLast; + + /// Converts this tag to Apple Profile format + public ProfileTag ToProfile() => new ProfileTag + { + AbsPage = AbsPage, Checksum = Checksum, FileId = FileId, IsFirst = IsFirst, + IsLast = IsLast, Kind = Kind, NextBlock = IsLast ? 0xFFFFFF : NextBlock & 0xFFFFFF, + PrevBlock = IsFirst ? 0xFFFFFF : PrevBlock & 0xFFFFFF, + RelPage = RelPage, UsedBytes = UsedBytes, + ValidChk = ValidChk, + Version = Version, + Volume = Volume + }; + + /// Converts this tag to Sony format + public SonyTag ToSony() => new SonyTag + { + FileId = FileId, IsFirst = IsFirst, IsLast = IsLast, Kind = Kind, + NextBlock = (ushort)(IsLast ? 0x7FF : NextBlock & 0x7FF), + PrevBlock = (ushort)(IsFirst ? 0x7FF : PrevBlock & 0x7FF), RelPage = RelPage, Version = Version, + Volume = Volume + }; + + /// Gets a byte array representation of this tag + public byte[] GetBytes() + { + byte[] tagBytes = new byte[24]; + + byte[] tmp = BigEndianBitConverter.GetBytes(Version); + Array.Copy(tmp, 0, tagBytes, 0, 2); + tagBytes[2] = (byte)(Kind << 6); + tagBytes[3] = Volume; + tmp = BigEndianBitConverter.GetBytes(FileId); + Array.Copy(tmp, 0, tagBytes, 4, 2); + tmp = BigEndianBitConverter.GetBytes((ushort)(UsedBytes & 0x7FFF)); + Array.Copy(tmp, 0, tagBytes, 6, 2); + + if(ValidChk) + tagBytes[6] += 0x80; + + tmp = BigEndianBitConverter.GetBytes(AbsPage); + Array.Copy(tmp, 1, tagBytes, 8, 3); + tagBytes[11] = Checksum; + tmp = BigEndianBitConverter.GetBytes(RelPage); + Array.Copy(tmp, 0, tagBytes, 12, 2); + tmp = BigEndianBitConverter.GetBytes(IsLast ? 0xFFFFFF : NextBlock); + Array.Copy(tmp, 1, tagBytes, 14, 3); + tmp = BigEndianBitConverter.GetBytes(IsFirst ? 0xFFFFFF : PrevBlock); + Array.Copy(tmp, 1, tagBytes, 17, 3); + tmp = BigEndianBitConverter.GetBytes(DiskSize); + Array.Copy(tmp, 0, tagBytes, 20, 4); + + return tagBytes; + } + } + + /// LisaOS tag as stored on Apple Sony disks (12 bytes) + public struct SonyTag + { + /// 0x00, Lisa OS version number + public ushort Version; + /// 0x02 bits 7 to 6, kind of info in this block + public byte Kind; + /// 0x02 bits 5 to 0, reserved + public byte Reserved; + /// 0x03, disk volume number + public byte Volume; + /// 0x04, file ID + public short FileId; + /// 0x06, relative page number + public ushort RelPage; + /// 0x08, 3 bytes, next block, 0x7FF if it's last block, 0x8000 set if block is valid + public ushort NextBlock; + /// 0x0A, 3 bytes, previous block, 0x7FF if it's first block + public ushort PrevBlock; + + /// On-memory value for easy first block search. + public bool IsFirst; + /// On-memory value for easy last block search. + public bool IsLast; + + /// Converts this tag to Apple Profile format + public ProfileTag ToProfile() => new ProfileTag + { + FileId = FileId, IsFirst = IsFirst, IsLast = IsLast, Kind = Kind, + NextBlock = (uint)(IsLast ? 0xFFFFFF : NextBlock & 0xFFFFFF), + PrevBlock = (uint)(IsFirst ? 0xFFFFFF : PrevBlock & 0xFFFFFF), RelPage = RelPage, Version = Version, + Volume = Volume + }; + + /// Converts this tag to Priam DataTower format + public PriamTag ToPriam() => new PriamTag + { + FileId = FileId, IsFirst = IsFirst, IsLast = IsLast, Kind = Kind, + NextBlock = (uint)(IsLast ? 0xFFFFFF : NextBlock & 0xFFFFFF), + PrevBlock = (uint)(IsFirst ? 0xFFFFFF : PrevBlock & 0xFFFFFF), RelPage = RelPage, Version = Version, + Volume = Volume + }; + + /// Gets a byte array representation of this tag + public byte[] GetBytes() + { + byte[] tagBytes = new byte[12]; + + byte[] tmp = BigEndianBitConverter.GetBytes(Version); + Array.Copy(tmp, 0, tagBytes, 0, 2); + tagBytes[2] = (byte)(Kind << 6); + tagBytes[3] = Volume; + tmp = BigEndianBitConverter.GetBytes(FileId); + Array.Copy(tmp, 0, tagBytes, 4, 2); + tmp = BigEndianBitConverter.GetBytes(RelPage); + Array.Copy(tmp, 0, tagBytes, 6, 2); + tmp = BigEndianBitConverter.GetBytes(IsLast ? 0x7FF : NextBlock); + Array.Copy(tmp, 1, tagBytes, 8, 2); + tmp = BigEndianBitConverter.GetBytes(IsFirst ? 0x7FF : PrevBlock); + Array.Copy(tmp, 1, tagBytes, 10, 2); + + return tagBytes; + } + } } } \ No newline at end of file diff --git a/MMC/CID.cs b/MMC/CID.cs index 6bea671..ebb69e7 100644 --- a/MMC/CID.cs +++ b/MMC/CID.cs @@ -36,30 +36,28 @@ using System.Text; namespace DiscImageChef.Decoders.MMC { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "UnassignedField.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "UnassignedField.Global")] public class CID { - public byte Manufacturer; - public byte DeviceType; public byte ApplicationID; + public byte CRC; + public byte DeviceType; + public byte Manufacturer; + public byte ManufacturingDate; public string ProductName; public byte ProductRevision; public uint ProductSerialNumber; - public byte ManufacturingDate; - public byte CRC; } - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Decoders { public static CID DecodeCID(uint[] response) { - if(response?.Length != 4) return null; + if(response?.Length != 4) + return null; byte[] data = new byte[16]; @@ -77,17 +75,17 @@ namespace DiscImageChef.Decoders.MMC public static CID DecodeCID(byte[] response) { - if(response?.Length != 16) return null; + if(response?.Length != 16) + return null; - CID cid = new CID + var cid = new CID { Manufacturer = response[0], - DeviceType = (byte)(response[1] & 0x03), - ProductRevision = response[9], - ProductSerialNumber = BitConverter.ToUInt32(response, 10), - ManufacturingDate = response[14], + DeviceType = (byte)(response[1] & 0x03), ProductRevision = response[9], + ProductSerialNumber = BitConverter.ToUInt32(response, 10), ManufacturingDate = response[14], CRC = (byte)((response[15] & 0xFE) >> 1) }; + byte[] tmp = new byte[6]; Array.Copy(response, 3, tmp, 0, 6); cid.ProductName = StringHandlers.CToString(tmp); @@ -97,85 +95,110 @@ namespace DiscImageChef.Decoders.MMC public static string PrettifyCID(CID cid) { - if(cid == null) return null; + if(cid == null) + return null; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendLine("MultiMediaCard Device Identification Register:"); sb.AppendFormat("\tManufacturer: {0}", VendorString.Prettify(cid.Manufacturer)).AppendLine(); + switch(cid.DeviceType) { case 0: sb.AppendLine("\tRemovable device"); + break; case 1: sb.AppendLine("\tBGA device"); + break; case 2: sb.AppendLine("\tPOP device"); + break; } sb.AppendFormat("\tApplication ID: {0}", cid.ApplicationID).AppendLine(); sb.AppendFormat("\tProduct name: {0}", cid.ProductName).AppendLine(); + sb.AppendFormat("\tProduct revision: {0:X2}.{1:X2}", (cid.ProductRevision & 0xF0) >> 4, cid.ProductRevision & 0x0F).AppendLine(); + sb.AppendFormat("\tProduct serial number: {0}", cid.ProductSerialNumber).AppendLine(); string year = ""; + switch(cid.ManufacturingDate & 0x0F) { case 0: year = "1997 or 2013"; + break; case 1: year = "1998 or 2014"; + break; case 2: year = "1999 or 2015"; + break; case 3: year = "2000 or 2016"; + break; case 4: year = "2001 or 2017"; + break; case 5: year = "2002 or 2018"; + break; case 6: year = "2003 or 2019"; + break; case 7: year = "2004 or 2020"; + break; case 8: year = "2005 or 2021"; + break; case 9: year = "2006 or 2022"; + break; case 10: year = "2007 or 2023"; + break; case 11: year = "2008 or 2024"; + break; case 12: year = "2009 or 2025"; + break; case 13: year = "2010"; + break; case 14: year = "2011"; + break; case 15: year = "2012"; + break; } - sb.AppendFormat("\tDevice manufactured month {0} of {1}", (cid.ManufacturingDate & 0xF0) >> 4, year) - .AppendLine(); + sb.AppendFormat("\tDevice manufactured month {0} of {1}", (cid.ManufacturingDate & 0xF0) >> 4, year). + AppendLine(); + sb.AppendFormat("\tCID CRC: 0x{0:X2}", cid.CRC).AppendLine(); return sb.ToString(); diff --git a/MMC/CSD.cs b/MMC/CSD.cs index 2469902..1bcbe2c 100644 --- a/MMC/CSD.cs +++ b/MMC/CSD.cs @@ -36,55 +36,53 @@ using System.Text; namespace DiscImageChef.Decoders.MMC { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] public class CSD { - public byte Structure; - public byte Version; - public byte TAAC; - public byte NSAC; - public byte Speed; public ushort Classes; - public byte ReadBlockLength; - public bool ReadsPartialBlocks; - public bool WriteMisalignment; - public bool ReadMisalignment; + public bool ContentProtection; + public bool Copy; + public byte CRC; + public byte DefaultECC; public bool DSRImplemented; - public ushort Size; - public byte ReadCurrentAtVddMin; - public byte ReadCurrentAtVddMax; - public byte WriteCurrentAtVddMin; - public byte WriteCurrentAtVddMax; - public byte SizeMultiplier; + public byte ECC; public byte EraseGroupSize; public byte EraseGroupSizeMultiplier; - public byte WriteProtectGroupSize; - public bool WriteProtectGroupEnable; - public byte DefaultECC; - public byte WriteSpeedFactor; - public byte WriteBlockLength; - public bool WritesPartialBlocks; - public bool ContentProtection; - public bool FileFormatGroup; - public bool Copy; - public bool PermanentWriteProtect; - public bool TemporaryWriteProtect; public byte FileFormat; - public byte ECC; - public byte CRC; + public bool FileFormatGroup; + public byte NSAC; + public bool PermanentWriteProtect; + public byte ReadBlockLength; + public byte ReadCurrentAtVddMax; + public byte ReadCurrentAtVddMin; + public bool ReadMisalignment; + public bool ReadsPartialBlocks; + public ushort Size; + public byte SizeMultiplier; + public byte Speed; + public byte Structure; + public byte TAAC; + public bool TemporaryWriteProtect; + public byte Version; + public byte WriteBlockLength; + public byte WriteCurrentAtVddMax; + public byte WriteCurrentAtVddMin; + public bool WriteMisalignment; + public bool WriteProtectGroupEnable; + public byte WriteProtectGroupSize; + public bool WritesPartialBlocks; + public byte WriteSpeedFactor; } - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Decoders { public static CSD DecodeCSD(uint[] response) { - if(response?.Length != 4) return null; + if(response?.Length != 4) + return null; byte[] data = new byte[16]; @@ -102,21 +100,23 @@ namespace DiscImageChef.Decoders.MMC public static CSD DecodeCSD(byte[] response) { - if(response?.Length != 16) return null; + if(response?.Length != 16) + return null; return new CSD { Structure = (byte)((response[0] & 0xC0) >> 6), Version = (byte)((response[0] & 0x3C) >> 2), - TAAC = response[1], - NSAC = response[2], + TAAC = response[1], NSAC = response[2], Speed = response[3], Classes = (ushort)((response[4] << 4) + ((response[5] & 0xF0) >> 4)), ReadBlockLength = (byte)(response[5] & 0x0F), ReadsPartialBlocks = (response[6] & 0x80) == 0x80, - WriteMisalignment = (response[6] & 0x40) == 0x40, - ReadMisalignment = (response[6] & 0x20) == 0x20, - DSRImplemented = (response[6] & 0x10) == 0x10, + WriteMisalignment = + (response[6] & 0x40) == 0x40, + ReadMisalignment = (response[6] & 0x20) == 0x20, + DSRImplemented = + (response[6] & 0x10) == 0x10, Size = (ushort)(((response[6] & 0x03) << 10) + (response[7] << 2) + ((response[8] & 0xC0) >> 6)), ReadCurrentAtVddMin = (byte)((response[8] & 0x38) >> 3), @@ -145,27 +145,33 @@ namespace DiscImageChef.Decoders.MMC public static string PrettifyCSD(CSD csd) { - if(csd == null) return null; + if(csd == null) + return null; double unitFactor = 0; double multiplier = 0; string unit = ""; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendLine("MultiMediaCard Device Specific Data Register:"); + switch(csd.Structure) { case 0: sb.AppendLine("\tRegister version 1.0"); + break; case 1: sb.AppendLine("\tRegister version 1.1"); + break; case 2: sb.AppendLine("\tRegister version 1.2"); + break; case 3: sb.AppendLine("\tRegister version is defined in Extended Device Specific Data Register"); + break; } @@ -174,34 +180,42 @@ namespace DiscImageChef.Decoders.MMC case 0: unit = "ns"; unitFactor = 1; + break; case 1: unit = "ns"; unitFactor = 10; + break; case 2: unit = "ns"; unitFactor = 100; + break; case 3: unit = "μs"; unitFactor = 1; + break; case 4: unit = "μs"; unitFactor = 10; + break; case 5: unit = "μs"; unitFactor = 100; + break; case 6: unit = "ms"; unitFactor = 1; + break; case 7: unit = "ms"; unitFactor = 10; + break; } @@ -209,51 +223,67 @@ namespace DiscImageChef.Decoders.MMC { case 0: multiplier = 0; + break; case 1: multiplier = 1; + break; case 2: multiplier = 1.2; + break; case 3: multiplier = 1.3; + break; case 4: multiplier = 1.5; + break; case 5: multiplier = 2; + break; case 6: multiplier = 2.5; + break; case 7: multiplier = 3; + break; case 8: multiplier = 3.5; + break; case 9: multiplier = 4; + break; case 10: multiplier = 4.5; + break; case 11: multiplier = 5; + break; case 12: multiplier = 5.5; + break; case 13: multiplier = 6; + break; case 14: multiplier = 7; + break; case 15: multiplier = 8; + break; } @@ -263,23 +293,29 @@ namespace DiscImageChef.Decoders.MMC sb.AppendFormat("\tClock dependent part of data access is {0} clock cycles", csd.NSAC * 100).AppendLine(); unit = "MHz"; + switch(csd.Speed & 0x07) { case 0: unitFactor = 0.1; + break; case 1: unitFactor = 1; + break; case 2: unitFactor = 10; + break; case 3: unitFactor = 100; + break; default: unit = "unknown"; unitFactor = 0; + break; } @@ -287,51 +323,67 @@ namespace DiscImageChef.Decoders.MMC { case 0: multiplier = 0; + break; case 1: multiplier = 1; + break; case 2: multiplier = 1.2; + break; case 3: multiplier = 1.3; + break; case 4: multiplier = 1.5; + break; case 5: multiplier = 2; + break; case 6: multiplier = 2.6; + break; case 7: multiplier = 3; + break; case 8: multiplier = 3.5; + break; case 9: multiplier = 4; + break; case 10: multiplier = 4.5; + break; case 11: multiplier = 5.2; + break; case 12: multiplier = 5.5; + break; case 13: multiplier = 6; + break; case 14: multiplier = 7; + break; case 15: multiplier = 8; + break; } @@ -339,20 +391,29 @@ namespace DiscImageChef.Decoders.MMC sb.AppendFormat("\tDevice's clock frequency: {0}{1}", result, unit).AppendLine(); unit = ""; + for(int cl = 0, mask = 1; cl <= 11; cl++, mask <<= 1) if((csd.Classes & mask) == mask) unit += $" {cl}"; sb.AppendFormat("\tDevice support command classes {0}", unit).AppendLine(); - if(csd.ReadBlockLength == 15) sb.AppendLine("\tRead block length size is defined in extended CSD"); - else sb.AppendFormat("\tRead block length is {0} bytes", Math.Pow(2, csd.ReadBlockLength)).AppendLine(); - if(csd.ReadsPartialBlocks) sb.AppendLine("\tDevice allows reading partial blocks"); + if(csd.ReadBlockLength == 15) + sb.AppendLine("\tRead block length size is defined in extended CSD"); + else + sb.AppendFormat("\tRead block length is {0} bytes", Math.Pow(2, csd.ReadBlockLength)).AppendLine(); - if(csd.WriteMisalignment) sb.AppendLine("\tWrite commands can cross physical block boundaries"); - if(csd.ReadMisalignment) sb.AppendLine("\tRead commands can cross physical block boundaries"); + if(csd.ReadsPartialBlocks) + sb.AppendLine("\tDevice allows reading partial blocks"); - if(csd.DSRImplemented) sb.AppendLine("\tDevice implements configurable driver stage"); + if(csd.WriteMisalignment) + sb.AppendLine("\tWrite commands can cross physical block boundaries"); + + if(csd.ReadMisalignment) + sb.AppendLine("\tRead commands can cross physical block boundaries"); + + if(csd.DSRImplemented) + sb.AppendLine("\tDevice implements configurable driver stage"); if(csd.Size == 0xFFF) sb.AppendLine("\tDevice may be bigger than 2GiB and have its real size defined in the extended CSD"); @@ -361,36 +422,49 @@ namespace DiscImageChef.Decoders.MMC sb.AppendFormat("\tDevice has {0} blocks", (int)result).AppendLine(); result = (csd.Size + 1) * Math.Pow(2, csd.SizeMultiplier + 2) * Math.Pow(2, csd.ReadBlockLength); - if(result > 1073741824) sb.AppendFormat("\tDevice has {0} GiB", result / 1073741824.0).AppendLine(); - else if(result > 1048576) sb.AppendFormat("\tDevice has {0} MiB", result / 1048576.0).AppendLine(); - else if(result > 1024) sb.AppendFormat("\tDevice has {0} KiB", result / 1024.0).AppendLine(); - else sb.AppendFormat("\tDevice has {0} bytes", result).AppendLine(); + + if(result > 1073741824) + sb.AppendFormat("\tDevice has {0} GiB", result / 1073741824.0).AppendLine(); + else if(result > 1048576) + sb.AppendFormat("\tDevice has {0} MiB", result / 1048576.0).AppendLine(); + else if(result > 1024) + sb.AppendFormat("\tDevice has {0} KiB", result / 1024.0).AppendLine(); + else + sb.AppendFormat("\tDevice has {0} bytes", result).AppendLine(); switch(csd.ReadCurrentAtVddMin & 0x07) { case 0: sb.AppendLine("\tDevice uses a maximum of 0.5mA for reading at minimum voltage"); + break; case 1: sb.AppendLine("\tDevice uses a maximum of 1mA for reading at minimum voltage"); + break; case 2: sb.AppendLine("\tDevice uses a maximum of 5mA for reading at minimum voltage"); + break; case 3: sb.AppendLine("\tDevice uses a maximum of 10mA for reading at minimum voltage"); + break; case 4: sb.AppendLine("\tDevice uses a maximum of 25mA for reading at minimum voltage"); + break; case 5: sb.AppendLine("\tDevice uses a maximum of 35mA for reading at minimum voltage"); + break; case 6: sb.AppendLine("\tDevice uses a maximum of 60mA for reading at minimum voltage"); + break; case 7: sb.AppendLine("\tDevice uses a maximum of 100mA for reading at minimum voltage"); + break; } @@ -398,27 +472,35 @@ namespace DiscImageChef.Decoders.MMC { case 0: sb.AppendLine("\tDevice uses a maximum of 1mA for reading at maximum voltage"); + break; case 1: sb.AppendLine("\tDevice uses a maximum of 5mA for reading at maximum voltage"); + break; case 2: sb.AppendLine("\tDevice uses a maximum of 10mA for reading at maximum voltage"); + break; case 3: sb.AppendLine("\tDevice uses a maximum of 25mA for reading at maximum voltage"); + break; case 4: sb.AppendLine("\tDevice uses a maximum of 35mA for reading at maximum voltage"); + break; case 5: sb.AppendLine("\tDevice uses a maximum of 45mA for reading at maximum voltage"); + break; case 6: sb.AppendLine("\tDevice uses a maximum of 80mA for reading at maximum voltage"); + break; case 7: sb.AppendLine("\tDevice uses a maximum of 200mA for reading at maximum voltage"); + break; } @@ -426,27 +508,35 @@ namespace DiscImageChef.Decoders.MMC { case 0: sb.AppendLine("\tDevice uses a maximum of 0.5mA for writing at minimum voltage"); + break; case 1: sb.AppendLine("\tDevice uses a maximum of 1mA for writing at minimum voltage"); + break; case 2: sb.AppendLine("\tDevice uses a maximum of 5mA for writing at minimum voltage"); + break; case 3: sb.AppendLine("\tDevice uses a maximum of 10mA for writing at minimum voltage"); + break; case 4: sb.AppendLine("\tDevice uses a maximum of 25mA for writing at minimum voltage"); + break; case 5: sb.AppendLine("\tDevice uses a maximum of 35mA for writing at minimum voltage"); + break; case 6: sb.AppendLine("\tDevice uses a maximum of 60mA for writing at minimum voltage"); + break; case 7: sb.AppendLine("\tDevice uses a maximum of 100mA for writing at minimum voltage"); + break; } @@ -454,27 +544,35 @@ namespace DiscImageChef.Decoders.MMC { case 0: sb.AppendLine("\tDevice uses a maximum of 1mA for writing at maximum voltage"); + break; case 1: sb.AppendLine("\tDevice uses a maximum of 5mA for writing at maximum voltage"); + break; case 2: sb.AppendLine("\tDevice uses a maximum of 10mA for writing at maximum voltage"); + break; case 3: sb.AppendLine("\tDevice uses a maximum of 25mA for writing at maximum voltage"); + break; case 4: sb.AppendLine("\tDevice uses a maximum of 35mA for writing at maximum voltage"); + break; case 5: sb.AppendLine("\tDevice uses a maximum of 45mA for writing at maximum voltage"); + break; case 6: sb.AppendLine("\tDevice uses a maximum of 80mA for writing at maximum voltage"); + break; case 7: sb.AppendLine("\tDevice uses a maximum of 200mA for writing at maximum voltage"); + break; } @@ -487,72 +585,92 @@ namespace DiscImageChef.Decoders.MMC if(csd.WriteProtectGroupEnable) { sb.AppendLine("\tDevice can write protect regions"); + // TODO: Check specification unitFactor = Convert.ToDouble(csd.WriteProtectGroupSize); - sb.AppendFormat("\tDevice can write protect a minimum of {0} blocks at a time", (int)(result + 1)) - .AppendLine(); + + sb.AppendFormat("\tDevice can write protect a minimum of {0} blocks at a time", (int)(result + 1)). + AppendLine(); } - else sb.AppendLine("\tDevice can't write protect regions"); + else + sb.AppendLine("\tDevice can't write protect regions"); switch(csd.DefaultECC) { case 0: sb.AppendLine("\tDevice uses no ECC by default"); + break; case 1: sb.AppendLine("\tDevice uses BCH(542, 512) ECC by default"); + break; case 2: sb.AppendFormat("\tDevice uses unknown ECC code {0} by default", csd.DefaultECC).AppendLine(); + break; } - sb.AppendFormat("\tWriting is {0} times slower than reading", Math.Pow(2, csd.WriteSpeedFactor)) - .AppendLine(); + sb.AppendFormat("\tWriting is {0} times slower than reading", Math.Pow(2, csd.WriteSpeedFactor)). + AppendLine(); - if(csd.WriteBlockLength == 15) sb.AppendLine("\tWrite block length size is defined in extended CSD"); - else sb.AppendFormat("\tWrite block length is {0} bytes", Math.Pow(2, csd.WriteBlockLength)).AppendLine(); + if(csd.WriteBlockLength == 15) + sb.AppendLine("\tWrite block length size is defined in extended CSD"); + else + sb.AppendFormat("\tWrite block length is {0} bytes", Math.Pow(2, csd.WriteBlockLength)).AppendLine(); - if(csd.WritesPartialBlocks) sb.AppendLine("\tDevice allows writing partial blocks"); + if(csd.WritesPartialBlocks) + sb.AppendLine("\tDevice allows writing partial blocks"); - if(csd.ContentProtection) sb.AppendLine("\tDevice supports content protection"); + if(csd.ContentProtection) + sb.AppendLine("\tDevice supports content protection"); - if(!csd.Copy) sb.AppendLine("\tDevice contents are original"); + if(!csd.Copy) + sb.AppendLine("\tDevice contents are original"); - if(csd.PermanentWriteProtect) sb.AppendLine("\tDevice is permanently write protected"); + if(csd.PermanentWriteProtect) + sb.AppendLine("\tDevice is permanently write protected"); - if(csd.TemporaryWriteProtect) sb.AppendLine("\tDevice is temporarily write protected"); + if(csd.TemporaryWriteProtect) + sb.AppendLine("\tDevice is temporarily write protected"); if(!csd.FileFormatGroup) switch(csd.FileFormat) { case 0: sb.AppendLine("\tDevice is formatted like a hard disk"); + break; case 1: sb.AppendLine("\tDevice is formatted like a floppy disk using Microsoft FAT"); + break; case 2: sb.AppendLine("\tDevice uses Universal File Format"); + break; default: sb.AppendFormat("\tDevice uses unknown file format code {0}", csd.FileFormat).AppendLine(); + break; } else - sb.AppendFormat("\tDevice uses unknown file format code {0} and file format group 1", csd.FileFormat) - .AppendLine(); + sb.AppendFormat("\tDevice uses unknown file format code {0} and file format group 1", csd.FileFormat). + AppendLine(); switch(csd.ECC) { case 0: sb.AppendLine("\tDevice currently uses no ECC"); + break; case 1: sb.AppendLine("\tDevice currently uses BCH(542, 512) ECC by default"); + break; case 2: sb.AppendFormat("\tDevice currently uses unknown ECC code {0}", csd.DefaultECC).AppendLine(); + break; } diff --git a/MMC/ExtendedCSD.cs b/MMC/ExtendedCSD.cs index 574181d..2f9d92f 100644 --- a/MMC/ExtendedCSD.cs +++ b/MMC/ExtendedCSD.cs @@ -37,193 +37,192 @@ using System.Text; namespace DiscImageChef.Decoders.MMC { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "UnassignedField.Global")] - [StructLayout(LayoutKind.Sequential)] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "UnassignedField.Global"), + StructLayout(LayoutKind.Sequential)] public class ExtendedCSD { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] - public byte[] Reserved0; - public byte ExtendedSecurityCommandsError; - public byte SupportedCommandSets; - public byte HPIFeatures; + public byte AccessSize; + public byte AddressedGroupToBeReleased; + public byte BackgroundOperationsStatus; public byte BackgroundOperationsSupport; - public byte MaxPackedReadCommands; - public byte MaxPackedWriteCommands; - public byte DataTagSupport; - public byte TagUnitSize; - public byte TagResourcesSize; - public byte ContextManagementCaps; - public byte LargeUnitSize; - public byte ExtendedPartitionsSupport; - public byte SupportedModes; - public byte FFUFeatures; - public byte OperationCodesTimeout; - public uint FFUArgument; + public byte BadBlockManagementMode; + public byte BarrierControl; public byte BarrierSupport; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 177)] - public byte[] Reserved1; - public byte CMDQueuingSupport; + public byte BootAreaWriteProtectionRegister; + public byte BootBusConditions; + public byte BootConfigProtection; + public byte BootInformation; + public byte BootPartitionSize; + public byte BootWriteProtectionStatus; + public byte BusWidth; + public byte CacheControl; + public byte CacheFlushing; + public byte CacheFlushingPolicy; + public uint CacheSize; + public byte Class6CommandsControl; public byte CMDQueuingDepth; - public uint NumberofFWSectorsCorrectlyProgrammed; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] - public byte[] VendorHealthReport; - public byte DeviceLifeEstimationTypeB; - public byte DeviceLifeEstimationTypeA; - public byte PreEOLInformation; - public byte OptimalReadSize; - public byte OptimalWriteSize; - public byte OptimalTrimUnitSize; - public ushort DeviceVersion; - public ulong FirmwareVersion; - public byte PowerClassDDR200; - public uint CacheSize; - public byte GenericCMD6Timeout; - public byte PowerOffNotificationTimeout; - public byte BackgroundOperationsStatus; + public byte CMDQueuingSupport; + public byte CommandQueueModeEnable; + public byte CommandSet; + public byte CommandSetRevision; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 15)] + public byte[] ContextConfiguration; + public byte ContextManagementCaps; public uint CorrectlyProgrammedSectors; - public byte InitializationTimeAfterPartition; - public byte CacheFlushingPolicy; - public byte PowerClassDDR52; - public byte PowerClassDDR52_195; - public byte PowerClassDDR200_195; - public byte PowerClassDDR200_130; - public byte MinimumWritePerformanceDDR52; - public byte MinimumReadPerformanceDDR52; - public byte Reserved2; - public byte TRIMMultiplier; - public byte SecureFeatureSupport; - public byte SecureEraseMultiplier; - public byte SecureTRIMMultiplier; - public byte BootInformation; - public byte Reserved3; - public byte BootPartitionSize; - public byte AccessSize; - public byte HighCapacityEraseUnitSize; - public byte HighCapacityEraseTimeout; - public byte ReliableWriteSectorCount; - public byte HighCapacityWriteProtectGroupSize; - public byte SleepCurrentVcc; - public byte SleepCurrentVccq; - public byte ProductionStateAwarenessTimeout; - public byte SleepAwakeTimeout; - public byte SleepNotificationTimeout; - public uint SectorCount; - public byte SecureWriteProtectInformation; - public byte MinimumWritePerformance52; - public byte MinimumReadPerformance52; - public byte MinimumWritePerformance26; - public byte MinimumReadPerformance26; - public byte MinimumWritePerformance26_4; - public byte MinimumReadPerformance26_4; - public byte Reserved4; - public byte PowerClass26; - public byte PowerClass52; - public byte PowerClass26_195; - public byte PowerClass52_195; - public byte PartitionSwitchingTime; - public byte OutOfInterruptBusyTiming; - public byte DriverStrength; + public byte DataTagSupport; + public byte DeviceLifeEstimationTypeA; + public byte DeviceLifeEstimationTypeB; public byte DeviceType; - public byte Reserved5; - public byte Structure; - public byte Reserved6; - public byte Revision; - public byte CommandSet; - public byte Reserved7; - public byte CommandSetRevision; - public byte Reserved8; - public byte PowerClass; - public byte Reserved9; - public byte HighSpeedInterfaceTiming; - public byte StrobeSupport; - public byte BusWidth; - public byte Reserved10; - public byte ErasedMemoryContent; - public byte Reserved11; - public byte PartitionConfiguration; - public byte BootConfigProtection; - public byte BootBusConditions; - public byte Reserved12; - public byte HighDensityEraseGroupDefinition; - public byte BootWriteProtectionStatus; - public byte BootAreaWriteProtectionRegister; - public byte Reserved13; - public byte UserAreaWriteProtectionRegister; - public byte Reserved14; - public byte FirmwareConfiguration; - public byte RPMBSize; - public byte WriteReliabilitySettingRegister; - public byte WriteReliabilityParameterRegister; - public byte StartSanitizeOperation; - public byte ManuallyStartBackgroundOperations; + public ushort DeviceVersion; + public byte DriverStrength; public byte EnableBackgroundOperationsHandshake; - public byte HWResetFunction; - public byte HPIManagement; - public byte PartitioningSupport; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] - public byte[] MaxEnhancedAreaSize; - public byte PartitionsAttribute; - public byte PartitioningSetting; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] - public byte[] GeneralPurposePartitionSize; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] EnhancedUserDataAreaSize; public uint EnhancedUserDataStartAddress; - public byte Reserved15; - public byte BadBlockManagementMode; - public byte ProductionStateAwareness; - public byte PackageCaseTemperatureControl; - public byte PeriodicWakeUp; - public byte SupportsProgramCxDInDDR; - public ushort Reserved16; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] - public byte[] VendorSpecific; - public byte NativeSectorSize; - public byte SectorSizeEmulation; - public byte SectorSize; - public byte InitializationTimeout; - public byte Class6CommandsControl; - public byte AddressedGroupToBeReleased; + public byte ErasedMemoryContent; public ushort ExceptionEventsControl; public ushort ExceptionEventsStatus; public ushort ExtendedPartitionsAttribute; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 15)] - public byte[] ContextConfiguration; - public byte PackedCommandStatus; - public byte PackedCommandFailureIndex; - public byte PowerOffNotification; - public byte CacheControl; - public byte CacheFlushing; - public byte BarrierControl; - public byte ModeConfig; - public byte ModeOperationCodes; - public ushort Reserved17; + public byte ExtendedPartitionsSupport; + public byte ExtendedSecurityCommandsError; + public uint FFUArgument; + public byte FFUFeatures; public byte FFUStatus; - public uint PreLoadingDataSize; - public uint MaxPreLoadingDataSize; - public byte ProductStateAwarenessEnablement; - public byte SecureRemovalType; - public byte CommandQueueModeEnable; + public byte FirmwareConfiguration; + public ulong FirmwareVersion; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] + public byte[] GeneralPurposePartitionSize; + public byte GenericCMD6Timeout; + public byte HighCapacityEraseTimeout; + public byte HighCapacityEraseUnitSize; + public byte HighCapacityWriteProtectGroupSize; + public byte HighDensityEraseGroupDefinition; + public byte HighSpeedInterfaceTiming; + public byte HPIFeatures; + public byte HPIManagement; + public byte HWResetFunction; + public byte InitializationTimeAfterPartition; + public byte InitializationTimeout; + public byte LargeUnitSize; + public byte ManuallyStartBackgroundOperations; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public byte[] MaxEnhancedAreaSize; + public byte MaxPackedReadCommands; + public byte MaxPackedWriteCommands; + public uint MaxPreLoadingDataSize; + public byte MinimumReadPerformance26; + public byte MinimumReadPerformance26_4; + public byte MinimumReadPerformance52; + public byte MinimumReadPerformanceDDR52; + public byte MinimumWritePerformance26; + public byte MinimumWritePerformance26_4; + public byte MinimumWritePerformance52; + public byte MinimumWritePerformanceDDR52; + public byte ModeConfig; + public byte ModeOperationCodes; + public byte NativeSectorSize; + public uint NumberofFWSectorsCorrectlyProgrammed; + public byte OperationCodesTimeout; + public byte OptimalReadSize; + public byte OptimalTrimUnitSize; + public byte OptimalWriteSize; + public byte OutOfInterruptBusyTiming; + public byte PackageCaseTemperatureControl; + public byte PackedCommandFailureIndex; + public byte PackedCommandStatus; + public byte PartitionConfiguration; + public byte PartitioningSetting; + public byte PartitioningSupport; + public byte PartitionsAttribute; + public byte PartitionSwitchingTime; + public byte PeriodicWakeUp; + public byte PowerClass; + public byte PowerClass26; + public byte PowerClass26_195; + public byte PowerClass52; + public byte PowerClass52_195; + public byte PowerClassDDR200; + public byte PowerClassDDR200_130; + public byte PowerClassDDR200_195; + public byte PowerClassDDR52; + public byte PowerClassDDR52_195; + public byte PowerOffNotification; + public byte PowerOffNotificationTimeout; + public byte PreEOLInformation; + public uint PreLoadingDataSize; + public byte ProductionStateAwareness; + public byte ProductionStateAwarenessTimeout; + public byte ProductStateAwarenessEnablement; + public byte ReliableWriteSectorCount; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] + public byte[] Reserved0; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 177)] + public byte[] Reserved1; + public byte Reserved10; + public byte Reserved11; + public byte Reserved12; + public byte Reserved13; + public byte Reserved14; + public byte Reserved15; + public ushort Reserved16; + public ushort Reserved17; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 15)] public byte[] Reserved18; + public byte Reserved2; + public byte Reserved3; + public byte Reserved4; + public byte Reserved5; + public byte Reserved6; + public byte Reserved7; + public byte Reserved8; + public byte Reserved9; + public byte Revision; + public byte RPMBSize; + public uint SectorCount; + public byte SectorSize; + public byte SectorSizeEmulation; + public byte SecureEraseMultiplier; + public byte SecureFeatureSupport; + public byte SecureRemovalType; + public byte SecureTRIMMultiplier; + public byte SecureWriteProtectInformation; + public byte SleepAwakeTimeout; + public byte SleepCurrentVcc; + public byte SleepCurrentVccq; + public byte SleepNotificationTimeout; + public byte StartSanitizeOperation; + public byte StrobeSupport; + public byte Structure; + public byte SupportedCommandSets; + public byte SupportedModes; + public byte SupportsProgramCxDInDDR; + public byte TagResourcesSize; + public byte TagUnitSize; + public byte TRIMMultiplier; + public byte UserAreaWriteProtectionRegister; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] + public byte[] VendorHealthReport; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] + public byte[] VendorSpecific; + public byte WriteReliabilityParameterRegister; + public byte WriteReliabilitySettingRegister; } - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Decoders { public static ExtendedCSD DecodeExtendedCSD(byte[] response) { - if(response == null) return null; + if(response == null) + return null; - if(response.Length != 512) return null; + if(response.Length != 512) + return null; - GCHandle handle = GCHandle.Alloc(response, GCHandleType.Pinned); - ExtendedCSD csd = (ExtendedCSD)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(ExtendedCSD)); + GCHandle handle = GCHandle.Alloc(response, GCHandleType.Pinned); + var csd = (ExtendedCSD)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(ExtendedCSD)); handle.Free(); return csd; @@ -231,16 +230,16 @@ namespace DiscImageChef.Decoders.MMC public static string PrettifyExtendedCSD(ExtendedCSD csd) { - if(csd == null) return null; + if(csd == null) + return null; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendLine("MultiMediaCard Extended Device Specific Data Register:"); double unit; if((csd.HPIFeatures & 0x01) == 0x01) - sb.AppendLine((csd.HPIFeatures & 0x02) == 0x02 - ? "\tDevice implements HPI using CMD12" + sb.AppendLine((csd.HPIFeatures & 0x02) == 0x02 ? "\tDevice implements HPI using CMD12" : "\tDevice implements HPI using CMD13"); if((csd.BackgroundOperationsSupport & 0x01) == 0x01) @@ -257,53 +256,68 @@ namespace DiscImageChef.Decoders.MMC if((csd.ExtendedPartitionsSupport & 0x01) == 0x01) sb.AppendLine("\tDevice supports non-persistent extended partitions"); + if((csd.ExtendedPartitionsSupport & 0x02) == 0x02) sb.AppendLine("\tDevice supports system code extended partitions"); - if((csd.SupportedModes & 0x01) == 0x01) sb.AppendLine("\tDevice supports FFU"); - if((csd.SupportedModes & 0x02) == 0x02) sb.AppendLine("\tDevice supports Vendor Specific Mode"); + if((csd.SupportedModes & 0x01) == 0x01) + sb.AppendLine("\tDevice supports FFU"); + + if((csd.SupportedModes & 0x02) == 0x02) + sb.AppendLine("\tDevice supports Vendor Specific Mode"); if((csd.CMDQueuingSupport & 0x01) == 0x01) - sb.AppendFormat("\tDevice supports command queuing with a depth of {0}", csd.CMDQueuingDepth + 1) - .AppendLine(); + sb.AppendFormat("\tDevice supports command queuing with a depth of {0}", csd.CMDQueuingDepth + 1). + AppendLine(); - sb.AppendFormat("\t{0} firmware sectors correctly programmed", csd.NumberofFWSectorsCorrectlyProgrammed) - .AppendLine(); + sb.AppendFormat("\t{0} firmware sectors correctly programmed", csd.NumberofFWSectorsCorrectlyProgrammed). + AppendLine(); switch(csd.DeviceLifeEstimationTypeB) { case 1: sb.AppendLine("\tDevice used between 0% and 10% of its estimated life time"); + break; case 2: sb.AppendLine("\tDevice used between 10% and 20% of its estimated life time"); + break; case 3: sb.AppendLine("\tDevice used between 20% and 30% of its estimated life time"); + break; case 4: sb.AppendLine("\tDevice used between 30% and 40% of its estimated life time"); + break; case 5: sb.AppendLine("\tDevice used between 40% and 50% of its estimated life time"); + break; case 6: sb.AppendLine("\tDevice used between 50% and 60% of its estimated life time"); + break; case 7: sb.AppendLine("\tDevice used between 60% and 70% of its estimated life time"); + break; case 8: sb.AppendLine("\tDevice used between 70% and 80% of its estimated life time"); + break; case 9: sb.AppendLine("\tDevice used between 80% and 90% of its estimated life time"); + break; case 10: sb.AppendLine("\tDevice used between 90% and 100% of its estimated life time"); + break; case 11: sb.AppendLine("\tDevice exceeded its maximum estimated life time"); + break; } @@ -311,36 +325,47 @@ namespace DiscImageChef.Decoders.MMC { case 1: sb.AppendLine("\tDevice used between 0% and 10% of its estimated life time"); + break; case 2: sb.AppendLine("\tDevice used between 10% and 20% of its estimated life time"); + break; case 3: sb.AppendLine("\tDevice used between 20% and 30% of its estimated life time"); + break; case 4: sb.AppendLine("\tDevice used between 30% and 40% of its estimated life time"); + break; case 5: sb.AppendLine("\tDevice used between 40% and 50% of its estimated life time"); + break; case 6: sb.AppendLine("\tDevice used between 50% and 60% of its estimated life time"); + break; case 7: sb.AppendLine("\tDevice used between 60% and 70% of its estimated life time"); + break; case 8: sb.AppendLine("\tDevice used between 70% and 80% of its estimated life time"); + break; case 9: sb.AppendLine("\tDevice used between 80% and 90% of its estimated life time"); + break; case 10: sb.AppendLine("\tDevice used between 90% and 100% of its estimated life time"); + break; case 11: sb.AppendLine("\tDevice exceeded its maximum estimated life time"); + break; } @@ -348,12 +373,15 @@ namespace DiscImageChef.Decoders.MMC { case 1: sb.AppendLine("\tDevice informs it's in good health"); + break; case 2: sb.AppendLine("\tDevice informs it should be replaced soon"); + break; case 3: sb.AppendLine("\tDevice informs it should be replace immediately"); + break; } @@ -364,31 +392,37 @@ namespace DiscImageChef.Decoders.MMC sb.AppendFormat("\tDevice version: {0}", csd.DeviceVersion).AppendLine(); sb.AppendFormat("\tFirmware version: {0}", csd.FirmwareVersion).AppendLine(); - if(csd.CacheSize == 0) sb.AppendLine("\tDevice has no cache"); - else sb.AppendFormat("\tDevice has {0} KiB of cache", csd.CacheSize).AppendLine(); + if(csd.CacheSize == 0) + sb.AppendLine("\tDevice has no cache"); + else + sb.AppendFormat("\tDevice has {0} KiB of cache", csd.CacheSize).AppendLine(); if(csd.GenericCMD6Timeout > 0) sb.AppendFormat("\tDevice takes a maximum of {0} ms by default for a SWITCH command", csd.GenericCMD6Timeout * 10).AppendLine(); if(csd.PowerOffNotificationTimeout > 0) - sb - .AppendFormat("\tDevice takes a maximum of {0} by default to power off from a SWITCH command notification", + sb. + AppendFormat("\tDevice takes a maximum of {0} by default to power off from a SWITCH command notification", csd.PowerOffNotificationTimeout * 10).AppendLine(); switch(csd.BackgroundOperationsStatus & 0x03) { case 0: sb.AppendLine("\tDevice has no pending background operations"); + break; case 1: sb.AppendLine("\tDevice has non critical operations outstanding"); + break; case 2: sb.AppendLine("\tDevice has performance impacted operations outstanding"); + break; case 3: sb.AppendLine("\tDevice has critical operations outstanding"); + break; } @@ -406,30 +440,41 @@ namespace DiscImageChef.Decoders.MMC sb.AppendFormat("\tDevice takes a maximum of {0} ms for trimming a single erase group", csd.TRIMMultiplier * 300).AppendLine(); - if((csd.SecureFeatureSupport & 0x40) == 0x40) sb.AppendLine("\tDevice supports the sanitize operation"); + if((csd.SecureFeatureSupport & 0x40) == 0x40) + sb.AppendLine("\tDevice supports the sanitize operation"); + if((csd.SecureFeatureSupport & 0x10) == 0x10) sb.AppendLine("\tDevice supports supports the secure and insecure trim operations"); + if((csd.SecureFeatureSupport & 0x04) == 0x04) sb.AppendLine("\tDevice supports automatic erase on retired defective blocks"); - if((csd.SecureFeatureSupport & 0x01) == 0x01) sb.AppendLine("\tDevice supports secure purge operations"); + + if((csd.SecureFeatureSupport & 0x01) == 0x01) + sb.AppendLine("\tDevice supports secure purge operations"); if(csd.SecureEraseMultiplier > 0) sb.AppendFormat("\tDevice takes a maximum of {0} ms for securely erasing a single erase group", csd.SecureEraseMultiplier * 300).AppendLine(); + if(csd.SecureTRIMMultiplier > 0) sb.AppendFormat("\tDevice takes a maximum of {0} ms for securely trimming a single erase group", csd.SecureTRIMMultiplier * 300).AppendLine(); - if((csd.BootInformation & 0x04) == 0x04) sb.AppendLine("\tDevice supports high speed timing on boot"); - if((csd.BootInformation & 0x02) == 0x02) sb.AppendLine("\tDevice supports dual data rate on boot"); - if((csd.BootInformation & 0x01) == 0x01) sb.AppendLine("\tDevice supports alternative boot method"); + if((csd.BootInformation & 0x04) == 0x04) + sb.AppendLine("\tDevice supports high speed timing on boot"); + + if((csd.BootInformation & 0x02) == 0x02) + sb.AppendLine("\tDevice supports dual data rate on boot"); + + if((csd.BootInformation & 0x01) == 0x01) + sb.AppendLine("\tDevice supports alternative boot method"); if(csd.BootPartitionSize > 0) sb.AppendFormat("\tDevice has a {0} KiB boot partition", csd.BootPartitionSize * 128).AppendLine(); if((csd.AccessSize & 0x0F) > 0) - sb.AppendFormat("\tDevice has a page size of {0} KiB", (csd.AccessSize & 0x0F) * 512.0 / 1024.0) - .AppendLine(); + sb.AppendFormat("\tDevice has a page size of {0} KiB", (csd.AccessSize & 0x0F) * 512.0 / 1024.0). + AppendLine(); if(csd.HighCapacityEraseUnitSize > 0) sb.AppendFormat("\tDevice erase groups are {0} KiB", csd.HighCapacityEraseUnitSize * 512).AppendLine(); @@ -445,20 +490,27 @@ namespace DiscImageChef.Decoders.MMC if(csd.SleepCurrentVcc > 0) { unit = Math.Pow(2, csd.SleepCurrentVcc); - if(unit > 1000) sb.AppendFormat("\tDevice uses {0} mA on Vcc when sleeping", unit / 1000).AppendLine(); - else sb.AppendFormat("\tDevice uses {0} μA on Vcc when sleeping", unit).AppendLine(); + + if(unit > 1000) + sb.AppendFormat("\tDevice uses {0} mA on Vcc when sleeping", unit / 1000).AppendLine(); + else + sb.AppendFormat("\tDevice uses {0} μA on Vcc when sleeping", unit).AppendLine(); } if(csd.SleepCurrentVccq > 0) { unit = Math.Pow(2, csd.SleepCurrentVccq); - if(unit > 1000) sb.AppendFormat("\tDevice uses {0} mA on Vccq when sleeping", unit / 1000).AppendLine(); - else sb.AppendFormat("\tDevice uses {0} μA on Vccq when sleeping", unit).AppendLine(); + + if(unit > 1000) + sb.AppendFormat("\tDevice uses {0} mA on Vccq when sleeping", unit / 1000).AppendLine(); + else + sb.AppendFormat("\tDevice uses {0} μA on Vccq when sleeping", unit).AppendLine(); } if(csd.ProductionStateAwarenessTimeout > 0) { unit = Math.Pow(2, csd.ProductionStateAwareness) * 100; + if(unit > 1000000) sb.AppendFormat("\tDevice takes a maximum of {0} s to switch production state awareness", unit / 1000000).AppendLine(); @@ -466,13 +518,14 @@ namespace DiscImageChef.Decoders.MMC sb.AppendFormat("\tDevice takes a maximum of {0} ms to switch production state awareness", unit / 1000).AppendLine(); else - sb.AppendFormat("\tDevice takes a maximum of {0} μs to switch production state awareness", unit) - .AppendLine(); + sb.AppendFormat("\tDevice takes a maximum of {0} μs to switch production state awareness", unit). + AppendLine(); } if(csd.SleepAwakeTimeout > 0) { unit = Math.Pow(2, csd.SleepAwakeTimeout) * 100; + if(unit > 1000000) sb.AppendFormat("\tDevice takes a maximum of {0} ms to transition between sleep and standby states", unit / 1000000).AppendLine(); @@ -487,13 +540,15 @@ namespace DiscImageChef.Decoders.MMC if(csd.SleepNotificationTimeout > 0) { unit = Math.Pow(2, csd.SleepNotificationTimeout) * 10; + if(unit > 1000000) - sb.AppendFormat("\tDevice takes a maximum of {0} s to move to sleep state", unit / 1000000) - .AppendLine(); + sb.AppendFormat("\tDevice takes a maximum of {0} s to move to sleep state", unit / 1000000). + AppendLine(); else if(unit > 1000) - sb.AppendFormat("\tDevice takes a maximum of {0} ms to move to sleep state", unit / 1000) - .AppendLine(); - else sb.AppendFormat("\tDevice takes a maximum of {0} μs to move to sleep state", unit).AppendLine(); + sb.AppendFormat("\tDevice takes a maximum of {0} ms to move to sleep state", unit / 1000). + AppendLine(); + else + sb.AppendFormat("\tDevice takes a maximum of {0} μs to move to sleep state", unit).AppendLine(); } sb.AppendFormat("\tDevice has {0} sectors", csd.SectorCount).AppendLine(); @@ -501,18 +556,21 @@ namespace DiscImageChef.Decoders.MMC if((csd.SecureWriteProtectInformation & 0x01) == 0x01) { sb.AppendLine("\tDevice supports secure write protection"); + if((csd.SecureWriteProtectInformation & 0x02) == 0x02) sb.AppendLine("\tDevice has secure write protection enabled"); } unit = csd.MinimumReadPerformance26 * 150; + if(csd.MinimumReadPerformance26 == 0) sb.AppendLine("\tDevice cannot achieve 2.4MB/s reading in SDR 26Mhz mode"); else - sb.AppendFormat("\tDevice can achieve a minimum of {0}MB/s reading in SDR 26Mhz mode", unit / 1000) - .AppendLine(); + sb.AppendFormat("\tDevice can achieve a minimum of {0}MB/s reading in SDR 26Mhz mode", unit / 1000). + AppendLine(); unit = csd.MinimumReadPerformance26_4 * 150; + if(csd.MinimumReadPerformance26_4 == 0) sb.AppendLine("\tDevice cannot achieve 2.4MB/s reading in SDR 26Mhz 4-bit mode"); else @@ -520,27 +578,31 @@ namespace DiscImageChef.Decoders.MMC unit / 1000).AppendLine(); unit = csd.MinimumReadPerformance52 * 150; + if(csd.MinimumReadPerformance52 == 0) sb.AppendLine("\tDevice cannot achieve 2.4MB/s reading in SDR 52Mhz mode"); else - sb.AppendFormat("\tDevice can achieve a minimum of {0}MB/s reading in SDR 52Mhz mode", unit / 1000) - .AppendLine(); + sb.AppendFormat("\tDevice can achieve a minimum of {0}MB/s reading in SDR 52Mhz mode", unit / 1000). + AppendLine(); unit = csd.MinimumReadPerformanceDDR52 * 300; + if(csd.MinimumReadPerformanceDDR52 == 0) sb.AppendLine("\tDevice cannot achieve 4.8MB/s reading in DDR 52Mhz mode"); else - sb.AppendFormat("\tDevice can achieve a minimum of {0}MB/s reading in DDR 52Mhz mode", unit / 1000) - .AppendLine(); + sb.AppendFormat("\tDevice can achieve a minimum of {0}MB/s reading in DDR 52Mhz mode", unit / 1000). + AppendLine(); unit = csd.MinimumWritePerformance26 * 150; + if(csd.MinimumWritePerformance26 == 0) sb.AppendLine("\tDevice cannot achieve 2.4MB/s writing in SDR 26Mhz mode"); else - sb.AppendFormat("\tDevice can achieve a minimum of {0}MB/s writing in SDR 26Mhz mode", unit / 1000) - .AppendLine(); + sb.AppendFormat("\tDevice can achieve a minimum of {0}MB/s writing in SDR 26Mhz mode", unit / 1000). + AppendLine(); unit = csd.MinimumWritePerformance26_4 * 150; + if(csd.MinimumWritePerformance26_4 == 0) sb.AppendLine("\tDevice cannot achieve 2.4MB/s writing in SDR 26Mhz 4-bit mode"); else @@ -548,18 +610,20 @@ namespace DiscImageChef.Decoders.MMC unit / 1000).AppendLine(); unit = csd.MinimumWritePerformance52 * 150; + if(csd.MinimumWritePerformance52 == 0) sb.AppendLine("\tDevice cannot achieve 2.4MB/s writing in SDR 52Mhz mode"); else - sb.AppendFormat("\tDevice can achieve a minimum of {0}MB/s writing in SDR 52Mhz mode", unit / 1000) - .AppendLine(); + sb.AppendFormat("\tDevice can achieve a minimum of {0}MB/s writing in SDR 52Mhz mode", unit / 1000). + AppendLine(); unit = csd.MinimumWritePerformanceDDR52 * 300; + if(csd.MinimumWritePerformanceDDR52 == 0) sb.AppendLine("\tDevice cannot achieve 4.8MB/s writing in DDR 52Mhz mode"); else - sb.AppendFormat("\tDevice can achieve a minimum of {0}MB/s writing in DDR 52Mhz mode", unit / 1000) - .AppendLine(); + sb.AppendFormat("\tDevice can achieve a minimum of {0}MB/s writing in DDR 52Mhz mode", unit / 1000). + AppendLine(); if(csd.PartitionSwitchingTime > 0) sb.AppendFormat("\tDevice can take a maximum of {0} ms when switching partitions", @@ -569,20 +633,36 @@ namespace DiscImageChef.Decoders.MMC sb.AppendFormat("\tDevice can take a maximum of {0} ms when releasing from an interrupt", csd.OutOfInterruptBusyTiming * 10).AppendLine(); - if((csd.DeviceType & 0x01) == 0x01) sb.AppendLine("\tDevice supports 26 Mhz mode"); - if((csd.DeviceType & 0x02) == 0x02) sb.AppendLine("\tDevice supports 52 Mhz mode"); - if((csd.DeviceType & 0x04) == 0x04) sb.AppendLine("\tDevice supports DDR 52 Mhz mode at 1.8V or 3V"); - if((csd.DeviceType & 0x08) == 0x08) sb.AppendLine("\tDevice supports DDR 52 Mhz mode 1.2V"); - if((csd.DeviceType & 0x10) == 0x10) sb.AppendLine("\tDevice supports HS-200 mode (SDR 200Mhz) at 1.8V"); - if((csd.DeviceType & 0x20) == 0x20) sb.AppendLine("\tDevice supports HS-200 mode (SDR 200Mhz) at 1.2V"); - if((csd.DeviceType & 0x40) == 0x40) sb.AppendLine("\tDevice supports HS-400 mode (DDR 200Mhz) at 1.8V"); - if((csd.DeviceType & 0x80) == 0x80) sb.AppendLine("\tDevice supports HS-400 mode (DDR 200Mhz) at 1.2V"); + if((csd.DeviceType & 0x01) == 0x01) + sb.AppendLine("\tDevice supports 26 Mhz mode"); + + if((csd.DeviceType & 0x02) == 0x02) + sb.AppendLine("\tDevice supports 52 Mhz mode"); + + if((csd.DeviceType & 0x04) == 0x04) + sb.AppendLine("\tDevice supports DDR 52 Mhz mode at 1.8V or 3V"); + + if((csd.DeviceType & 0x08) == 0x08) + sb.AppendLine("\tDevice supports DDR 52 Mhz mode 1.2V"); + + if((csd.DeviceType & 0x10) == 0x10) + sb.AppendLine("\tDevice supports HS-200 mode (SDR 200Mhz) at 1.8V"); + + if((csd.DeviceType & 0x20) == 0x20) + sb.AppendLine("\tDevice supports HS-200 mode (SDR 200Mhz) at 1.2V"); + + if((csd.DeviceType & 0x40) == 0x40) + sb.AppendLine("\tDevice supports HS-400 mode (DDR 200Mhz) at 1.8V"); + + if((csd.DeviceType & 0x80) == 0x80) + sb.AppendLine("\tDevice supports HS-400 mode (DDR 200Mhz) at 1.2V"); sb.AppendFormat("\tCSD version 1.{0} revision 1.{1}", csd.Structure, csd.Revision).AppendLine(); if((csd.StrobeSupport & 0x01) == 0x01) { sb.AppendLine("\tDevice supports enhanced strobe mode"); + sb.AppendLine((csd.BusWidth & 0x80) == 0x80 ? "\tDevice uses strobe during Data Out, CRC and CMD responses" : "\tDevice uses strobe during Data Out and CRC responses"); @@ -592,43 +672,55 @@ namespace DiscImageChef.Decoders.MMC { case 0: sb.AppendLine("\tDevice is using 1-bit data bus"); + break; case 1: sb.AppendLine("\tDevice is using 4-bit data bus"); + break; case 2: sb.AppendLine("\tDevice is using 8-bit data bus"); + break; case 5: sb.AppendLine("\tDevice is using 4-bit DDR data bus"); + break; case 6: sb.AppendLine("\tDevice is using 8-bit DDR data bus"); + break; default: sb.AppendFormat("\tDevice is using unknown data bus code {0}", csd.BusWidth & 0x0F).AppendLine(); + break; } - if((csd.PartitionConfiguration & 0x80) == 0x80) sb.AppendLine("\tDevice sends boot acknowledge"); + if((csd.PartitionConfiguration & 0x80) == 0x80) + sb.AppendLine("\tDevice sends boot acknowledge"); switch((csd.PartitionConfiguration & 0x38) >> 3) { case 0: sb.AppendLine("\tDevice is not boot enabled"); + break; case 1: sb.AppendLine("\tDevice boot partition 1 is enabled"); + break; case 2: sb.AppendLine("\tDevice boot partition 2 is enabled"); + break; case 7: sb.AppendLine("\tDevice user area is enable for boot"); + break; default: sb.AppendFormat("\tUnknown enabled boot partition code {0}", (csd.PartitionConfiguration & 0x38) >> 3).AppendLine(); + break; } @@ -636,39 +728,48 @@ namespace DiscImageChef.Decoders.MMC { case 0: sb.AppendLine("\tThere is no access to boot partition"); + break; case 1: sb.AppendLine("\tThere is read/write access to boot partition 1"); + break; case 2: sb.AppendLine("\tThere is read/write access to boot partition 2"); + break; case 3: sb.AppendLine("\tThere is read/write access to replay protected memory block"); + break; default: sb.AppendFormat("\tThere is access to general purpose partition {0}", (csd.PartitionConfiguration & 0x07) - 3).AppendLine(); + break; } - if((csd.FirmwareConfiguration & 0x01) == 0x01) sb.AppendLine("\tFirmware updates are permanently disabled"); + if((csd.FirmwareConfiguration & 0x01) == 0x01) + sb.AppendLine("\tFirmware updates are permanently disabled"); if(csd.RPMBSize > 0) - sb.AppendFormat("\tDevice has a {0} KiB replay protected memory block", csd.RPMBSize * 128) - .AppendLine(); + sb.AppendFormat("\tDevice has a {0} KiB replay protected memory block", csd.RPMBSize * 128). + AppendLine(); switch(csd.NativeSectorSize) { case 0: sb.AppendLine("\tDevice natively uses 512 byte sectors"); + break; case 1: sb.AppendLine("\tDevice natively uses 4096 byte sectors"); + break; default: sb.AppendFormat("\tDevice natively uses unknown sector size indicated by code {0}", csd.NativeSectorSize).AppendLine(); + break; } @@ -676,13 +777,16 @@ namespace DiscImageChef.Decoders.MMC { case 0: sb.AppendLine("\tDevice is emulating 512 byte sectors"); + break; case 1: sb.AppendLine("\tDevice is using natively sized sectors"); + break; default: - sb.AppendFormat("\tDevice emulates unknown sector size indicated by code {0}", csd.NativeSectorSize) - .AppendLine(); + sb.AppendFormat("\tDevice emulates unknown sector size indicated by code {0}", + csd.NativeSectorSize).AppendLine(); + break; } @@ -690,19 +794,24 @@ namespace DiscImageChef.Decoders.MMC { case 0: sb.AppendLine("\tDevice currently addresses 512 byte sectors"); + break; case 1: sb.AppendLine("\tDevice currently addresses 4096 byte sectors"); + break; default: sb.AppendFormat("\tDevice currently addresses unknown sector size indicated by code {0}", csd.NativeSectorSize).AppendLine(); + break; } - if((csd.CacheControl & 0x01) == 0x01) sb.AppendLine("\tDevice's cache is enabled"); + if((csd.CacheControl & 0x01) == 0x01) + sb.AppendLine("\tDevice's cache is enabled"); - if((csd.CommandQueueModeEnable & 0x01) == 0x01) sb.AppendLine("\tDevice has enabled command queuing"); + if((csd.CommandQueueModeEnable & 0x01) == 0x01) + sb.AppendLine("\tDevice has enabled command queuing"); return sb.ToString(); } diff --git a/MMC/OCR.cs b/MMC/OCR.cs index 5a4dcc1..9dc21ea 100644 --- a/MMC/OCR.cs +++ b/MMC/OCR.cs @@ -36,101 +36,126 @@ using System.Text; namespace DiscImageChef.Decoders.MMC { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] public class OCR { - public bool PowerUp; public byte AccessMode; + public bool OneSix; + public bool PowerUp; public bool ThreeFive; public bool ThreeFour; + public bool ThreeOne; public bool ThreeThree; public bool ThreeTwo; - public bool ThreeOne; public bool ThreeZero; - public bool TwoNine; public bool TwoEight; - public bool TwoSeven; - public bool TwoSix; public bool TwoFive; public bool TwoFour; + public bool TwoNine; + public bool TwoOne; + public bool TwoSeven; + public bool TwoSix; public bool TwoThree; public bool TwoTwo; - public bool TwoOne; public bool TwoZero; - public bool OneSix; } - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Decoders { - public static OCR DecodeOCR(uint response) => - new OCR - { - PowerUp = (response & 0x80000000) == 0x80000000, - AccessMode = (byte)((response & 0x60000000) >> 29), - ThreeFive = (response & 0x00800000) == 0x00800000, - ThreeFour = (response & 0x00400000) == 0x00400000, - ThreeThree = (response & 0x00200000) == 0x00200000, - ThreeTwo = (response & 0x00100000) == 0x00100000, - ThreeOne = (response & 0x00080000) == 0x00080000, - ThreeZero = (response & 0x00040000) == 0x00040000, - TwoNine = (response & 0x00020000) == 0x00020000, - TwoEight = (response & 0x00010000) == 0x00010000, - TwoSeven = (response & 0x00008000) == 0x00008000, - TwoSix = (response & 0x00004000) == 0x00004000, - TwoFive = (response & 0x00002000) == 0x00002000, - TwoFour = (response & 0x00001000) == 0x00001000, - TwoThree = (response & 0x00000800) == 0x00000800, - TwoTwo = (response & 0x00000400) == 0x00000400, - TwoOne = (response & 0x00000200) == 0x00000200, - TwoZero = (response & 0x00000100) == 0x00000100, - OneSix = (response & 0x00000080) == 0x00000080 - }; + public static OCR DecodeOCR(uint response) => new OCR + { + PowerUp = (response & 0x80000000) == 0x80000000, AccessMode = (byte)((response & 0x60000000) >> 29), + ThreeFive = (response & 0x00800000) == 0x00800000, ThreeFour = (response & 0x00400000) == 0x00400000, + ThreeThree = (response & 0x00200000) == 0x00200000, ThreeTwo = (response & 0x00100000) == 0x00100000, + ThreeOne = (response & 0x00080000) == 0x00080000, ThreeZero = (response & 0x00040000) == 0x00040000, + TwoNine = (response & 0x00020000) == 0x00020000, TwoEight = (response & 0x00010000) == 0x00010000, + TwoSeven = (response & 0x00008000) == 0x00008000, TwoSix = (response & 0x00004000) == 0x00004000, + TwoFive = (response & 0x00002000) == 0x00002000, TwoFour = (response & 0x00001000) == 0x00001000, + TwoThree = (response & 0x00000800) == 0x00000800, TwoTwo = (response & 0x00000400) == 0x00000400, + TwoOne = (response & 0x00000200) == 0x00000200, TwoZero = (response & 0x00000100) == 0x00000100, + OneSix = (response & 0x00000080) == 0x00000080 + }; public static OCR DecodeOCR(byte[] response) => response?.Length != 4 ? null : DecodeOCR(BitConverter.ToUInt32(response, 0)); public static string PrettifyOCR(OCR ocr) { - if(ocr == null) return null; + if(ocr == null) + return null; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendLine("MultiMediaCard Operation Conditions Register:"); - if(!ocr.PowerUp) sb.AppendLine("\tDevice is powering up"); + + if(!ocr.PowerUp) + sb.AppendLine("\tDevice is powering up"); + switch(ocr.AccessMode) { case 0: sb.AppendLine("\tDevice is byte addressed"); + break; case 2: sb.AppendLine("\tDevice is sector addressed"); + break; default: sb.AppendFormat("\tUnknown device access mode {0}", ocr.AccessMode).AppendLine(); + break; } - if(ocr.ThreeFive) sb.AppendLine("\tDevice can work with supply 3.5~3.6V"); - if(ocr.ThreeFour) sb.AppendLine("\tDevice can work with supply 3.4~3.5V"); - if(ocr.ThreeThree) sb.AppendLine("\tDevice can work with supply 3.3~3.4V"); - if(ocr.ThreeTwo) sb.AppendLine("\tDevice can work with supply 3.2~3.3V"); - if(ocr.ThreeOne) sb.AppendLine("\tDevice can work with supply 3.1~3.2V"); - if(ocr.TwoNine) sb.AppendLine("\tDevice can work with supply 2.9~3.0V"); - if(ocr.TwoEight) sb.AppendLine("\tDevice can work with supply 2.8~2.9V"); - if(ocr.TwoSeven) sb.AppendLine("\tDevice can work with supply 2.7~2.8V"); - if(ocr.TwoSix) sb.AppendLine("\tDevice can work with supply 2.6~2.7V"); - if(ocr.TwoFive) sb.AppendLine("\tDevice can work with supply 2.5~2.6V"); - if(ocr.TwoFour) sb.AppendLine("\tDevice can work with supply 2.4~2.5V"); - if(ocr.TwoThree) sb.AppendLine("\tDevice can work with supply 2.3~2.4V"); - if(ocr.TwoTwo) sb.AppendLine("\tDevice can work with supply 2.2~2.3V"); - if(ocr.TwoOne) sb.AppendLine("\tDevice can work with supply 2.1~2.2V"); - if(ocr.TwoZero) sb.AppendLine("\tDevice can work with supply 2.0~2.1V"); - if(ocr.OneSix) sb.AppendLine("\tDevice can work with supply 1.65~1.95V"); + if(ocr.ThreeFive) + sb.AppendLine("\tDevice can work with supply 3.5~3.6V"); + + if(ocr.ThreeFour) + sb.AppendLine("\tDevice can work with supply 3.4~3.5V"); + + if(ocr.ThreeThree) + sb.AppendLine("\tDevice can work with supply 3.3~3.4V"); + + if(ocr.ThreeTwo) + sb.AppendLine("\tDevice can work with supply 3.2~3.3V"); + + if(ocr.ThreeOne) + sb.AppendLine("\tDevice can work with supply 3.1~3.2V"); + + if(ocr.TwoNine) + sb.AppendLine("\tDevice can work with supply 2.9~3.0V"); + + if(ocr.TwoEight) + sb.AppendLine("\tDevice can work with supply 2.8~2.9V"); + + if(ocr.TwoSeven) + sb.AppendLine("\tDevice can work with supply 2.7~2.8V"); + + if(ocr.TwoSix) + sb.AppendLine("\tDevice can work with supply 2.6~2.7V"); + + if(ocr.TwoFive) + sb.AppendLine("\tDevice can work with supply 2.5~2.6V"); + + if(ocr.TwoFour) + sb.AppendLine("\tDevice can work with supply 2.4~2.5V"); + + if(ocr.TwoThree) + sb.AppendLine("\tDevice can work with supply 2.3~2.4V"); + + if(ocr.TwoTwo) + sb.AppendLine("\tDevice can work with supply 2.2~2.3V"); + + if(ocr.TwoOne) + sb.AppendLine("\tDevice can work with supply 2.1~2.2V"); + + if(ocr.TwoZero) + sb.AppendLine("\tDevice can work with supply 2.0~2.1V"); + + if(ocr.OneSix) + sb.AppendLine("\tDevice can work with supply 1.65~1.95V"); return sb.ToString(); } diff --git a/MMC/VendorString.cs b/MMC/VendorString.cs index 6545e42..1f338b7 100644 --- a/MMC/VendorString.cs +++ b/MMC/VendorString.cs @@ -38,9 +38,9 @@ namespace DiscImageChef.Decoders.MMC { switch(mmcVendorId) { - case 0x15: return "Samsung"; - case 0x2C: return "extreMEmory"; - default: return $"Unknown manufacturer ID 0x{mmcVendorId:X2}"; + case 0x15: return"Samsung"; + case 0x2C: return"extreMEmory"; + default: return$"Unknown manufacturer ID 0x{mmcVendorId:X2}"; } } } diff --git a/PCMCIA/CIS.cs b/PCMCIA/CIS.cs index 21112ca..9a2509a 100644 --- a/PCMCIA/CIS.cs +++ b/PCMCIA/CIS.cs @@ -38,9 +38,8 @@ using System.Text; namespace DiscImageChef.Decoders.PCMCIA { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static class CIS { // TODO: Handle links? Or are they removed in lower layers of the operating system drivers? @@ -51,15 +50,21 @@ namespace DiscImageChef.Decoders.PCMCIA while(position < data.Length) { - Tuple tuple = new Tuple {Code = (TupleCodes)data[position]}; + var tuple = new Tuple + { + Code = (TupleCodes)data[position] + }; - if(tuple.Code == TupleCodes.CISTPL_NULL) continue; + if(tuple.Code == TupleCodes.CISTPL_NULL) + continue; - if(tuple.Code == TupleCodes.CISTPL_END) break; + if(tuple.Code == TupleCodes.CISTPL_END) + break; tuple.Link = data[position + 1]; - if(position + 2 + tuple.Link > data.Length) break; + if(position + 2 + tuple.Link > data.Length) + break; tuple.Data = new byte[tuple.Link + 2]; Array.Copy(data, position, tuple.Data, 0, tuple.Link + 2); @@ -73,31 +78,35 @@ namespace DiscImageChef.Decoders.PCMCIA public static DeviceGeometryTuple DecodeDeviceGeometryTuple(Tuple tuple) { - if(tuple == null) return null; + if(tuple == null) + return null; - if(tuple.Code != TupleCodes.CISTPL_DEVICEGEO && tuple.Code != TupleCodes.CISTPL_DEVICEGEO_A) return null; + if(tuple.Code != TupleCodes.CISTPL_DEVICEGEO && + tuple.Code != TupleCodes.CISTPL_DEVICEGEO_A) + return null; return tuple.Data == null ? null : DecodeDeviceGeometryTuple(tuple.Data); } public static DeviceGeometryTuple DecodeDeviceGeometryTuple(byte[] data) { - if((data?.Length - 2) % 6 != 0) return null; + if((data?.Length - 2) % 6 != 0) + return null; - DeviceGeometryTuple tuple = new DeviceGeometryTuple(); + var tuple = new DeviceGeometryTuple(); List geometries = new List(); for(int position = 2; position < data.Length; position += 6) { - DeviceGeometry geometry = new DeviceGeometry + var geometry = new DeviceGeometry { - CardInterface = data[position], - EraseBlockSize = data[position + 1], - ReadBlockSize = data[position + 2], - WriteBlockSize = data[position + 3], - Partitions = data[position + 4], - Interleaving = data[position + 5] + CardInterface = data[position], EraseBlockSize = data[position + 1], + ReadBlockSize = data[position + 2], + WriteBlockSize = data[position + 3], + Partitions = data[position + 4], + Interleaving = data[position + 5] }; + geometries.Add(geometry); } @@ -110,22 +119,30 @@ namespace DiscImageChef.Decoders.PCMCIA public static string PrettifyDeviceGeometryTuple(DeviceGeometryTuple tuple) { - if(tuple == null) return null; + if(tuple == null) + return null; - if(tuple.Code != TupleCodes.CISTPL_DEVICEGEO && tuple.Code != TupleCodes.CISTPL_DEVICEGEO_A) return null; + if(tuple.Code != TupleCodes.CISTPL_DEVICEGEO && + tuple.Code != TupleCodes.CISTPL_DEVICEGEO_A) + return null; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendLine("PCMCIA Device Geometry Tuples:"); + foreach(DeviceGeometry geometry in tuple.Geometries) { sb.AppendLine("\tGeometry:"); sb.AppendFormat("\t\tDevice width: {0} bits", (1 << (geometry.CardInterface - 1)) * 8).AppendLine(); + sb.AppendFormat("\t\tErase block = {0} bytes", (1 << (geometry.EraseBlockSize - 1)) * (1 << (geometry.Interleaving - 1))).AppendLine(); + sb.AppendFormat("\t\tRead block = {0} bytes", (1 << (geometry.ReadBlockSize - 1)) * (1 << (geometry.Interleaving - 1))).AppendLine(); + sb.AppendFormat("\t\tWrite block = {0} bytes", (1 << (geometry.WriteBlockSize - 1)) * (1 << (geometry.Interleaving - 1))).AppendLine(); + sb.AppendFormat("\t\tPartition alignment = {0} bytes", (1 << (geometry.EraseBlockSize - 1)) * (1 << (geometry.Interleaving - 1)) * (1 << (geometry.Partitions - 1))).AppendLine(); @@ -142,31 +159,33 @@ namespace DiscImageChef.Decoders.PCMCIA public static ManufacturerIdentificationTuple DecodeManufacturerIdentificationTuple(Tuple tuple) { - if(tuple?.Code != TupleCodes.CISTPL_MANFID) return null; + if(tuple?.Code != TupleCodes.CISTPL_MANFID) + return null; return tuple.Data == null ? null : DecodeManufacturerIdentificationTuple(tuple.Data); } public static ManufacturerIdentificationTuple DecodeManufacturerIdentificationTuple(byte[] data) { - if(data == null) return null; + if(data == null) + return null; - if(data.Length < 6) return null; + if(data.Length < 6) + return null; return new ManufacturerIdentificationTuple { - Code = (TupleCodes)data[0], - Link = data[1], - ManufacturerID = BitConverter.ToUInt16(data, 2), - CardID = BitConverter.ToUInt16(data, 4) + Code = (TupleCodes)data[0], Link = data[1], ManufacturerID = BitConverter.ToUInt16(data, 2), + CardID = BitConverter.ToUInt16(data, 4) }; } public static string PrettifyManufacturerIdentificationTuple(ManufacturerIdentificationTuple tuple) { - if(tuple?.Code != TupleCodes.CISTPL_MANFID) return null; + if(tuple?.Code != TupleCodes.CISTPL_MANFID) + return null; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendLine("PCMCIA Manufacturer Identification Tuple:"); sb.AppendFormat("\tManufacturer ID: {0}", VendorCode.Prettify(tuple.ManufacturerID)).AppendLine(); sb.AppendFormat("\tCard ID:D 0x{0:X4}", tuple.CardID).AppendLine(); @@ -182,40 +201,46 @@ namespace DiscImageChef.Decoders.PCMCIA public static Level1VersionTuple DecodeLevel1VersionTuple(Tuple tuple) { - if(tuple?.Code != TupleCodes.CISTPL_VERS_1) return null; + if(tuple?.Code != TupleCodes.CISTPL_VERS_1) + return null; return tuple.Data == null ? null : DecodeLevel1VersionTuple(tuple.Data); } public static Level1VersionTuple DecodeLevel1VersionTuple(byte[] data) { - if(data == null) return null; + if(data == null) + return null; - if(data.Length < 4) return null; + if(data.Length < 4) + return null; List buffer = new List(); List strings = null; bool firstString = false; bool secondString = false; - Level1VersionTuple tuple = new Level1VersionTuple + var tuple = new Level1VersionTuple { Code = (TupleCodes)data[0], Link = data[1], MajorVersion = data[2], MinorVersion = data[3] }; for(int position = 4; position < data.Length; position++) { - if(data[position] == 0xFF) break; + if(data[position] == 0xFF) + break; buffer.Add(data[position]); - if(data[position] != 0x00) continue; + if(data[position] != 0x00) + continue; if(!firstString) { tuple.Manufacturer = StringHandlers.CToString(buffer.ToArray()); buffer = new List(); firstString = true; + continue; } @@ -225,41 +250,51 @@ namespace DiscImageChef.Decoders.PCMCIA tuple.Product = StringHandlers.CToString(buffer.ToArray()); buffer = new List(); firstString = true; + continue; } - if(strings == null) strings = new List(); + if(strings == null) + strings = new List(); strings.Add(StringHandlers.CToString(buffer.ToArray())); buffer = new List(); } - if(strings != null) tuple.AdditionalInformation = strings.ToArray(); + if(strings != null) + tuple.AdditionalInformation = strings.ToArray(); return tuple; } public static string PrettifyLevel1VersionTuple(Level1VersionTuple tuple) { - if(tuple?.Code != TupleCodes.CISTPL_VERS_1) return null; + if(tuple?.Code != TupleCodes.CISTPL_VERS_1) + return null; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendLine("PCMCIA Level 1 Version / Product Information Tuple:"); sb.AppendFormat("\tCard indicates compliance with PC Card Standard Release {0}.{1}", tuple.MajorVersion, tuple.MinorVersion).AppendLine(); - if(string.IsNullOrEmpty(tuple.Manufacturer)) sb.AppendLine("\tNo manufacturer information string."); - else sb.AppendFormat("\tManufacturer: {0}", tuple.Manufacturer).AppendLine(); + if(string.IsNullOrEmpty(tuple.Manufacturer)) + sb.AppendLine("\tNo manufacturer information string."); + else + sb.AppendFormat("\tManufacturer: {0}", tuple.Manufacturer).AppendLine(); - if(string.IsNullOrEmpty(tuple.Product)) sb.AppendLine("\tNo product name string."); - else sb.AppendFormat("\tProduct name: {0}", tuple.Product).AppendLine(); + if(string.IsNullOrEmpty(tuple.Product)) + sb.AppendLine("\tNo product name string."); + else + sb.AppendFormat("\tProduct name: {0}", tuple.Product).AppendLine(); - if(tuple.AdditionalInformation == null || tuple.AdditionalInformation.Length == 0) + if(tuple.AdditionalInformation == null || + tuple.AdditionalInformation.Length == 0) sb.AppendLine("\tNo additional information."); else { sb.AppendLine("\tAdditional information:"); + foreach(string info in tuple.AdditionalInformation.Where(info => !string.IsNullOrEmpty(info))) sb.AppendFormat("\t\t{0}", info).AppendLine(); } diff --git a/PCMCIA/Enums.cs b/PCMCIA/Enums.cs index bc4ae60..241bf78 100644 --- a/PCMCIA/Enums.cs +++ b/PCMCIA/Enums.cs @@ -34,263 +34,88 @@ using System.Diagnostics.CodeAnalysis; namespace DiscImageChef.Decoders.PCMCIA { - /// - /// Tuple codes. - /// + /// Tuple codes. [SuppressMessage("ReSharper", "InconsistentNaming")] public enum TupleCodes : byte { - /// - /// Checksum control - /// - CISTPL_CHECKSUM = 0x10, - /// - /// End-of-chain - /// - CISTPL_END = 0xFF, - /// - /// Indirect access PC Card memory - /// - CISTPL_INDIRECT = 0x03, - /// - /// Link-target-control - /// - CISTPL_LINKTARGET = 0x13, - /// - /// Longlink to attribute memory - /// - CISTPL_LONGLINK_A = 0x11, - /// - /// Longlink to common memory - /// - CISTPL_LONGLINK_C = 0x12, - /// - /// Longlink to next chain on a Cardbus PC Card - /// - CISTPL_LONGLINK_CB = 0x02, - /// - /// Longlink to function specific chains - /// - CISTPL_LONGLINK_MFC = 0x06, - /// - /// No-link to common memory - /// - CISTPL_NO_LINK = 0x14, - /// - /// Null tuple - /// - CISTPL_NULL = 0x00, - /// - /// Alternate language string - /// - CISTPL_ALTSTR = 0x16, - /// - /// Common memory device information - /// - CISTPL_DEVICE = 0x01, - /// - /// Attribute memory device information - /// - CISTPL_DEVICE_A = 0x17, - /// - /// Other operating conditions information for attribute memory - /// - CISTPL_DEVICE_OA = 0x1D, - /// - /// Other operating conditions information for common memory - /// - CISTPL_DEVICE_OC = 0x1C, - /// - /// Device geometry information for common memory - /// - CISTPL_DEVICEGEO = 0x1E, - /// - /// Device geometry information for attribute memory - /// - CISTPL_DEVICEGEO_A = 0x1F, - /// - /// Extended common memory device information - /// - CISTPL_EXTDEVIC = 0x09, - /// - /// Function extensions - /// - CISTPL_FUNCE = 0x22, - /// - /// Function class identification - /// - CISTPL_FUNCID = 0x21, - /// - /// JEDEC programming information for attribute memory - /// - CISTPL_JEDEC_A = 0x19, - /// - /// JEDEC programming information for common memory - /// - CISTPL_JEDEC_C = 0x18, - /// - /// Manufacturer identification string - /// - CISTPL_MANFID = 0x20, - /// - /// Level 1 version/product information - /// - CISTPL_VERS_1 = 0x15, - /// - /// BAR for a CardBus PC Card - /// - CISTPL_BAR = 0x07, - /// - /// Configuration-table-entry - /// - CISTPL_CFTABLE_ENTRY = 0x1B, - /// - /// Configuration-table-entry for a CardBus PC Card - /// - CISTPL_CFTABLE_ENTRY_CB = 0x05, - /// - /// Configuration tuple for a 16-bit PC Card - /// - CISTPL_CONFIG = 0x1A, - /// - /// Configuration tuple for a CardBus PC Card - /// - CISTPL_CONFIG_CB = 0x04, - /// - /// Function state save/restore definition - /// - CISTPL_PWR_MGMNT = 0x08, - /// - /// Battery replacement date - /// - CISTPL_BATTERY = 0x45, - /// - /// Card initialization date - /// - CISTPL_DATE = 0x44, - /// - /// Level 2 version/product information - /// - CISTPL_VERS_2 = 0x40, - /// - /// Byte ordering for disk-like partitions - /// - CISTPL_BYTEORDER = 0x43, - /// - /// Data recording format for common memory - /// - CISTPL_FORMAT = 0x41, - /// - /// Data recording format for attribute memory - /// - CISTPL_FORMAT_A = 0x47, - /// - /// Partition geometry - /// - CISTPL_GEOMETRY = 0x42, - /// - /// Software interleaving - /// - CISTPL_SWIL = 0x23, - /// - /// Partition organization - /// - CISTPL_ORG = 0x46, - /// - /// Special purpose - /// + /// Checksum control + CISTPL_CHECKSUM = 0x10, /// End-of-chain + CISTPL_END = 0xFF, /// Indirect access PC Card memory + CISTPL_INDIRECT = 0x03, /// Link-target-control + CISTPL_LINKTARGET = 0x13, /// Longlink to attribute memory + CISTPL_LONGLINK_A = 0x11, /// Longlink to common memory + CISTPL_LONGLINK_C = 0x12, /// Longlink to next chain on a Cardbus PC Card + CISTPL_LONGLINK_CB = 0x02, /// Longlink to function specific chains + CISTPL_LONGLINK_MFC = 0x06, /// No-link to common memory + CISTPL_NO_LINK = 0x14, /// Null tuple + CISTPL_NULL = 0x00, /// Alternate language string + CISTPL_ALTSTR = 0x16, /// Common memory device information + CISTPL_DEVICE = 0x01, /// Attribute memory device information + CISTPL_DEVICE_A = 0x17, /// Other operating conditions information for attribute memory + CISTPL_DEVICE_OA = 0x1D, /// Other operating conditions information for common memory + CISTPL_DEVICE_OC = 0x1C, /// Device geometry information for common memory + CISTPL_DEVICEGEO = 0x1E, /// Device geometry information for attribute memory + CISTPL_DEVICEGEO_A = 0x1F, /// Extended common memory device information + CISTPL_EXTDEVIC = 0x09, /// Function extensions + CISTPL_FUNCE = 0x22, /// Function class identification + CISTPL_FUNCID = 0x21, /// JEDEC programming information for attribute memory + CISTPL_JEDEC_A = 0x19, /// JEDEC programming information for common memory + CISTPL_JEDEC_C = 0x18, /// Manufacturer identification string + CISTPL_MANFID = 0x20, /// Level 1 version/product information + CISTPL_VERS_1 = 0x15, /// BAR for a CardBus PC Card + CISTPL_BAR = 0x07, /// Configuration-table-entry + CISTPL_CFTABLE_ENTRY = 0x1B, /// Configuration-table-entry for a CardBus PC Card + CISTPL_CFTABLE_ENTRY_CB = 0x05, /// Configuration tuple for a 16-bit PC Card + CISTPL_CONFIG = 0x1A, /// Configuration tuple for a CardBus PC Card + CISTPL_CONFIG_CB = 0x04, /// Function state save/restore definition + CISTPL_PWR_MGMNT = 0x08, /// Battery replacement date + CISTPL_BATTERY = 0x45, /// Card initialization date + CISTPL_DATE = 0x44, /// Level 2 version/product information + CISTPL_VERS_2 = 0x40, /// Byte ordering for disk-like partitions + CISTPL_BYTEORDER = 0x43, /// Data recording format for common memory + CISTPL_FORMAT = 0x41, /// Data recording format for attribute memory + CISTPL_FORMAT_A = 0x47, /// Partition geometry + CISTPL_GEOMETRY = 0x42, /// Software interleaving + CISTPL_SWIL = 0x23, /// Partition organization + CISTPL_ORG = 0x46, /// Special purpose CISTPL_SPCL = 0x90 } [SuppressMessage("ReSharper", "InconsistentNaming")] public enum DeviceTypeCodes : byte { - /// - /// No device, used to designate a hole - /// - DTYPE_NULL = 0, - /// - /// Masked ROM - /// - DTYPE_ROM = 1, - /// - /// One-type-programmable ROM - /// - DTYPE_OTPROM = 2, - /// - /// UV-Erasable Programmable ROM - /// - DTYPE_EPROM = 3, - /// - /// Electronically-Erasable Programmable ROM - /// - DTYPE_EEPROM = 4, - /// - /// Flash memory - /// - DTYPE_FLASH = 5, - /// - /// Static RAM - /// - DTYPE_SRAM = 6, - /// - /// Dynamic RAM - /// - DTYPE_DRAM = 7, - /// - /// Function-specific memory address range - /// - DTYPE_FUNCSPEC = 13, - /// - /// Extended type follows - /// + /// No device, used to designate a hole + DTYPE_NULL = 0, /// Masked ROM + DTYPE_ROM = 1, /// One-type-programmable ROM + DTYPE_OTPROM = 2, /// UV-Erasable Programmable ROM + DTYPE_EPROM = 3, /// Electronically-Erasable Programmable ROM + DTYPE_EEPROM = 4, /// Flash memory + DTYPE_FLASH = 5, /// Static RAM + DTYPE_SRAM = 6, /// Dynamic RAM + DTYPE_DRAM = 7, /// Function-specific memory address range + DTYPE_FUNCSPEC = 13, /// Extended type follows DTYPE_EXTEND = 14 } [SuppressMessage("ReSharper", "InconsistentNaming")] public enum DeviceSpeedCodes : byte { - /// - /// No device - /// - DSPEED_NULL = 0, - /// - /// 250 ns - /// - DSPEED_250NS = 1, - /// - /// 200 ns - /// - DSPEED_200NS = 2, - /// - /// 150 ns - /// - DSPEED_150NS = 3, - /// - /// 100 ns - /// - DSPEED_100NS = 4, - /// - /// Extended speed follows - /// + /// No device + DSPEED_NULL = 0, /// 250 ns + DSPEED_250NS = 1, /// 200 ns + DSPEED_200NS = 2, /// 150 ns + DSPEED_150NS = 3, /// 100 ns + DSPEED_100NS = 4, /// Extended speed follows DSPEED_EXT = 7 } [SuppressMessage("ReSharper", "InconsistentNaming")] public enum FunctionCodes : byte { - MultiFunction = 0x00, - Memory = 0x01, - Serial = 0x02, - Parallel = 0x03, - FixedDisk = 0x04, - Video = 0x05, - Network = 0x06, - AIMS = 0x07, - SCSI = 0x08, - Security = 0x09, - Instrument = 0x0A, - HighSpeedSerial = 0x0B, - VendorSpecific = 0xFE + MultiFunction = 0x00, Memory = 0x01, Serial = 0x02, + Parallel = 0x03, FixedDisk = 0x04, Video = 0x05, + Network = 0x06, AIMS = 0x07, SCSI = 0x08, + Security = 0x09, Instrument = 0x0A, HighSpeedSerial = 0x0B, + VendorSpecific = 0xFE } } \ No newline at end of file diff --git a/PCMCIA/Types.cs b/PCMCIA/Types.cs index 45e7ae6..edcd2cf 100644 --- a/PCMCIA/Types.cs +++ b/PCMCIA/Types.cs @@ -34,181 +34,128 @@ using System.Diagnostics.CodeAnalysis; namespace DiscImageChef.Decoders.PCMCIA { - /// - /// Basic classure of a PCMCIA tuple - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + /// Basic classure of a PCMCIA tuple + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public class Tuple { public TupleCodes Code; - public byte Link; public byte[] Data; + public byte Link; } - /// - /// Checksum tuple - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + /// Checksum tuple + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public class ChecksumTuple { + /// Modulo-256 sum of region + public byte Checksum; /// /// /// public TupleCodes Code; - /// - /// Link to next tuple - /// - public byte Link; - /// - /// Offset to region to be checksummed - /// - public short Offset; - /// - /// Length of region to be checksummed - /// + /// Length of region to be checksummed public ushort Length; - /// - /// Modulo-256 sum of region - /// - public byte Checksum; + /// Link to next tuple + public byte Link; + /// Offset to region to be checksummed + public short Offset; } - /// - /// Indirect Access PC Card Memory - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + /// Indirect Access PC Card Memory + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public class IndirectTuple { /// /// /// public TupleCodes Code; - /// - /// Link to next tuple - /// + /// Link to next tuple public byte Link; } - /// - /// Link target tuple - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + /// Link target tuple + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public class LinkTargetTuple { /// /// /// public TupleCodes Code; - /// - /// Link to next tuple - /// + /// Link to next tuple public byte Link; - /// - /// 'C''I''S' in ASCII - /// + /// 'C''I''S' in ASCII public byte[] Tag; } - /// - /// 16-bit PC Card Long Link Tuple - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + /// 16-bit PC Card Long Link Tuple + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public class LongLinkTuple { + /// Target address + public uint Address; /// /// or or /// /// public TupleCodes Code; - /// - /// Link to next tuple - /// + /// Link to next tuple public byte Link; - /// - /// Target address - /// - public uint Address; } - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "ClassNeverInstantiated.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), + SuppressMessage("ReSharper", "ClassNeverInstantiated.Global")] public class ConfigurationAddress { - /// - /// Target address space, 0 = attribute, 1 = common - /// - public byte TargetAddressSpace; - /// - /// Target address - /// + /// Target address public uint Address; + /// Target address space, 0 = attribute, 1 = common + public byte TargetAddressSpace; } - /// - /// Multiple function link tuple - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + /// Multiple function link tuple + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public class MultipleFunctionLinkTuple { + /// Link to more configuration registers + public ConfigurationAddress[] Addresses; /// /// /// public TupleCodes Code; - /// - /// Link to next tuple - /// + /// Link to next tuple public byte Link; - /// - /// How many functions follow - /// + /// How many functions follow public byte NumberFunctions; - /// - /// Link to more configuration registers - /// - public ConfigurationAddress[] Addresses; } - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public class NoLinkTuple { /// /// /// public TupleCodes Code; - /// - /// Link to next tuple - /// + /// Link to next tuple public byte Link; } - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public class AlternateStringTuple { /// /// /// public TupleCodes Code; - /// - /// Link to next tuple - /// + /// Link to next tuple public byte Link; /// /// Array of strings. On memory they're preceded by an ISO Escape Code indicating codepage. Here they're stored as @@ -217,335 +164,218 @@ namespace DiscImageChef.Decoders.PCMCIA public string[] Strings; } - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "ClassNeverInstantiated.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), + SuppressMessage("ReSharper", "ClassNeverInstantiated.Global")] public class ExtendedDeviceSpeed { - /// - /// Another extended follows - /// - public bool Extended; - /// - /// Speed mantisa - /// - public byte Mantissa; - /// - /// Speed exponent - /// + /// Speed exponent public byte Exponent; + /// Another extended follows + public bool Extended; + /// Speed mantisa + public byte Mantissa; } - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public struct DeviceInfo { - /// - /// Device type code - /// + /// Device type code public DeviceTypeCodes Type; - /// - /// Write protected - /// + /// Write protected public bool WPS; - /// - /// Speed code - /// + /// Speed code public DeviceSpeedCodes Speed; - /// - /// Extended speeds - /// + /// Extended speeds public ExtendedDeviceSpeed[] ExtendedSpeeds; - /// - /// Extended types - /// + /// Extended types public byte[] ExtendedTypes; - /// - /// Size in units - 1 - /// + /// Size in units - 1 public byte Units; - /// - /// Code to define units unit - /// + /// Code to define units unit public byte SizeCode; } - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public class DeviceTuple { - /// - /// or - /// + /// or public TupleCodes Code; - /// - /// Link to next tuple - /// - public byte Link; - /// - /// Array of device information bytes - /// + /// Array of device information bytes public DeviceInfo[] Infos; + /// Link to next tuple + public byte Link; } - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public struct OtherConditionInfo { - /// - /// True if another other condition info follows - /// + /// True if another other condition info follows public bool Extended; - /// - /// Vcc used - /// + /// Vcc used public byte VccUsed; - /// - /// Supports WAIT# signal - /// + /// Supports WAIT# signal public bool MWAIT; } - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public class OtherConditionTuple { - /// - /// or - /// + /// or public TupleCodes Code; - /// - /// Link to next tuple - /// - public byte Link; - /// - /// Array of other condition information bytes - /// - public OtherConditionInfo[] OtherConditionInfos; - /// - /// Array of device information bytes - /// + /// Array of device information bytes public DeviceInfo[] Infos; + /// Link to next tuple + public byte Link; + /// Array of other condition information bytes + public OtherConditionInfo[] OtherConditionInfos; } - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public struct DeviceGeometry { - /// - /// 1 << n-1 bytes, 2 = 16-bit PC Card, 3 = CardBus PC Card - /// + /// 1 << n-1 bytes, 2 = 16-bit PC Card, 3 = CardBus PC Card public byte CardInterface; /// - /// Erase block size in 1 << n-1 increments of wide accesses. - /// If n == 4, and == 16, erase block size = 32 * 4 = 128 bytes + /// Erase block size in 1 << n-1 increments of wide accesses. If n == 4, and + /// == 16, erase block size = 32 * 4 = 128 bytes /// public byte EraseBlockSize; /// - /// Read block size in 1 << n-1 increments of wide accesses. - /// If n == 4, and == 16, read block size = 32 * 4 = 128 bytes + /// Read block size in 1 << n-1 increments of wide accesses. If n == 4, and + /// == 16, read block size = 32 * 4 = 128 bytes /// public byte ReadBlockSize; /// - /// Write block size in 1 << n-1 increments of wide accesses. - /// If n == 4, and == 16, write block size = 32 * 4 = 128 bytes + /// Write block size in 1 << n-1 increments of wide accesses. If n == 4, and + /// == 16, write block size = 32 * 4 = 128 bytes /// public byte WriteBlockSize; /// - /// Device partitioning in granularity of 1 << n-1 erase blocks - /// If n == 4, and erase block is 128 bytes, partitions must be aligned to 32 erase block, or 4096 bytes + /// Device partitioning in granularity of 1 << n-1 erase blocks If n == 4, and erase block is 128 bytes, + /// partitions must be aligned to 32 erase block, or 4096 bytes /// public byte Partitions; - /// - /// Card employs a multiple of 1 << n-1 times interleaving the entire memory arrays - /// + /// Card employs a multiple of 1 << n-1 times interleaving the entire memory arrays public byte Interleaving; } - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] public class DeviceGeometryTuple { - /// - /// or - /// + /// or public TupleCodes Code; - /// - /// Link to next tuple - /// - public byte Link; - /// - /// Array of device geometries - /// + /// Array of device geometries public DeviceGeometry[] Geometries; + /// Link to next tuple + public byte Link; } - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public class FunctionIdentificationTuple { /// /// /// public TupleCodes Code; - /// - /// Link to next tuple - /// - public byte Link; - /// - /// Function code - /// + /// Function code public FunctionCodes Function; - /// - /// Device contains boot ROM - /// - public bool ROM; - /// - /// Device wants to be part of power-on-self-test - /// + /// Link to next tuple + public byte Link; + /// Device wants to be part of power-on-self-test public bool POST; + /// Device contains boot ROM + public bool ROM; } - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] public class ManufacturerIdentificationTuple { + /// Card ID + public ushort CardID; /// /// /// public TupleCodes Code; - /// - /// Link to next tuple - /// + /// Link to next tuple public byte Link; - /// - /// Manufacturer ID - /// + /// Manufacturer ID public ushort ManufacturerID; - /// - /// Card ID - /// - public ushort CardID; } - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] public class Level1VersionTuple { + /// Additional information strings + public string[] AdditionalInformation; /// /// /// public TupleCodes Code; - /// - /// Link to next tuple - /// + /// Link to next tuple public byte Link; - /// - /// Major version of standard compliance - /// + /// Major version of standard compliance public byte MajorVersion; - /// - /// Minor version of standard compliance - /// - public byte MinorVersion; - /// - /// Manufacturer string - /// + /// Manufacturer string public string Manufacturer; - /// - /// Product string - /// + /// Minor version of standard compliance + public byte MinorVersion; + /// Product string public string Product; - /// - /// Additional information strings - /// - public string[] AdditionalInformation; } - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public class Level2VersionTuple { + /// Address of first data byte + public ushort Address; + /// Number of copies of CIS present + public byte CISCopies; /// /// /// public TupleCodes Code; - /// - /// Link to next tuple - /// - public byte Link; - /// - /// Version of this classure - /// - public byte StructureVersion; - /// - /// Level of compliance - /// + /// Level of compliance public byte Compliance; - /// - /// Address of first data byte - /// - public ushort Address; - /// - /// Vendor-specific byte - /// - public byte VendorSpecific1; - /// - /// Vendor-specific byte - /// - public byte VendorSpecific2; - /// - /// Number of copies of CIS present - /// - public byte CISCopies; - /// - /// Vendor of software that formatted the card - /// - public string OEM; - /// - /// Informational message about the card - /// + /// Informational message about the card public string Information; + /// Link to next tuple + public byte Link; + /// Vendor of software that formatted the card + public string OEM; + /// Version of this classure + public byte StructureVersion; + /// Vendor-specific byte + public byte VendorSpecific1; + /// Vendor-specific byte + public byte VendorSpecific2; } - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public class GeometryTuple { /// /// /// public TupleCodes Code; - /// - /// Link to next tuple - /// - public byte Link; - /// - /// Sectors per track - /// - public byte SectorsPerTrack; - /// - /// Tracks per cylinder - /// - public byte TracksPerCylinder; - /// - /// Cylinders - /// + /// Cylinders public ushort Cylinders; + /// Link to next tuple + public byte Link; + /// Sectors per track + public byte SectorsPerTrack; + /// Tracks per cylinder + public byte TracksPerCylinder; } } \ No newline at end of file diff --git a/PCMCIA/VendorCode.cs b/PCMCIA/VendorCode.cs index 290c2b6..4bb69d6 100644 --- a/PCMCIA/VendorCode.cs +++ b/PCMCIA/VendorCode.cs @@ -42,321 +42,321 @@ namespace DiscImageChef.Decoders.PCMCIA switch(id) { #region JEDEC - case 0x01: return "AMD"; - case 0x02: return "AMI"; - case 0x83: return "Fairchild"; - case 0x04: return "Fujitsu"; - case 0x85: return "GTE"; - case 0x86: return "Harris"; - case 0x07: return "Hitachi"; - case 0x08: return "Inmos"; - case 0x89: return "Intel"; - case 0x8A: return "I.T.T."; - case 0x0B: return "Intersil"; - case 0x8C: return "Monolithic Memories"; - case 0x0D: return "Mostek"; - case 0x0E: return "Freescale"; - case 0x8F: return "National"; - case 0x10: return "NEC"; - case 0x91: return "RCA"; - case 0x92: return "Raytheon"; - case 0x13: return "Conexant"; - case 0x94: return "Seeq"; - case 0x15: return "NXP"; - case 0x16: return "Synertek"; - case 0x97: return "Texas Instruments"; - case 0x98: return "Toshiba"; - case 0x19: return "Xicor"; - case 0x1A: return "Zilog"; - case 0x9B: return "Eurotechnique"; - case 0x1C: return "Mitsubishi2"; - case 0x9D: return "Lucent"; - case 0x9E: return "Exel"; - case 0x1F: return "Atmel"; - case 0x20: return "SGS/Thomson"; - case 0xA1: return "Lattice Semiconductor"; - case 0xA2: return "NCR"; - case 0x23: return "Wafer Scale Integration"; - case 0xA4: return "International Business Machines"; - case 0x25: return "Tristar"; - case 0x26: return "Visic"; - case 0xA7: return "International CMOS Technology"; - case 0xA8: return "SSSI"; - case 0x29: return "Microchip Technology"; - case 0x2A: return "Ricoh"; - case 0xAB: return "VLSI"; - case 0x2C: return "Micron Technology"; - case 0xAD: return "Hynix Semiconductor"; - case 0xAE: return "OKI Semiconductor"; - case 0x2F: return "ACTEL"; - case 0xB0: return "Sharp"; - case 0x31: return "Catalyst"; - case 0x32: return "Panasonic"; - case 0xB3: return "IDT"; - case 0x34: return "Cypress"; - case 0xB5: return "Digital Equipment Corporation"; - case 0xB6: return "LSI Logic"; - case 0x37: return "Zarlink"; - case 0x38: return "UTMC"; - case 0xB9: return "Thinking Machine"; - case 0xBA: return "Thomson CSF"; - case 0x3B: return "Integrated CMOS"; - case 0xBC: return "Honeywell"; - case 0x3D: return "Tektronix"; - case 0x3E: return "Oracle Corporation"; - case 0xBF: return "Silicon Storage Technology"; - case 0x40: return "ProMos"; - case 0xC1: return "Infineon"; - case 0xC2: return "Macronix"; - case 0x43: return "Xerox"; - case 0xC4: return "Plus Logic"; - case 0x45: return "SanDisk Corporation"; - case 0x46: return "Elan Circuit Technology"; - case 0xC7: return "European Silicon"; - case 0xC8: return "Apple"; - case 0x49: return "Xilinx"; - case 0x4A: return "Compaq"; - case 0xCB: return "Protocol Engines"; - case 0x4C: return "SCI"; - case 0xCD: return "Seiko Instruments"; - case 0xCE: return "Samsung"; - case 0x4F: return "I3 Design System"; - case 0xD0: return "Klic"; - case 0x51: return "Crosspoint Solutions"; - case 0x52: return "Alliance Semiconductor"; - case 0xD3: return "Tandem"; - case 0x54: return "Hewlett-Packard"; - case 0xD5: return "Integrated Silicon Solutions"; - case 0xD6: return "Brooktree"; - case 0x57: return "New Media"; - case 0x58: return "MHS Electronic"; - case 0xD9: return "Performance Semiconductors"; - case 0xDA: return "Winbond Electronic"; - case 0x5B: return "Kawasaki Steel"; - case 0x5D: return "TECMAR"; - case 0x5E: return "Exar"; - case 0xDF: return "PCMCIA"; - case 0xE0: return "LG Semiconductor"; - case 0x61: return "Northern Telecom"; - case 0x62: return "Sanyo2"; - case 0xE3: return "Array Microsystems"; - case 0x64: return "Crystal Semiconductor"; - case 0xE5: return "Analog Devices"; - case 0xE6: return "PMC-Sierra"; - case 0x67: return "Asparix"; - case 0x68: return "Convex Computer"; - case 0xE9: return "Nimbus Technology"; - case 0x6B: return "Transwitch"; - case 0xEC: return "Micronas"; - case 0x6D: return "Canon"; - case 0x6E: return "Altera"; - case 0xEF: return "NEXCOM"; - case 0x70: return "Qualcomm"; - case 0xF1: return "Sony"; - case 0xF2: return "Cray Research"; - case 0x73: return "AMS"; - case 0xF4: return "Vitesse"; - case 0x75: return "Aster Electronics"; - case 0x76: return "Bay Networks"; - case 0xF7: return "Zentrum"; - case 0xF8: return "TRW"; - case 0x79: return "Thesys"; - case 0x7A: return "Solbourne Computer"; - case 0xFB: return "Allied-Signal"; - case 0x7C: return "Dialog Semiconductor"; - case 0xFD: return "Media Vision"; - case 0xFE: return "Numonyx Corporation"; - case 0x7F01: return "Cirrus Logic"; - case 0x7F02: return "National Instruments"; - case 0x7F04: return "Alcatel Mietec"; - case 0x7F07: return "JTAG Technologies"; - case 0x7F08: return "Loral"; - case 0x7F0B: return "Bestlink Systems"; - case 0x7F0D: return "GENNUM"; - case 0x7F0E: return "VideoLogic"; - case 0x7F10: return "Chip Express"; - case 0x7F13: return "TCSI"; - case 0x7F15: return "Hughes Aircraft"; - case 0x7F16: return "Lanstar Semiconductor"; - case 0x7F19: return "Music Semi"; - case 0x7F1A: return "Ericsson Components"; - case 0x7F1C: return "Eon Silicon Devices"; - case 0x7F1F: return "Integ.Memories Tech."; - case 0x7F20: return "Corollary Inc."; - case 0x7F23: return "EIV(Switzerland)"; - case 0x7F25: return "Zarlink(formerly Mitel)"; - case 0x7F26: return "Clearpoint"; - case 0x7F29: return "Vanguard"; - case 0x7F2A: return "Hagiwara Sys-Com"; - case 0x7F2C: return "Celestica"; - case 0x7F2F: return "Rohm Company Ltd."; - case 0x7F31: return "Libit Signal Processing"; - case 0x7F32: return "Enhanced Memories Inc."; - case 0x7F34: return "Adaptec Inc."; - case 0x7F37: return "AMIC Technology"; - case 0x7F38: return "Adobe Systems"; - case 0x7F3B: return "Newport Digital"; - case 0x7F3D: return "T Square"; - case 0x7F3E: return "Seiko Epson"; - case 0x7F40: return "Viking Components"; - case 0x7F43: return "Suwa Electronics"; - case 0x7F45: return "Micron CMS"; - case 0x7F46: return "American Computer &Digital Components Inc"; - case 0x7F49: return "CPU Design"; - case 0x7F4A: return "Price Point"; - case 0x7F4C: return "Tellabs"; - case 0x7F4F: return "Transcend Information"; - case 0x7F51: return "CKD Corporation Ltd."; - case 0x7F52: return "Capital Instruments, Inc."; - case 0x7F54: return "Linvex Technology"; - case 0x7F57: return "Dynamem, Inc."; - case 0x7F58: return "NERA ASA"; - case 0x7F5B: return "Acorn Computers"; - case 0x7F5D: return "Oak Technology, Inc."; - case 0x7F5E: return "Itec Memory"; - case 0x7F61: return "Wintec Industries"; - case 0x7F62: return "Super PC Memory"; - case 0x7F64: return "Galvantech"; - case 0x7F67: return "GateField"; - case 0x7F68: return "Integrated Memory System"; - case 0x7F6B: return "Goldenram"; - case 0x7F6D: return "Cimaron Communications"; - case 0x7F6E: return "Nippon Steel Semi.Corp."; - case 0x7F70: return "AMCC"; - case 0x7F73: return "Digital Microwave"; - case 0x7F75: return "MIMOS Semiconductor"; - case 0x7F76: return "Advanced Fibre"; - case 0x7F79: return "Acbel Polytech Inc."; - case 0x7F7A: return "Apacer Technology"; - case 0x7F7C: return "FOXCONN"; - case 0x7F83: return "ILC Data Device"; - case 0x7F85: return "Micro Linear"; - case 0x7F86: return "Univ.Of NC"; - case 0x7F89: return "Nchip"; - case 0x7F8A: return "Galileo Tech"; - case 0x7F8C: return "Graychip"; - case 0x7F8F: return "Robert Bosch"; - case 0x7F91: return "DATARAM"; - case 0x7F92: return "United Microelec Corp."; - case 0x7F94: return "Smart Modular"; - case 0x7F97: return "Qlogic"; - case 0x7F98: return "Kingston"; - case 0x7F9B: return "SpaSE"; - case 0x7F9D: return "Programmable Micro Corp"; - case 0x7F9E: return "DoD"; - case 0x7FA1: return "Dallas Semiconductor"; - case 0x7FA2: return "Omnivision"; - case 0x7FA4: return "Novatel Wireless"; - case 0x7FA7: return "Cabletron"; - case 0x7FA8: return "Silicon Technology"; - case 0x7FAB: return "Vantis"; - case 0x7FAD: return "Century"; - case 0x7FAE: return "Hal Computers"; - case 0x7FB0: return "Juniper Networks"; - case 0x7FB3: return "Tundra Semiconductor"; - case 0x7FB5: return "LightSpeed Semi."; - case 0x7FB6: return "ZSP Corp."; - case 0x7FB9: return "Dynachip"; - case 0x7FBA: return "PNY Electronics"; - case 0x7FBC: return "MMC Networks"; - case 0x7FBF: return "Broadcom"; - case 0x7FC1: return "V3 Semiconductor"; - case 0x7FC2: return "Flextronics(formerly Orbit)"; - case 0x7FC4: return "Transmeta"; - case 0x7FC7: return "Enhance 3000 Inc"; - case 0x7FC8: return "Tower Semiconductor"; - case 0x7FCB: return "Maxim Integrated Product"; - case 0x7FCD: return "Centaur Technology"; - case 0x7FCE: return "Unigen Corporation"; - case 0x7FD0: return "Memory Card Technology"; - case 0x7FD3: return "Aica Kogyo, Ltd."; - case 0x7FD5: return "MSC Vertriebs GmbH"; - case 0x7FD6: return "AKM Company, Ltd."; - case 0x7FD9: return "GSI Technology"; - case 0x7FDA: return "Dane-Elec (C Memory)"; - case 0x7FDC: return "Lara Technology"; - case 0x7FDF: return "Tanisys Technology"; - case 0x7FE0: return "Truevision"; - case 0x7FE3: return "MGV Memory"; - case 0x7FE5: return "Gadzoox Networks"; - case 0x7FE6: return "Multi Dimensional Cons."; - case 0x7FE9: return "Triscend"; - case 0x7FEA: return "XaQti"; - case 0x7FEC: return "Clear Logic"; - case 0x7FEF: return "Advantage Memory"; - case 0x7FF1: return "LeCroy"; - case 0x7FF2: return "Yamaha Corporation"; - case 0x7FF4: return "NetLogic Microsystems"; - case 0x7FF7: return "BF Goodrich Data."; - case 0x7FF8: return "Epigram"; - case 0x7FFB: return "Admor Memory"; - case 0x7FFD: return "Quadratics Superconductor"; - case 0x7FFE: return "3COM"; + case 0x01: return"AMD"; + case 0x02: return"AMI"; + case 0x83: return"Fairchild"; + case 0x04: return"Fujitsu"; + case 0x85: return"GTE"; + case 0x86: return"Harris"; + case 0x07: return"Hitachi"; + case 0x08: return"Inmos"; + case 0x89: return"Intel"; + case 0x8A: return"I.T.T."; + case 0x0B: return"Intersil"; + case 0x8C: return"Monolithic Memories"; + case 0x0D: return"Mostek"; + case 0x0E: return"Freescale"; + case 0x8F: return"National"; + case 0x10: return"NEC"; + case 0x91: return"RCA"; + case 0x92: return"Raytheon"; + case 0x13: return"Conexant"; + case 0x94: return"Seeq"; + case 0x15: return"NXP"; + case 0x16: return"Synertek"; + case 0x97: return"Texas Instruments"; + case 0x98: return"Toshiba"; + case 0x19: return"Xicor"; + case 0x1A: return"Zilog"; + case 0x9B: return"Eurotechnique"; + case 0x1C: return"Mitsubishi2"; + case 0x9D: return"Lucent"; + case 0x9E: return"Exel"; + case 0x1F: return"Atmel"; + case 0x20: return"SGS/Thomson"; + case 0xA1: return"Lattice Semiconductor"; + case 0xA2: return"NCR"; + case 0x23: return"Wafer Scale Integration"; + case 0xA4: return"International Business Machines"; + case 0x25: return"Tristar"; + case 0x26: return"Visic"; + case 0xA7: return"International CMOS Technology"; + case 0xA8: return"SSSI"; + case 0x29: return"Microchip Technology"; + case 0x2A: return"Ricoh"; + case 0xAB: return"VLSI"; + case 0x2C: return"Micron Technology"; + case 0xAD: return"Hynix Semiconductor"; + case 0xAE: return"OKI Semiconductor"; + case 0x2F: return"ACTEL"; + case 0xB0: return"Sharp"; + case 0x31: return"Catalyst"; + case 0x32: return"Panasonic"; + case 0xB3: return"IDT"; + case 0x34: return"Cypress"; + case 0xB5: return"Digital Equipment Corporation"; + case 0xB6: return"LSI Logic"; + case 0x37: return"Zarlink"; + case 0x38: return"UTMC"; + case 0xB9: return"Thinking Machine"; + case 0xBA: return"Thomson CSF"; + case 0x3B: return"Integrated CMOS"; + case 0xBC: return"Honeywell"; + case 0x3D: return"Tektronix"; + case 0x3E: return"Oracle Corporation"; + case 0xBF: return"Silicon Storage Technology"; + case 0x40: return"ProMos"; + case 0xC1: return"Infineon"; + case 0xC2: return"Macronix"; + case 0x43: return"Xerox"; + case 0xC4: return"Plus Logic"; + case 0x45: return"SanDisk Corporation"; + case 0x46: return"Elan Circuit Technology"; + case 0xC7: return"European Silicon"; + case 0xC8: return"Apple"; + case 0x49: return"Xilinx"; + case 0x4A: return"Compaq"; + case 0xCB: return"Protocol Engines"; + case 0x4C: return"SCI"; + case 0xCD: return"Seiko Instruments"; + case 0xCE: return"Samsung"; + case 0x4F: return"I3 Design System"; + case 0xD0: return"Klic"; + case 0x51: return"Crosspoint Solutions"; + case 0x52: return"Alliance Semiconductor"; + case 0xD3: return"Tandem"; + case 0x54: return"Hewlett-Packard"; + case 0xD5: return"Integrated Silicon Solutions"; + case 0xD6: return"Brooktree"; + case 0x57: return"New Media"; + case 0x58: return"MHS Electronic"; + case 0xD9: return"Performance Semiconductors"; + case 0xDA: return"Winbond Electronic"; + case 0x5B: return"Kawasaki Steel"; + case 0x5D: return"TECMAR"; + case 0x5E: return"Exar"; + case 0xDF: return"PCMCIA"; + case 0xE0: return"LG Semiconductor"; + case 0x61: return"Northern Telecom"; + case 0x62: return"Sanyo2"; + case 0xE3: return"Array Microsystems"; + case 0x64: return"Crystal Semiconductor"; + case 0xE5: return"Analog Devices"; + case 0xE6: return"PMC-Sierra"; + case 0x67: return"Asparix"; + case 0x68: return"Convex Computer"; + case 0xE9: return"Nimbus Technology"; + case 0x6B: return"Transwitch"; + case 0xEC: return"Micronas"; + case 0x6D: return"Canon"; + case 0x6E: return"Altera"; + case 0xEF: return"NEXCOM"; + case 0x70: return"Qualcomm"; + case 0xF1: return"Sony"; + case 0xF2: return"Cray Research"; + case 0x73: return"AMS"; + case 0xF4: return"Vitesse"; + case 0x75: return"Aster Electronics"; + case 0x76: return"Bay Networks"; + case 0xF7: return"Zentrum"; + case 0xF8: return"TRW"; + case 0x79: return"Thesys"; + case 0x7A: return"Solbourne Computer"; + case 0xFB: return"Allied-Signal"; + case 0x7C: return"Dialog Semiconductor"; + case 0xFD: return"Media Vision"; + case 0xFE: return"Numonyx Corporation"; + case 0x7F01: return"Cirrus Logic"; + case 0x7F02: return"National Instruments"; + case 0x7F04: return"Alcatel Mietec"; + case 0x7F07: return"JTAG Technologies"; + case 0x7F08: return"Loral"; + case 0x7F0B: return"Bestlink Systems"; + case 0x7F0D: return"GENNUM"; + case 0x7F0E: return"VideoLogic"; + case 0x7F10: return"Chip Express"; + case 0x7F13: return"TCSI"; + case 0x7F15: return"Hughes Aircraft"; + case 0x7F16: return"Lanstar Semiconductor"; + case 0x7F19: return"Music Semi"; + case 0x7F1A: return"Ericsson Components"; + case 0x7F1C: return"Eon Silicon Devices"; + case 0x7F1F: return"Integ.Memories Tech."; + case 0x7F20: return"Corollary Inc."; + case 0x7F23: return"EIV(Switzerland)"; + case 0x7F25: return"Zarlink(formerly Mitel)"; + case 0x7F26: return"Clearpoint"; + case 0x7F29: return"Vanguard"; + case 0x7F2A: return"Hagiwara Sys-Com"; + case 0x7F2C: return"Celestica"; + case 0x7F2F: return"Rohm Company Ltd."; + case 0x7F31: return"Libit Signal Processing"; + case 0x7F32: return"Enhanced Memories Inc."; + case 0x7F34: return"Adaptec Inc."; + case 0x7F37: return"AMIC Technology"; + case 0x7F38: return"Adobe Systems"; + case 0x7F3B: return"Newport Digital"; + case 0x7F3D: return"T Square"; + case 0x7F3E: return"Seiko Epson"; + case 0x7F40: return"Viking Components"; + case 0x7F43: return"Suwa Electronics"; + case 0x7F45: return"Micron CMS"; + case 0x7F46: return"American Computer &Digital Components Inc"; + case 0x7F49: return"CPU Design"; + case 0x7F4A: return"Price Point"; + case 0x7F4C: return"Tellabs"; + case 0x7F4F: return"Transcend Information"; + case 0x7F51: return"CKD Corporation Ltd."; + case 0x7F52: return"Capital Instruments, Inc."; + case 0x7F54: return"Linvex Technology"; + case 0x7F57: return"Dynamem, Inc."; + case 0x7F58: return"NERA ASA"; + case 0x7F5B: return"Acorn Computers"; + case 0x7F5D: return"Oak Technology, Inc."; + case 0x7F5E: return"Itec Memory"; + case 0x7F61: return"Wintec Industries"; + case 0x7F62: return"Super PC Memory"; + case 0x7F64: return"Galvantech"; + case 0x7F67: return"GateField"; + case 0x7F68: return"Integrated Memory System"; + case 0x7F6B: return"Goldenram"; + case 0x7F6D: return"Cimaron Communications"; + case 0x7F6E: return"Nippon Steel Semi.Corp."; + case 0x7F70: return"AMCC"; + case 0x7F73: return"Digital Microwave"; + case 0x7F75: return"MIMOS Semiconductor"; + case 0x7F76: return"Advanced Fibre"; + case 0x7F79: return"Acbel Polytech Inc."; + case 0x7F7A: return"Apacer Technology"; + case 0x7F7C: return"FOXCONN"; + case 0x7F83: return"ILC Data Device"; + case 0x7F85: return"Micro Linear"; + case 0x7F86: return"Univ.Of NC"; + case 0x7F89: return"Nchip"; + case 0x7F8A: return"Galileo Tech"; + case 0x7F8C: return"Graychip"; + case 0x7F8F: return"Robert Bosch"; + case 0x7F91: return"DATARAM"; + case 0x7F92: return"United Microelec Corp."; + case 0x7F94: return"Smart Modular"; + case 0x7F97: return"Qlogic"; + case 0x7F98: return"Kingston"; + case 0x7F9B: return"SpaSE"; + case 0x7F9D: return"Programmable Micro Corp"; + case 0x7F9E: return"DoD"; + case 0x7FA1: return"Dallas Semiconductor"; + case 0x7FA2: return"Omnivision"; + case 0x7FA4: return"Novatel Wireless"; + case 0x7FA7: return"Cabletron"; + case 0x7FA8: return"Silicon Technology"; + case 0x7FAB: return"Vantis"; + case 0x7FAD: return"Century"; + case 0x7FAE: return"Hal Computers"; + case 0x7FB0: return"Juniper Networks"; + case 0x7FB3: return"Tundra Semiconductor"; + case 0x7FB5: return"LightSpeed Semi."; + case 0x7FB6: return"ZSP Corp."; + case 0x7FB9: return"Dynachip"; + case 0x7FBA: return"PNY Electronics"; + case 0x7FBC: return"MMC Networks"; + case 0x7FBF: return"Broadcom"; + case 0x7FC1: return"V3 Semiconductor"; + case 0x7FC2: return"Flextronics(formerly Orbit)"; + case 0x7FC4: return"Transmeta"; + case 0x7FC7: return"Enhance 3000 Inc"; + case 0x7FC8: return"Tower Semiconductor"; + case 0x7FCB: return"Maxim Integrated Product"; + case 0x7FCD: return"Centaur Technology"; + case 0x7FCE: return"Unigen Corporation"; + case 0x7FD0: return"Memory Card Technology"; + case 0x7FD3: return"Aica Kogyo, Ltd."; + case 0x7FD5: return"MSC Vertriebs GmbH"; + case 0x7FD6: return"AKM Company, Ltd."; + case 0x7FD9: return"GSI Technology"; + case 0x7FDA: return"Dane-Elec (C Memory)"; + case 0x7FDC: return"Lara Technology"; + case 0x7FDF: return"Tanisys Technology"; + case 0x7FE0: return"Truevision"; + case 0x7FE3: return"MGV Memory"; + case 0x7FE5: return"Gadzoox Networks"; + case 0x7FE6: return"Multi Dimensional Cons."; + case 0x7FE9: return"Triscend"; + case 0x7FEA: return"XaQti"; + case 0x7FEC: return"Clear Logic"; + case 0x7FEF: return"Advantage Memory"; + case 0x7FF1: return"LeCroy"; + case 0x7FF2: return"Yamaha Corporation"; + case 0x7FF4: return"NetLogic Microsystems"; + case 0x7FF7: return"BF Goodrich Data."; + case 0x7FF8: return"Epigram"; + case 0x7FFB: return"Admor Memory"; + case 0x7FFD: return"Quadratics Superconductor"; + case 0x7FFE: return"3COM"; #endregion JEDEC - case 0x0100: return "Digital Equipment Corporation"; - case 0x0101: return "3Com Corporation"; - case 0x0102: return "Megahertz Corporation"; - case 0x0104: return "Socket Communications"; - case 0x0105: return "TDK Corporation"; - case 0x0108: return "Standard Microsystems Corporation"; - case 0x0109: return "Motorola Corporation"; - case 0x010b: return "National Instruments"; - case 0x0115: return "US Robotics Corporation"; - case 0x0121: return "Olicom"; - case 0x0126: return "Proxim"; - case 0x0128: return "Megahertz Corporation"; - case 0x012F: return "Adaptec Corporation"; - case 0x0137: return "Quatech"; - case 0x0138: return "Compaq"; - case 0x0140: return "Ositech"; - case 0x0143: return "D-Link"; - case 0x0149: return "Netgear"; - case 0x014D: return "Simple Technology"; - case 0x0156: return "Lucent Technologies"; - case 0x015F: return "Aironet Wireless Communications"; - case 0x016B: return "Ericsson"; - case 0x016C: return "Psion"; - case 0x0183: return "Compaq"; - case 0x0186: return "Kingston"; - case 0x0192: return "Sierra Wireless"; - case 0x0194: return "Dayna Corporation"; - case 0x01a6: return "Raytheon"; - case 0x01BF: return "Belkin"; - case 0x01EB: return "Bay Networks"; - case 0x0200: return "Farallon Communications"; - case 0x021B: return "Telecom Device"; - case 0x023D: return "Nokia Communications"; - case 0x0250: return "Samsung"; - case 0x0264: return "Anycom"; - case 0x0268: return "Alvarion Ltd."; - case 0x026C: return "Symbol"; - case 0x026F: return "BUFFALO"; - case 0x0274: return "The Linksys Group"; - case 0x0288: return "NEC Infrontia"; - case 0x028A: return "I-O DATA"; - case 0x02AA: return "Asustek Computer"; - case 0x02AC: return "Siemens"; - case 0x02D2: return "Microsoft Corporation"; - case 0x02DF: return "AmbiCom Inc"; - case 0x0a02: return "BreezeCOM"; - case 0x10CD: return "NewMedia"; - case 0x1668: return "ACTIONTEC"; - case 0x3401: return "Lasat Communications A/S"; - case 0x4E01: return "Lexar Media"; - case 0x5241: return "Archos"; - case 0x890F: return "Dual"; - case 0x8A01: return "Compex Corporation"; - case 0xC001: return "Contec"; - case 0xC00B: return "MACNICA"; - case 0xC00C: return "Roland"; - case 0xC00F: return "Corega K.K."; - case 0xC012: return "Hagiwara SYS-COM"; - case 0xC015: return "RATOC System Inc."; - case 0xC020: return "NextCom K.K."; - case 0xC250: return "EMTAC Technology Corporation"; - case 0xD601: return "Elsa"; - default: return $"Unknown vendor id 0x{id:X4}"; + case 0x0100: return"Digital Equipment Corporation"; + case 0x0101: return"3Com Corporation"; + case 0x0102: return"Megahertz Corporation"; + case 0x0104: return"Socket Communications"; + case 0x0105: return"TDK Corporation"; + case 0x0108: return"Standard Microsystems Corporation"; + case 0x0109: return"Motorola Corporation"; + case 0x010b: return"National Instruments"; + case 0x0115: return"US Robotics Corporation"; + case 0x0121: return"Olicom"; + case 0x0126: return"Proxim"; + case 0x0128: return"Megahertz Corporation"; + case 0x012F: return"Adaptec Corporation"; + case 0x0137: return"Quatech"; + case 0x0138: return"Compaq"; + case 0x0140: return"Ositech"; + case 0x0143: return"D-Link"; + case 0x0149: return"Netgear"; + case 0x014D: return"Simple Technology"; + case 0x0156: return"Lucent Technologies"; + case 0x015F: return"Aironet Wireless Communications"; + case 0x016B: return"Ericsson"; + case 0x016C: return"Psion"; + case 0x0183: return"Compaq"; + case 0x0186: return"Kingston"; + case 0x0192: return"Sierra Wireless"; + case 0x0194: return"Dayna Corporation"; + case 0x01a6: return"Raytheon"; + case 0x01BF: return"Belkin"; + case 0x01EB: return"Bay Networks"; + case 0x0200: return"Farallon Communications"; + case 0x021B: return"Telecom Device"; + case 0x023D: return"Nokia Communications"; + case 0x0250: return"Samsung"; + case 0x0264: return"Anycom"; + case 0x0268: return"Alvarion Ltd."; + case 0x026C: return"Symbol"; + case 0x026F: return"BUFFALO"; + case 0x0274: return"The Linksys Group"; + case 0x0288: return"NEC Infrontia"; + case 0x028A: return"I-O DATA"; + case 0x02AA: return"Asustek Computer"; + case 0x02AC: return"Siemens"; + case 0x02D2: return"Microsoft Corporation"; + case 0x02DF: return"AmbiCom Inc"; + case 0x0a02: return"BreezeCOM"; + case 0x10CD: return"NewMedia"; + case 0x1668: return"ACTIONTEC"; + case 0x3401: return"Lasat Communications A/S"; + case 0x4E01: return"Lexar Media"; + case 0x5241: return"Archos"; + case 0x890F: return"Dual"; + case 0x8A01: return"Compex Corporation"; + case 0xC001: return"Contec"; + case 0xC00B: return"MACNICA"; + case 0xC00C: return"Roland"; + case 0xC00F: return"Corega K.K."; + case 0xC012: return"Hagiwara SYS-COM"; + case 0xC015: return"RATOC System Inc."; + case 0xC020: return"NextCom K.K."; + case 0xC250: return"EMTAC Technology Corporation"; + case 0xD601: return"Elsa"; + default: return$"Unknown vendor id 0x{id:X4}"; } } } diff --git a/SCSI/DiscStructureCapabilities.cs b/SCSI/DiscStructureCapabilities.cs index 5a2aa51..6b937a2 100644 --- a/SCSI/DiscStructureCapabilities.cs +++ b/SCSI/DiscStructureCapabilities.cs @@ -35,33 +35,16 @@ using System.Diagnostics.CodeAnalysis; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] public static class DiscStructureCapabilities { - public struct Capability - { - /// - /// READ/SEND DISC STRUCTURE format code - /// - public byte FormatCode; - /// - /// Supported in SEND DISC STRUCTURE - /// - public bool SDS; - /// - /// Supported in READ DISC STRUCTURE - /// - public bool RDS; - } - public static Capability[] Decode(byte[] response) { ushort len = (ushort)((response[0] << 8) + response[1]); - if(len + 2 != response.Length) return null; + if(len + 2 != response.Length) + return null; List caps = new List(); @@ -69,17 +52,27 @@ namespace DiscImageChef.Decoders.SCSI while(offset < response.Length) { - Capability cap = new Capability + var cap = new Capability { - FormatCode = response[offset], - SDS = (response[offset + 1] & 0x80) == 0x80, - RDS = (response[offset + 1] & 0x40) == 0x40 + FormatCode = response[offset], SDS = (response[offset + 1] & 0x80) == 0x80, + RDS = (response[offset + 1] & 0x40) == 0x40 }; + caps.Add(cap); offset += 4; } return caps.ToArray(); } + + public struct Capability + { + /// READ/SEND DISC STRUCTURE format code + public byte FormatCode; + /// Supported in SEND DISC STRUCTURE + public bool SDS; + /// Supported in READ DISC STRUCTURE + public bool RDS; + } } } \ No newline at end of file diff --git a/SCSI/EVPD.cs b/SCSI/EVPD.cs index a147ec9..2baa925 100644 --- a/SCSI/EVPD.cs +++ b/SCSI/EVPD.cs @@ -40,23 +40,21 @@ using DiscImageChef.Decoders.ATA; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] - [SuppressMessage("ReSharper", "UnassignedField.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global"), + SuppressMessage("ReSharper", "UnassignedField.Global")] public static class EVPD { - /// - /// Decodes VPD page 0x00: Supported VPD pages - /// + /// Decodes VPD page 0x00: Supported VPD pages /// A byte array containing all supported VPD pages. /// Page 0x00. public static byte[] DecodePage00(byte[] page) { - if(page?[1] != 0) return null; + if(page?[1] != 0) + return null; - if(page.Length != page[3] + 4) return null; + if(page.Length != page[3] + 4) + return null; byte[] decoded = new byte[page.Length - 4]; @@ -65,18 +63,20 @@ namespace DiscImageChef.Decoders.SCSI return decoded; } - /// - /// Decides VPD pages 0x01 to 0x7F: ASCII Information - /// + /// Decides VPD pages 0x01 to 0x7F: ASCII Information /// An ASCII string with the contents of the page. /// Page 0x01-0x7F. public static string DecodeASCIIPage(byte[] page) { - if(page == null) return null; + if(page == null) + return null; - if(page[1] == 0 || page[1] > 0x7F) return null; + if(page[1] == 0 || + page[1] > 0x7F) + return null; - if(page.Length != page[3] + 4) return null; + if(page.Length != page[3] + 4) + return null; byte[] ascii = new byte[page[4]]; @@ -85,16 +85,16 @@ namespace DiscImageChef.Decoders.SCSI return StringHandlers.CToString(ascii); } - /// - /// Decodes VPD page 0x80: Unit Serial Number - /// + /// Decodes VPD page 0x80: Unit Serial Number /// The unit serial number. /// Page 0x80. public static string DecodePage80(byte[] page) { - if(page?[1] != 0x80) return null; + if(page?[1] != 0x80) + return null; - if(page.Length != page[3] + 4) return null; + if(page.Length != page[3] + 4) + return null; byte[] ascii = new byte[page.Length - 4]; @@ -103,58 +103,131 @@ namespace DiscImageChef.Decoders.SCSI return StringHandlers.CToString(ascii); } + /// Decodes VPD page 0x82: ASCII implemented operating definition + /// ASCII implemented operating definition. + /// Page 0x82. + public static string DecodePage82(byte[] page) + { + if(page?[1] != 0x82) + return null; + + if(page.Length != page[3] + 4) + return null; + + byte[] ascii = new byte[page.Length - 4]; + + Array.Copy(page, 4, ascii, 0, page.Length - 4); + + return StringHandlers.CToString(ascii); + } + + #region EVPD Page 0xB1: Manufacturer-assigned Serial Number page + public static string DecodePageB1(byte[] page) + { + if(page?[1] != 0xB1) + return null; + + if(page.Length != page[3] + 4) + return null; + + byte[] ascii = new byte[page.Length - 4]; + + Array.Copy(page, 4, ascii, 0, page.Length - 4); + + return StringHandlers.CToString(ascii).Trim(); + } + #endregion EVPD Page 0xB1: Manufacturer-assigned Serial Number page + + #region EVPD Page 0xB2: TapeAlert Supported Flags page + public static ulong DecodePageB2(byte[] page) + { + if(page?[1] != 0xB2) + return 0; + + if(page.Length != 12) + return 0; + + byte[] bitmap = new byte[8]; + + Array.Copy(page, 4, bitmap, 0, 8); + + return BitConverter.ToUInt64(bitmap.Reverse().ToArray(), 0); + } + #endregion EVPD Page 0xB2: TapeAlert Supported Flags page + + #region EVPD Page 0xB3: Automation Device Serial Number page + public static string DecodePageB3(byte[] page) + { + if(page?[1] != 0xB3) + return null; + + if(page.Length != page[3] + 4) + return null; + + byte[] ascii = new byte[page.Length - 4]; + + Array.Copy(page, 4, ascii, 0, page.Length - 4); + + return StringHandlers.CToString(ascii).Trim(); + } + #endregion EVPD Page 0xB3: Automation Device Serial Number page + + #region EVPD Page 0xB4: Data Transfer Device Element Address page + public static string DecodePageB4(byte[] page) + { + if(page?[1] != 0xB3) + return null; + + if(page.Length != page[3] + 4) + return null; + + byte[] element = new byte[page.Length - 4]; + var sb = new StringBuilder(); + + foreach(byte b in element) + sb.AppendFormat("{0:X2}", b); + + return sb.ToString(); + } + #endregion EVPD Page 0xB4: Data Transfer Device Element Address page + #region EVPD Page 0x81: Implemented operating definition page - /// - /// Implemented operating definition page - /// Page code 0x81 - /// + /// Implemented operating definition page Page code 0x81 public struct Page_81 { - /// - /// The peripheral qualifier. - /// + /// The peripheral qualifier. public PeripheralQualifiers PeripheralQualifier; - /// - /// The type of the peripheral device. - /// + /// The type of the peripheral device. public PeripheralDeviceTypes PeripheralDeviceType; - /// - /// The page code. - /// + /// The page code. public byte PageCode; - /// - /// The length of the page. - /// + /// The length of the page. public byte PageLength; - /// - /// Current operating definition - /// + /// Current operating definition public ScsiDefinitions Current; - /// - /// Default operating definition - /// + /// Default operating definition public ScsiDefinitions Default; - /// - /// Support operating definition list - /// + /// Support operating definition list public ScsiDefinitions[] Supported; } public static Page_81? DecodePage_81(byte[] pageResponse) { - if(pageResponse?[1] != 0x81) return null; + if(pageResponse?[1] != 0x81) + return null; - if(pageResponse[3] + 4 != pageResponse.Length) return null; + if(pageResponse[3] + 4 != pageResponse.Length) + return null; - if(pageResponse.Length < 6) return null; + if(pageResponse.Length < 6) + return null; - Page_81 decoded = new Page_81 + var decoded = new Page_81 { PeripheralQualifier = (PeripheralQualifiers)((pageResponse[0] & 0xE0) >> 5), - PeripheralDeviceType = (PeripheralDeviceTypes)(pageResponse[0] & 0x1F), - PageLength = (byte)(pageResponse[3] + 4), - Current = (ScsiDefinitions)(pageResponse[4] & 0x7F), - Default = (ScsiDefinitions)(pageResponse[5] & 0x7F) + PeripheralDeviceType = (PeripheralDeviceTypes)(pageResponse[0] & 0x1F), + PageLength = (byte)(pageResponse[3] + 4), Current = (ScsiDefinitions)(pageResponse[4] & 0x7F), + Default = (ScsiDefinitions)(pageResponse[5] & 0x7F) }; int position = 6; @@ -162,7 +235,7 @@ namespace DiscImageChef.Decoders.SCSI while(position < pageResponse.Length) { - ScsiDefinitions definition = (ScsiDefinitions)(pageResponse[position] & 0x7F); + var definition = (ScsiDefinitions)(pageResponse[position] & 0x7F); position++; definitions.Add(definition); } @@ -178,21 +251,22 @@ namespace DiscImageChef.Decoders.SCSI { switch(definition) { - case ScsiDefinitions.Current: return ""; - case ScsiDefinitions.CCS: return "CCS"; - case ScsiDefinitions.SCSI1: return "SCSI-1"; - case ScsiDefinitions.SCSI2: return "SCSI-2"; - case ScsiDefinitions.SCSI3: return "SCSI-3"; - default: return $"Unknown definition code {(byte)definition}"; + case ScsiDefinitions.Current: return""; + case ScsiDefinitions.CCS: return"CCS"; + case ScsiDefinitions.SCSI1: return"SCSI-1"; + case ScsiDefinitions.SCSI2: return"SCSI-2"; + case ScsiDefinitions.SCSI3: return"SCSI-3"; + default: return$"Unknown definition code {(byte)definition}"; } } public static string PrettifyPage_81(Page_81? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; - Page_81 page = modePage.Value; - StringBuilder sb = new StringBuilder(); + Page_81 page = modePage.Value; + var sb = new StringBuilder(); sb.AppendLine("SCSI Implemented operating definitions:"); @@ -202,10 +276,12 @@ namespace DiscImageChef.Decoders.SCSI if(page.Supported.Length == 0) { sb.AppendLine("\tThere are no supported definitions"); + return sb.ToString(); } sb.AppendLine("\tSupported operating definitions:"); + foreach(ScsiDefinitions definition in page.Supported) sb.AppendFormat("\t\t{0}", DefinitionToString(definition)).AppendLine(); @@ -213,174 +289,85 @@ namespace DiscImageChef.Decoders.SCSI } #endregion EVPD Page 0x81: Implemented operating definition page - /// - /// Decodes VPD page 0x82: ASCII implemented operating definition - /// - /// ASCII implemented operating definition. - /// Page 0x82. - public static string DecodePage82(byte[] page) - { - if(page?[1] != 0x82) return null; - - if(page.Length != page[3] + 4) return null; - - byte[] ascii = new byte[page.Length - 4]; - - Array.Copy(page, 4, ascii, 0, page.Length - 4); - - return StringHandlers.CToString(ascii); - } - #region EVPD Page 0x83: Device identification page public enum IdentificationAssociation : byte { - /// - /// Identifier field is associated with the addressed logical unit - /// - LogicalUnit = 0, - /// - /// Identifier field is associated with the target port - /// - TargetPort = 1, - /// - /// Identifier field is associated with the target device that contains the LUN - /// + /// Identifier field is associated with the addressed logical unit + LogicalUnit = 0, /// Identifier field is associated with the target port + TargetPort = 1, /// Identifier field is associated with the target device that contains the LUN TargetDevice = 2 } public enum IdentificationCodeSet : byte { - /// - /// Identifier is binary - /// - Binary = 1, - /// - /// Identifier is pure ASCII - /// - ASCII = 2, - /// - /// Identifier is in UTF-8 - /// + /// Identifier is binary + Binary = 1, /// Identifier is pure ASCII + ASCII = 2, /// Identifier is in UTF-8 UTF8 = 3 } public enum IdentificationTypes : byte { - /// - /// No assignment authority was used and there is no guarantee the identifier is unique - /// - NoAuthority = 0, - /// - /// Concatenates vendor and product identifier from INQUIRY plus unit serial number from page 80h - /// - Inquiry = 1, - /// - /// Identifier is a 64-bit IEEE EUI-64, or extended - /// - EUI = 2, - /// - /// Identifier is compatible with 64-bit FC-PH Name_Identifier - /// - NAA = 3, - /// - /// Identifier to relative port in device - /// - Relative = 4, - /// - /// Identifier to group of target ports in device - /// - TargetPortGroup = 5, - /// - /// Identifier to group of target LUNs in device - /// - LogicalUnitGroup = 6, - /// - /// MD5 of device identification values - /// - MD5 = 7, - /// - /// SCSI name string - /// - SCSI = 8, - /// - /// Protocol specific port identifier - /// + /// No assignment authority was used and there is no guarantee the identifier is unique + NoAuthority = 0, /// Concatenates vendor and product identifier from INQUIRY plus unit serial number from page 80h + Inquiry = 1, /// Identifier is a 64-bit IEEE EUI-64, or extended + EUI = 2, /// Identifier is compatible with 64-bit FC-PH Name_Identifier + NAA = 3, /// Identifier to relative port in device + Relative = 4, /// Identifier to group of target ports in device + TargetPortGroup = 5, /// Identifier to group of target LUNs in device + LogicalUnitGroup = 6, /// MD5 of device identification values + MD5 = 7, /// SCSI name string + SCSI = 8, /// Protocol specific port identifier ProtocolSpecific = 9 } public struct IdentificatonDescriptor { - /// - /// Protocol identifier - /// + /// Protocol identifier public ProtocolIdentifiers ProtocolIdentifier; - /// - /// Defines how the identifier is stored - /// + /// Defines how the identifier is stored public IdentificationCodeSet CodeSet; - /// - /// Set if protocol identifier is valid - /// + /// Set if protocol identifier is valid public bool PIV; - /// - /// Identifies which decide the identifier associates with - /// + /// Identifies which decide the identifier associates with public IdentificationAssociation Association; - /// - /// Defines the type of the identifier - /// + /// Defines the type of the identifier public IdentificationTypes Type; - /// - /// Length of the identifier - /// + /// Length of the identifier public byte Length; - /// - /// Identifier as a string if applicable - /// + /// Identifier as a string if applicable public string ASCII; - /// - /// Binary identifier - /// + /// Binary identifier public byte[] Binary; } - /// - /// Device identification page - /// Page code 0x83 - /// + /// Device identification page Page code 0x83 public struct Page_83 { - /// - /// The peripheral qualifier. - /// + /// The peripheral qualifier. public PeripheralQualifiers PeripheralQualifier; - /// - /// The type of the peripheral device. - /// + /// The type of the peripheral device. public PeripheralDeviceTypes PeripheralDeviceType; - /// - /// The page code. - /// + /// The page code. public byte PageCode; - /// - /// The length of the page. - /// + /// The length of the page. public byte PageLength; - /// - /// The descriptors. - /// + /// The descriptors. public IdentificatonDescriptor[] Descriptors; } public static Page_83? DecodePage_83(byte[] pageResponse) { - if(pageResponse?[1] != 0x83) return null; + if(pageResponse?[1] != 0x83) + return null; - if(pageResponse[3] + 4 != pageResponse.Length) return null; + if(pageResponse[3] + 4 != pageResponse.Length) + return null; - if(pageResponse.Length < 6) return null; + if(pageResponse.Length < 6) + return null; - Page_83 decoded = new Page_83 + var decoded = new Page_83 { PeripheralQualifier = (PeripheralQualifiers)((pageResponse[0] & 0xE0) >> 5), PeripheralDeviceType = (PeripheralDeviceTypes)(pageResponse[0] & 0x1F), @@ -392,7 +379,7 @@ namespace DiscImageChef.Decoders.SCSI while(position < pageResponse.Length) { - IdentificatonDescriptor descriptor = new IdentificatonDescriptor + var descriptor = new IdentificatonDescriptor { ProtocolIdentifier = (ProtocolIdentifiers)((pageResponse[position] & 0xF0) >> 4), CodeSet = (IdentificationCodeSet)(pageResponse[position] & 0x0F), @@ -401,20 +388,27 @@ namespace DiscImageChef.Decoders.SCSI Type = (IdentificationTypes)(pageResponse[position + 1] & 0x0F), Length = pageResponse[position + 3] }; + descriptor.Binary = new byte[descriptor.Length]; + if(descriptor.Length + position + 4 >= pageResponse.Length) descriptor.Length = (byte)(pageResponse.Length - position - 4); + Array.Copy(pageResponse, position + 4, descriptor.Binary, 0, descriptor.Length); + switch(descriptor.CodeSet) { case IdentificationCodeSet.ASCII: descriptor.ASCII = StringHandlers.CToString(descriptor.Binary); + break; case IdentificationCodeSet.UTF8: descriptor.ASCII = Encoding.UTF8.GetString(descriptor.Binary); + break; default: descriptor.ASCII = ""; + break; } @@ -431,16 +425,18 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyPage_83(Page_83? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; - Page_83 page = modePage.Value; - StringBuilder sb = new StringBuilder(); + Page_83 page = modePage.Value; + var sb = new StringBuilder(); sb.AppendLine("SCSI Device identification:"); if(page.Descriptors.Length == 0) { sb.AppendLine("\tThere are no identifiers"); + return sb.ToString(); } @@ -450,65 +446,84 @@ namespace DiscImageChef.Decoders.SCSI { case IdentificationAssociation.LogicalUnit: sb.AppendLine("\tIdentifier belongs to addressed logical unit"); + break; case IdentificationAssociation.TargetPort: sb.AppendLine("\tIdentifier belongs to target port"); + break; case IdentificationAssociation.TargetDevice: sb.AppendLine("\tIdentifier belongs to target device that contains the addressed logical unit"); + break; default: sb.AppendFormat("\tIndentifier has unknown association with code {0}", (byte)descriptor.Association).AppendLine(); + break; } if(descriptor.PIV) { string protocol; + switch(descriptor.ProtocolIdentifier) { case ProtocolIdentifiers.ADT: protocol = "Automation/Drive Interface Transport"; + break; case ProtocolIdentifiers.ATA: protocol = "AT Attachment Interface (ATA/ATAPI)"; + break; case ProtocolIdentifiers.FibreChannel: protocol = "Fibre Channel"; + break; case ProtocolIdentifiers.Firewire: protocol = "IEEE 1394"; + break; case ProtocolIdentifiers.iSCSI: protocol = "Internet SCSI"; + break; case ProtocolIdentifiers.NoProtocol: protocol = "no specific"; + break; case ProtocolIdentifiers.PCIe: protocol = "PCI Express"; + break; case ProtocolIdentifiers.RDMAP: protocol = "SCSI Remote Direct Memory Access"; + break; case ProtocolIdentifiers.SAS: protocol = "Serial Attachment SCSI"; + break; case ProtocolIdentifiers.SCSI: protocol = "Parallel SCSI"; + break; case ProtocolIdentifiers.SCSIe: protocol = "SCSI over PCI Express"; + break; case ProtocolIdentifiers.SSA: protocol = "SSA"; + break; case ProtocolIdentifiers.UAS: protocol = "USB Attached SCSI"; + break; default: protocol = $"unknown code {(byte)descriptor.ProtocolIdentifier}"; + break; } @@ -523,15 +538,18 @@ namespace DiscImageChef.Decoders.SCSI case IdentificationCodeSet.ASCII: case IdentificationCodeSet.UTF8: sb.AppendFormat("\tVendor descriptor contains: {0}", descriptor.ASCII).AppendLine(); + break; case IdentificationCodeSet.Binary: sb.AppendFormat("\tVendor descriptor contains binary data (hex): {0}", PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)).AppendLine(); + break; default: sb.AppendFormat("\tVendor descriptor contains unknown kind {1} of data (hex): {0}", PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40), (byte)descriptor.CodeSet).AppendLine(); + break; } @@ -542,15 +560,18 @@ namespace DiscImageChef.Decoders.SCSI case IdentificationCodeSet.ASCII: case IdentificationCodeSet.UTF8: sb.AppendFormat("\tInquiry descriptor contains: {0}", descriptor.ASCII).AppendLine(); + break; case IdentificationCodeSet.Binary: sb.AppendFormat("\tInquiry descriptor contains binary data (hex): {0}", PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)).AppendLine(); + break; default: sb.AppendFormat("\tInquiry descriptor contains unknown kind {1} of data (hex): {0}", PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40), (byte)descriptor.CodeSet).AppendLine(); + break; } @@ -562,6 +583,7 @@ namespace DiscImageChef.Decoders.SCSI else { sb.AppendFormat("\tIEEE EUI-64: {0:X2}", descriptor.Binary[0]); + for(int i = 1; i < descriptor.Binary.Length; i++) sb.AppendFormat(":{0:X2}", descriptor.Binary[i]); @@ -576,6 +598,7 @@ namespace DiscImageChef.Decoders.SCSI else { sb.AppendFormat("\tNAA: {0:X2}", descriptor.Binary[0]); + for(int i = 1; i < descriptor.Binary.Length; i++) sb.AppendFormat(":{0:X2}", descriptor.Binary[i]); @@ -590,6 +613,7 @@ namespace DiscImageChef.Decoders.SCSI else sb.AppendFormat("\tRelative target port identifier: {0}", (descriptor.Binary[2] << 8) + descriptor.Binary[3]).AppendLine(); + break; case IdentificationTypes.TargetPortGroup: if(descriptor.CodeSet == IdentificationCodeSet.ASCII || @@ -598,6 +622,7 @@ namespace DiscImageChef.Decoders.SCSI else sb.AppendFormat("\tTarget group identifier: {0}", (descriptor.Binary[2] << 8) + descriptor.Binary[3]).AppendLine(); + break; case IdentificationTypes.LogicalUnitGroup: if(descriptor.CodeSet == IdentificationCodeSet.ASCII || @@ -606,6 +631,7 @@ namespace DiscImageChef.Decoders.SCSI else sb.AppendFormat("\tLogical unit group identifier: {0}", (descriptor.Binary[2] << 8) + descriptor.Binary[3]).AppendLine(); + break; case IdentificationTypes.MD5: if(descriptor.CodeSet == IdentificationCodeSet.ASCII || @@ -614,6 +640,7 @@ namespace DiscImageChef.Decoders.SCSI else { sb.AppendFormat("\tMD5 logical unit identifier: {0:x2}", descriptor.Binary[0]); + for(int i = 1; i < descriptor.Binary.Length; i++) sb.AppendFormat("{0:x2}", descriptor.Binary[i]); @@ -628,6 +655,7 @@ namespace DiscImageChef.Decoders.SCSI else sb.AppendFormat("\tSCSI name string identifier (hex): {0}", PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)).AppendLine(); + break; case IdentificationTypes.ProtocolSpecific: { @@ -635,86 +663,100 @@ namespace DiscImageChef.Decoders.SCSI switch(descriptor.ProtocolIdentifier) { case ProtocolIdentifiers.ADT: - sb - .AppendFormat("\tProtocol (Automation/Drive Interface Transport) specific descriptor with unknown format (hex): {0}", - PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)) - .AppendLine(); + sb. + AppendFormat("\tProtocol (Automation/Drive Interface Transport) specific descriptor with unknown format (hex): {0}", + PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)). + AppendLine(); + break; case ProtocolIdentifiers.ATA: - sb - .AppendFormat("\tProtocol (ATA/ATAPI) specific descriptor with unknown format (hex): {0}", - PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)) - .AppendLine(); + sb. + AppendFormat("\tProtocol (ATA/ATAPI) specific descriptor with unknown format (hex): {0}", + PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)). + AppendLine(); + break; case ProtocolIdentifiers.FibreChannel: - sb - .AppendFormat("\tProtocol (Fibre Channel) specific descriptor with unknown format (hex): {0}", - PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)) - .AppendLine(); + sb. + AppendFormat("\tProtocol (Fibre Channel) specific descriptor with unknown format (hex): {0}", + PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)). + AppendLine(); + break; case ProtocolIdentifiers.Firewire: - sb - .AppendFormat("\tProtocol (IEEE 1394) specific descriptor with unknown format (hex): {0}", - PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)) - .AppendLine(); + sb. + AppendFormat("\tProtocol (IEEE 1394) specific descriptor with unknown format (hex): {0}", + PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)). + AppendLine(); + break; case ProtocolIdentifiers.iSCSI: - sb - .AppendFormat("\tProtocol (Internet SCSI) specific descriptor with unknown format (hex): {0}", - PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)) - .AppendLine(); + sb. + AppendFormat("\tProtocol (Internet SCSI) specific descriptor with unknown format (hex): {0}", + PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)). + AppendLine(); + break; case ProtocolIdentifiers.NoProtocol: - sb - .AppendFormat("\tProtocol (unknown) specific descriptor with unknown format (hex): {0}", - PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)) - .AppendLine(); + sb. + AppendFormat("\tProtocol (unknown) specific descriptor with unknown format (hex): {0}", + PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)). + AppendLine(); + break; case ProtocolIdentifiers.PCIe: - sb - .AppendFormat("\tProtocol (PCI Express) specific descriptor with unknown format (hex): {0}", - PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)) - .AppendLine(); + sb. + AppendFormat("\tProtocol (PCI Express) specific descriptor with unknown format (hex): {0}", + PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)). + AppendLine(); + break; case ProtocolIdentifiers.RDMAP: - sb - .AppendFormat("\tProtocol (SCSI Remote Direct Memory Access) specific descriptor with unknown format (hex): {0}", - PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)) - .AppendLine(); + sb. + AppendFormat("\tProtocol (SCSI Remote Direct Memory Access) specific descriptor with unknown format (hex): {0}", + PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)). + AppendLine(); + break; case ProtocolIdentifiers.SAS: - sb - .AppendFormat("\tProtocol (Serial Attachment SCSI) specific descriptor with unknown format (hex): {0}", - PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)) - .AppendLine(); + sb. + AppendFormat("\tProtocol (Serial Attachment SCSI) specific descriptor with unknown format (hex): {0}", + PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)). + AppendLine(); + break; case ProtocolIdentifiers.SCSI: - sb - .AppendFormat("\tProtocol (Parallel SCSI) specific descriptor with unknown format (hex): {0}", - PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)) - .AppendLine(); + sb. + AppendFormat("\tProtocol (Parallel SCSI) specific descriptor with unknown format (hex): {0}", + PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)). + AppendLine(); + break; case ProtocolIdentifiers.SSA: - sb - .AppendFormat("\tProtocol (SSA) specific descriptor with unknown format (hex): {0}", - PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)) - .AppendLine(); + sb. + AppendFormat("\tProtocol (SSA) specific descriptor with unknown format (hex): {0}", + PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)). + AppendLine(); + break; case ProtocolIdentifiers.SCSIe: sb.AppendFormat("\tProtocol (SCSIe) specific descriptor: Routing ID is {0}", (descriptor.Binary[0] << 8) + descriptor.Binary[1]).AppendLine(); + break; case ProtocolIdentifiers.UAS: - sb - .AppendFormat("\tProtocol (UAS) specific descriptor: USB address {0} interface {1}", + sb. + AppendFormat("\tProtocol (UAS) specific descriptor: USB address {0} interface {1}", descriptor.Binary[0] & 0x7F, descriptor.Binary[2]).AppendLine(); + break; default: - sb - .AppendFormat("\tProtocol (unknown code {0}) specific descriptor with unknown format (hex): {1}", + sb. + AppendFormat("\tProtocol (unknown code {0}) specific descriptor with unknown format (hex): {1}", (byte)descriptor.ProtocolIdentifier, - PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)) - .AppendLine(); + PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)). + AppendLine(); + break; } } @@ -727,17 +769,20 @@ namespace DiscImageChef.Decoders.SCSI case IdentificationCodeSet.UTF8: sb.AppendFormat("\tUnknown descriptor type {1} contains: {0}", descriptor.ASCII, (byte)descriptor.Type).AppendLine(); + break; case IdentificationCodeSet.Binary: sb.AppendFormat("\tUnknown descriptor type {1} contains binary data (hex): {0}", PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40), (byte)descriptor.Type).AppendLine(); + break; default: - sb - .AppendFormat("Inquiry descriptor type {2} contains unknown kind {1} of data (hex): {0}", + sb. + AppendFormat("Inquiry descriptor type {2} contains unknown kind {1} of data (hex): {0}", PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40), (byte)descriptor.CodeSet, (byte)descriptor.Type).AppendLine(); + break; } @@ -752,49 +797,37 @@ namespace DiscImageChef.Decoders.SCSI #region EVPD Page 0x84: Software Interface Identification page public struct SoftwareIdentifier { - /// - /// EUI-48 identifier - /// + /// EUI-48 identifier public byte[] Identifier; } - /// - /// Software Interface Identification page - /// Page code 0x84 - /// + /// Software Interface Identification page Page code 0x84 public struct Page_84 { - /// - /// The peripheral qualifier. - /// + /// The peripheral qualifier. public PeripheralQualifiers PeripheralQualifier; - /// - /// The type of the peripheral device. - /// + /// The type of the peripheral device. public PeripheralDeviceTypes PeripheralDeviceType; - /// - /// The page code. - /// + /// The page code. public byte PageCode; - /// - /// The length of the page. - /// + /// The length of the page. public byte PageLength; - /// - /// The descriptors. - /// + /// The descriptors. public SoftwareIdentifier[] Identifiers; } public static Page_84? DecodePage_84(byte[] pageResponse) { - if(pageResponse?[1] != 0x84) return null; + if(pageResponse?[1] != 0x84) + return null; - if(pageResponse[3] + 4 != pageResponse.Length) return null; + if(pageResponse[3] + 4 != pageResponse.Length) + return null; - if(pageResponse.Length < 10) return null; + if(pageResponse.Length < 10) + return null; - Page_84 decoded = new Page_84 + var decoded = new Page_84 { PeripheralQualifier = (PeripheralQualifiers)((pageResponse[0] & 0xE0) >> 5), PeripheralDeviceType = (PeripheralDeviceTypes)(pageResponse[0] & 0x1F), @@ -806,7 +839,11 @@ namespace DiscImageChef.Decoders.SCSI while(position < pageResponse.Length) { - SoftwareIdentifier identifier = new SoftwareIdentifier {Identifier = new byte[6]}; + var identifier = new SoftwareIdentifier + { + Identifier = new byte[6] + }; + Array.Copy(pageResponse, position, identifier.Identifier, 0, 6); identifiers.Add(identifier); position += 6; @@ -821,22 +858,25 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyPage_84(Page_84? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; - Page_84 page = modePage.Value; - StringBuilder sb = new StringBuilder(); + Page_84 page = modePage.Value; + var sb = new StringBuilder(); sb.AppendLine("SCSI Software Interface Identifiers:"); if(page.Identifiers.Length == 0) { sb.AppendLine("\tThere are no identifiers"); + return sb.ToString(); } foreach(SoftwareIdentifier identifier in page.Identifiers) { sb.AppendFormat("\t{0:X2}", identifier.Identifier[0]); + for(int i = 1; i < identifier.Identifier.Length; i++) sb.AppendFormat(":{0:X2}", identifier.Identifier[i]); @@ -850,73 +890,50 @@ namespace DiscImageChef.Decoders.SCSI #region EVPD Page 0x85: Management Network Addresses page public enum NetworkServiceTypes : byte { - Unspecified = 0, - StorageConf = 1, - Diagnostics = 2, - Status = 3, - Logging = 4, - CodeDownload = 5, - CopyService = 6, - Administrative = 7 + Unspecified = 0, StorageConf = 1, Diagnostics = 2, + Status = 3, Logging = 4, CodeDownload = 5, + CopyService = 6, Administrative = 7 } public struct NetworkDescriptor { - /// - /// Identifies which device the identifier associates with - /// + /// Identifies which device the identifier associates with public IdentificationAssociation Association; - /// - /// Defines the type of the identifier - /// + /// Defines the type of the identifier public NetworkServiceTypes Type; - /// - /// Length of the identifier - /// + /// Length of the identifier public ushort Length; - /// - /// Binary identifier - /// + /// Binary identifier public byte[] Address; } - /// - /// Device identification page - /// Page code 0x85 - /// + /// Device identification page Page code 0x85 public struct Page_85 { - /// - /// The peripheral qualifier. - /// + /// The peripheral qualifier. public PeripheralQualifiers PeripheralQualifier; - /// - /// The type of the peripheral device. - /// + /// The type of the peripheral device. public PeripheralDeviceTypes PeripheralDeviceType; - /// - /// The page code. - /// + /// The page code. public byte PageCode; - /// - /// The length of the page. - /// + /// The length of the page. public ushort PageLength; - /// - /// The descriptors. - /// + /// The descriptors. public NetworkDescriptor[] Descriptors; } public static Page_85? DecodePage_85(byte[] pageResponse) { - if(pageResponse?[1] != 0x85) return null; + if(pageResponse?[1] != 0x85) + return null; - if((pageResponse[2] << 8) + pageResponse[3] + 4 != pageResponse.Length) return null; + if((pageResponse[2] << 8) + pageResponse[3] + 4 != pageResponse.Length) + return null; - if(pageResponse.Length < 4) return null; + if(pageResponse.Length < 4) + return null; - Page_85 decoded = new Page_85 + var decoded = new Page_85 { PeripheralQualifier = (PeripheralQualifiers)((pageResponse[0] & 0xE0) >> 5), PeripheralDeviceType = (PeripheralDeviceTypes)(pageResponse[0] & 0x1F), @@ -928,12 +945,13 @@ namespace DiscImageChef.Decoders.SCSI while(position < pageResponse.Length) { - NetworkDescriptor descriptor = new NetworkDescriptor + var descriptor = new NetworkDescriptor { Association = (IdentificationAssociation)((pageResponse[position] & 0x60) >> 5), Type = (NetworkServiceTypes)(pageResponse[position] & 0x1F), Length = (ushort)((pageResponse[position + 2] << 8) + pageResponse[position + 3]) }; + descriptor.Address = new byte[descriptor.Length]; Array.Copy(pageResponse, position + 4, descriptor.Address, 0, descriptor.Length); @@ -950,16 +968,18 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyPage_85(Page_85? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; - Page_85 page = modePage.Value; - StringBuilder sb = new StringBuilder(); + Page_85 page = modePage.Value; + var sb = new StringBuilder(); sb.AppendLine("SCSI Management Network Addresses:"); if(page.Descriptors.Length == 0) { sb.AppendLine("\tThere are no addresses"); + return sb.ToString(); } @@ -969,57 +989,70 @@ namespace DiscImageChef.Decoders.SCSI { case IdentificationAssociation.LogicalUnit: sb.AppendLine("\tIdentifier belongs to addressed logical unit"); + break; case IdentificationAssociation.TargetPort: sb.AppendLine("\tIdentifier belongs to target port"); + break; case IdentificationAssociation.TargetDevice: sb.AppendLine("\tIdentifier belongs to target device that contains the addressed logical unit"); + break; default: sb.AppendFormat("\tIndentifier has unknown association with code {0}", (byte)descriptor.Association).AppendLine(); + break; } switch(descriptor.Type) { case NetworkServiceTypes.CodeDownload: - sb.AppendFormat("Address for code download: {0}", StringHandlers.CToString(descriptor.Address)) - .AppendLine(); + sb.AppendFormat("Address for code download: {0}", StringHandlers.CToString(descriptor.Address)). + AppendLine(); + break; case NetworkServiceTypes.Diagnostics: - sb.AppendFormat("Address for diagnostics: {0}", StringHandlers.CToString(descriptor.Address)) - .AppendLine(); + sb.AppendFormat("Address for diagnostics: {0}", StringHandlers.CToString(descriptor.Address)). + AppendLine(); + break; case NetworkServiceTypes.Logging: - sb.AppendFormat("Address for logging: {0}", StringHandlers.CToString(descriptor.Address)) - .AppendLine(); + sb.AppendFormat("Address for logging: {0}", StringHandlers.CToString(descriptor.Address)). + AppendLine(); + break; case NetworkServiceTypes.Status: - sb.AppendFormat("Address for status: {0}", StringHandlers.CToString(descriptor.Address)) - .AppendLine(); + sb.AppendFormat("Address for status: {0}", StringHandlers.CToString(descriptor.Address)). + AppendLine(); + break; case NetworkServiceTypes.StorageConf: sb.AppendFormat("Address for storage configuration service: {0}", StringHandlers.CToString(descriptor.Address)).AppendLine(); + break; case NetworkServiceTypes.Unspecified: - sb.AppendFormat("Unspecified address: {0}", StringHandlers.CToString(descriptor.Address)) - .AppendLine(); + sb.AppendFormat("Unspecified address: {0}", StringHandlers.CToString(descriptor.Address)). + AppendLine(); + break; case NetworkServiceTypes.CopyService: - sb.AppendFormat("Address for copy service: {0}", StringHandlers.CToString(descriptor.Address)) - .AppendLine(); + sb.AppendFormat("Address for copy service: {0}", StringHandlers.CToString(descriptor.Address)). + AppendLine(); + break; case NetworkServiceTypes.Administrative: sb.AppendFormat("Address for administrative configuration service: {0}", StringHandlers.CToString(descriptor.Address)).AppendLine(); + break; default: sb.AppendFormat("Address of unknown type {1}: {0}", - StringHandlers.CToString(descriptor.Address), (byte)descriptor.Type) - .AppendLine(); + StringHandlers.CToString(descriptor.Address), (byte)descriptor.Type). + AppendLine(); + break; } } @@ -1029,145 +1062,83 @@ namespace DiscImageChef.Decoders.SCSI #endregion EVPD Page 0x85: Management Network Addresses page #region EVPD Page 0x86: Extended INQUIRY data page - /// - /// Device identification page - /// Page code 0x86 - /// + /// Device identification page Page code 0x86 public struct Page_86 { - /// - /// The peripheral qualifier. - /// + /// The peripheral qualifier. public PeripheralQualifiers PeripheralQualifier; - /// - /// The type of the peripheral device. - /// + /// The type of the peripheral device. public PeripheralDeviceTypes PeripheralDeviceType; - /// - /// The page code. - /// + /// The page code. public byte PageCode; - /// - /// The length of the page. - /// + /// The length of the page. public byte PageLength; - /// - /// Indicates how a device server activates microcode - /// + /// Indicates how a device server activates microcode public byte ActivateMicrocode; - /// - /// Protection types supported by device - /// + /// Protection types supported by device public byte SPT; - /// - /// Checks logical block guard field - /// + /// Checks logical block guard field public bool GRD_CHK; - /// - /// Checks logical block application tag - /// + /// Checks logical block application tag public bool APP_CHK; - /// - /// Checks logical block reference - /// + /// Checks logical block reference public bool REF_CHK; - /// - /// Supports unit attention condition sense key specific data - /// + /// Supports unit attention condition sense key specific data public bool UASK_SUP; - /// - /// Supports grouping - /// + /// Supports grouping public bool GROUP_SUP; - /// - /// Supports priority - /// + /// Supports priority public bool PRIOR_SUP; - /// - /// Supports head of queue - /// + /// Supports head of queue public bool HEADSUP; - /// - /// Supports ordered - /// + /// Supports ordered public bool ORDSUP; - /// - /// Supports simple - /// + /// Supports simple public bool SIMPSUP; - /// - /// Supports marking a block as uncorrectable - /// + /// Supports marking a block as uncorrectable public bool WU_SUP; - /// - /// Supports disabling correction on WRITE LONG - /// + /// Supports disabling correction on WRITE LONG public bool CRD_SUP; - /// - /// Supports a non-volatile cache - /// + /// Supports a non-volatile cache public bool NV_SUP; - /// - /// Supports a volatile cache - /// + /// Supports a volatile cache public bool V_SUP; - /// - /// Disable protection information checks - /// + /// Disable protection information checks public bool NO_PI_CHK; - /// - /// Protection information interval supported - /// + /// Protection information interval supported public bool P_I_I_SUP; - /// - /// Clears all LUNs unit attention when clearing one - /// + /// Clears all LUNs unit attention when clearing one public bool LUICLR; - /// - /// Referrals support - /// + /// Referrals support public bool R_SUP; - /// - /// History snapshots release effects - /// + /// History snapshots release effects public bool HSSRELEF; - /// - /// Capability based command security - /// + /// Capability based command security public bool CBCS; - /// - /// Indicates how it handles microcode updating with multiple nexuxes - /// + /// Indicates how it handles microcode updating with multiple nexuxes public byte Nexus; - /// - /// Time to complete extended self-test - /// + /// Time to complete extended self-test public ushort ExtendedTestMinutes; - /// - /// Power on activation support - /// + /// Power on activation support public bool POA_SUP; - /// - /// Hard reset actication - /// + /// Hard reset actication public bool HRA_SUP; - /// - /// Vendor specific activation - /// + /// Vendor specific activation public bool VSA_SUP; - /// - /// Maximum length in bytes of sense data - /// + /// Maximum length in bytes of sense data public byte MaximumSenseLength; } public static Page_86? DecodePage_86(byte[] pageResponse) { - if(pageResponse?[1] != 0x86) return null; + if(pageResponse?[1] != 0x86) + return null; - if(pageResponse[3] + 4 != pageResponse.Length) return null; + if(pageResponse[3] + 4 != pageResponse.Length) + return null; - if(pageResponse.Length < 64) return null; + if(pageResponse.Length < 64) + return null; return new Page_86 { @@ -1175,32 +1146,62 @@ namespace DiscImageChef.Decoders.SCSI PeripheralDeviceType = (PeripheralDeviceTypes)(pageResponse[0] & 0x1F), PageLength = (byte)(pageResponse[3] + 4), ActivateMicrocode = (byte)((pageResponse[4] & 0xC0) >> 6), - SPT = (byte)((pageResponse[4] & 0x38) >> 3), - GRD_CHK = (pageResponse[4] & 0x04) == 0x04, - APP_CHK = (pageResponse[4] & 0x02) == 0x02, - REF_CHK = (pageResponse[4] & 0x01) == 0x01, - UASK_SUP = (pageResponse[5] & 0x20) == 0x20, - GROUP_SUP = (pageResponse[5] & 0x10) == 0x10, - PRIOR_SUP = (pageResponse[5] & 0x08) == 0x08, - HEADSUP = (pageResponse[5] & 0x04) == 0x04, - ORDSUP = (pageResponse[5] & 0x02) == 0x02, - SIMPSUP = (pageResponse[5] & 0x01) == 0x01, - WU_SUP = (pageResponse[6] & 0x08) == 0x08, - CRD_SUP = (pageResponse[6] & 0x04) == 0x04, - NV_SUP = (pageResponse[6] & 0x02) == 0x02, - V_SUP = (pageResponse[6] & 0x01) == 0x01, - NO_PI_CHK = (pageResponse[7] & 0x20) == 0x20, - P_I_I_SUP = (pageResponse[7] & 0x10) == 0x10, - LUICLR = (pageResponse[7] & 0x01) == 0x01, - R_SUP = (pageResponse[8] & 0x10) == 0x10, - HSSRELEF = (pageResponse[8] & 0x02) == 0x02, - CBCS = (pageResponse[8] & 0x01) == 0x01, - Nexus = (byte)(pageResponse[9] & 0x0F), - ExtendedTestMinutes = (ushort)((pageResponse[10] << 8) + pageResponse[11]), - POA_SUP = (pageResponse[12] & 0x80) == 0x80, - HRA_SUP = (pageResponse[12] & 0x40) == 0x40, - VSA_SUP = (pageResponse[12] & 0x20) == 0x20, - MaximumSenseLength = pageResponse[13] + SPT = + (byte)((pageResponse[4] & 0x38) >> 3), + GRD_CHK = (pageResponse[4] & 0x04) == 0x04, + APP_CHK = + (pageResponse + [4] & + 0x02) == 0x02, + REF_CHK = (pageResponse[4] & 0x01) == 0x01, + UASK_SUP = + (pageResponse + [5] & + 0x20) == 0x20, + GROUP_SUP = (pageResponse[5] & 0x10) == 0x10, + PRIOR_SUP = + (pageResponse + [5] & + 0x08) == 0x08, + HEADSUP = (pageResponse[5] & 0x04) == 0x04, + ORDSUP = + (pageResponse + [5] & + 0x02) == 0x02, + SIMPSUP = (pageResponse[5] & 0x01) == 0x01, + WU_SUP = + (pageResponse + [6] & + 0x08) == 0x08, + CRD_SUP = (pageResponse[6] & 0x04) == 0x04, + NV_SUP = + (pageResponse + [6] & + 0x02) == 0x02, + V_SUP = (pageResponse[6] & 0x01) == 0x01, + NO_PI_CHK = + (pageResponse + [7] & + 0x20) == 0x20, + P_I_I_SUP = (pageResponse[7] & 0x10) == 0x10, + LUICLR = + (pageResponse + [7] & + 0x01) == 0x01, + R_SUP = (pageResponse[8] & 0x10) == 0x10, + HSSRELEF = + (pageResponse + [8] & + 0x02) == 0x02, + CBCS = (pageResponse[8] & 0x01) == 0x01, + Nexus = + (byte)(pageResponse + [9] & + 0x0F), + ExtendedTestMinutes = (ushort)((pageResponse[10] << 8) + pageResponse[11]), + POA_SUP = (pageResponse[12] & 0x80) == 0x80, + HRA_SUP = (pageResponse[12] & 0x40) == 0x40, + VSA_SUP = (pageResponse[12] & 0x20) == 0x20, MaximumSenseLength = pageResponse[13] }; } @@ -1208,10 +1209,11 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyPage_86(Page_86? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; - Page_86 page = modePage.Value; - StringBuilder sb = new StringBuilder(); + Page_86 page = modePage.Value; + var sb = new StringBuilder(); sb.AppendLine("SCSI Extended INQUIRY Data:"); @@ -1223,146 +1225,176 @@ namespace DiscImageChef.Decoders.SCSI { case 0: sb.AppendLine("Logical unit supports type 1 protection"); + break; case 1: sb.AppendLine("Logical unit supports types 1 and 2 protection"); + break; case 2: sb.AppendLine("Logical unit supports type 2 protection"); + break; case 3: sb.AppendLine("Logical unit supports types 1 and 3 protection"); + break; case 4: sb.AppendLine("Logical unit supports type 3 protection"); + break; case 5: sb.AppendLine("Logical unit supports types 2 and 3 protection"); + break; case 7: sb.AppendLine("Logical unit supports types 1, 2 and 3 protection"); + break; default: - sb.AppendFormat("Logical unit supports unknown protection defined by code {0}", page.SPT) - .AppendLine(); + sb.AppendFormat("Logical unit supports unknown protection defined by code {0}", page.SPT). + AppendLine(); + break; } break; case PeripheralDeviceTypes.SequentialAccess when page.SPT == 1: sb.AppendLine("Logical unit supports logical block protection"); + break; } - if(page.GRD_CHK) sb.AppendLine("Device checks the logical block guard"); - if(page.APP_CHK) sb.AppendLine("Device checks the logical block application tag"); - if(page.REF_CHK) sb.AppendLine("Device checks the logical block reference tag"); - if(page.UASK_SUP) sb.AppendLine("Device supports unit attention condition sense key specific data"); - if(page.GROUP_SUP) sb.AppendLine("Device supports grouping"); - if(page.PRIOR_SUP) sb.AppendLine("Device supports priority"); - if(page.HEADSUP) sb.AppendLine("Device supports head of queue"); - if(page.ORDSUP) sb.AppendLine("Device supports the ORDERED task attribute"); - if(page.SIMPSUP) sb.AppendLine("Device supports the SIMPLE task attribute"); - if(page.WU_SUP) sb.AppendLine("Device supports marking a block as uncorrectable with WRITE LONG"); - if(page.CRD_SUP) sb.AppendLine("Device supports disabling correction with WRITE LONG"); - if(page.NV_SUP) sb.AppendLine("Device has a non-volatile cache"); - if(page.V_SUP) sb.AppendLine("Device has a volatile cache"); - if(page.NO_PI_CHK) sb.AppendLine("Device has disabled protection information checks"); - if(page.P_I_I_SUP) sb.AppendLine("Device supports protection information intervals"); + if(page.GRD_CHK) + sb.AppendLine("Device checks the logical block guard"); + + if(page.APP_CHK) + sb.AppendLine("Device checks the logical block application tag"); + + if(page.REF_CHK) + sb.AppendLine("Device checks the logical block reference tag"); + + if(page.UASK_SUP) + sb.AppendLine("Device supports unit attention condition sense key specific data"); + + if(page.GROUP_SUP) + sb.AppendLine("Device supports grouping"); + + if(page.PRIOR_SUP) + sb.AppendLine("Device supports priority"); + + if(page.HEADSUP) + sb.AppendLine("Device supports head of queue"); + + if(page.ORDSUP) + sb.AppendLine("Device supports the ORDERED task attribute"); + + if(page.SIMPSUP) + sb.AppendLine("Device supports the SIMPLE task attribute"); + + if(page.WU_SUP) + sb.AppendLine("Device supports marking a block as uncorrectable with WRITE LONG"); + + if(page.CRD_SUP) + sb.AppendLine("Device supports disabling correction with WRITE LONG"); + + if(page.NV_SUP) + sb.AppendLine("Device has a non-volatile cache"); + + if(page.V_SUP) + sb.AppendLine("Device has a volatile cache"); + + if(page.NO_PI_CHK) + sb.AppendLine("Device has disabled protection information checks"); + + if(page.P_I_I_SUP) + sb.AppendLine("Device supports protection information intervals"); + if(page.LUICLR) sb.AppendLine("Device clears any unit attention condition in all LUNs after reporting for any LUN"); - if(page.R_SUP) sb.AppendLine("Device supports referrals"); - if(page.HSSRELEF) sb.AppendLine("Devoce implements alternate reset handling"); - if(page.CBCS) sb.AppendLine("Device supports capability-based command security"); - if(page.POA_SUP) sb.AppendLine("Device supports power-on activation for new microcode"); - if(page.HRA_SUP) sb.AppendLine("Device supports hard reset activation for new microcode"); - if(page.VSA_SUP) sb.AppendLine("Device supports vendor specific activation for new microcode"); + + if(page.R_SUP) + sb.AppendLine("Device supports referrals"); + + if(page.HSSRELEF) + sb.AppendLine("Devoce implements alternate reset handling"); + + if(page.CBCS) + sb.AppendLine("Device supports capability-based command security"); + + if(page.POA_SUP) + sb.AppendLine("Device supports power-on activation for new microcode"); + + if(page.HRA_SUP) + sb.AppendLine("Device supports hard reset activation for new microcode"); + + if(page.VSA_SUP) + sb.AppendLine("Device supports vendor specific activation for new microcode"); if(page.ExtendedTestMinutes > 0) sb.AppendFormat("Extended self-test takes {0} to complete", TimeSpan.FromMinutes(page.ExtendedTestMinutes)).AppendLine(); if(page.MaximumSenseLength > 0) - sb.AppendFormat("Device supports a maximum of {0} bytes for sense data", page.MaximumSenseLength) - .AppendLine(); + sb.AppendFormat("Device supports a maximum of {0} bytes for sense data", page.MaximumSenseLength). + AppendLine(); return sb.ToString(); } #endregion EVPD Page 0x86: Extended INQUIRY data page #region EVPD Page 0x89: ATA Information page - /// - /// ATA Information page - /// Page code 0x89 - /// + /// ATA Information page Page code 0x89 public struct Page_89 { - /// - /// The peripheral qualifier. - /// + /// The peripheral qualifier. public PeripheralQualifiers PeripheralQualifier; - /// - /// The type of the peripheral device. - /// + /// The type of the peripheral device. public PeripheralDeviceTypes PeripheralDeviceType; - /// - /// The page code. - /// + /// The page code. public byte PageCode; - /// - /// The length of the page. - /// + /// The length of the page. public ushort PageLength; - /// - /// Contains the SAT vendor identification - /// + /// Contains the SAT vendor identification public byte[] VendorIdentification; - /// - /// Contains the SAT product identification - /// + /// Contains the SAT product identification public byte[] ProductIdentification; - /// - /// Contains the SAT revision level - /// + /// Contains the SAT revision level public byte[] ProductRevisionLevel; - /// - /// Contains the ATA device signature - /// + /// Contains the ATA device signature public byte[] Signature; - /// - /// Contains the command code used to identify the device - /// + /// Contains the command code used to identify the device public byte CommandCode; - /// - /// Contains the response to ATA IDENTIFY (PACKET) DEVICE - /// + /// Contains the response to ATA IDENTIFY (PACKET) DEVICE public byte[] IdentifyData; } public static Page_89? DecodePage_89(byte[] pageResponse) { - if(pageResponse?[1] != 0x89) return null; + if(pageResponse?[1] != 0x89) + return null; - if((pageResponse[2] << 8) + pageResponse[3] + 4 != pageResponse.Length) return null; + if((pageResponse[2] << 8) + pageResponse[3] + 4 != pageResponse.Length) + return null; - if(pageResponse.Length < 572) return null; + if(pageResponse.Length < 572) + return null; - Page_89 decoded = new Page_89 + var decoded = new Page_89 { PeripheralQualifier = (PeripheralQualifiers)((pageResponse[0] & 0xE0) >> 5), PeripheralDeviceType = (PeripheralDeviceTypes)(pageResponse[0] & 0x1F), PageLength = (ushort)((pageResponse[2] << 8) + pageResponse[3] + 4), VendorIdentification = new byte[8], ProductIdentification = new byte[16], - ProductRevisionLevel = new byte[4], - Signature = new byte[20], + ProductRevisionLevel = new byte[4], Signature = new byte[20], IdentifyData = new byte[512] }; - Array.Copy(pageResponse, 8, decoded.VendorIdentification, 0, 8); + Array.Copy(pageResponse, 8, decoded.VendorIdentification, 0, 8); Array.Copy(pageResponse, 16, decoded.ProductIdentification, 0, 16); - Array.Copy(pageResponse, 32, decoded.ProductRevisionLevel, 0, 4); - Array.Copy(pageResponse, 36, decoded.Signature, 0, 20); + Array.Copy(pageResponse, 32, decoded.ProductRevisionLevel, 0, 4); + Array.Copy(pageResponse, 36, decoded.Signature, 0, 20); decoded.CommandCode = pageResponse[56]; Array.Copy(pageResponse, 60, decoded.IdentifyData, 0, 512); @@ -1374,30 +1406,37 @@ namespace DiscImageChef.Decoders.SCSI // TODO: Decode ATA signature? public static string PrettifyPage_89(Page_89? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; - Page_89 page = modePage.Value; - StringBuilder sb = new StringBuilder(); + Page_89 page = modePage.Value; + var sb = new StringBuilder(); sb.AppendLine("SCSI to ATA Translation Layer Data:"); sb.AppendFormat("\tTranslation layer vendor: {0}", - VendorString.Prettify(StringHandlers.CToString(page.VendorIdentification).Trim())) - .AppendLine(); + VendorString.Prettify(StringHandlers.CToString(page.VendorIdentification).Trim())). + AppendLine(); + sb.AppendFormat("\tTranslation layer name: {0}", StringHandlers.CToString(page.ProductIdentification).Trim()).AppendLine(); + sb.AppendFormat("\tTranslation layer release level: {0}", StringHandlers.CToString(page.ProductRevisionLevel).Trim()).AppendLine(); + switch(page.CommandCode) { case 0xEC: sb.AppendLine("\tDevice responded to ATA IDENTIFY DEVICE command."); + break; case 0xA1: sb.AppendLine("\tDevice responded to ATA IDENTIFY PACKET DEVICE command."); + break; default: sb.AppendFormat("\tDevice responded to ATA command {0:X2}h", page.CommandCode).AppendLine(); + break; } @@ -1405,86 +1444,74 @@ namespace DiscImageChef.Decoders.SCSI { case 0x00: sb.AppendLine("\tDevice uses Parallel ATA."); + break; case 0x34: sb.AppendLine("\tDevice uses Serial ATA."); + break; default: sb.AppendFormat("\tDevice uses unknown transport with code {0}", page.Signature[0]).AppendLine(); + break; } Identify.IdentifyDevice? id = Identify.Decode(page.IdentifyData); + if(id != null) { sb.AppendLine("\tATA IDENTIFY information follows:"); sb.AppendFormat("{0}", Identify.Prettify(id)).AppendLine(); } - else sb.AppendLine("\tCould not decode ATA IDENTIFY information"); + else + sb.AppendLine("\tCould not decode ATA IDENTIFY information"); return sb.ToString(); } #endregion EVPD Page 0x89: ATA Information page #region EVPD Page 0xC0 (Quantum): Firmware Build Information page - /// - /// Firmware Build Information page - /// Page code 0xC0 (Quantum) - /// + /// Firmware Build Information page Page code 0xC0 (Quantum) public struct Page_C0_Quantum { - /// - /// The peripheral qualifier. - /// + /// The peripheral qualifier. public PeripheralQualifiers PeripheralQualifier; - /// - /// The type of the peripheral device. - /// + /// The type of the peripheral device. public PeripheralDeviceTypes PeripheralDeviceType; - /// - /// The page code. - /// + /// The page code. public byte PageCode; - /// - /// The length of the page. - /// + /// The length of the page. public byte PageLength; - /// - /// Servo firmware checksum - /// + /// Servo firmware checksum public ushort ServoFirmwareChecksum; - /// - /// Servo EEPROM checksum - /// + /// Servo EEPROM checksum public ushort ServoEEPROMChecksum; - /// - /// Read/Write firmware checksum - /// + /// Read/Write firmware checksum public uint ReadWriteFirmwareChecksum; - /// - /// Read/Write firmware build data - /// + /// Read/Write firmware build data public byte[] ReadWriteFirmwareBuildData; } public static Page_C0_Quantum? DecodePage_C0_Quantum(byte[] pageResponse) { - if(pageResponse?[1] != 0xC0) return null; + if(pageResponse?[1] != 0xC0) + return null; - if(pageResponse[3] != 20) return null; + if(pageResponse[3] != 20) + return null; - if(pageResponse.Length != 36) return null; + if(pageResponse.Length != 36) + return null; - Page_C0_Quantum decoded = new Page_C0_Quantum + var decoded = new Page_C0_Quantum { PeripheralQualifier = (PeripheralQualifiers)((pageResponse[0] & 0xE0) >> 5), PeripheralDeviceType = (PeripheralDeviceTypes)(pageResponse[0] & 0x1F), PageLength = (byte)(pageResponse[3] + 4), ServoFirmwareChecksum = (ushort)((pageResponse[4] << 8) + pageResponse[5]), ServoEEPROMChecksum = (ushort)((pageResponse[6] << 8) + pageResponse[7]), - ReadWriteFirmwareChecksum = - (uint)((pageResponse[8] << 24) + (pageResponse[9] << 16) + (pageResponse[10] << 8) + - pageResponse[11]), + ReadWriteFirmwareChecksum = (uint)((pageResponse[8] << 24) + (pageResponse[9] << 16) + + (pageResponse[10] << 8) + pageResponse[11]), ReadWriteFirmwareBuildData = new byte[24] }; @@ -1498,16 +1525,18 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyPage_C0_Quantum(Page_C0_Quantum? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; Page_C0_Quantum page = modePage.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendLine("Quantum Firmware Build Information page:"); sb.AppendFormat("\tServo firmware checksum: 0x{0:X4}", page.ServoFirmwareChecksum).AppendLine(); sb.AppendFormat("\tEEPROM firmware checksum: 0x{0:X4}", page.ServoEEPROMChecksum).AppendLine(); sb.AppendFormat("\tRead/write firmware checksum: 0x{0:X8}", page.ReadWriteFirmwareChecksum).AppendLine(); + sb.AppendFormat("\tRead/write firmware build date: {0}", StringHandlers.CToString(page.ReadWriteFirmwareBuildData)).AppendLine(); @@ -1516,27 +1545,16 @@ namespace DiscImageChef.Decoders.SCSI #endregion EVPD Page 0xC0 (Quantum): Firmware Build Information page #region EVPD Pages 0xC0, 0xC1 (Certance): Drive component revision level pages - /// - /// Drive component revision level pages - /// Page codes 0xC0, 0xC1 (Certance) - /// + /// Drive component revision level pages Page codes 0xC0, 0xC1 (Certance) public struct Page_C0_C1_Certance { - /// - /// The peripheral qualifier. - /// + /// The peripheral qualifier. public PeripheralQualifiers PeripheralQualifier; - /// - /// The type of the peripheral device. - /// + /// The type of the peripheral device. public PeripheralDeviceTypes PeripheralDeviceType; - /// - /// The page code. - /// + /// The page code. public byte PageCode; - /// - /// The length of the page. - /// + /// The length of the page. public byte PageLength; public byte[] Component; public byte[] Version; @@ -1546,29 +1564,31 @@ namespace DiscImageChef.Decoders.SCSI public static Page_C0_C1_Certance? DecodePage_C0_C1_Certance(byte[] pageResponse) { - if(pageResponse == null) return null; + if(pageResponse == null) + return null; - if(pageResponse[1] != 0xC0 && pageResponse[1] != 0xC1) return null; + if(pageResponse[1] != 0xC0 && + pageResponse[1] != 0xC1) + return null; - if(pageResponse[3] != 92) return null; + if(pageResponse[3] != 92) + return null; - if(pageResponse.Length != 96) return null; + if(pageResponse.Length != 96) + return null; - Page_C0_C1_Certance decoded = new Page_C0_C1_Certance + var decoded = new Page_C0_C1_Certance { PeripheralQualifier = (PeripheralQualifiers)((pageResponse[0] & 0xE0) >> 5), PeripheralDeviceType = (PeripheralDeviceTypes)(pageResponse[0] & 0x1F), - PageLength = (byte)(pageResponse[3] + 4), - Component = new byte[26], - Version = new byte[19], - Date = new byte[24], - Variant = new byte[23] + PageLength = (byte)(pageResponse[3] + 4), Component = new byte[26], Version = new byte[19], + Date = new byte[24], Variant = new byte[23] }; - Array.Copy(pageResponse, 4, decoded.Component, 0, 26); - Array.Copy(pageResponse, 30, decoded.Version, 0, 19); - Array.Copy(pageResponse, 49, decoded.Date, 0, 24); - Array.Copy(pageResponse, 73, decoded.Variant, 0, 23); + Array.Copy(pageResponse, 4, decoded.Component, 0, 26); + Array.Copy(pageResponse, 30, decoded.Version, 0, 19); + Array.Copy(pageResponse, 49, decoded.Date, 0, 24); + Array.Copy(pageResponse, 73, decoded.Variant, 0, 23); return decoded; } @@ -1578,10 +1598,11 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyPage_C0_C1_Certance(Page_C0_C1_Certance? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; Page_C0_C1_Certance page = modePage.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendLine("Certance Drive Component Revision Levels page:"); @@ -1595,48 +1616,43 @@ namespace DiscImageChef.Decoders.SCSI #endregion EVPD Pages 0xC0, 0xC1 (Certance): Drive component revision level pages #region EVPD Pages 0xC2, 0xC3, 0xC4, 0xC5, 0xC6 (Certance): Drive component serial number pages - /// - /// Drive component serial number pages - /// Page codes 0xC2, 0xC3, 0xC4, 0xC5, 0xC6 (Certance) - /// + /// Drive component serial number pages Page codes 0xC2, 0xC3, 0xC4, 0xC5, 0xC6 (Certance) public struct Page_C2_C3_C4_C5_C6_Certance { - /// - /// The peripheral qualifier. - /// + /// The peripheral qualifier. public PeripheralQualifiers PeripheralQualifier; - /// - /// The type of the peripheral device. - /// + /// The type of the peripheral device. public PeripheralDeviceTypes PeripheralDeviceType; - /// - /// The page code. - /// + /// The page code. public byte PageCode; - /// - /// The length of the page. - /// + /// The length of the page. public byte PageLength; public byte[] SerialNumber; } public static Page_C2_C3_C4_C5_C6_Certance? DecodePage_C2_C3_C4_C5_C6_Certance(byte[] pageResponse) { - if(pageResponse == null) return null; + if(pageResponse == null) + return null; - if(pageResponse[1] != 0xC2 && pageResponse[1] != 0xC3 && pageResponse[1] != 0xC4 && - pageResponse[1] != 0xC5 && pageResponse[1] != 0xC6) return null; + if(pageResponse[1] != 0xC2 && + pageResponse[1] != 0xC3 && + pageResponse[1] != 0xC4 && + pageResponse[1] != 0xC5 && + pageResponse[1] != 0xC6) + return null; - if(pageResponse[3] != 12) return null; + if(pageResponse[3] != 12) + return null; - if(pageResponse.Length != 16) return null; + if(pageResponse.Length != 16) + return null; - Page_C2_C3_C4_C5_C6_Certance decoded = new Page_C2_C3_C4_C5_C6_Certance + var decoded = new Page_C2_C3_C4_C5_C6_Certance { PeripheralQualifier = (PeripheralQualifiers)((pageResponse[0] & 0xE0) >> 5), PeripheralDeviceType = (PeripheralDeviceTypes)(pageResponse[0] & 0x1F), - PageLength = (byte)(pageResponse[3] + 4), - SerialNumber = new byte[12] + PageLength = (byte)(pageResponse[3] + 4), SerialNumber = new byte[12] }; Array.Copy(pageResponse, 4, decoded.SerialNumber, 0, 12); @@ -1649,34 +1665,40 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyPage_C2_C3_C4_C5_C6_Certance(Page_C2_C3_C4_C5_C6_Certance? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; Page_C2_C3_C4_C5_C6_Certance page = modePage.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendLine("Certance Drive Component Serial Number page:"); switch(page.PageCode) { case 0xC2: - sb.AppendFormat("\tHead Assembly Serial Number: {0}", StringHandlers.CToString(page.SerialNumber)) - .AppendLine(); + sb.AppendFormat("\tHead Assembly Serial Number: {0}", StringHandlers.CToString(page.SerialNumber)). + AppendLine(); + break; case 0xC3: - sb.AppendFormat("\tReel Motor 1 Serial Number: {0}", StringHandlers.CToString(page.SerialNumber)) - .AppendLine(); + sb.AppendFormat("\tReel Motor 1 Serial Number: {0}", StringHandlers.CToString(page.SerialNumber)). + AppendLine(); + break; case 0xC4: - sb.AppendFormat("\tReel Motor 2 Serial Number: {0}", StringHandlers.CToString(page.SerialNumber)) - .AppendLine(); + sb.AppendFormat("\tReel Motor 2 Serial Number: {0}", StringHandlers.CToString(page.SerialNumber)). + AppendLine(); + break; case 0xC5: - sb.AppendFormat("\tBoard Serial Number: {0}", StringHandlers.CToString(page.SerialNumber)) - .AppendLine(); + sb.AppendFormat("\tBoard Serial Number: {0}", StringHandlers.CToString(page.SerialNumber)). + AppendLine(); + break; case 0xC6: - sb.AppendFormat("\tBase Mechanical Serial Number: {0}", StringHandlers.CToString(page.SerialNumber)) - .AppendLine(); + sb.AppendFormat("\tBase Mechanical Serial Number: {0}", + StringHandlers.CToString(page.SerialNumber)).AppendLine(); + break; } @@ -1685,103 +1707,63 @@ namespace DiscImageChef.Decoders.SCSI #endregion EVPD Pages 0xC0, 0xC1 (Certance): Drive component revision level pages #region EVPD Page 0xDF (Certance): Drive status pages - /// - /// Drive status pages - /// Page codes 0xDF (Certance) - /// + /// Drive status pages Page codes 0xDF (Certance) public struct Page_DF_Certance { - /// - /// The peripheral qualifier. - /// + /// The peripheral qualifier. public PeripheralQualifiers PeripheralQualifier; - /// - /// The type of the peripheral device. - /// + /// The type of the peripheral device. public PeripheralDeviceTypes PeripheralDeviceType; - /// - /// The page code. - /// + /// The page code. public byte PageCode; - /// - /// The length of the page. - /// + /// The length of the page. public byte PageLength; - /// - /// Command forwarding - /// + /// Command forwarding public byte CmdFwd; - /// - /// Alerts - /// + /// Alerts public bool Alerts; - /// - /// Removable prevention - /// + /// Removable prevention public bool NoRemov; - /// - /// Unit reservation - /// + /// Unit reservation public bool UnitRsvd; - /// - /// Needs cleaning - /// + /// Needs cleaning public bool Clean; - /// - /// Tape threaded - /// + /// Tape threaded public bool Threaded; - /// - /// Commands await forwarding - /// + /// Commands await forwarding public bool Lun1Cmd; - /// - /// Autoload mode - /// + /// Autoload mode public byte AutoloadMode; - /// - /// Cartridge type - /// + /// Cartridge type public byte CartridgeType; - /// - /// Cartridge format - /// + /// Cartridge format public byte CartridgeFormat; - /// - /// Cartridge capacity in 10e9 bytes - /// + /// Cartridge capacity in 10e9 bytes public ushort CartridgeCapacity; - /// - /// Port A transport type - /// + /// Port A transport type public byte PortATransportType; - /// - /// Port A SCSI ID - /// + /// Port A SCSI ID public byte PortASelectionID; - /// - /// Total number of head-tape contact time - /// + /// Total number of head-tape contact time public uint OperatingHours; - /// - /// ID that reserved the device - /// + /// ID that reserved the device public ulong InitiatorID; - /// - /// Cartridge serial number - /// + /// Cartridge serial number public byte[] CartridgeSerialNumber; } public static Page_DF_Certance? DecodePage_DF_Certance(byte[] pageResponse) { - if(pageResponse?[1] != 0xDF) return null; + if(pageResponse?[1] != 0xDF) + return null; - if(pageResponse[3] != 60) return null; + if(pageResponse[3] != 60) + return null; - if(pageResponse.Length != 64) return null; + if(pageResponse.Length != 64) + return null; - Page_DF_Certance decoded = new Page_DF_Certance + var decoded = new Page_DF_Certance { PeripheralQualifier = (PeripheralQualifiers)((pageResponse[0] & 0xE0) >> 5), PeripheralDeviceType = (PeripheralDeviceTypes)(pageResponse[0] & 0x1F), @@ -1793,15 +1775,12 @@ namespace DiscImageChef.Decoders.SCSI Clean = (pageResponse[5] & 0x01) == 0x01, Threaded = (pageResponse[6] & 0x10) == 0x10, Lun1Cmd = (pageResponse[6] & 0x08) == 0x08, - AutoloadMode = (byte)(pageResponse[6] & 0x07), - CartridgeType = pageResponse[8], + AutoloadMode = (byte)(pageResponse[6] & 0x07), CartridgeType = pageResponse[8], CartridgeFormat = pageResponse[9], CartridgeCapacity = (ushort)((pageResponse[10] << 8) + pageResponse[11] + 4), - PortATransportType = pageResponse[12], - PortASelectionID = pageResponse[15], - OperatingHours = - (uint)((pageResponse[20] << 24) + (pageResponse[21] << 16) + (pageResponse[22] << 8) + - pageResponse[23]), + PortATransportType = pageResponse[12], PortASelectionID = pageResponse[15], + OperatingHours = (uint)((pageResponse[20] << 24) + (pageResponse[21] << 16) + (pageResponse[22] << 8) + + pageResponse[23]), CartridgeSerialNumber = new byte[32] }; @@ -1818,10 +1797,11 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyPage_DF_Certance(Page_DF_Certance? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; Page_DF_Certance page = modePage.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendLine("Certance drive status page:"); @@ -1829,36 +1809,53 @@ namespace DiscImageChef.Decoders.SCSI { case 0: sb.AppendLine("\tCommand forwarding is disabled"); + break; case 1: sb.AppendLine("\tCommand forwarding is enabled"); + break; default: sb.AppendFormat("\tUnknown command forwarding code {0}", page.CmdFwd).AppendLine(); + break; } - if(page.Alerts) sb.AppendLine("\tAlerts are enabled"); - if(page.NoRemov) sb.AppendLine("\tCartridge removable is prevented"); + if(page.Alerts) + sb.AppendLine("\tAlerts are enabled"); + + if(page.NoRemov) + sb.AppendLine("\tCartridge removable is prevented"); + if(page.UnitRsvd) sb.AppendFormat("\tUnit is reserved by initiator ID {0:X16}", page.InitiatorID).AppendLine(); - if(page.Clean) sb.AppendLine("\tDevice needs cleaning cartridge"); - if(page.Threaded) sb.AppendLine("\tCartridge tape is threaded"); - if(page.Lun1Cmd) sb.AppendLine("\tThere are commands pending to be forwarded"); + + if(page.Clean) + sb.AppendLine("\tDevice needs cleaning cartridge"); + + if(page.Threaded) + sb.AppendLine("\tCartridge tape is threaded"); + + if(page.Lun1Cmd) + sb.AppendLine("\tThere are commands pending to be forwarded"); switch(page.AutoloadMode) { case 0: sb.AppendLine("\tCartridge will be loaded and threaded on insertion"); + break; case 1: sb.AppendLine("\tCartridge will be loaded but not threaded on insertion"); + break; case 2: sb.AppendLine("\tCartridge will not be loaded"); + break; default: sb.AppendFormat("\tUnknown autoloading mode code {0}", page.AutoloadMode).AppendLine(); + break; } @@ -1866,12 +1863,15 @@ namespace DiscImageChef.Decoders.SCSI { case 0: sb.AppendLine("\tPort A link is down"); + break; case 3: sb.AppendLine("\tPort A uses Parallel SCSI Ultra-160 interface"); + break; default: sb.AppendFormat("\tUnknown port A transport type code {0}", page.PortATransportType).AppendLine(); + break; } @@ -1886,9 +1886,11 @@ namespace DiscImageChef.Decoders.SCSI { case 0: sb.AppendLine("\tInserted cartridge is LTO"); + break; default: sb.AppendFormat("\tUnknown cartridge format code {0}", page.CartridgeType).AppendLine(); + break; } @@ -1896,69 +1898,70 @@ namespace DiscImageChef.Decoders.SCSI { case 0: sb.AppendLine("\tThere is no cartridge inserted"); + break; case 1: sb.AppendLine("\tCleaning cartridge inserted"); + break; case 2: sb.AppendLine("\tUnknown data cartridge inserted"); + break; case 3: sb.AppendLine("\tFirmware cartridge inserted"); + break; case 4: sb.AppendLine("\tLTO Ultrium 1 Type A cartridge inserted"); + break; case 5: sb.AppendLine("\tLTO Ultrium 1 Type B cartridge inserted"); + break; case 6: sb.AppendLine("\tLTO Ultrium 1 Type C cartridge inserted"); + break; case 7: sb.AppendLine("\tLTO Ultrium 1 Type D cartridge inserted"); + break; case 8: sb.AppendLine("\tLTO Ultrium 2 cartridge inserted"); + break; default: sb.AppendFormat("\tUnknown cartridge type code {0}", page.CartridgeType).AppendLine(); + break; } - sb.AppendFormat("\tCartridge has an uncompressed capabity of {0} gigabytes", page.CartridgeCapacity) - .AppendLine(); + sb.AppendFormat("\tCartridge has an uncompressed capabity of {0} gigabytes", page.CartridgeCapacity). + AppendLine(); + sb.AppendFormat("\tCartridge serial number: {0}", StringHandlers.SpacePaddedToString(page.CartridgeSerialNumber)).AppendLine(); } - else sb.AppendLine("\tThere is no cartridge inserted"); + else + sb.AppendLine("\tThere is no cartridge inserted"); return sb.ToString(); } #endregion EVPD Page 0xDF (Certance): Drive status pages #region EVPD Page 0xC0 (IBM): Drive Component Revision Levels page - /// - /// Drive Component Revision Levels page - /// Page code 0xC0 (IBM) - /// + /// Drive Component Revision Levels page Page code 0xC0 (IBM) public struct Page_C0_IBM { - /// - /// The peripheral qualifier. - /// + /// The peripheral qualifier. public PeripheralQualifiers PeripheralQualifier; - /// - /// The type of the peripheral device. - /// + /// The type of the peripheral device. public PeripheralDeviceTypes PeripheralDeviceType; - /// - /// The page code. - /// + /// The page code. public byte PageCode; - /// - /// The length of the page. - /// + /// The length of the page. public byte PageLength; public byte[] CodeName; public byte[] Date; @@ -1966,23 +1969,24 @@ namespace DiscImageChef.Decoders.SCSI public static Page_C0_IBM? DecodePage_C0_IBM(byte[] pageResponse) { - if(pageResponse?[1] != 0xC0) return null; + if(pageResponse?[1] != 0xC0) + return null; - if(pageResponse[3] != 39) return null; + if(pageResponse[3] != 39) + return null; - if(pageResponse.Length != 43) return null; + if(pageResponse.Length != 43) + return null; - Page_C0_IBM decoded = new Page_C0_IBM + var decoded = new Page_C0_IBM { PeripheralQualifier = (PeripheralQualifiers)((pageResponse[0] & 0xE0) >> 5), PeripheralDeviceType = (PeripheralDeviceTypes)(pageResponse[0] & 0x1F), - PageLength = (byte)(pageResponse[3] + 4), - CodeName = new byte[12], - Date = new byte[8] + PageLength = (byte)(pageResponse[3] + 4), CodeName = new byte[12], Date = new byte[8] }; - Array.Copy(pageResponse, 4, decoded.CodeName, 0, 12); - Array.Copy(pageResponse, 23, decoded.Date, 0, 8); + Array.Copy(pageResponse, 4, decoded.CodeName, 0, 12); + Array.Copy(pageResponse, 23, decoded.Date, 0, 8); return decoded; } @@ -1992,10 +1996,11 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyPage_C0_IBM(Page_C0_IBM? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; - Page_C0_IBM page = modePage.Value; - StringBuilder sb = new StringBuilder(); + Page_C0_IBM page = modePage.Value; + var sb = new StringBuilder(); sb.AppendLine("IBM Drive Component Revision Levels page:"); @@ -2007,27 +2012,16 @@ namespace DiscImageChef.Decoders.SCSI #endregion EVPD Page 0xC0 (IBM): Drive Component Revision Levels page #region EVPD Page 0xC1 (IBM): Drive Serial Numbers page - /// - /// Drive Serial Numbers page - /// Page code 0xC1 (IBM) - /// + /// Drive Serial Numbers page Page code 0xC1 (IBM) public struct Page_C1_IBM { - /// - /// The peripheral qualifier. - /// + /// The peripheral qualifier. public PeripheralQualifiers PeripheralQualifier; - /// - /// The type of the peripheral device. - /// + /// The type of the peripheral device. public PeripheralDeviceTypes PeripheralDeviceType; - /// - /// The page code. - /// + /// The page code. public byte PageCode; - /// - /// The length of the page. - /// + /// The length of the page. public byte PageLength; public byte[] ManufacturingSerial; public byte[] ReportedSerial; @@ -2035,23 +2029,25 @@ namespace DiscImageChef.Decoders.SCSI public static Page_C1_IBM? DecodePage_C1_IBM(byte[] pageResponse) { - if(pageResponse?[1] != 0xC1) return null; + if(pageResponse?[1] != 0xC1) + return null; - if(pageResponse[3] != 24) return null; + if(pageResponse[3] != 24) + return null; - if(pageResponse.Length != 28) return null; + if(pageResponse.Length != 28) + return null; - Page_C1_IBM decoded = new Page_C1_IBM + var decoded = new Page_C1_IBM { PeripheralQualifier = (PeripheralQualifiers)((pageResponse[0] & 0xE0) >> 5), PeripheralDeviceType = (PeripheralDeviceTypes)(pageResponse[0] & 0x1F), - PageLength = (byte)(pageResponse[3] + 4), - ManufacturingSerial = new byte[12], + PageLength = (byte)(pageResponse[3] + 4), ManufacturingSerial = new byte[12], ReportedSerial = new byte[12] }; - Array.Copy(pageResponse, 4, decoded.ManufacturingSerial, 0, 12); - Array.Copy(pageResponse, 16, decoded.ReportedSerial, 0, 12); + Array.Copy(pageResponse, 4, decoded.ManufacturingSerial, 0, 12); + Array.Copy(pageResponse, 16, decoded.ReportedSerial, 0, 12); return decoded; } @@ -2061,44 +2057,35 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyPage_C1_IBM(Page_C1_IBM? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; - Page_C1_IBM page = modePage.Value; - StringBuilder sb = new StringBuilder(); + Page_C1_IBM page = modePage.Value; + var sb = new StringBuilder(); sb.AppendLine("IBM Drive Serial Numbers page:"); - sb.AppendFormat("\tManufacturing serial number: {0}", StringHandlers.CToString(page.ManufacturingSerial)) - .AppendLine(); - sb.AppendFormat("\tReported serial number: {0}", StringHandlers.CToString(page.ReportedSerial)) - .AppendLine(); + sb.AppendFormat("\tManufacturing serial number: {0}", StringHandlers.CToString(page.ManufacturingSerial)). + AppendLine(); + + sb.AppendFormat("\tReported serial number: {0}", StringHandlers.CToString(page.ReportedSerial)). + AppendLine(); return sb.ToString(); } #endregion EVPD Page 0xC1 (IBM): Drive Serial Numbers page #region EVPD Page 0xB0: Sequential-access device capabilities page - /// - /// Sequential-access device capabilities page - /// Page code 0xB0 - /// + /// Sequential-access device capabilities page Page code 0xB0 public struct Page_B0 { - /// - /// The peripheral qualifier. - /// + /// The peripheral qualifier. public PeripheralQualifiers PeripheralQualifier; - /// - /// The type of the peripheral device. - /// + /// The type of the peripheral device. public PeripheralDeviceTypes PeripheralDeviceType; - /// - /// The page code. - /// + /// The page code. public byte PageCode; - /// - /// The length of the page. - /// + /// The length of the page. public ushort PageLength; public bool TSMC; public bool WORM; @@ -2106,19 +2093,21 @@ namespace DiscImageChef.Decoders.SCSI public static Page_B0? DecodePage_B0(byte[] pageResponse) { - if(pageResponse?[1] != 0xB0) return null; + if(pageResponse?[1] != 0xB0) + return null; - if((pageResponse[2] << 8) + pageResponse[3] + 4 != pageResponse.Length) return null; + if((pageResponse[2] << 8) + pageResponse[3] + 4 != pageResponse.Length) + return null; - if(pageResponse.Length < 5) return null; + if(pageResponse.Length < 5) + return null; - Page_B0 decoded = new Page_B0 + var decoded = new Page_B0 { PeripheralQualifier = (PeripheralQualifiers)((pageResponse[0] & 0xE0) >> 5), PeripheralDeviceType = (PeripheralDeviceTypes)(pageResponse[0] & 0x1F), PageLength = (ushort)((pageResponse[2] << 8) + pageResponse[3] + 4), - TSMC = (pageResponse[4] & 0x02) == 0x02, - WORM = (pageResponse[4] & 0x01) == 0x01 + TSMC = (pageResponse[4] & 0x02) == 0x02, WORM = (pageResponse[4] & 0x01) == 0x01 }; return decoded; @@ -2128,102 +2117,35 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyPage_B0(Page_B0? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; - Page_B0 page = modePage.Value; - StringBuilder sb = new StringBuilder(); + Page_B0 page = modePage.Value; + var sb = new StringBuilder(); sb.AppendLine("SCSI Sequential-access Device Capabilities:"); - if(page.WORM) sb.AppendLine("\tDevice supports WORM media"); - if(page.TSMC) sb.AppendLine("\tDevice supports Tape Stream Mirroring"); + if(page.WORM) + sb.AppendLine("\tDevice supports WORM media"); + + if(page.TSMC) + sb.AppendLine("\tDevice supports Tape Stream Mirroring"); return sb.ToString(); } #endregion EVPD Page 0xB0: Sequential-access device capabilities page - #region EVPD Page 0xB1: Manufacturer-assigned Serial Number page - public static string DecodePageB1(byte[] page) - { - if(page?[1] != 0xB1) return null; - - if(page.Length != page[3] + 4) return null; - - byte[] ascii = new byte[page.Length - 4]; - - Array.Copy(page, 4, ascii, 0, page.Length - 4); - - return StringHandlers.CToString(ascii).Trim(); - } - #endregion EVPD Page 0xB1: Manufacturer-assigned Serial Number page - - #region EVPD Page 0xB2: TapeAlert Supported Flags page - public static ulong DecodePageB2(byte[] page) - { - if(page?[1] != 0xB2) return 0; - - if(page.Length != 12) return 0; - - byte[] bitmap = new byte[8]; - - Array.Copy(page, 4, bitmap, 0, 8); - - return BitConverter.ToUInt64(bitmap.Reverse().ToArray(), 0); - } - #endregion EVPD Page 0xB2: TapeAlert Supported Flags page - - #region EVPD Page 0xB3: Automation Device Serial Number page - public static string DecodePageB3(byte[] page) - { - if(page?[1] != 0xB3) return null; - - if(page.Length != page[3] + 4) return null; - - byte[] ascii = new byte[page.Length - 4]; - - Array.Copy(page, 4, ascii, 0, page.Length - 4); - - return StringHandlers.CToString(ascii).Trim(); - } - #endregion EVPD Page 0xB3: Automation Device Serial Number page - - #region EVPD Page 0xB4: Data Transfer Device Element Address page - public static string DecodePageB4(byte[] page) - { - if(page?[1] != 0xB3) return null; - - if(page.Length != page[3] + 4) return null; - - byte[] element = new byte[page.Length - 4]; - StringBuilder sb = new StringBuilder(); - foreach(byte b in element) sb.AppendFormat("{0:X2}", b); - - return sb.ToString(); - } - #endregion EVPD Page 0xB4: Data Transfer Device Element Address page - #region EVPD Pages 0xC0 to 0xC5 (HP): Drive component revision level pages - /// - /// Drive component revision level pages - /// Page codes 0xC0 to 0xC5 (HP) - /// + /// Drive component revision level pages Page codes 0xC0 to 0xC5 (HP) public struct Page_C0_to_C5_HP { - /// - /// The peripheral qualifier. - /// + /// The peripheral qualifier. public PeripheralQualifiers PeripheralQualifier; - /// - /// The type of the peripheral device. - /// + /// The type of the peripheral device. public PeripheralDeviceTypes PeripheralDeviceType; - /// - /// The page code. - /// + /// The page code. public byte PageCode; - /// - /// The length of the page. - /// + /// The length of the page. public byte PageLength; public byte[] Component; public byte[] Version; @@ -2234,46 +2156,56 @@ namespace DiscImageChef.Decoders.SCSI public static Page_C0_to_C5_HP? DecodePage_C0_to_C5_HP(byte[] pageResponse) { - if(pageResponse == null) return null; + if(pageResponse == null) + return null; - if(pageResponse[1] != 0xC0 && pageResponse[1] != 0xC1 && pageResponse[1] != 0xC2 && - pageResponse[1] != 0xC3 && pageResponse[1] != 0xC4 && pageResponse[1] != 0xC5) return null; + if(pageResponse[1] != 0xC0 && + pageResponse[1] != 0xC1 && + pageResponse[1] != 0xC2 && + pageResponse[1] != 0xC3 && + pageResponse[1] != 0xC4 && + pageResponse[1] != 0xC5) + return null; - if(pageResponse.Length < 4) return null; + if(pageResponse.Length < 4) + return null; - Page_C0_to_C5_HP decoded = new Page_C0_to_C5_HP + var decoded = new Page_C0_to_C5_HP { PeripheralQualifier = (PeripheralQualifiers)((pageResponse[0] & 0xE0) >> 5), PeripheralDeviceType = (PeripheralDeviceTypes)(pageResponse[0] & 0x1F), - PageLength = (byte)(pageResponse[3] + 4), - PageCode = pageResponse[1] + PageLength = (byte)(pageResponse[3] + 4), PageCode = pageResponse[1] }; - if(pageResponse[3] == 92 && pageResponse.Length >= 96) + if(pageResponse[3] == 92 && + pageResponse.Length >= 96) { decoded.Component = new byte[26]; decoded.Version = new byte[19]; decoded.Date = new byte[24]; decoded.Variant = new byte[23]; - Array.Copy(pageResponse, 4, decoded.Component, 0, 26); - Array.Copy(pageResponse, 30, decoded.Version, 0, 19); - Array.Copy(pageResponse, 49, decoded.Date, 0, 24); - Array.Copy(pageResponse, 73, decoded.Variant, 0, 23); + Array.Copy(pageResponse, 4, decoded.Component, 0, 26); + Array.Copy(pageResponse, 30, decoded.Version, 0, 19); + Array.Copy(pageResponse, 49, decoded.Date, 0, 24); + Array.Copy(pageResponse, 73, decoded.Variant, 0, 23); return decoded; } - if(pageResponse[4] != pageResponse[3] - 1) return null; + if(pageResponse[4] != pageResponse[3] - 1) + return null; List array = new List(); + const string fwRegExStr = @"Firmware Rev\s+=\s+(?\d+\.\d+)\s+Build date\s+=\s+(?(\w|\d|\s*.)*)\s*$"; + const string fwcRegExStr = @"FW_CONF\s+=\s+(?0x[0-9A-Fa-f]{8})\s*$"; const string servoRegExStr = @"Servo\s+Rev\s+=\s+(?\d+\.\d+)\s*$"; - Regex fwRegEx = new Regex(fwRegExStr); - Regex fwcRegEx = new Regex(fwcRegExStr); - Regex servoRegEx = new Regex(servoRegExStr); + var fwRegEx = new Regex(fwRegExStr); + var fwcRegEx = new Regex(fwcRegExStr); + var servoRegEx = new Regex(servoRegExStr); for(int pos = 5; pos < pageResponse.Length; pos++) if(pageResponse[pos] == 0x00) @@ -2291,7 +2223,8 @@ namespace DiscImageChef.Decoders.SCSI decoded.Version = Encoding.ASCII.GetBytes(fwMatch.Groups["fw"].Value); decoded.Date = Encoding.ASCII.GetBytes(fwMatch.Groups["date"].Value); } - else if(fwcMatch.Success) decoded.Variant = Encoding.ASCII.GetBytes(fwMatch.Groups["value"].Value); + else if(fwcMatch.Success) + decoded.Variant = Encoding.ASCII.GetBytes(fwMatch.Groups["value"].Value); else if(servoMatch.Success) { decoded.Component = Encoding.ASCII.GetBytes("Servo"); @@ -2311,42 +2244,58 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyPage_C0_to_C5_HP(Page_C0_to_C5_HP? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; Page_C0_to_C5_HP page = modePage.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); switch(page.PageCode) { case 0xC0: sb.AppendLine("HP Drive Firmware Revision Levels page:"); + break; case 0xC1: sb.AppendLine("HP Drive Hardware Revision Levels page:"); + break; case 0xC2: sb.AppendLine("HP Drive PCA Revision Levels page:"); + break; case 0xC3: sb.AppendLine("HP Drive Mechanism Revision Levels page:"); + break; case 0xC4: sb.AppendLine("HP Drive Head Assembly Revision Levels page:"); + break; case 0xC5: sb.AppendLine("HP Drive ACI Revision Levels page:"); + break; } - if(page.Component != null && page.Component.Length > 0) + if(page.Component != null && + page.Component.Length > 0) sb.AppendFormat("\tComponent: {0}", StringHandlers.CToString(page.Component)).AppendLine(); - if(page.Version != null && page.Version.Length > 0) + + if(page.Version != null && + page.Version.Length > 0) sb.AppendFormat("\tVersion: {0}", StringHandlers.CToString(page.Version)).AppendLine(); - if(page.Date != null && page.Date.Length > 0) + + if(page.Date != null && + page.Date.Length > 0) sb.AppendFormat("\tDate: {0}", StringHandlers.CToString(page.Date)).AppendLine(); - if(page.Variant != null && page.Variant.Length > 0) + + if(page.Variant != null && + page.Variant.Length > 0) sb.AppendFormat("\tVariant: {0}", StringHandlers.CToString(page.Variant)).AppendLine(); - if(page.Copyright != null && page.Copyright.Length > 0) + + if(page.Copyright != null && + page.Copyright.Length > 0) sb.AppendFormat("\tCopyright: {0}", StringHandlers.CToString(page.Copyright)).AppendLine(); return sb.ToString(); @@ -2354,27 +2303,16 @@ namespace DiscImageChef.Decoders.SCSI #endregion EVPD Pages 0xC0 to 0xC5 (HP): Drive component revision level pages #region EVPD Page 0xC0 (Seagate): Firmware numbers page - /// - /// Firmware numbers page - /// Page code 0xC0 (Seagate) - /// + /// Firmware numbers page Page code 0xC0 (Seagate) public struct Page_C0_Seagate { - /// - /// The peripheral qualifier. - /// + /// The peripheral qualifier. public PeripheralQualifiers PeripheralQualifier; - /// - /// The type of the peripheral device. - /// + /// The type of the peripheral device. public PeripheralDeviceTypes PeripheralDeviceType; - /// - /// The page code. - /// + /// The page code. public byte PageCode; - /// - /// The length of the page. - /// + /// The length of the page. public byte PageLength; public byte[] ControllerFirmware; public byte[] BootFirmware; @@ -2383,26 +2321,27 @@ namespace DiscImageChef.Decoders.SCSI public static Page_C0_Seagate? DecodePage_C0_Seagate(byte[] pageResponse) { - if(pageResponse?[1] != 0xC0) return null; + if(pageResponse?[1] != 0xC0) + return null; - if(pageResponse[3] != 12) return null; + if(pageResponse[3] != 12) + return null; - if(pageResponse.Length != 16) return null; + if(pageResponse.Length != 16) + return null; - Page_C0_Seagate decoded = new Page_C0_Seagate + var decoded = new Page_C0_Seagate { PeripheralQualifier = (PeripheralQualifiers)((pageResponse[0] & 0xE0) >> 5), PeripheralDeviceType = (PeripheralDeviceTypes)(pageResponse[0] & 0x1F), - PageLength = (byte)(pageResponse[3] + 4), - PageCode = pageResponse[1], + PageLength = (byte)(pageResponse[3] + 4), PageCode = pageResponse[1], ControllerFirmware = new byte[4], - BootFirmware = new byte[4], - ServoFirmware = new byte[4] + BootFirmware = new byte[4], ServoFirmware = new byte[4] }; - Array.Copy(pageResponse, 4, decoded.ControllerFirmware, 0, 4); - Array.Copy(pageResponse, 8, decoded.BootFirmware, 0, 4); - Array.Copy(pageResponse, 12, decoded.ServoFirmware, 0, 4); + Array.Copy(pageResponse, 4, decoded.ControllerFirmware, 0, 4); + Array.Copy(pageResponse, 8, decoded.BootFirmware, 0, 4); + Array.Copy(pageResponse, 12, decoded.ServoFirmware, 0, 4); return decoded; } @@ -2412,15 +2351,17 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyPage_C0_Seagate(Page_C0_Seagate? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; Page_C0_Seagate page = modePage.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendLine("Seagate Firmware Numbers page:"); - sb.AppendFormat("\tController firmware version: {0}", StringHandlers.CToString(page.ControllerFirmware)) - .AppendLine(); + sb.AppendFormat("\tController firmware version: {0}", StringHandlers.CToString(page.ControllerFirmware)). + AppendLine(); + sb.AppendFormat("\tBoot firmware version: {0}", StringHandlers.CToString(page.BootFirmware)).AppendLine(); sb.AppendFormat("\tServo firmware version: {0}", StringHandlers.CToString(page.ServoFirmware)).AppendLine(); diff --git a/SCSI/Enums.cs b/SCSI/Enums.cs index 160e4e0..96819ff 100644 --- a/SCSI/Enums.cs +++ b/SCSI/Enums.cs @@ -36,290 +36,115 @@ namespace DiscImageChef.Decoders.SCSI { public enum PeripheralQualifiers : byte { - /// - /// Peripheral qualifier: Device is connected and supported - /// - Supported = 0x00, - /// - /// Peripheral qualifier: Device is supported but not connected - /// - Unconnected = 0x01, - /// - /// Peripheral qualifier: Reserved value - /// - Reserved = 0x02, - /// - /// Peripheral qualifier: Device is connected but unsupported - /// - Unsupported = 0x03, - /// - /// Peripheral qualifier: Vendor values: 0x04, 0x05, 0x06 and 0x07 - /// + /// Peripheral qualifier: Device is connected and supported + Supported = 0x00, /// Peripheral qualifier: Device is supported but not connected + Unconnected = 0x01, /// Peripheral qualifier: Reserved value + Reserved = 0x02, /// Peripheral qualifier: Device is connected but unsupported + Unsupported = 0x03, /// Peripheral qualifier: Vendor values: 0x04, 0x05, 0x06 and 0x07 VendorMask = 0x04 } [SuppressMessage("ReSharper", "InconsistentNaming")] public enum PeripheralDeviceTypes : byte { - /// - /// Direct-access device - /// - DirectAccess = 0x00, - /// - /// Sequential-access device - /// - SequentialAccess = 0x01, - /// - /// Printer device - /// - PrinterDevice = 0x02, - /// - /// Processor device - /// - ProcessorDevice = 0x03, - /// - /// Write-once device - /// - WriteOnceDevice = 0x04, - /// - /// CD-ROM/DVD/etc device - /// - MultiMediaDevice = 0x05, - /// - /// Scanner device - /// - ScannerDevice = 0x06, - /// - /// Optical memory device - /// - OpticalDevice = 0x07, - /// - /// Medium change device - /// - MediumChangerDevice = 0x08, - /// - /// Communications device - /// - CommsDevice = 0x09, - /// - /// Graphics arts pre-press device (defined in ASC IT8) - /// - PrePressDevice1 = 0x0A, - /// - /// Graphics arts pre-press device (defined in ASC IT8) - /// - PrePressDevice2 = 0x0B, - /// - /// Array controller device - /// - ArrayControllerDevice = 0x0C, - /// - /// Enclosure services device - /// - EnclosureServiceDevice = 0x0D, - /// - /// Simplified direct-access device - /// - SimplifiedDevice = 0x0E, - /// - /// Optical card reader/writer device - /// - OCRWDevice = 0x0F, - /// - /// Bridging Expanders - /// - BridgingExpander = 0x10, - /// - /// Object-based Storage Device - /// - ObjectDevice = 0x11, - /// - /// Automation/Drive Interface - /// - ADCDevice = 0x12, - /// - /// Security Manager Device - /// - SCSISecurityManagerDevice = 0x13, - /// - /// Host managed zoned block device - /// - SCSIZonedBlockDevice = 0x14, - /// - /// Well known logical unit - /// - WellKnownDevice = 0x1E, - /// - /// Unknown or no device type - /// + /// Direct-access device + DirectAccess = 0x00, /// Sequential-access device + SequentialAccess = 0x01, /// Printer device + PrinterDevice = 0x02, /// Processor device + ProcessorDevice = 0x03, /// Write-once device + WriteOnceDevice = 0x04, /// CD-ROM/DVD/etc device + MultiMediaDevice = 0x05, /// Scanner device + ScannerDevice = 0x06, /// Optical memory device + OpticalDevice = 0x07, /// Medium change device + MediumChangerDevice = 0x08, /// Communications device + CommsDevice = 0x09, /// Graphics arts pre-press device (defined in ASC IT8) + PrePressDevice1 = 0x0A, /// Graphics arts pre-press device (defined in ASC IT8) + PrePressDevice2 = 0x0B, /// Array controller device + ArrayControllerDevice = 0x0C, /// Enclosure services device + EnclosureServiceDevice = 0x0D, /// Simplified direct-access device + SimplifiedDevice = 0x0E, /// Optical card reader/writer device + OCRWDevice = 0x0F, /// Bridging Expanders + BridgingExpander = 0x10, /// Object-based Storage Device + ObjectDevice = 0x11, /// Automation/Drive Interface + ADCDevice = 0x12, /// Security Manager Device + SCSISecurityManagerDevice = 0x13, /// Host managed zoned block device + SCSIZonedBlockDevice = 0x14, /// Well known logical unit + WellKnownDevice = 0x1E, /// Unknown or no device type UnknownDevice = 0x1F } [SuppressMessage("ReSharper", "InconsistentNaming")] public enum ANSIVersions : byte { - /// - /// Device does not claim conformance to any ANSI version - /// - ANSINoVersion = 0x00, - /// - /// Device complies with ANSI X3.131:1986 - /// - ANSI1986Version = 0x01, - /// - /// Device complies with ANSI X3.131:1994 - /// - ANSI1994Version = 0x02, - /// - /// Device complies with ANSI X3.301:1997 - /// - ANSI1997Version = 0x03, - /// - /// Device complies with ANSI X3.351:2001 - /// - ANSI2001Version = 0x04, - /// - /// Device complies with ANSI X3.408:2005. - /// - ANSI2005Version = 0x05, - /// - /// Device complies with SPC-4 - /// + /// Device does not claim conformance to any ANSI version + ANSINoVersion = 0x00, /// Device complies with ANSI X3.131:1986 + ANSI1986Version = 0x01, /// Device complies with ANSI X3.131:1994 + ANSI1994Version = 0x02, /// Device complies with ANSI X3.301:1997 + ANSI1997Version = 0x03, /// Device complies with ANSI X3.351:2001 + ANSI2001Version = 0x04, /// Device complies with ANSI X3.408:2005. + ANSI2005Version = 0x05, /// Device complies with SPC-4 ANSI2008Version = 0x06 } [SuppressMessage("ReSharper", "InconsistentNaming")] public enum ECMAVersions : byte { - /// - /// Device does not claim conformance to any ECMA version - /// - ECMANoVersion = 0x00, - /// - /// Device complies with a ECMA-111 standard - /// + /// Device does not claim conformance to any ECMA version + ECMANoVersion = 0x00, /// Device complies with a ECMA-111 standard ECMA111 = 0x01 } [SuppressMessage("ReSharper", "InconsistentNaming")] public enum ISOVersions : byte { - /// - /// Device does not claim conformance to any ISO/IEC version - /// - ISONoVersion = 0x00, - /// - /// Device complies with ISO/IEC 9316:1995 - /// + /// Device does not claim conformance to any ISO/IEC version + ISONoVersion = 0x00, /// Device complies with ISO/IEC 9316:1995 ISO1995Version = 0x02 } [SuppressMessage("ReSharper", "InconsistentNaming")] public enum SPIClocking : byte { - /// - /// Supports only ST - /// - ST = 0x00, - /// - /// Supports only DT - /// - DT = 0x01, - /// - /// Reserved value - /// - Reserved = 0x02, - /// - /// Supports ST and DT - /// + /// Supports only ST + ST = 0x00, /// Supports only DT + DT = 0x01, /// Reserved value + Reserved = 0x02, /// Supports ST and DT STandDT = 0x03 } [SuppressMessage("ReSharper", "InconsistentNaming")] public enum TGPSValues : byte { - /// - /// Assymetrical access not supported - /// - NotSupported = 0x00, - /// - /// Only implicit assymetrical access is supported - /// - OnlyImplicit = 0x01, - /// - /// Only explicit assymetrical access is supported - /// - OnlyExplicit = 0x02, - /// - /// Both implicit and explicit assymetrical access are supported - /// + /// Assymetrical access not supported + NotSupported = 0x00, /// Only implicit assymetrical access is supported + OnlyImplicit = 0x01, /// Only explicit assymetrical access is supported + OnlyExplicit = 0x02, /// Both implicit and explicit assymetrical access are supported Both = 0x03 } [SuppressMessage("ReSharper", "InconsistentNaming")] public enum ProtocolIdentifiers : byte { - /// - /// Fibre Channel - /// - FibreChannel = 0, - /// - /// Parallel SCSI - /// - SCSI = 1, - /// - /// SSA - /// - SSA = 2, - /// - /// IEEE-1394 - /// - Firewire = 3, - /// - /// SCSI Remote Direct Memory Access Protocol - /// - RDMAP = 4, - /// - /// Internet SCSI - /// - iSCSI = 5, - /// - /// Serial SCSI - /// - SAS = 6, - /// - /// Automation/Drive Interface Transport Protocol - /// - ADT = 7, - /// - /// AT Attachment Interface (ATA/ATAPI) - /// - ATA = 8, - /// - /// USB Attached SCSI - /// - UAS = 9, - /// - /// SCSI over PCI Express - /// - SCSIe = 10, - /// - /// PCI Express - /// - PCIe = 11, - /// - /// No specific protocol - /// + /// Fibre Channel + FibreChannel = 0, /// Parallel SCSI + SCSI = 1, /// SSA + SSA = 2, /// IEEE-1394 + Firewire = 3, /// SCSI Remote Direct Memory Access Protocol + RDMAP = 4, /// Internet SCSI + iSCSI = 5, /// Serial SCSI + SAS = 6, /// Automation/Drive Interface Transport Protocol + ADT = 7, /// AT Attachment Interface (ATA/ATAPI) + ATA = 8, /// USB Attached SCSI + UAS = 9, /// SCSI over PCI Express + SCSIe = 10, /// PCI Express + PCIe = 11, /// No specific protocol NoProtocol = 15 } [SuppressMessage("ReSharper", "InconsistentNaming")] public enum ScsiDefinitions : byte { - Current = 0, - SCSI1 = 1, - CCS = 2, - SCSI2 = 3, - SCSI3 = 4 + Current = 0, SCSI1 = 1, CCS = 2, + SCSI2 = 3, SCSI3 = 4 } } \ No newline at end of file diff --git a/SCSI/Inquiry.cs b/SCSI/Inquiry.cs index 21516e4..ee9340c 100644 --- a/SCSI/Inquiry.cs +++ b/SCSI/Inquiry.cs @@ -39,31 +39,217 @@ using DiscImageChef.Console; namespace DiscImageChef.Decoders.SCSI { /// - /// Information from the following standards: - /// T9/375-D revision 10l - /// T10/995-D revision 10 - /// T10/1236-D revision 20 - /// T10/1416-D revision 23 - /// T10/1731-D revision 16 - /// T10/502 revision 05 - /// RFC 7144 - /// ECMA-111 + /// Information from the following standards: T9/375-D revision 10l T10/995-D revision 10 T10/1236-D revision 20 + /// T10/1416-D revision 23 T10/1731-D revision 16 T10/502 revision 05 RFC 7144 ECMA-111 /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static class Inquiry { + #region Public structures + // SCSI INQUIRY command response + public struct SCSIInquiry + { + /// Peripheral qualifier Byte 0, bits 7 to 5 + public byte PeripheralQualifier; + /// Peripheral device type Byte 0, bits 4 to 0 + public byte PeripheralDeviceType; + /// Removable device Byte 1, bit 7 + public bool RMB; + /// SCSI-1 vendor-specific qualification codes Byte 1, bits 6 to 0 + public byte DeviceTypeModifier; + /// ISO/IEC SCSI Standard Version Byte 2, bits 7 to 6, mask = 0xC0, >> 6 + public byte ISOVersion; + /// ECMA SCSI Standard Version Byte 2, bits 5 to 3, mask = 0x38, >> 3 + public byte ECMAVersion; + /// ANSI SCSI Standard Version Byte 2, bits 2 to 0, mask = 0x07 + public byte ANSIVersion; + /// Asynchronous Event Reporting Capability supported Byte 3, bit 7 + public bool AERC; + /// Device supports TERMINATE TASK command Byte 3, bit 6 + public bool TrmTsk; + /// Supports setting Normal ACA Byte 3, bit 5 + public bool NormACA; + /// Supports LUN hierarchical addressing Byte 3, bit 4 + public bool HiSup; + /// Responde data format Byte 3, bit 3 to 0 + public byte ResponseDataFormat; + /// Lenght of total INQUIRY response minus 4 Byte 4 + public byte AdditionalLength; + /// Device contains an embedded storage array controller Byte 5, bit 7 + public bool SCCS; + /// Device contains an Access Control Coordinator Byte 5, bit 6 + public bool ACC; + /// Supports asymetrical logical unit access Byte 5, bits 5 to 4 + public byte TPGS; + /// Supports third-party copy commands Byte 5, bit 3 + public bool ThreePC; + /// Reserved Byte 5, bits 2 to 1 + public byte Reserved2; + /// Supports protection information Byte 5, bit 0 + public bool Protect; + /// Supports basic queueing Byte 6, bit 7 + public bool BQue; + /// Device contains an embedded enclosure services component Byte 6, bit 6 + public bool EncServ; + /// Vendor-specific Byte 6, bit 5 + public bool VS1; + /// Multi-port device Byte 6, bit 4 + public bool MultiP; + /// Device contains or is attached to a medium changer Byte 6, bit 3 + public bool MChngr; + /// Device supports request and acknowledge handshakes Byte 6, bit 2 + public bool ACKREQQ; + /// Supports 32-bit wide SCSI addresses Byte 6, bit 1 + public bool Addr32; + /// Supports 16-bit wide SCSI addresses Byte 6, bit 0 + public bool Addr16; + /// Device supports relative addressing Byte 7, bit 7 + public bool RelAddr; + /// Supports 32-bit wide data transfers Byte 7, bit 6 + public bool WBus32; + /// Supports 16-bit wide data transfers Byte 7, bit 5 + public bool WBus16; + /// Supports synchronous data transfer Byte 7, bit 4 + public bool Sync; + /// Supports linked commands Byte 7, bit 3 + public bool Linked; + /// Supports CONTINUE TASK and TARGET TRANSFER DISABLE commands Byte 7, bit 2 + public bool TranDis; + /// Supports TCQ queue Byte 7, bit 1 + public bool CmdQue; + /// Indicates that the devices responds to RESET with soft reset Byte 7, bit 0 + public bool SftRe; + /// Vendor identification Bytes 8 to 15 + public byte[] VendorIdentification; + /// Product identification Bytes 16 to 31 + public byte[] ProductIdentification; + /// Product revision level Bytes 32 to 35 + public byte[] ProductRevisionLevel; + /// Vendor-specific data Bytes 36 to 55 + public byte[] VendorSpecific; + /// Byte 56, bits 7 to 4 + public byte Reserved3; + /// Supported SPI clocking Byte 56, bits 3 to 2 + public byte Clocking; + /// Device supports Quick Arbitration and Selection Byte 56, bit 1 + public bool QAS; + /// Supports information unit transfers Byte 56, bit 0 + public bool IUS; + /// Reserved Byte 57 + public byte Reserved4; + /// Array of version descriptors Bytes 58 to 73 + public ushort[] VersionDescriptors; + /// Reserved Bytes 74 to 95 + public byte[] Reserved5; + /// Reserved Bytes 96 to end + public byte[] VendorSpecific2; + + // Per DLT4000/DLT4500/DLT4700 Cartridge Tape Subsystem Product Manual + + #region Quantum vendor unique inquiry data structure + /// Means that the INQUIRY response contains 56 bytes or more, so this data has been filled + public bool QuantumPresent; + /// The product family. Byte 36, bits 7 to 5 + public byte Qt_ProductFamily; + /// The released firmware. Byte 36, bits 4 to 0 + public byte Qt_ReleasedFirmware; + /// The firmware major version. Byte 37 + public byte Qt_FirmwareMajorVersion; + /// The firmware minor version. Byte 38 + public byte Qt_FirmwareMinorVersion; + /// The EEPROM format major version. Byte 39 + public byte Qt_EEPROMFormatMajorVersion; + /// The EEPROM format minor version. Byte 40 + public byte Qt_EEPROMFormatMinorVersion; + /// The firmware personality. Byte 41 + public byte Qt_FirmwarePersonality; + /// The firmware sub personality. Byte 42 + public byte Qt_FirmwareSubPersonality; + /// The tape directory format version. Byte 43 + public byte Qt_TapeDirectoryFormatVersion; + /// The controller hardware version. Byte 44 + public byte Qt_ControllerHardwareVersion; + /// The drive EEPROM version. Byte 45 + public byte Qt_DriveEEPROMVersion; + /// The drive hardware version. Byte 46 + public byte Qt_DriveHardwareVersion; + /// The media loader firmware version. Byte 47 + public byte Qt_MediaLoaderFirmwareVersion; + /// The media loader hardware version. Byte 48 + public byte Qt_MediaLoaderHardwareVersion; + /// The media loader mechanical version. Byte 49 + public byte Qt_MediaLoaderMechanicalVersion; + /// Is a media loader present? Byte 50 + public bool Qt_MediaLoaderPresent; + /// Is a library present? Byte 51 + public bool Qt_LibraryPresent; + /// The module revision. Bytes 52 to 55 + public byte[] Qt_ModuleRevision; + #endregion Quantum vendor unique inquiry data structure + + #region IBM vendor unique inquiry data structure + /// Means that the INQUIRY response contains 56 bytes or more, so this data has been filled + public bool IBMPresent; + /// Drive is not capable of automation Byte 36 bit 0 + public bool IBM_AutDis; + /// If not zero, limit in MB/s = Max * (this / 256) Byte 37 + public byte IBM_PerformanceLimit; + /// Byte 41 + public byte IBM_OEMSpecific; + #endregion IBM vendor unique inquiry data structure + + #region HP vendor unique inquiry data structure + /// Means that the INQUIRY response contains 49 bytes or more, so this data has been filled + public bool HPPresent; + /// WORM version Byte 40 bits 7 to 1 + public byte HP_WORMVersion; + /// WORM supported Byte 40 bit 0 + public bool HP_WORM; + /// Bytes 43 to 48 + public byte[] HP_OBDR; + #endregion HP vendor unique inquiry data structure + + #region Seagate vendor unique inquiry data structure + /// Means that bytes 36 to 43 are filled + public bool SeagatePresent; + /// Drive Serial Number Bytes 36 to 43 + public byte[] Seagate_DriveSerialNumber; + /// Means that bytes 96 to 143 are filled + public bool Seagate2Present; + /// Contains Seagate copyright notice Bytes 96 to 143 + public byte[] Seagate_Copyright; + /// Means that bytes 144 to 147 are filled + public bool Seagate3Present; + /// Reserved Seagate field Bytes 144 to 147 + public byte[] Seagate_ServoPROMPartNo; + #endregion Seagate vendor unique inquiry data structure + + #region Kreon vendor unique inquiry data structure + /// Means that firmware is Kreon + public bool KreonPresent; + /// Kreon identifier Bytes 36 to 40 + public byte[] KreonIdentifier; + /// Kreon just a 0x20 Bytes 41 + public byte KreonSpace; + /// Kreon version string Bytes 42 to 46 + public byte[] KreonVersion; + #endregion Kreon vendor unique inquiry data structure + } + #endregion Public structures #region Public methods public static SCSIInquiry? Decode(byte[] SCSIInquiryResponse) { - if(SCSIInquiryResponse == null) return null; + if(SCSIInquiryResponse == null) + return null; - if(SCSIInquiryResponse.Length < 36 && SCSIInquiryResponse.Length != 5) + if(SCSIInquiryResponse.Length < 36 && + SCSIInquiryResponse.Length != 5) { DicConsole.DebugWriteLine("SCSI INQUIRY decoder", "INQUIRY response is {0} bytes, less than minimum of 36 bytes, decoded data can be incorrect, not decoding.", SCSIInquiryResponse.Length); + return null; } @@ -73,10 +259,11 @@ namespace DiscImageChef.Decoders.SCSI DicConsole.DebugWriteLine("SCSI INQUIRY decoder", "INQUIRY response length ({0} bytes) is different than specified in length field ({1} bytes), decoded data can be incorrect, not decoding.", SCSIInquiryResponse.Length, SCSIInquiryResponse[4] + 4); + return null; } - SCSIInquiry decoded = new SCSIInquiry(); + var decoded = new SCSIInquiry(); if(SCSIInquiryResponse.Length >= 1) { @@ -106,7 +293,9 @@ namespace DiscImageChef.Decoders.SCSI decoded.ResponseDataFormat = (byte)(SCSIInquiryResponse[3] & 0x07); } - if(SCSIInquiryResponse.Length >= 5) decoded.AdditionalLength = SCSIInquiryResponse[4]; + if(SCSIInquiryResponse.Length >= 5) + decoded.AdditionalLength = SCSIInquiryResponse[4]; + if(SCSIInquiryResponse.Length >= 6) { decoded.SCCS = Convert.ToBoolean(SCSIInquiryResponse[5] & 0x80); @@ -177,7 +366,10 @@ namespace DiscImageChef.Decoders.SCSI Array.Copy(SCSIInquiryResponse, 42, decoded.KreonVersion, 0, 5); if(decoded.KreonSpace == 0x20 && - decoded.KreonIdentifier.SequenceEqual(new byte[] {0x4B, 0x52, 0x45, 0x4F, 0x4E})) + decoded.KreonIdentifier.SequenceEqual(new byte[] + { + 0x4B, 0x52, 0x45, 0x4F, 0x4E + })) decoded.KreonPresent = true; } @@ -233,20 +425,26 @@ namespace DiscImageChef.Decoders.SCSI decoded.IUS = Convert.ToBoolean(SCSIInquiryResponse[56] & 0x01); } - if(SCSIInquiryResponse.Length >= 58) decoded.Reserved4 = SCSIInquiryResponse[57]; + if(SCSIInquiryResponse.Length >= 58) + decoded.Reserved4 = SCSIInquiryResponse[57]; + if(SCSIInquiryResponse.Length >= 60) { int descriptorsNo; - if(SCSIInquiryResponse.Length >= 74) descriptorsNo = 8; - else descriptorsNo = (SCSIInquiryResponse.Length - 58) / 2; + if(SCSIInquiryResponse.Length >= 74) + descriptorsNo = 8; + else + descriptorsNo = (SCSIInquiryResponse.Length - 58) / 2; decoded.VersionDescriptors = new ushort[descriptorsNo]; + for(int i = 0; i < descriptorsNo; i++) decoded.VersionDescriptors[i] = BitConverter.ToUInt16(SCSIInquiryResponse, 58 + i * 2); } - if(SCSIInquiryResponse.Length >= 75 && SCSIInquiryResponse.Length < 96) + if(SCSIInquiryResponse.Length >= 75 && + SCSIInquiryResponse.Length < 96) { decoded.Reserved5 = new byte[SCSIInquiryResponse.Length - 74]; Array.Copy(SCSIInquiryResponse, 74, decoded.Reserved5, 0, SCSIInquiryResponse.Length - 74); @@ -272,7 +470,8 @@ namespace DiscImageChef.Decoders.SCSI Array.Copy(SCSIInquiryResponse, 96, decoded.Seagate_Copyright, 0, 48); } - if(SCSIInquiryResponse.Length < 148) return decoded; + if(SCSIInquiryResponse.Length < 148) + return decoded; // Seagate 2 decoded.Seagate3Present = true; @@ -284,7 +483,8 @@ namespace DiscImageChef.Decoders.SCSI public static byte[] Encode(SCSIInquiry? inq) { - if(inq is null) return null; + if(inq is null) + return null; SCSIInquiry decoded = inq.Value; @@ -294,17 +494,27 @@ namespace DiscImageChef.Decoders.SCSI buffer[0] = (byte)(decoded.PeripheralQualifier << 5); buffer[0] += decoded.PeripheralDeviceType; - if(decoded.RMB) buffer[1] = 0x80; + if(decoded.RMB) + buffer[1] = 0x80; + buffer[1] += decoded.DeviceTypeModifier; buffer[2] = (byte)(decoded.ISOVersion << 6); buffer[2] += (byte)(decoded.ECMAVersion << 3); buffer[2] += decoded.ANSIVersion; - if(decoded.AERC) buffer[3] = 0x80; - if(decoded.TrmTsk) buffer[3] += 0x40; - if(decoded.NormACA) buffer[3] += 0x20; - if(decoded.HiSup) buffer[3] += 0x10; + if(decoded.AERC) + buffer[3] = 0x80; + + if(decoded.TrmTsk) + buffer[3] += 0x40; + + if(decoded.NormACA) + buffer[3] += 0x20; + + if(decoded.HiSup) + buffer[3] += 0x10; + buffer[3] += decoded.ResponseDataFormat; if(decoded.AdditionalLength > 0) @@ -313,51 +523,109 @@ namespace DiscImageChef.Decoders.SCSI buffer[4] = decoded.AdditionalLength; } - if(decoded.SCCS || decoded.ACC || decoded.TPGS > 0 || decoded.ThreePC || decoded.Reserved2 > 0 || + if(decoded.SCCS || + decoded.ACC || + decoded.TPGS > 0 || + decoded.ThreePC || + decoded.Reserved2 > 0 || decoded.Protect) { length = 6; - if(decoded.SCCS) buffer[5] = 0x80; - if(decoded.ACC) buffer[5] += 0x40; + + if(decoded.SCCS) + buffer[5] = 0x80; + + if(decoded.ACC) + buffer[5] += 0x40; + buffer[5] += (byte)(decoded.TPGS << 4); - if(decoded.ThreePC) buffer[5] += 0x08; + + if(decoded.ThreePC) + buffer[5] += 0x08; + buffer[5] += (byte)(decoded.Reserved2 << 1); - if(decoded.Protect) buffer[5] += 0x01; + + if(decoded.Protect) + buffer[5] += 0x01; } - if(decoded.BQue || decoded.EncServ || decoded.VS1 || decoded.MultiP || decoded.MChngr || + if(decoded.BQue || + decoded.EncServ || + decoded.VS1 || + decoded.MultiP || + decoded.MChngr || decoded.ACKREQQ || - decoded.Addr32 || decoded.Addr16) + decoded.Addr32 || + decoded.Addr16) { length = 7; - if(decoded.BQue) buffer[6] = 0x80; - if(decoded.EncServ) buffer[6] += 0x40; - if(decoded.VS1) buffer[6] += 0x20; - if(decoded.MultiP) buffer[6] += 0x10; - if(decoded.MChngr) buffer[6] += 0x08; - if(decoded.ACKREQQ) buffer[6] += 0x04; - if(decoded.Addr32) buffer[6] += 0x02; - if(decoded.Addr16) buffer[6] += 0x01; + + if(decoded.BQue) + buffer[6] = 0x80; + + if(decoded.EncServ) + buffer[6] += 0x40; + + if(decoded.VS1) + buffer[6] += 0x20; + + if(decoded.MultiP) + buffer[6] += 0x10; + + if(decoded.MChngr) + buffer[6] += 0x08; + + if(decoded.ACKREQQ) + buffer[6] += 0x04; + + if(decoded.Addr32) + buffer[6] += 0x02; + + if(decoded.Addr16) + buffer[6] += 0x01; } - if(decoded.RelAddr || decoded.WBus32 || decoded.WBus16 || decoded.Sync || decoded.Linked || - decoded.TranDis || decoded.CmdQue || decoded.SftRe) + if(decoded.RelAddr || + decoded.WBus32 || + decoded.WBus16 || + decoded.Sync || + decoded.Linked || + decoded.TranDis || + decoded.CmdQue || + decoded.SftRe) { length = 8; - if(decoded.RelAddr) buffer[7] = 0x80; - if(decoded.WBus32) buffer[7] += 0x40; - if(decoded.WBus16) buffer[7] += 0x20; - if(decoded.Sync) buffer[7] += 0x10; - if(decoded.Linked) buffer[7] += 0x08; - if(decoded.TranDis) buffer[7] += 0x04; - if(decoded.CmdQue) buffer[7] += 0x02; - if(decoded.SftRe) buffer[7] += 0x01; + + if(decoded.RelAddr) + buffer[7] = 0x80; + + if(decoded.WBus32) + buffer[7] += 0x40; + + if(decoded.WBus16) + buffer[7] += 0x20; + + if(decoded.Sync) + buffer[7] += 0x10; + + if(decoded.Linked) + buffer[7] += 0x08; + + if(decoded.TranDis) + buffer[7] += 0x04; + + if(decoded.CmdQue) + buffer[7] += 0x02; + + if(decoded.SftRe) + buffer[7] += 0x01; } if(decoded.VendorIdentification != null) { length = 16; + Array.Copy(decoded.VendorIdentification, 0, buffer, 8, decoded.VendorIdentification.Length >= 8 ? 8 : decoded.VendorIdentification.Length); } @@ -365,6 +633,7 @@ namespace DiscImageChef.Decoders.SCSI if(decoded.ProductIdentification != null) { length = 32; + Array.Copy(decoded.ProductIdentification, 0, buffer, 16, decoded.ProductIdentification.Length >= 16 ? 16 : decoded.ProductIdentification.Length); } @@ -372,6 +641,7 @@ namespace DiscImageChef.Decoders.SCSI if(decoded.ProductRevisionLevel != null) { length = 36; + Array.Copy(decoded.ProductRevisionLevel, 0, buffer, 32, decoded.ProductRevisionLevel.Length >= 4 ? 4 : decoded.ProductRevisionLevel.Length); } @@ -382,7 +652,8 @@ namespace DiscImageChef.Decoders.SCSI Array.Copy(decoded.Seagate_DriveSerialNumber, 0, buffer, 36, 8); } - if(decoded.KreonIdentifier != null && decoded.KreonVersion != null) + if(decoded.KreonIdentifier != null && + decoded.KreonVersion != null) { length = 46; Array.Copy(decoded.KreonIdentifier, 0, buffer, 36, 5); @@ -390,10 +661,15 @@ namespace DiscImageChef.Decoders.SCSI Array.Copy(decoded.KreonVersion, 0, buffer, 42, 5); } - if(decoded.HP_WORM || decoded.HP_WORMVersion > 0 || decoded.HP_OBDR != null) + if(decoded.HP_WORM || + decoded.HP_WORMVersion > 0 || + decoded.HP_OBDR != null) { length = 49; - if(decoded.HP_WORM) buffer[40] = 0x01; + + if(decoded.HP_WORM) + buffer[40] = 0x01; + buffer[40] += (byte)(decoded.HP_WORMVersion << 1); Array.Copy(decoded.HP_OBDR, 0, buffer, 43, 6); } @@ -404,13 +680,20 @@ namespace DiscImageChef.Decoders.SCSI Array.Copy(decoded.VendorSpecific, 0, buffer, 36, 20); } - if(decoded.Reserved3 > 0 || decoded.Clocking > 0 || decoded.QAS || decoded.IUS) + if(decoded.Reserved3 > 0 || + decoded.Clocking > 0 || + decoded.QAS || + decoded.IUS) { length = 57; buffer[56] = (byte)(decoded.Reserved3 << 4); buffer[56] += (byte)(decoded.Clocking << 2); - if(decoded.QAS) buffer[56] += 0x02; - if(decoded.IUS) buffer[56] += 0x01; + + if(decoded.QAS) + buffer[56] += 0x02; + + if(decoded.IUS) + buffer[56] += 0x01; } if(decoded.Reserved4 != 0) @@ -422,6 +705,7 @@ namespace DiscImageChef.Decoders.SCSI if(decoded.VersionDescriptors != null) { length = (byte)(58 + decoded.VersionDescriptors.Length * 2); + for(int i = 0; i < decoded.VersionDescriptors.Length; i++) Array.Copy(BitConverter.GetBytes(decoded.VersionDescriptors[i]), 0, buffer, 56 + i * 2, 2); } @@ -453,41 +737,51 @@ namespace DiscImageChef.Decoders.SCSI buffer[4] = length; byte[] dest = new byte[length]; Array.Copy(buffer, 0, dest, 0, length); + return dest; } public static string Prettify(SCSIInquiry? SCSIInquiryResponse) { - if(SCSIInquiryResponse == null) return null; + if(SCSIInquiryResponse == null) + return null; SCSIInquiry response = SCSIInquiryResponse.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendFormat("Device vendor: {0}", - VendorString.Prettify(StringHandlers.CToString(response.VendorIdentification).Trim())) - .AppendLine(); - sb.AppendFormat("Device name: {0}", StringHandlers.CToString(response.ProductIdentification).Trim()) - .AppendLine(); - sb.AppendFormat("Device release level: {0}", StringHandlers.CToString(response.ProductRevisionLevel).Trim()) - .AppendLine(); + VendorString.Prettify(StringHandlers.CToString(response.VendorIdentification).Trim())). + AppendLine(); + + sb.AppendFormat("Device name: {0}", StringHandlers.CToString(response.ProductIdentification).Trim()). + AppendLine(); + + sb.AppendFormat("Device release level: {0}", + StringHandlers.CToString(response.ProductRevisionLevel).Trim()).AppendLine(); + switch((PeripheralQualifiers)response.PeripheralQualifier) { case PeripheralQualifiers.Supported: sb.AppendLine("Device is connected and supported."); + break; case PeripheralQualifiers.Unconnected: sb.AppendLine("Device is supported but not connected."); + break; case PeripheralQualifiers.Reserved: sb.AppendLine("Reserved value set in Peripheral Qualifier field."); + break; case PeripheralQualifiers.Unsupported: sb.AppendLine("Device is connected but unsupported."); + break; default: - sb.AppendFormat("Vendor value {0} set in Peripheral Qualifier field.", response.PeripheralQualifier) - .AppendLine(); + sb.AppendFormat("Vendor value {0} set in Peripheral Qualifier field.", + response.PeripheralQualifier).AppendLine(); + break; } @@ -495,76 +789,100 @@ namespace DiscImageChef.Decoders.SCSI { case PeripheralDeviceTypes.DirectAccess: //0x00, sb.AppendLine("Direct-access device"); + break; case PeripheralDeviceTypes.SequentialAccess: //0x01, sb.AppendLine("Sequential-access device"); + break; case PeripheralDeviceTypes.PrinterDevice: //0x02, sb.AppendLine("Printer device"); + break; case PeripheralDeviceTypes.ProcessorDevice: //0x03, sb.AppendLine("Processor device"); + break; case PeripheralDeviceTypes.WriteOnceDevice: //0x04, sb.AppendLine("Write-once device"); + break; case PeripheralDeviceTypes.MultiMediaDevice: //0x05, sb.AppendLine("CD-ROM/DVD/etc device"); + break; case PeripheralDeviceTypes.ScannerDevice: //0x06, sb.AppendLine("Scanner device"); + break; case PeripheralDeviceTypes.OpticalDevice: //0x07, sb.AppendLine("Optical memory device"); + break; case PeripheralDeviceTypes.MediumChangerDevice: //0x08, sb.AppendLine("Medium change device"); + break; case PeripheralDeviceTypes.CommsDevice: //0x09, sb.AppendLine("Communications device"); + break; case PeripheralDeviceTypes.PrePressDevice1: //0x0A, sb.AppendLine("Graphics arts pre-press device (defined in ASC IT8)"); + break; case PeripheralDeviceTypes.PrePressDevice2: //0x0B, sb.AppendLine("Graphics arts pre-press device (defined in ASC IT8)"); + break; case PeripheralDeviceTypes.ArrayControllerDevice: //0x0C, sb.AppendLine("Array controller device"); + break; case PeripheralDeviceTypes.EnclosureServiceDevice: //0x0D, sb.AppendLine("Enclosure services device"); + break; case PeripheralDeviceTypes.SimplifiedDevice: //0x0E, sb.AppendLine("Simplified direct-access device"); + break; case PeripheralDeviceTypes.OCRWDevice: //0x0F, sb.AppendLine("Optical card reader/writer device"); + break; case PeripheralDeviceTypes.BridgingExpander: //0x10, sb.AppendLine("Bridging Expanders"); + break; case PeripheralDeviceTypes.ObjectDevice: //0x11, sb.AppendLine("Object-based Storage Device"); + break; case PeripheralDeviceTypes.ADCDevice: //0x12, sb.AppendLine("Automation/Drive Interface"); + break; case PeripheralDeviceTypes.SCSISecurityManagerDevice: //0x13, sb.AppendLine("Security Manager Device"); + break; case PeripheralDeviceTypes.SCSIZonedBlockDevice: //0x14 sb.AppendLine("Host managed zoned block device"); + break; case PeripheralDeviceTypes.WellKnownDevice: //0x1E, sb.AppendLine("Well known logical unit"); + break; case PeripheralDeviceTypes.UnknownDevice: //0x1F sb.AppendLine("Unknown or no device type"); + break; default: - sb.AppendFormat("Unknown device type field value 0x{0:X2}", response.PeripheralDeviceType) - .AppendLine(); + sb.AppendFormat("Unknown device type field value 0x{0:X2}", response.PeripheralDeviceType). + AppendLine(); + break; } @@ -572,28 +890,36 @@ namespace DiscImageChef.Decoders.SCSI { case ANSIVersions.ANSINoVersion: sb.AppendLine("Device does not claim to comply with any SCSI ANSI standard"); + break; case ANSIVersions.ANSI1986Version: sb.AppendLine("Device claims to comply with ANSI X3.131:1986 (SCSI-1)"); + break; case ANSIVersions.ANSI1994Version: sb.AppendLine("Device claims to comply with ANSI X3.131:1994 (SCSI-2)"); + break; case ANSIVersions.ANSI1997Version: sb.AppendLine("Device claims to comply with ANSI X3.301:1997 (SPC-1)"); + break; case ANSIVersions.ANSI2001Version: sb.AppendLine("Device claims to comply with ANSI X3.351:2001 (SPC-2)"); + break; case ANSIVersions.ANSI2005Version: sb.AppendLine("Device claims to comply with ANSI X3.408:2005 (SPC-3)"); + break; case ANSIVersions.ANSI2008Version: sb.AppendLine("Device claims to comply with ANSI X3.408:2005 (SPC-4)"); + break; default: sb.AppendFormat("Device claims to comply with unknown SCSI ANSI standard value 0x{0:X2})", response.ANSIVersion).AppendLine(); + break; } @@ -601,13 +927,16 @@ namespace DiscImageChef.Decoders.SCSI { case ECMAVersions.ECMANoVersion: sb.AppendLine("Device does not claim to comply with any SCSI ECMA standard"); + break; case ECMAVersions.ECMA111: sb.AppendLine("Device claims to comply ECMA-111: Small Computer System Interface SCSI"); + break; default: sb.AppendFormat("Device claims to comply with unknown SCSI ECMA standard value 0x{0:X2})", response.ECMAVersion).AppendLine(); + break; } @@ -615,62 +944,122 @@ namespace DiscImageChef.Decoders.SCSI { case ISOVersions.ISONoVersion: sb.AppendLine("Device does not claim to comply with any SCSI ISO/IEC standard"); + break; case ISOVersions.ISO1995Version: sb.AppendLine("Device claims to comply with ISO/IEC 9316:1995"); + break; default: sb.AppendFormat("Device claims to comply with unknown SCSI ISO/IEC standard value 0x{0:X2})", response.ISOVersion).AppendLine(); + break; } - if(response.RMB) sb.AppendLine("Device is removable"); - if(response.AERC) sb.AppendLine("Device supports Asynchronous Event Reporting Capability"); - if(response.TrmTsk) sb.AppendLine("Device supports TERMINATE TASK command"); - if(response.NormACA) sb.AppendLine("Device supports setting Normal ACA"); - if(response.HiSup) sb.AppendLine("Device supports LUN hierarchical addressing"); - if(response.SCCS) sb.AppendLine("Device contains an embedded storage array controller"); - if(response.ACC) sb.AppendLine("Device contains an Access Control Coordinator"); - if(response.ThreePC) sb.AppendLine("Device supports third-party copy commands"); - if(response.Protect) sb.AppendLine("Device supports protection information"); - if(response.BQue) sb.AppendLine("Device supports basic queueing"); - if(response.EncServ) sb.AppendLine("Device contains an embedded enclosure services component"); - if(response.MultiP) sb.AppendLine("Multi-port device"); - if(response.MChngr) sb.AppendLine("Device contains or is attached to a medium changer"); - if(response.ACKREQQ) sb.AppendLine("Device supports request and acknowledge handshakes"); - if(response.Addr32) sb.AppendLine("Device supports 32-bit wide SCSI addresses"); - if(response.Addr16) sb.AppendLine("Device supports 16-bit wide SCSI addresses"); - if(response.RelAddr) sb.AppendLine("Device supports relative addressing"); - if(response.WBus32) sb.AppendLine("Device supports 32-bit wide data transfers"); - if(response.WBus16) sb.AppendLine("Device supports 16-bit wide data transfers"); - if(response.Sync) sb.AppendLine("Device supports synchronous data transfer"); - if(response.Linked) sb.AppendLine("Device supports linked commands"); - if(response.TranDis) sb.AppendLine("Device supports CONTINUE TASK and TARGET TRANSFER DISABLE commands"); - if(response.QAS) sb.AppendLine("Device supports Quick Arbitration and Selection"); - if(response.CmdQue) sb.AppendLine("Device supports TCQ queue"); - if(response.IUS) sb.AppendLine("Device supports information unit transfers"); - if(response.SftRe) sb.AppendLine("Device implements RESET as a soft reset"); - #if DEBUG - if(response.VS1) sb.AppendLine("Vendor specific bit 5 on byte 6 of INQUIRY response is set"); - #endif + if(response.RMB) + sb.AppendLine("Device is removable"); + + if(response.AERC) + sb.AppendLine("Device supports Asynchronous Event Reporting Capability"); + + if(response.TrmTsk) + sb.AppendLine("Device supports TERMINATE TASK command"); + + if(response.NormACA) + sb.AppendLine("Device supports setting Normal ACA"); + + if(response.HiSup) + sb.AppendLine("Device supports LUN hierarchical addressing"); + + if(response.SCCS) + sb.AppendLine("Device contains an embedded storage array controller"); + + if(response.ACC) + sb.AppendLine("Device contains an Access Control Coordinator"); + + if(response.ThreePC) + sb.AppendLine("Device supports third-party copy commands"); + + if(response.Protect) + sb.AppendLine("Device supports protection information"); + + if(response.BQue) + sb.AppendLine("Device supports basic queueing"); + + if(response.EncServ) + sb.AppendLine("Device contains an embedded enclosure services component"); + + if(response.MultiP) + sb.AppendLine("Multi-port device"); + + if(response.MChngr) + sb.AppendLine("Device contains or is attached to a medium changer"); + + if(response.ACKREQQ) + sb.AppendLine("Device supports request and acknowledge handshakes"); + + if(response.Addr32) + sb.AppendLine("Device supports 32-bit wide SCSI addresses"); + + if(response.Addr16) + sb.AppendLine("Device supports 16-bit wide SCSI addresses"); + + if(response.RelAddr) + sb.AppendLine("Device supports relative addressing"); + + if(response.WBus32) + sb.AppendLine("Device supports 32-bit wide data transfers"); + + if(response.WBus16) + sb.AppendLine("Device supports 16-bit wide data transfers"); + + if(response.Sync) + sb.AppendLine("Device supports synchronous data transfer"); + + if(response.Linked) + sb.AppendLine("Device supports linked commands"); + + if(response.TranDis) + sb.AppendLine("Device supports CONTINUE TASK and TARGET TRANSFER DISABLE commands"); + + if(response.QAS) + sb.AppendLine("Device supports Quick Arbitration and Selection"); + + if(response.CmdQue) + sb.AppendLine("Device supports TCQ queue"); + + if(response.IUS) + sb.AppendLine("Device supports information unit transfers"); + + if(response.SftRe) + sb.AppendLine("Device implements RESET as a soft reset"); + #if DEBUG + if(response.VS1) + sb.AppendLine("Vendor specific bit 5 on byte 6 of INQUIRY response is set"); + #endif switch((TGPSValues)response.TPGS) { case TGPSValues.NotSupported: sb.AppendLine("Device does not support assymetrical access"); + break; case TGPSValues.OnlyImplicit: sb.AppendLine("Device only supports implicit assymetrical access"); + break; case TGPSValues.OnlyExplicit: sb.AppendLine("Device only supports explicit assymetrical access"); + break; case TGPSValues.Both: sb.AppendLine("Device supports implicit and explicit assymetrical access"); + break; default: sb.AppendFormat("Unknown value in TPGS field 0x{0:X2}", response.TPGS).AppendLine(); + break; } @@ -678,18 +1067,23 @@ namespace DiscImageChef.Decoders.SCSI { case SPIClocking.ST: sb.AppendLine("Device supports only ST clocking"); + break; case SPIClocking.DT: sb.AppendLine("Device supports only DT clocking"); + break; case SPIClocking.Reserved: sb.AppendLine("Reserved value 0x02 found in SPI clocking field"); + break; case SPIClocking.STandDT: sb.AppendLine("Device supports ST and DT clocking"); + break; default: sb.AppendFormat("Unknown value in SPI clocking field 0x{0:X2}", response.Clocking).AppendLine(); + break; } @@ -701,630 +1095,839 @@ namespace DiscImageChef.Decoders.SCSI case 0x0000: break; case 0x0020: sb.AppendLine("Device complies with SAM (no version claimed)"); + break; case 0x003B: sb.AppendLine("Device complies with SAM T10/0994-D revision 18"); + break; case 0x003C: sb.AppendLine("Device complies with SAM ANSI INCITS 270-1996"); + break; case 0x0040: sb.AppendLine("Device complies with SAM-2 (no version claimed)"); + break; case 0x0054: sb.AppendLine("Device complies with SAM-2 T10/1157-D revision 23"); + break; case 0x0055: sb.AppendLine("Device complies with SAM-2 T10/1157-D revision 24"); + break; case 0x005C: sb.AppendLine("Device complies with SAM-2 ANSI INCITS 366-2003"); + break; case 0x005E: sb.AppendLine("Device complies with SAM-2 ISO/IEC 14776-412"); + break; case 0x0060: sb.AppendLine("Device complies with SAM-3 (no version claimed)"); + break; case 0x0062: sb.AppendLine("Device complies with SAM-3 T10/1561-D revision 7"); + break; case 0x0075: sb.AppendLine("Device complies with SAM-3 T10/1561-D revision 13"); + break; case 0x0076: sb.AppendLine("Device complies with SAM-3 T10/1561-D revision 14"); + break; case 0x0077: sb.AppendLine("Device complies with SAM-3 ANSI INCITS 402-2005"); + break; case 0x0080: sb.AppendLine("Device complies with SAM-4 (no version claimed)"); + break; case 0x0087: sb.AppendLine("Device complies with SAM-4 T10/1683-D revision 13"); + break; case 0x008B: sb.AppendLine("Device complies with SAM-4 T10/1683-D revision 14"); + break; case 0x0090: sb.AppendLine("Device complies with SAM-4 ANSI INCITS 447-2008"); + break; case 0x0092: sb.AppendLine("Device complies with SAM-4 ISO/IEC 14776-414"); + break; case 0x00A0: sb.AppendLine("Device complies with SAM-5 (no version claimed)"); + break; case 0x00A2: sb.AppendLine("Device complies with SAM-5 T10/2104-D revision 4"); + break; case 0x00A4: sb.AppendLine("Device complies with SAM-5 T10/2104-D revision 20"); + break; case 0x00A6: sb.AppendLine("Device complies with SAM-5 T10/2104-D revision 21"); + break; case 0x00C0: sb.AppendLine("Device complies with SAM-6 (no version claimed)"); + break; case 0x0120: sb.AppendLine("Device complies with SPC (no version claimed)"); + break; case 0x013B: sb.AppendLine("Device complies with SPC T10/0995-D revision 11a"); + break; case 0x013C: sb.AppendLine("Device complies with SPC ANSI INCITS 301-1997"); + break; case 0x0140: sb.AppendLine("Device complies with MMC (no version claimed)"); + break; case 0x015B: sb.AppendLine("Device complies with MMC T10/1048-D revision 10a"); + break; case 0x015C: sb.AppendLine("Device complies with MMC ANSI INCITS 304-1997"); + break; case 0x0160: sb.AppendLine("Device complies with SCC (no version claimed)"); + break; case 0x017B: sb.AppendLine("Device complies with SCC T10/1047-D revision 06c"); + break; case 0x017C: sb.AppendLine("Device complies with SCC ANSI INCITS 276-1997"); + break; case 0x0180: sb.AppendLine("Device complies with SBC (no version claimed)"); + break; case 0x019B: sb.AppendLine("Device complies with SBC T10/0996-D revision 08c"); + break; case 0x019C: sb.AppendLine("Device complies with SBC ANSI INCITS 306-1998"); + break; case 0x01A0: sb.AppendLine("Device complies with SMC (no version claimed)"); + break; case 0x01BB: sb.AppendLine("Device complies with SMC T10/0999-D revision 10a"); + break; case 0x01BC: sb.AppendLine("Device complies with SMC ANSI INCITS 314-1998"); + break; case 0x01BE: sb.AppendLine("Device complies with SMC ISO/IEC 14776-351"); + break; case 0x01C0: sb.AppendLine("Device complies with SES (no version claimed)"); + break; case 0x01DB: sb.AppendLine("Device complies with SES T10/1212-D revision 08b"); + break; case 0x01DC: sb.AppendLine("Device complies with SES ANSI INCITS 305-1998"); + break; case 0x01DD: sb.AppendLine("Device complies with SES T10/1212 revision 08b w/ Amendment ANSI INCITS.305/AM1-2000"); + break; case 0x01DE: sb.AppendLine("Device complies with SES ANSI INCITS 305-1998 w/ Amendment ANSI INCITS.305/AM1-2000"); + break; case 0x01E0: sb.AppendLine("Device complies with SCC-2 (no version claimed)"); + break; case 0x01FB: sb.AppendLine("Device complies with SCC-2 T10/1125-D revision 04"); + break; case 0x01FC: sb.AppendLine("Device complies with SCC-2 ANSI INCITS 318-1998"); + break; case 0x0200: sb.AppendLine("Device complies with SSC (no version claimed)"); + break; case 0x0201: sb.AppendLine("Device complies with SSC T10/0997-D revision 17"); + break; case 0x0207: sb.AppendLine("Device complies with SSC T10/0997-D revision 22"); + break; case 0x021C: sb.AppendLine("Device complies with SSC ANSI INCITS 335-2000"); + break; case 0x0220: sb.AppendLine("Device complies with RBC (no version claimed)"); + break; case 0x0238: sb.AppendLine("Device complies with RBC T10/1240-D revision 10a"); + break; case 0x023C: sb.AppendLine("Device complies with RBC ANSI INCITS 330-2000"); + break; case 0x0240: sb.AppendLine("Device complies with MMC-2 (no version claimed)"); + break; case 0x0255: sb.AppendLine("Device complies with MMC-2 T10/1228-D revision 11"); + break; case 0x025B: sb.AppendLine("Device complies with MMC-2 T10/1228-D revision 11a"); + break; case 0x025C: sb.AppendLine("Device complies with MMC-2 ANSI INCITS 333-2000"); + break; case 0x0260: sb.AppendLine("Device complies with SPC-2 (no version claimed)"); + break; case 0x0267: sb.AppendLine("Device complies with SPC-2 T10/1236-D revision 12"); + break; case 0x0269: sb.AppendLine("Device complies with SPC-2 T10/1236-D revision 18"); + break; case 0x0275: sb.AppendLine("Device complies with SPC-2 T10/1236-D revision 19"); + break; case 0x0276: sb.AppendLine("Device complies with SPC-2 T10/1236-D revision 20"); + break; case 0x0277: sb.AppendLine("Device complies with SPC-2 ANSI INCITS 351-2001"); + break; case 0x0278: sb.AppendLine("Device complies with SPC-2 ISO/IEC 14776-452"); + break; case 0x0280: sb.AppendLine("Device complies with OCRW (no version claimed)"); + break; case 0x029E: sb.AppendLine("Device complies with OCRW ISO/IEC 14776-381"); + break; case 0x02A0: sb.AppendLine("Device complies with MMC-3 (no version claimed)"); + break; case 0x02B5: sb.AppendLine("Device complies with MMC-3 T10/1363-D revision 9"); + break; case 0x02B6: sb.AppendLine("Device complies with MMC-3 T10/1363-D revision 10g"); + break; case 0x02B8: sb.AppendLine("Device complies with MMC-3 ANSI INCITS 360-2002"); + break; case 0x02E0: sb.AppendLine("Device complies with SMC-2 (no version claimed)"); + break; case 0x02F5: sb.AppendLine("Device complies with SMC-2 T10/1383-D revision 5"); + break; case 0x02FC: sb.AppendLine("Device complies with SMC-2 T10/1383-D revision 6"); + break; case 0x02FD: sb.AppendLine("Device complies with SMC-2 T10/1383-D revision 7"); + break; case 0x02FE: sb.AppendLine("Device complies with SMC-2 ANSI INCITS 382-2004"); + break; case 0x0300: sb.AppendLine("Device complies with SPC-3 (no version claimed)"); + break; case 0x0301: sb.AppendLine("Device complies with SPC-3 T10/1416-D revision 7"); + break; case 0x0307: sb.AppendLine("Device complies with SPC-3 T10/1416-D revision 21"); + break; case 0x030F: sb.AppendLine("Device complies with SPC-3 T10/1416-D revision 22"); + break; case 0x0312: sb.AppendLine("Device complies with SPC-3 T10/1416-D revision 23"); + break; case 0x0314: sb.AppendLine("Device complies with SPC-3 ANSI INCITS 408-2005"); + break; case 0x0316: sb.AppendLine("Device complies with SPC-3 ISO/IEC 14776-453"); + break; case 0x0320: sb.AppendLine("Device complies with SBC-2 (no version claimed)"); + break; case 0x0322: sb.AppendLine("Device complies with SBC-2 T10/1417-D revision 5a"); + break; case 0x0324: sb.AppendLine("Device complies with SBC-2 T10/1417-D revision 15"); + break; case 0x033B: sb.AppendLine("Device complies with SBC-2 T10/1417-D revision 16"); + break; case 0x033D: sb.AppendLine("Device complies with SBC-2 ANSI INCITS 405-2005"); + break; case 0x033E: sb.AppendLine("Device complies with SBC-2 ISO/IEC 14776-322"); + break; case 0x0340: sb.AppendLine("Device complies with OSD (no version claimed)"); + break; case 0x0341: sb.AppendLine("Device complies with OSD T10/1355-D revision 0"); + break; case 0x0342: sb.AppendLine("Device complies with OSD T10/1355-D revision 7a"); + break; case 0x0343: sb.AppendLine("Device complies with OSD T10/1355-D revision 8"); + break; case 0x0344: sb.AppendLine("Device complies with OSD T10/1355-D revision 9"); + break; case 0x0355: sb.AppendLine("Device complies with OSD T10/1355-D revision 10"); + break; case 0x0356: sb.AppendLine("Device complies with OSD ANSI INCITS 400-2004"); + break; case 0x0360: sb.AppendLine("Device complies with SSC-2 (no version claimed)"); + break; case 0x0374: sb.AppendLine("Device complies with SSC-2 T10/1434-D revision 7"); + break; case 0x0375: sb.AppendLine("Device complies with SSC-2 T10/1434-D revision 9"); + break; case 0x037D: sb.AppendLine("Device complies with SSC-2 ANSI INCITS 380-2003"); + break; case 0x0380: sb.AppendLine("Device complies with BCC (no version claimed)"); + break; case 0x03A0: sb.AppendLine("Device complies with MMC-4 (no version claimed)"); + break; case 0x03B0: sb.AppendLine("Device complies with MMC-4 T10/1545-D revision 5"); + break; case 0x03B1: sb.AppendLine("Device complies with MMC-4 T10/1545-D revision 5a"); + break; case 0x03BD: sb.AppendLine("Device complies with MMC-4 T10/1545-D revision 3"); + break; case 0x03BE: sb.AppendLine("Device complies with MMC-4 T10/1545-D revision 3d"); + break; case 0x03BF: sb.AppendLine("Device complies with MMC-4 ANSI INCITS 401-2005"); + break; case 0x03C0: sb.AppendLine("Device complies with ADC (no version claimed)"); + break; case 0x03D5: sb.AppendLine("Device complies with ADC T10/1558-D revision 6"); + break; case 0x03D6: sb.AppendLine("Device complies with ADC T10/1558-D revision 7"); + break; case 0x03D7: sb.AppendLine("Device complies with ADC ANSI INCITS 403-2005"); + break; case 0x03E0: sb.AppendLine("Device complies with SES-2 (no version claimed)"); + break; case 0x03E1: sb.AppendLine("Device complies with SES-2 T10/1559-D revision 16"); + break; case 0x03E7: sb.AppendLine("Device complies with SES-2 T10/1559-D revision 19"); + break; case 0x03EB: sb.AppendLine("Device complies with SES-2 T10/1559-D revision 20"); + break; case 0x03F0: sb.AppendLine("Device complies with SES-2 ANSI INCITS 448-2008"); + break; case 0x03F2: sb.AppendLine("Device complies with SES-2 ISO/IEC 14776-372"); + break; case 0x0400: sb.AppendLine("Device complies with SSC-3 (no version claimed)"); + break; case 0x0403: sb.AppendLine("Device complies with SSC-3 T10/1611-D revision 04a"); + break; case 0x0407: sb.AppendLine("Device complies with SSC-3 T10/1611-D revision 05"); + break; case 0x0409: sb.AppendLine("Device complies with SSC-3 ANSI INCITS 467-2011"); + break; case 0x040B: sb.AppendLine("Device complies with SSC-3 ISO/IEC 14776-333:2013"); + break; case 0x0420: sb.AppendLine("Device complies with MMC-5 (no version claimed)"); + break; case 0x042F: sb.AppendLine("Device complies with MMC-5 T10/1675-D revision 03"); + break; case 0x0431: sb.AppendLine("Device complies with MMC-5 T10/1675-D revision 03b"); + break; case 0x0432: sb.AppendLine("Device complies with MMC-5 T10/1675-D revision 04"); + break; case 0x0434: sb.AppendLine("Device complies with MMC-5 ANSI INCITS 430-2007"); + break; case 0x0440: sb.AppendLine("Device complies with OSD-2 (no version claimed)"); + break; case 0x0444: sb.AppendLine("Device complies with OSD-2 T10/1729-D revision 4"); + break; case 0x0446: sb.AppendLine("Device complies with OSD-2 T10/1729-D revision 5"); + break; case 0x0448: sb.AppendLine("Device complies with OSD-2 ANSI INCITS 458-2011"); + break; case 0x0460: sb.AppendLine("Device complies with SPC-4 (no version claimed)"); + break; case 0x0461: sb.AppendLine("Device complies with SPC-4 T10/BSR INCITS 513 revision 16"); + break; case 0x0462: sb.AppendLine("Device complies with SPC-4 T10/BSR INCITS 513 revision 18"); + break; case 0x0463: sb.AppendLine("Device complies with SPC-4 T10/BSR INCITS 513 revision 23"); + break; case 0x0466: sb.AppendLine("Device complies with SPC-4 T10/BSR INCITS 513 revision 36"); + break; case 0x0468: sb.AppendLine("Device complies with SPC-4 T10/BSR INCITS 513 revision 37"); + break; case 0x0469: sb.AppendLine("Device complies with SPC-4 T10/BSR INCITS 513 revision 37a"); + break; case 0x046C: sb.AppendLine("Device complies with SPC-4 ANSI INCITS 513-2015"); + break; case 0x0480: sb.AppendLine("Device complies with SMC-3 (no version claimed)"); + break; case 0x0482: sb.AppendLine("Device complies with SMC-3 T10/1730-D revision 15"); + break; case 0x0484: sb.AppendLine("Device complies with SMC-3 T10/1730-D revision 16"); + break; case 0x0486: sb.AppendLine("Device complies with SMC-3 ANSI INCITS 484-2012"); + break; case 0x04A0: sb.AppendLine("Device complies with ADC-2 (no version claimed)"); + break; case 0x04A7: sb.AppendLine("Device complies with ADC-2 T10/1741-D revision 7"); + break; case 0x04AA: sb.AppendLine("Device complies with ADC-2 T10/1741-D revision 8"); + break; case 0x04AC: sb.AppendLine("Device complies with ADC-2 ANSI INCITS 441-2008"); + break; case 0x04C0: sb.AppendLine("Device complies with SBC-3 (no version claimed)"); + break; case 0x04C3: sb.AppendLine("Device complies with SBC-3 T10/BSR INCITS 514 revision 35"); + break; case 0x04C5: sb.AppendLine("Device complies with SBC-3 T10/BSR INCITS 514 revision 36"); + break; case 0x04C8: sb.AppendLine("Device complies with SBC-3 ANSI INCITS 514-2014"); + break; case 0x04E0: sb.AppendLine("Device complies with MMC-6 (no version claimed)"); + break; case 0x04E3: sb.AppendLine("Device complies with MMC-6 T10/1836-D revision 02b"); + break; case 0x04E5: sb.AppendLine("Device complies with MMC-6 T10/1836-D revision 02g"); + break; case 0x04E6: sb.AppendLine("Device complies with MMC-6 ANSI INCITS 468-2010"); + break; case 0x04E7: sb.AppendLine("Device complies with MMC-6 ANSI INCITS 468-2010 + MMC-6/AM1 ANSI INCITS 468-2010/AM 1"); + break; case 0x0500: sb.AppendLine("Device complies with ADC-3 (no version claimed)"); + break; case 0x0502: sb.AppendLine("Device complies with ADC-3 T10/1895-D revision 04"); + break; case 0x0504: sb.AppendLine("Device complies with ADC-3 T10/1895-D revision 05"); + break; case 0x0506: sb.AppendLine("Device complies with ADC-3 T10/1895-D revision 05a"); + break; case 0x050A: sb.AppendLine("Device complies with ADC-3 ANSI INCITS 497-2012"); + break; case 0x0520: sb.AppendLine("Device complies with SSC-4 (no version claimed)"); + break; case 0x0523: sb.AppendLine("Device complies with SSC-4 T10/BSR INCITS 516 revision 2"); + break; case 0x0525: sb.AppendLine("Device complies with SSC-4 T10/BSR INCITS 516 revision 3"); + break; case 0x0527: sb.AppendLine("Device complies with SSC-4 ANSI INCITS 516-2013"); + break; case 0x0560: sb.AppendLine("Device complies with OSD-3 (no version claimed)"); + break; case 0x0580: sb.AppendLine("Device complies with SES-3 (no version claimed)"); + break; case 0x05A0: sb.AppendLine("Device complies with SSC-5 (no version claimed)"); + break; case 0x05C0: sb.AppendLine("Device complies with SPC-5 (no version claimed)"); + break; case 0x05E0: sb.AppendLine("Device complies with SFSC (no version claimed)"); + break; case 0x05E3: sb.AppendLine("Device complies with SFSC BSR INCITS 501 revision 01"); + break; case 0x0600: sb.AppendLine("Device complies with SBC-4 (no version claimed)"); + break; case 0x0620: sb.AppendLine("Device complies with ZBC (no version claimed)"); + break; case 0x0622: sb.AppendLine("Device complies with ZBC BSR INCITS 536 revision 02"); + break; case 0x0640: sb.AppendLine("Device complies with ADC-4 (no version claimed)"); + break; case 0x0820: sb.AppendLine("Device complies with SSA-TL2 (no version claimed)"); + break; case 0x083B: sb.AppendLine("Device complies with SSA-TL2 T10.1/1147-D revision 05b"); + break; case 0x083C: sb.AppendLine("Device complies with SSA-TL2 ANSI INCITS 308-1998"); + break; case 0x0840: sb.AppendLine("Device complies with SSA-TL1 (no version claimed)"); + break; case 0x085B: sb.AppendLine("Device complies with SSA-TL1 T10.1/0989-D revision 10b"); + break; case 0x085C: sb.AppendLine("Device complies with SSA-TL1 ANSI INCITS 295-1996"); + break; case 0x0860: sb.AppendLine("Device complies with SSA-S3P (no version claimed)"); + break; case 0x087B: sb.AppendLine("Device complies with SSA-S3P T10.1/1051-D revision 05b"); + break; case 0x087C: sb.AppendLine("Device complies with SSA-S3P ANSI INCITS 309-1998"); + break; case 0x0880: sb.AppendLine("Device complies with SSA-S2P (no version claimed)"); + break; case 0x089B: sb.AppendLine("Device complies with SSA-S2P T10.1/1121-D revision 07b"); + break; case 0x089C: sb.AppendLine("Device complies with SSA-S2P ANSI INCITS 294-1996"); + break; case 0x08A0: sb.AppendLine("Device complies with SIP (no version claimed)"); + break; case 0x08BB: sb.AppendLine("Device complies with SIP T10/0856-D revision 10"); + break; case 0x08BC: sb.AppendLine("Device complies with SIP ANSI INCITS 292-1997"); + break; case 0x08C0: sb.AppendLine("Device complies with FCP (no version claimed)"); + break; case 0x08DB: sb.AppendLine("Device complies with FCP T10/0993-D revision 12"); + break; case 0x08DC: sb.AppendLine("Device complies with FCP ANSI INCITS 269-1996"); + break; case 0x08E0: sb.AppendLine("Device complies with SBP-2 (no version claimed)"); + break; case 0x08FB: sb.AppendLine("Device complies with SBP-2 T10/1155-D revision 04"); + break; case 0x08FC: sb.AppendLine("Device complies with SBP-2 ANSI INCITS 325-1998"); + break; case 0x0900: sb.AppendLine("Device complies with FCP-2 (no version claimed)"); + break; case 0x0901: sb.AppendLine("Device complies with FCP-2 T10/1144-D revision 4"); + break; case 0x0915: sb.AppendLine("Device complies with FCP-2 T10/1144-D revision 7"); + break; case 0x0916: sb.AppendLine("Device complies with FCP-2 T10/1144-D revision 7a"); + break; case 0x0917: sb.AppendLine("Device complies with FCP-2 ANSI INCITS 350-2003"); + break; case 0x0918: sb.AppendLine("Device complies with FCP-2 T10/1144-D revision 8"); + break; case 0x0920: sb.AppendLine("Device complies with SST (no version claimed)"); + break; case 0x0935: sb.AppendLine("Device complies with SST T10/1380-D revision 8b"); + break; case 0x0940: sb.AppendLine("Device complies with SRP (no version claimed)"); + break; case 0x0954: sb.AppendLine("Device complies with SRP T10/1415-D revision 10"); + break; case 0x0955: sb.AppendLine("Device complies with SRP T10/1415-D revision 16a"); + break; case 0x095C: sb.AppendLine("Device complies with SRP ANSI INCITS 365-2002"); + break; case 0x0960: sb.AppendLine("Device complies with iSCSI (no version claimed)"); + break; case 0x0961: case 0x0962: @@ -1357,756 +1960,1006 @@ namespace DiscImageChef.Decoders.SCSI case 0x097D: case 0x097E: case 0x097F: - sb.AppendFormat("Device complies with iSCSI revision {0}", VersionDescriptor & 0x1F) - .AppendLine(); + sb.AppendFormat("Device complies with iSCSI revision {0}", VersionDescriptor & 0x1F). + AppendLine(); + break; case 0x0980: sb.AppendLine("Device complies with SBP-3 (no version claimed)"); + break; case 0x0982: sb.AppendLine("Device complies with SBP-3 T10/1467-D revision 1f"); + break; case 0x0994: sb.AppendLine("Device complies with SBP-3 T10/1467-D revision 3"); + break; case 0x099A: sb.AppendLine("Device complies with SBP-3 T10/1467-D revision 4"); + break; case 0x099B: sb.AppendLine("Device complies with SBP-3 T10/1467-D revision 5"); + break; case 0x099C: sb.AppendLine("Device complies with SBP-3 ANSI INCITS 375-2004"); + break; case 0x09C0: sb.AppendLine("Device complies with ADP (no version claimed)"); + break; case 0x09E0: sb.AppendLine("Device complies with ADT (no version claimed)"); + break; case 0x09F9: sb.AppendLine("Device complies with ADT T10/1557-D revision 11"); + break; case 0x09FA: sb.AppendLine("Device complies with ADT T10/1557-D revision 14"); + break; case 0x09FD: sb.AppendLine("Device complies with ADT ANSI INCITS 406-2005"); + break; case 0x0A00: sb.AppendLine("Device complies with FCP-3 (no version claimed)"); + break; case 0x0A07: sb.AppendLine("Device complies with FCP-3 T10/1560-D revision 3f"); + break; case 0x0A0F: sb.AppendLine("Device complies with FCP-3 T10/1560-D revision 4"); + break; case 0x0A11: sb.AppendLine("Device complies with FCP-3 ANSI INCITS 416-2006"); + break; case 0x0A1C: sb.AppendLine("Device complies with FCP-3 ISO/IEC 14776-223"); + break; case 0x0A20: sb.AppendLine("Device complies with ADT-2 (no version claimed)"); + break; case 0x0A22: sb.AppendLine("Device complies with ADT-2 T10/1742-D revision 06"); + break; case 0x0A27: sb.AppendLine("Device complies with ADT-2 T10/1742-D revision 08"); + break; case 0x0A28: sb.AppendLine("Device complies with ADT-2 T10/1742-D revision 09"); + break; case 0x0A2B: sb.AppendLine("Device complies with ADT-2 ANSI INCITS 472-2011"); + break; case 0x0A40: sb.AppendLine("Device complies with FCP-4 (no version claimed)"); + break; case 0x0A42: sb.AppendLine("Device complies with FCP-4 T10/1828-D revision 01"); + break; case 0x0A44: sb.AppendLine("Device complies with FCP-4 T10/1828-D revision 02"); + break; case 0x0A45: sb.AppendLine("Device complies with FCP-4 T10/1828-D revision 02b"); + break; case 0x0A46: sb.AppendLine("Device complies with FCP-4 ANSI INCITS 481-2012"); + break; case 0x0A60: sb.AppendLine("Device complies with ADT-3 (no version claimed)"); + break; case 0x0AA0: sb.AppendLine("Device complies with SPI (no version claimed)"); + break; case 0x0AB9: sb.AppendLine("Device complies with SPI T10/0855-D revision 15a"); + break; case 0x0ABA: sb.AppendLine("Device complies with SPI ANSI INCITS 253-1995"); + break; case 0x0ABB: sb.AppendLine("Device complies with SPI T10/0855-D revision 15a with SPI Amnd revision 3a"); + break; case 0x0ABC: sb.AppendLine("Device complies with SPI ANSI INCITS 253-1995 with SPI Amnd ANSI INCITS 253/AM1-1998"); + break; case 0x0AC0: sb.AppendLine("Device complies with Fast-20 (no version claimed)"); + break; case 0x0ADB: sb.AppendLine("Device complies with Fast-20 T10/1071 revision 06"); + break; case 0x0ADC: sb.AppendLine("Device complies with Fast-20 ANSI INCITS 277-1996"); + break; case 0x0AE0: sb.AppendLine("Device complies with SPI-2 (no version claimed)"); + break; case 0x0AFB: sb.AppendLine("Device complies with SPI-2 T10/1142-D revision 20b"); + break; case 0x0AFC: sb.AppendLine("Device complies with SPI-2 ANSI INCITS 302-1999"); + break; case 0x0B00: sb.AppendLine("Device complies with SPI-3 (no version claimed)"); + break; case 0x0B18: sb.AppendLine("Device complies with SPI-3 T10/1302-D revision 10"); + break; case 0x0B19: sb.AppendLine("Device complies with SPI-3 T10/1302-D revision 13a"); + break; case 0x0B1A: sb.AppendLine("Device complies with SPI-3 T10/1302-D revision 14"); + break; case 0x0B1C: sb.AppendLine("Device complies with SPI-3 ANSI INCITS 336-2000"); + break; case 0x0B20: sb.AppendLine("Device complies with EPI (no version claimed)"); + break; case 0x0B3B: sb.AppendLine("Device complies with EPI T10/1134 revision 16"); + break; case 0x0B3C: sb.AppendLine("Device complies with EPI ANSI INCITS TR-23 1999"); + break; case 0x0B40: sb.AppendLine("Device complies with SPI-4 (no version claimed)"); + break; case 0x0B54: sb.AppendLine("Device complies with SPI-4 T10/1365-D revision 7"); + break; case 0x0B55: sb.AppendLine("Device complies with SPI-4 T10/1365-D revision 9"); + break; case 0x0B56: sb.AppendLine("Device complies with SPI-4 ANSI INCITS 362-2002"); + break; case 0x0B59: sb.AppendLine("Device complies with SPI-4 T10/1365-D revision 10"); + break; case 0x0B60: sb.AppendLine("Device complies with SPI-5 (no version claimed)"); + break; case 0x0B79: sb.AppendLine("Device complies with SPI-5 T10/1525-D revision 3"); + break; case 0x0B7A: sb.AppendLine("Device complies with SPI-5 T10/1525-D revision 5"); + break; case 0x0B7B: sb.AppendLine("Device complies with SPI-5 T10/1525-D revision 6"); + break; case 0x0B7C: sb.AppendLine("Device complies with SPI-5 ANSI INCITS 367-2003"); + break; case 0x0BE0: sb.AppendLine("Device complies with SAS (no version claimed)"); + break; case 0x0BE1: sb.AppendLine("Device complies with SAS T10/1562-D revision 01"); + break; case 0x0BF5: sb.AppendLine("Device complies with SAS T10/1562-D revision 03"); + break; case 0x0BFA: sb.AppendLine("Device complies with SAS T10/1562-D revision 04"); + break; case 0x0BFB: sb.AppendLine("Device complies with SAS T10/1562-D revision 04"); + break; case 0x0BFC: sb.AppendLine("Device complies with SAS T10/1562-D revision 05"); + break; case 0x0BFD: sb.AppendLine("Device complies with SAS ANSI INCITS 376-2003"); + break; case 0x0C00: sb.AppendLine("Device complies with SAS-1.1 (no version claimed)"); + break; case 0x0C07: sb.AppendLine("Device complies with SAS-1.1 T10/1601-D revision 9"); + break; case 0x0C0F: sb.AppendLine("Device complies with SAS-1.1 T10/1601-D revision 10"); + break; case 0x0C11: sb.AppendLine("Device complies with SAS-1.1 ANSI INCITS 417-2006"); + break; case 0x0C12: sb.AppendLine("Device complies with SAS-1.1 ISO/IEC 14776-151"); + break; case 0x0C20: sb.AppendLine("Device complies with SAS-2 (no version claimed)"); + break; case 0x0C23: sb.AppendLine("Device complies with SAS-2 T10/1760-D revision 14"); + break; case 0x0C27: sb.AppendLine("Device complies with SAS-2 T10/1760-D revision 15"); + break; case 0x0C28: sb.AppendLine("Device complies with SAS-2 T10/1760-D revision 16"); + break; case 0x0C2A: sb.AppendLine("Device complies with SAS-2 ANSI INCITS 457-2010"); + break; case 0x0C40: sb.AppendLine("Device complies with SAS-2.1 (no version claimed)"); + break; case 0x0C48: sb.AppendLine("Device complies with SAS-2.1 T10/2125-D revision 04"); + break; case 0x0C4A: sb.AppendLine("Device complies with SAS-2.1 T10/2125-D revision 06"); + break; case 0x0C4B: sb.AppendLine("Device complies with SAS-2.1 T10/2125-D revision 07"); + break; case 0x0C4E: sb.AppendLine("Device complies with SAS-2.1 ANSI INCITS 478-2011"); + break; case 0x0C4F: sb.AppendLine("Device complies with SAS-2.1 ANSI INCITS 478-2011 w/ Amnd 1 ANSI INCITS 478/AM1-2014"); + break; case 0x0C52: sb.AppendLine("Device complies with SAS-2.1 ISO/IEC 14776-153"); + break; case 0x0C60: sb.AppendLine("Device complies with SAS-3 (no version claimed)"); + break; case 0x0C63: sb.AppendLine("Device complies with SAS-3 T10/BSR INCITS 519 revision 05a"); + break; case 0x0C65: sb.AppendLine("Device complies with SAS-3 T10/BSR INCITS 519 revision 06"); + break; case 0x0C68: sb.AppendLine("Device complies with SAS-3 ANSI INCITS 519-2014"); + break; case 0x0C80: sb.AppendLine("Device complies with SAS-4 (no version claimed)"); + break; case 0x0D20: sb.AppendLine("Device complies with FC-PH (no version claimed)"); + break; case 0x0D3B: sb.AppendLine("Device complies with FC-PH ANSI INCITS 230-1994"); + break; case 0x0D3C: sb.AppendLine("Device complies with FC-PH ANSI INCITS 230-1994 with Amnd 1 ANSI INCITS 230/AM1-1996"); + break; case 0x0D40: sb.AppendLine("Device complies with FC-AL (no version claimed)"); + break; case 0x0D5C: sb.AppendLine("Device complies with FC-AL ANSI INCITS 272-1996"); + break; case 0x0D60: sb.AppendLine("Device complies with FC-AL-2 (no version claimed)"); + break; case 0x0D61: sb.AppendLine("Device complies with FC-AL-2 T11/1133-D revision 7.0"); + break; case 0x0D63: sb.AppendLine("Device complies with FC-AL-2 ANSI INCITS 332-1999 with AM1-2003 & AM2-2006"); + break; case 0x0D64: sb.AppendLine("Device complies with FC-AL-2 ANSI INCITS 332-1999 with Amnd 2 AM2-2006"); + break; case 0x0D65: sb.AppendLine("Device complies with FC-AL-2 ISO/IEC 14165-122 with AM1 & AM2"); + break; case 0x0D7C: sb.AppendLine("Device complies with FC-AL-2 ANSI INCITS 332-1999"); + break; case 0x0D7D: sb.AppendLine("Device complies with FC-AL-2 ANSI INCITS 332-1999 with Amnd 1 AM1-2003"); + break; case 0x0D80: sb.AppendLine("Device complies with FC-PH-3 (no version claimed)"); + break; case 0x0D9C: sb.AppendLine("Device complies with FC-PH-3 ANSI INCITS 303-1998"); + break; case 0x0DA0: sb.AppendLine("Device complies with FC-FS (no version claimed)"); + break; case 0x0DB7: sb.AppendLine("Device complies with FC-FS T11/1331-D revision 1.2"); + break; case 0x0DB8: sb.AppendLine("Device complies with FC-FS T11/1331-D revision 1.7"); + break; case 0x0DBC: sb.AppendLine("Device complies with FC-FS ANSI INCITS 373-2003"); + break; case 0x0DBD: sb.AppendLine("Device complies with FC-FS ISO/IEC 14165-251"); + break; case 0x0DC0: sb.AppendLine("Device complies with FC-PI (no version claimed)"); + break; case 0x0DDC: sb.AppendLine("Device complies with FC-PI ANSI INCITS 352-2002"); + break; case 0x0DE0: sb.AppendLine("Device complies with FC-PI-2 (no version claimed)"); + break; case 0x0DE2: sb.AppendLine("Device complies with FC-PI-2 T11/1506-D revision 5.0"); + break; case 0x0DE4: sb.AppendLine("Device complies with FC-PI-2 ANSI INCITS 404-2006"); + break; case 0x0E00: sb.AppendLine("Device complies with FC-FS-2 (no version claimed)"); + break; case 0x0E02: sb.AppendLine("Device complies with FC-FS-2 ANSI INCITS 242-2007"); + break; case 0x0E03: sb.AppendLine("Device complies with FC-FS-2 ANSI INCITS 242-2007 with AM1 ANSI INCITS 242/AM1-2007"); + break; case 0x0E20: sb.AppendLine("Device complies with FC-LS (no version claimed)"); + break; case 0x0E21: sb.AppendLine("Device complies with FC-LS T11/1620-D revision 1.62"); + break; case 0x0E29: sb.AppendLine("Device complies with FC-LS ANSI INCITS 433-2007"); + break; case 0x0E40: sb.AppendLine("Device complies with FC-SP (no version claimed)"); + break; case 0x0E42: sb.AppendLine("Device complies with FC-SP T11/1570-D revision 1.6"); + break; case 0x0E45: sb.AppendLine("Device complies with FC-SP ANSI INCITS 426-2007"); + break; case 0x0E60: sb.AppendLine("Device complies with FC-PI-3 (no version claimed)"); + break; case 0x0E62: sb.AppendLine("Device complies with FC-PI-3 T11/1625-D revision 2.0"); + break; case 0x0E68: sb.AppendLine("Device complies with FC-PI-3 T11/1625-D revision 2.1"); + break; case 0x0E6A: sb.AppendLine("Device complies with FC-PI-3 T11/1625-D revision 4.0"); + break; case 0x0E6E: sb.AppendLine("Device complies with FC-PI-3 ANSI INCITS 460-2011"); + break; case 0x0E80: sb.AppendLine("Device complies with FC-PI-4 (no version claimed)"); + break; case 0x0E82: sb.AppendLine("Device complies with FC-PI-4 T11/1647-D revision 8.0"); + break; case 0x0E88: sb.AppendLine("Device complies with FC-PI-4 ANSI INCITS 450-2009"); + break; case 0x0EA0: sb.AppendLine("Device complies with FC 10GFC (no version claimed)"); + break; case 0x0EA2: sb.AppendLine("Device complies with FC 10GFC ANSI INCITS 364-2003"); + break; case 0x0EA3: sb.AppendLine("Device complies with FC 10GFC ISO/IEC 14165-116"); + break; case 0x0EA5: sb.AppendLine("Device complies with FC 10GFC ISO/IEC 14165-116 with AM1"); + break; case 0x0EA6: sb.AppendLine("Device complies with FC 10GFC ANSI INCITS 364-2003 with AM1 ANSI INCITS 364/AM1-2007"); + break; case 0x0EC0: sb.AppendLine("Device complies with FC-SP-2 (no version claimed)"); + break; case 0x0EE0: sb.AppendLine("Device complies with FC-FS-3 (no version claimed)"); + break; case 0x0EE2: sb.AppendLine("Device complies with FC-FS-3 T11/1861-D revision 0.9"); + break; case 0x0EE7: sb.AppendLine("Device complies with FC-FS-3 T11/1861-D revision 1.0"); + break; case 0x0EE9: sb.AppendLine("Device complies with FC-FS-3 T11/1861-D revision 1.10"); + break; case 0x0EEB: sb.AppendLine("Device complies with FC-FS-3 ANSI INCITS 470-2011"); + break; case 0x0F00: sb.AppendLine("Device complies with FC-LS-2 (no version claimed)"); + break; case 0x0F03: sb.AppendLine("Device complies with FC-LS-2 T11/2103-D revision 2.11"); + break; case 0x0F05: sb.AppendLine("Device complies with FC-LS-2 T11/2103-D revision 2.21"); + break; case 0x0F07: sb.AppendLine("Device complies with FC-LS-2 ANSI INCITS 477-2011"); + break; case 0x0F20: sb.AppendLine("Device complies with FC-PI-5 (no version claimed)"); + break; case 0x0F27: sb.AppendLine("Device complies with FC-PI-5 T11/2118-D revision 2.00"); + break; case 0x0F28: sb.AppendLine("Device complies with FC-PI-5 T11/2118-D revision 3.00"); + break; case 0x0F2A: sb.AppendLine("Device complies with FC-PI-5 T11/2118-D revision 6.00"); + break; case 0x0F2B: sb.AppendLine("Device complies with FC-PI-5 T11/2118-D revision 6.10"); + break; case 0x0F2E: sb.AppendLine("Device complies with FC-PI-5 ANSI INCITS 479-2011"); + break; case 0x0F40: sb.AppendLine("Device complies with FC-PI-6 (no version claimed)"); + break; case 0x0F60: sb.AppendLine("Device complies with FC-FS-4 (no version claimed)"); + break; case 0x0F80: sb.AppendLine("Device complies with FC-LS-3 (no version claimed)"); + break; case 0x12A0: sb.AppendLine("Device complies with FC-SCM (no version claimed)"); + break; case 0x12A3: sb.AppendLine("Device complies with FC-SCM T11/1824DT revision 1.0"); + break; case 0x12A5: sb.AppendLine("Device complies with FC-SCM T11/1824DT revision 1.1"); + break; case 0x12A7: sb.AppendLine("Device complies with FC-SCM T11/1824DT revision 1.4"); + break; case 0x12AA: sb.AppendLine("Device complies with FC-SCM INCITS TR-47 2012"); + break; case 0x12C0: sb.AppendLine("Device complies with FC-DA-2 (no version claimed)"); + break; case 0x12C3: sb.AppendLine("Device complies with FC-DA-2 T11/1870DT revision 1.04"); + break; case 0x12C5: sb.AppendLine("Device complies with FC-DA-2 T11/1870DT revision 1.06"); + break; case 0x12C9: sb.AppendLine("Device complies with FC-DA-2 INCITS TR-49 2012"); + break; case 0x12E0: sb.AppendLine("Device complies with FC-DA (no version claimed)"); + break; case 0x12E2: sb.AppendLine("Device complies with FC-DA T11/1513-DT revision 3.1"); + break; case 0x12E8: sb.AppendLine("Device complies with FC-DA ANSI INCITS TR-36 2004"); + break; case 0x12E9: sb.AppendLine("Device complies with FC-DA ISO/IEC 14165-341"); + break; case 0x1300: sb.AppendLine("Device complies with FC-Tape (no version claimed)"); + break; case 0x1301: sb.AppendLine("Device complies with FC-Tape T11/1315 revision 1.16"); + break; case 0x131B: sb.AppendLine("Device complies with FC-Tape T11/1315 revision 1.17"); + break; case 0x131C: sb.AppendLine("Device complies with FC-Tape ANSI INCITS TR-24 1999"); + break; case 0x1320: sb.AppendLine("Device complies with FC-FLA (no version claimed)"); + break; case 0x133B: sb.AppendLine("Device complies with FC-FLA T11/1235 revision 7"); + break; case 0x133C: sb.AppendLine("Device complies with FC-FLA ANSI INCITS TR-20 1998"); + break; case 0x1340: sb.AppendLine("Device complies with FC-PLDA (no version claimed)"); + break; case 0x135B: sb.AppendLine("Device complies with FC-PLDA T11/1162 revision 2.1"); + break; case 0x135C: sb.AppendLine("Device complies with FC-PLDA ANSI INCITS TR-19 1998"); + break; case 0x1360: sb.AppendLine("Device complies with SSA-PH2 (no version claimed)"); + break; case 0x137B: sb.AppendLine("Device complies with SSA-PH2 T10.1/1145-D revision 09c"); + break; case 0x137C: sb.AppendLine("Device complies with SSA-PH2 ANSI INCITS 293-1996"); + break; case 0x1380: sb.AppendLine("Device complies with SSA-PH3 (no version claimed)"); + break; case 0x139B: sb.AppendLine("Device complies with SSA-PH3 T10.1/1146-D revision 05b"); + break; case 0x139C: sb.AppendLine("Device complies with SSA-PH3 ANSI INCITS 307-1998"); + break; case 0x14A0: sb.AppendLine("Device complies with IEEE 1394 (no version claimed)"); + break; case 0x14BD: sb.AppendLine("Device complies with ANSI IEEE 1394-1995"); + break; case 0x14C0: sb.AppendLine("Device complies with IEEE 1394a (no version claimed)"); + break; case 0x14E0: sb.AppendLine("Device complies with IEEE 1394b (no version claimed)"); + break; case 0x15E0: sb.AppendLine("Device complies with ATA/ATAPI-6 (no version claimed)"); + break; case 0x15FD: sb.AppendLine("Device complies with ATA/ATAPI-6 ANSI INCITS 361-2002"); + break; case 0x1600: sb.AppendLine("Device complies with ATA/ATAPI-7 (no version claimed)"); + break; case 0x1602: sb.AppendLine("Device complies with ATA/ATAPI-7 T13/1532-D revision 3"); + break; case 0x161C: sb.AppendLine("Device complies with ATA/ATAPI-7 ANSI INCITS 397-2005"); + break; case 0x161E: sb.AppendLine("Device complies with ATA/ATAPI-7 ISO/IEC 24739"); + break; case 0x1620: sb.AppendLine("Device complies with ATA/ATAPI-8 ATA8-AAM (no version claimed)"); + break; case 0x1621: sb.AppendLine("Device complies with ATA/ATAPI-8 ATA8-APT Parallel Transport (no version claimed)"); + break; case 0x1622: sb.AppendLine("Device complies with ATA/ATAPI-8 ATA8-AST Serial Transport (no version claimed)"); + break; case 0x1623: sb.AppendLine("Device complies with ATA/ATAPI-8 ATA8-ACS ATA/ATAPI Command Set (no version claimed)"); + break; case 0x1628: sb.AppendLine("Device complies with ATA/ATAPI-8 ATA8-AAM ANSI INCITS 451-2008"); + break; case 0x162A: sb.AppendLine("Device complies with ATA/ATAPI-8 ATA8-ACS ANSI INCITS 452-2009 w/ Amendment 1"); + break; case 0x1728: sb.AppendLine("Device complies with Universal Serial Bus Specification, Revision 1.1"); + break; case 0x1729: sb.AppendLine("Device complies with Universal Serial Bus Specification, Revision 2.0"); + break; case 0x1730: sb.AppendLine("Device complies with USB Mass Storage Class Bulk-Only Transport, Revision 1.0"); + break; case 0x1740: sb.AppendLine("Device complies with UAS (no version claimed)"); + break; case 0x1743: sb.AppendLine("Device complies with UAS T10/2095-D revision 02"); + break; case 0x1747: sb.AppendLine("Device complies with UAS T10/2095-D revision 04"); + break; case 0x1748: sb.AppendLine("Device complies with UAS ANSI INCITS 471-2010"); + break; case 0x1749: sb.AppendLine("Device complies with UAS ISO/IEC 14776-251:2014"); + break; case 0x1761: sb.AppendLine("Device complies with ACS-2 (no version claimed)"); + break; case 0x1762: sb.AppendLine("Device complies with ACS-2 ANSI INCITS 482-2013"); + break; case 0x1765: sb.AppendLine("Device complies with ACS-3 (no version claimed)"); + break; case 0x1780: sb.AppendLine("Device complies with UAS-2 (no version claimed)"); + break; case 0x1EA0: sb.AppendLine("Device complies with SAT (no version claimed)"); + break; case 0x1EA7: sb.AppendLine("Device complies with SAT T10/1711-D revision 8"); + break; case 0x1EAB: sb.AppendLine("Device complies with SAT T10/1711-D revision 9"); + break; case 0x1EAD: sb.AppendLine("Device complies with SAT ANSI INCITS 431-2007"); + break; case 0x1EC0: sb.AppendLine("Device complies with SAT-2 (no version claimed)"); + break; case 0x1EC4: sb.AppendLine("Device complies with SAT-2 T10/1826-D revision 06"); + break; case 0x1EC8: sb.AppendLine("Device complies with SAT-2 T10/1826-D revision 09"); + break; case 0x1ECA: sb.AppendLine("Device complies with SAT-2 ANSI INCITS 465-2010"); + break; case 0x1EE0: sb.AppendLine("Device complies with SAT-3 (no version claimed)"); + break; case 0x1EE2: sb.AppendLine("Device complies with SAT-3 T10/BSR INCITS 517 revision 4"); + break; case 0x1EE4: sb.AppendLine("Device complies with SAT-3 T10/BSR INCITS 517 revision 7"); + break; case 0x1EE8: sb.AppendLine("Device complies with SAT-3 ANSI INCITS 517-2015"); + break; case 0x1F00: sb.AppendLine("Device complies with SAT-4 (no version claimed)"); + break; case 0x20A0: sb.AppendLine("Device complies with SPL (no version claimed)"); + break; case 0x20A3: sb.AppendLine("Device complies with SPL T10/2124-D revision 6a"); + break; case 0x20A5: sb.AppendLine("Device complies with SPL T10/2124-D revision 7"); + break; case 0x20A7: sb.AppendLine("Device complies with SPL ANSI INCITS 476-2011"); + break; case 0x20A8: sb.AppendLine("Device complies with SPL ANSI INCITS 476-2011 + SPL AM1 INCITS 476/AM1 2012"); + break; case 0x20AA: sb.AppendLine("Device complies with SPL ISO/IEC 14776-261:2012"); + break; case 0x20C0: sb.AppendLine("Device complies with SPL-2 (no version claimed)"); + break; case 0x20C2: sb.AppendLine("Device complies with SPL-2 T10/BSR INCITS 505 revision 4"); + break; case 0x20C4: sb.AppendLine("Device complies with SPL-2 T10/BSR INCITS 505 revision 5"); + break; case 0x20C8: sb.AppendLine("Device complies with SPL-2 ANSI INCITS 505-2013"); + break; case 0x20E0: sb.AppendLine("Device complies with SPL-3 (no version claimed)"); + break; case 0x20E4: sb.AppendLine("Device complies with SPL-3 T10/BSR INCITS 492 revision 6"); + break; case 0x20E6: sb.AppendLine("Device complies with SPL-3 T10/BSR INCITS 492 revision 7"); + break; case 0x20E8: sb.AppendLine("Device complies with SPL-3 ANSI INCITS 492-2015"); + break; case 0x2100: sb.AppendLine("Device complies with SPL-4 (no version claimed)"); + break; case 0x21E0: sb.AppendLine("Device complies with SOP (no version claimed)"); + break; case 0x21E4: sb.AppendLine("Device complies with SOP T10/BSR INCITS 489 revision 4"); + break; case 0x21E6: sb.AppendLine("Device complies with SOP T10/BSR INCITS 489 revision 5"); + break; case 0x21E8: sb.AppendLine("Device complies with SOP ANSI INCITS 489-2014"); + break; case 0x2200: sb.AppendLine("Device complies with PQI (no version claimed)"); + break; case 0x2204: sb.AppendLine("Device complies with PQI T10/BSR INCITS 490 revision 6"); + break; case 0x2206: sb.AppendLine("Device complies with PQI T10/BSR INCITS 490 revision 7"); + break; case 0x2208: sb.AppendLine("Device complies with PQI ANSI INCITS 490-2014"); + break; case 0x2220: sb.AppendLine("Device complies with SOP-2 (no version claimed)"); + break; case 0x2240: sb.AppendLine("Device complies with PQI-2 (no version claimed)"); + break; case 0xFFC0: sb.AppendLine("Device complies with IEEE 1667 (no version claimed)"); + break; case 0xFFC1: sb.AppendLine("Device complies with IEEE 1667-2006"); + break; case 0xFFC2: sb.AppendLine("Device complies with IEEE 1667-2009"); + break; default: - sb.AppendFormat("Device complies with unknown standard code 0x{0:X4}", VersionDescriptor) - .AppendLine(); + sb.AppendFormat("Device complies with unknown standard code 0x{0:X4}", VersionDescriptor). + AppendLine(); + break; } @@ -2115,53 +2968,74 @@ namespace DiscImageChef.Decoders.SCSI StringHandlers.CToString(response.VendorIdentification).ToLowerInvariant().Trim() == "quantum") { sb.AppendLine("Quantum vendor-specific information:"); + switch(response.Qt_ProductFamily) { case 0: sb.AppendLine("Product family is not specified"); + break; case 1: sb.AppendLine("Product family is 2.6 GB"); + break; case 2: sb.AppendLine("Product family is 6.0 GB"); + break; case 3: sb.AppendLine("Product family is 10.0/20.0 GB"); + break; case 5: sb.AppendLine("Product family is 20.0/40.0 GB"); + break; case 6: sb.AppendLine("Product family is 15.0/30.0 GB"); + break; default: sb.AppendFormat("Product family: {0}", response.Qt_ProductFamily).AppendLine(); + break; } sb.AppendFormat("Release firmware: {0}", response.Qt_ReleasedFirmware).AppendLine(); + sb.AppendFormat("Firmware version: {0}.{1}", response.Qt_FirmwareMajorVersion, response.Qt_FirmwareMinorVersion).AppendLine(); + sb.AppendFormat("EEPROM format version: {0}.{1}", response.Qt_EEPROMFormatMajorVersion, response.Qt_EEPROMFormatMinorVersion).AppendLine(); + sb.AppendFormat("Firmware personality: {0}", response.Qt_FirmwarePersonality).AppendLine(); sb.AppendFormat("Firmware subpersonality: {0}", response.Qt_FirmwareSubPersonality).AppendLine(); - sb.AppendFormat("Tape directory format version: {0}", response.Qt_TapeDirectoryFormatVersion) - .AppendLine(); + + sb.AppendFormat("Tape directory format version: {0}", response.Qt_TapeDirectoryFormatVersion). + AppendLine(); + sb.AppendFormat("Controller hardware version: {0}", response.Qt_ControllerHardwareVersion).AppendLine(); sb.AppendFormat("Drive EEPROM version: {0}", response.Qt_DriveEEPROMVersion).AppendLine(); sb.AppendFormat("Drive hardware version: {0}", response.Qt_DriveHardwareVersion).AppendLine(); - sb.AppendFormat("Media loader firmware version: {0}", response.Qt_MediaLoaderFirmwareVersion) - .AppendLine(); - sb.AppendFormat("Media loader hardware version: {0}", response.Qt_MediaLoaderHardwareVersion) - .AppendLine(); - sb.AppendFormat("Media loader mechanical version: {0}", response.Qt_MediaLoaderMechanicalVersion) - .AppendLine(); - if(response.Qt_LibraryPresent) sb.AppendLine("Library is present"); - if(response.Qt_MediaLoaderPresent) sb.AppendLine("Media loader is present"); - sb.AppendFormat("Module revision: {0}", StringHandlers.CToString(response.Qt_ModuleRevision)) - .AppendLine(); + + sb.AppendFormat("Media loader firmware version: {0}", response.Qt_MediaLoaderFirmwareVersion). + AppendLine(); + + sb.AppendFormat("Media loader hardware version: {0}", response.Qt_MediaLoaderHardwareVersion). + AppendLine(); + + sb.AppendFormat("Media loader mechanical version: {0}", response.Qt_MediaLoaderMechanicalVersion). + AppendLine(); + + if(response.Qt_LibraryPresent) + sb.AppendLine("Library is present"); + + if(response.Qt_MediaLoaderPresent) + sb.AppendLine("Media loader is present"); + + sb.AppendFormat("Module revision: {0}", StringHandlers.CToString(response.Qt_ModuleRevision)). + AppendLine(); } #endregion Quantum vendor prettifying @@ -2171,10 +3045,13 @@ namespace DiscImageChef.Decoders.SCSI { sb.AppendLine("IBM vendor-specific information:"); - if(response.IBM_PerformanceLimit == 0) sb.AppendLine("Performance is not limited"); - else sb.AppendFormat("Performance is limited using factor {0}", response.IBM_PerformanceLimit); + if(response.IBM_PerformanceLimit == 0) + sb.AppendLine("Performance is not limited"); + else + sb.AppendFormat("Performance is limited using factor {0}", response.IBM_PerformanceLimit); - if(response.IBM_AutDis) sb.AppendLine("Automation is disabled"); + if(response.IBM_AutDis) + sb.AppendLine("Automation is disabled"); sb.AppendFormat("IBM OEM Specific Field: {0}", response.IBM_OEMSpecific).AppendLine(); } @@ -2189,8 +3066,13 @@ namespace DiscImageChef.Decoders.SCSI if(response.HP_WORM) sb.AppendFormat("Device supports WORM version {0}", response.HP_WORMVersion).AppendLine(); - byte[] OBDRSign = {0x24, 0x44, 0x52, 0x2D, 0x31, 0x30}; - if(OBDRSign.SequenceEqual(response.HP_OBDR)) sb.AppendLine("Device supports Tape Disaster Recovery"); + byte[] OBDRSign = + { + 0x24, 0x44, 0x52, 0x2D, 0x31, 0x30 + }; + + if(OBDRSign.SequenceEqual(response.HP_OBDR)) + sb.AppendLine("Device supports Tape Disaster Recovery"); } #endregion HP vendor prettifying @@ -2205,13 +3087,13 @@ namespace DiscImageChef.Decoders.SCSI StringHandlers.CToString(response.Seagate_DriveSerialNumber)).AppendLine(); if(response.Seagate2Present) - sb.AppendFormat("Drive copyright: {0}", StringHandlers.CToString(response.Seagate_Copyright)) - .AppendLine(); + sb.AppendFormat("Drive copyright: {0}", StringHandlers.CToString(response.Seagate_Copyright)). + AppendLine(); if(response.Seagate3Present) sb.AppendFormat("Drive servo part number: {0}", - PrintHex.ByteArrayToHexArrayString(response.Seagate_ServoPROMPartNo, 40)) - .AppendLine(); + PrintHex.ByteArrayToHexArrayString(response.Seagate_ServoPROMPartNo, 40)). + AppendLine(); } #endregion Seagate vendor prettifying @@ -2221,14 +3103,18 @@ namespace DiscImageChef.Decoders.SCSI StringHandlers.CToString(response.KreonVersion)).AppendLine(); #endregion Kreon vendor prettifying - #if DEBUG + #if DEBUG if(response.DeviceTypeModifier != 0) sb.AppendFormat("Vendor's device type modifier = 0x{0:X2}", response.DeviceTypeModifier).AppendLine(); + if(response.Reserved2 != 0) sb.AppendFormat("Reserved byte 5, bits 2 to 1 = 0x{0:X2}", response.Reserved2).AppendLine(); + if(response.Reserved3 != 0) sb.AppendFormat("Reserved byte 56, bits 7 to 4 = 0x{0:X2}", response.Reserved3).AppendLine(); - if(response.Reserved4 != 0) sb.AppendFormat("Reserved byte 57 = 0x{0:X2}", response.Reserved4).AppendLine(); + + if(response.Reserved4 != 0) + sb.AppendFormat("Reserved byte 57 = 0x{0:X2}", response.Reserved4).AppendLine(); if(response.Reserved5 != null) { @@ -2256,13 +3142,14 @@ namespace DiscImageChef.Decoders.SCSI sb.AppendLine("============================================================"); } - if(response.VendorSpecific2 == null) return sb.ToString(); + if(response.VendorSpecific2 == null) + return sb.ToString(); sb.AppendFormat("Vendor-specific bytes 96 to {0}", response.AdditionalLength + 4).AppendLine(); sb.AppendLine("============================================================"); sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.VendorSpecific2, 60)); sb.AppendLine("============================================================"); - #endif + #endif return sb.ToString(); } @@ -2270,442 +3157,9 @@ namespace DiscImageChef.Decoders.SCSI public static string Prettify(byte[] SCSIInquiryResponse) { SCSIInquiry? decoded = Decode(SCSIInquiryResponse); + return Prettify(decoded); } #endregion Public methods - - #region Public structures - // SCSI INQUIRY command response - public struct SCSIInquiry - { - /// - /// Peripheral qualifier - /// Byte 0, bits 7 to 5 - /// - public byte PeripheralQualifier; - /// - /// Peripheral device type - /// Byte 0, bits 4 to 0 - /// - public byte PeripheralDeviceType; - /// - /// Removable device - /// Byte 1, bit 7 - /// - public bool RMB; - /// - /// SCSI-1 vendor-specific qualification codes - /// Byte 1, bits 6 to 0 - /// - public byte DeviceTypeModifier; - /// - /// ISO/IEC SCSI Standard Version - /// Byte 2, bits 7 to 6, mask = 0xC0, >> 6 - /// - public byte ISOVersion; - /// - /// ECMA SCSI Standard Version - /// Byte 2, bits 5 to 3, mask = 0x38, >> 3 - /// - public byte ECMAVersion; - /// - /// ANSI SCSI Standard Version - /// Byte 2, bits 2 to 0, mask = 0x07 - /// - public byte ANSIVersion; - /// - /// Asynchronous Event Reporting Capability supported - /// Byte 3, bit 7 - /// - public bool AERC; - /// - /// Device supports TERMINATE TASK command - /// Byte 3, bit 6 - /// - public bool TrmTsk; - /// - /// Supports setting Normal ACA - /// Byte 3, bit 5 - /// - public bool NormACA; - /// - /// Supports LUN hierarchical addressing - /// Byte 3, bit 4 - /// - public bool HiSup; - /// - /// Responde data format - /// Byte 3, bit 3 to 0 - /// - public byte ResponseDataFormat; - /// - /// Lenght of total INQUIRY response minus 4 - /// Byte 4 - /// - public byte AdditionalLength; - /// - /// Device contains an embedded storage array controller - /// Byte 5, bit 7 - /// - public bool SCCS; - /// - /// Device contains an Access Control Coordinator - /// Byte 5, bit 6 - /// - public bool ACC; - /// - /// Supports asymetrical logical unit access - /// Byte 5, bits 5 to 4 - /// - public byte TPGS; - /// - /// Supports third-party copy commands - /// Byte 5, bit 3 - /// - public bool ThreePC; - /// - /// Reserved - /// Byte 5, bits 2 to 1 - /// - public byte Reserved2; - /// - /// Supports protection information - /// Byte 5, bit 0 - /// - public bool Protect; - /// - /// Supports basic queueing - /// Byte 6, bit 7 - /// - public bool BQue; - /// - /// Device contains an embedded enclosure services component - /// Byte 6, bit 6 - /// - public bool EncServ; - /// - /// Vendor-specific - /// Byte 6, bit 5 - /// - public bool VS1; - /// - /// Multi-port device - /// Byte 6, bit 4 - /// - public bool MultiP; - /// - /// Device contains or is attached to a medium changer - /// Byte 6, bit 3 - /// - public bool MChngr; - /// - /// Device supports request and acknowledge handshakes - /// Byte 6, bit 2 - /// - public bool ACKREQQ; - /// - /// Supports 32-bit wide SCSI addresses - /// Byte 6, bit 1 - /// - public bool Addr32; - /// - /// Supports 16-bit wide SCSI addresses - /// Byte 6, bit 0 - /// - public bool Addr16; - /// - /// Device supports relative addressing - /// Byte 7, bit 7 - /// - public bool RelAddr; - /// - /// Supports 32-bit wide data transfers - /// Byte 7, bit 6 - /// - public bool WBus32; - /// - /// Supports 16-bit wide data transfers - /// Byte 7, bit 5 - /// - public bool WBus16; - /// - /// Supports synchronous data transfer - /// Byte 7, bit 4 - /// - public bool Sync; - /// - /// Supports linked commands - /// Byte 7, bit 3 - /// - public bool Linked; - /// - /// Supports CONTINUE TASK and TARGET TRANSFER DISABLE commands - /// Byte 7, bit 2 - /// - public bool TranDis; - /// - /// Supports TCQ queue - /// Byte 7, bit 1 - /// - public bool CmdQue; - /// - /// Indicates that the devices responds to RESET with soft reset - /// Byte 7, bit 0 - /// - public bool SftRe; - /// - /// Vendor identification - /// Bytes 8 to 15 - /// - public byte[] VendorIdentification; - /// - /// Product identification - /// Bytes 16 to 31 - /// - public byte[] ProductIdentification; - /// - /// Product revision level - /// Bytes 32 to 35 - /// - public byte[] ProductRevisionLevel; - /// - /// Vendor-specific data - /// Bytes 36 to 55 - /// - public byte[] VendorSpecific; - /// - /// Byte 56, bits 7 to 4 - /// - public byte Reserved3; - /// - /// Supported SPI clocking - /// Byte 56, bits 3 to 2 - /// - public byte Clocking; - /// - /// Device supports Quick Arbitration and Selection - /// Byte 56, bit 1 - /// - public bool QAS; - /// - /// Supports information unit transfers - /// Byte 56, bit 0 - /// - public bool IUS; - /// - /// Reserved - /// Byte 57 - /// - public byte Reserved4; - /// - /// Array of version descriptors - /// Bytes 58 to 73 - /// - public ushort[] VersionDescriptors; - /// - /// Reserved - /// Bytes 74 to 95 - /// - public byte[] Reserved5; - /// - /// Reserved - /// Bytes 96 to end - /// - public byte[] VendorSpecific2; - - // Per DLT4000/DLT4500/DLT4700 Cartridge Tape Subsystem Product Manual - - #region Quantum vendor unique inquiry data structure - /// - /// Means that the INQUIRY response contains 56 bytes or more, so this data has been filled - /// - public bool QuantumPresent; - /// - /// The product family. - /// Byte 36, bits 7 to 5 - /// - public byte Qt_ProductFamily; - /// - /// The released firmware. - /// Byte 36, bits 4 to 0 - /// - public byte Qt_ReleasedFirmware; - /// - /// The firmware major version. - /// Byte 37 - /// - public byte Qt_FirmwareMajorVersion; - /// - /// The firmware minor version. - /// Byte 38 - /// - public byte Qt_FirmwareMinorVersion; - /// - /// The EEPROM format major version. - /// Byte 39 - /// - public byte Qt_EEPROMFormatMajorVersion; - /// - /// The EEPROM format minor version. - /// Byte 40 - /// - public byte Qt_EEPROMFormatMinorVersion; - /// - /// The firmware personality. - /// Byte 41 - /// - public byte Qt_FirmwarePersonality; - /// - /// The firmware sub personality. - /// Byte 42 - /// - public byte Qt_FirmwareSubPersonality; - /// - /// The tape directory format version. - /// Byte 43 - /// - public byte Qt_TapeDirectoryFormatVersion; - /// - /// The controller hardware version. - /// Byte 44 - /// - public byte Qt_ControllerHardwareVersion; - /// - /// The drive EEPROM version. - /// Byte 45 - /// - public byte Qt_DriveEEPROMVersion; - /// - /// The drive hardware version. - /// Byte 46 - /// - public byte Qt_DriveHardwareVersion; - /// - /// The media loader firmware version. - /// Byte 47 - /// - public byte Qt_MediaLoaderFirmwareVersion; - /// - /// The media loader hardware version. - /// Byte 48 - /// - public byte Qt_MediaLoaderHardwareVersion; - /// - /// The media loader mechanical version. - /// Byte 49 - /// - public byte Qt_MediaLoaderMechanicalVersion; - /// - /// Is a media loader present? - /// Byte 50 - /// - public bool Qt_MediaLoaderPresent; - /// - /// Is a library present? - /// Byte 51 - /// - public bool Qt_LibraryPresent; - /// - /// The module revision. - /// Bytes 52 to 55 - /// - public byte[] Qt_ModuleRevision; - #endregion Quantum vendor unique inquiry data structure - - #region IBM vendor unique inquiry data structure - /// - /// Means that the INQUIRY response contains 56 bytes or more, so this data has been filled - /// - public bool IBMPresent; - /// - /// Drive is not capable of automation - /// Byte 36 bit 0 - /// - public bool IBM_AutDis; - /// - /// If not zero, limit in MB/s = Max * (this / 256) - /// Byte 37 - /// - public byte IBM_PerformanceLimit; - /// - /// Byte 41 - /// - public byte IBM_OEMSpecific; - #endregion IBM vendor unique inquiry data structure - - #region HP vendor unique inquiry data structure - /// - /// Means that the INQUIRY response contains 49 bytes or more, so this data has been filled - /// - public bool HPPresent; - /// - /// WORM version - /// Byte 40 bits 7 to 1 - /// - public byte HP_WORMVersion; - /// - /// WORM supported - /// Byte 40 bit 0 - /// - public bool HP_WORM; - /// - /// Bytes 43 to 48 - /// - public byte[] HP_OBDR; - #endregion HP vendor unique inquiry data structure - - #region Seagate vendor unique inquiry data structure - /// - /// Means that bytes 36 to 43 are filled - /// - public bool SeagatePresent; - /// - /// Drive Serial Number - /// Bytes 36 to 43 - /// - public byte[] Seagate_DriveSerialNumber; - /// - /// Means that bytes 96 to 143 are filled - /// - public bool Seagate2Present; - /// - /// Contains Seagate copyright notice - /// Bytes 96 to 143 - /// - public byte[] Seagate_Copyright; - /// - /// Means that bytes 144 to 147 are filled - /// - public bool Seagate3Present; - /// - /// Reserved Seagate field - /// Bytes 144 to 147 - /// - public byte[] Seagate_ServoPROMPartNo; - #endregion Seagate vendor unique inquiry data structure - - #region Kreon vendor unique inquiry data structure - /// - /// Means that firmware is Kreon - /// - public bool KreonPresent; - /// - /// Kreon identifier - /// Bytes 36 to 40 - /// - public byte[] KreonIdentifier; - /// - /// Kreon just a 0x20 - /// Bytes 41 - /// - public byte KreonSpace; - /// - /// Kreon version string - /// Bytes 42 to 46 - /// - public byte[] KreonVersion; - #endregion Kreon vendor unique inquiry data structure - } - #endregion Public structures } } \ No newline at end of file diff --git a/SCSI/MMC/AACS.cs b/SCSI/MMC/AACS.cs index 2ef859e..04f77d0 100644 --- a/SCSI/MMC/AACS.cs +++ b/SCSI/MMC/AACS.cs @@ -37,195 +37,20 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI.MMC { /// - /// Information from the following standards: - /// ANSI X3.304-1997 - /// T10/1048-D revision 9.0 - /// T10/1048-D revision 10a - /// T10/1228-D revision 7.0c - /// T10/1228-D revision 11a - /// T10/1363-D revision 10g - /// T10/1545-D revision 1d - /// T10/1545-D revision 5 - /// T10/1545-D revision 5a - /// T10/1675-D revision 2c - /// T10/1675-D revision 4 - /// T10/1836-D revision 2g + /// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a + /// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision + /// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] public static class AACS { - public struct AACSVolumeIdentifier - { - /// - /// Bytes 0 to 1 - /// Data length - /// - public ushort DataLength; - /// - /// Byte 2 - /// Reserved - /// - public byte Reserved1; - /// - /// Byte 3 - /// Reserved - /// - public byte Reserved2; - /// - /// Bytes 4 to end - /// AACS volume identifier data - /// - public byte[] VolumeIdentifier; - } - - public struct AACSMediaSerialNumber - { - /// - /// Bytes 0 to 1 - /// Data length - /// - public ushort DataLength; - /// - /// Byte 2 - /// Reserved - /// - public byte Reserved1; - /// - /// Byte 3 - /// Reserved - /// - public byte Reserved2; - /// - /// Bytes 4 to end - /// AACS media serial number - /// - public byte[] MediaSerialNumber; - } - - public struct AACSMediaIdentifier - { - /// - /// Bytes 0 to 1 - /// Data length - /// - public ushort DataLength; - /// - /// Byte 2 - /// Reserved - /// - public byte Reserved1; - /// - /// Byte 3 - /// Reserved - /// - public byte Reserved2; - /// - /// Bytes 4 to end - /// AACS media identifier data - /// - public byte[] MediaIdentifier; - } - - public struct AACSMediaKeyBlock - { - /// - /// Bytes 0 to 1 - /// Data length - /// - public ushort DataLength; - /// - /// Byte 2 - /// Reserved - /// - public byte Reserved; - /// - /// Byte 3 - /// Number of MKB packs available to transfer - /// - public byte TotalPacks; - /// - /// Bytes 4 to end - /// AACS media key block packs - /// - public byte[] MediaKeyBlockPacks; - } - - public struct AACSDataKeys - { - /// - /// Bytes 0 to 1 - /// Data length - /// - public ushort DataLength; - /// - /// Byte 2 - /// Reserved - /// - public byte Reserved1; - /// - /// Byte 3 - /// Reserved - /// - public byte Reserved2; - /// - /// Bytes 4 to end - /// AACS data keys - /// - public byte[] DataKeys; - } - - public struct AACSLBAExtentsResponse - { - /// - /// Bytes 0 to 1 - /// Data Length - /// - public ushort DataLength; - /// - /// Byte 2 - /// Reserved - /// - public byte Reserved; - /// - /// Byte 3 - /// Number of LBA extents the drive can store. - /// if(MaxLBAExtents == 0 && DataLength > 2), 256 extents can be stored - /// - public byte MaxLBAExtents; - /// - /// Bytes 4 to end - /// LBA Extents - /// - public AACSLBAExtent[] Extents; - } - - public struct AACSLBAExtent - { - /// - /// Bytes 0 to 7 - /// Reserved - /// - public byte[] Reserved; - /// - /// Bytes 8 to 11 - /// Start LBA of extent - /// - public uint StartLBA; - /// - /// Bytes 12 to 15 - /// Extent length - /// - public uint LBACount; - } - public static AACSVolumeIdentifier? DecodeAACSVolumeIdentifier(byte[] AACSVIResponse) { - if(AACSVIResponse == null) return null; + if(AACSVIResponse == null) + return null; - AACSVolumeIdentifier decoded = new AACSVolumeIdentifier(); + var decoded = new AACSVolumeIdentifier(); decoded.VolumeIdentifier = new byte[AACSVIResponse.Length - 4]; @@ -239,16 +64,20 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string PrettifyAACSVolumeIdentifier(AACSVolumeIdentifier? AACSVIResponse) { - if(AACSVIResponse == null) return null; + if(AACSVIResponse == null) + return null; AACSVolumeIdentifier response = AACSVIResponse.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); - #if DEBUG - if(response.Reserved1 != 0) sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); - if(response.Reserved2 != 0) sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); - #endif + #if DEBUG + if(response.Reserved1 != 0) + sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); + + if(response.Reserved2 != 0) + sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); + #endif sb.AppendFormat("AACS Volume Identifier in hex follows:"); sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.VolumeIdentifier, 80)); @@ -258,14 +87,16 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string PrettifyAACSVolumeIdentifier(byte[] AACSVIResponse) { AACSVolumeIdentifier? decoded = DecodeAACSVolumeIdentifier(AACSVIResponse); + return PrettifyAACSVolumeIdentifier(decoded); } public static AACSMediaSerialNumber? DecodeAACSMediaSerialNumber(byte[] AACSMSNResponse) { - if(AACSMSNResponse == null) return null; + if(AACSMSNResponse == null) + return null; - AACSMediaSerialNumber decoded = new AACSMediaSerialNumber(); + var decoded = new AACSMediaSerialNumber(); decoded.MediaSerialNumber = new byte[AACSMSNResponse.Length - 4]; @@ -279,16 +110,20 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string PrettifyAACSMediaSerialNumber(AACSMediaSerialNumber? AACSMSNResponse) { - if(AACSMSNResponse == null) return null; + if(AACSMSNResponse == null) + return null; AACSMediaSerialNumber response = AACSMSNResponse.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); - #if DEBUG - if(response.Reserved1 != 0) sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); - if(response.Reserved2 != 0) sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); - #endif + #if DEBUG + if(response.Reserved1 != 0) + sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); + + if(response.Reserved2 != 0) + sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); + #endif sb.AppendFormat("AACS Media Serial Number in hex follows:"); sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.MediaSerialNumber, 80)); @@ -298,14 +133,16 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string PrettifyAACSMediaSerialNumber(byte[] AACSMSNResponse) { AACSMediaSerialNumber? decoded = DecodeAACSMediaSerialNumber(AACSMSNResponse); + return PrettifyAACSMediaSerialNumber(decoded); } public static AACSMediaIdentifier? DecodeAACSMediaIdentifier(byte[] AACSMIResponse) { - if(AACSMIResponse == null) return null; + if(AACSMIResponse == null) + return null; - AACSMediaIdentifier decoded = new AACSMediaIdentifier(); + var decoded = new AACSMediaIdentifier(); decoded.MediaIdentifier = new byte[AACSMIResponse.Length - 4]; @@ -319,16 +156,20 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string PrettifyAACSMediaIdentifier(AACSMediaIdentifier? AACSMIResponse) { - if(AACSMIResponse == null) return null; + if(AACSMIResponse == null) + return null; AACSMediaIdentifier response = AACSMIResponse.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); - #if DEBUG - if(response.Reserved1 != 0) sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); - if(response.Reserved2 != 0) sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); - #endif + #if DEBUG + if(response.Reserved1 != 0) + sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); + + if(response.Reserved2 != 0) + sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); + #endif sb.AppendFormat("AACS Media Identifier in hex follows:"); sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.MediaIdentifier, 80)); @@ -338,14 +179,16 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string PrettifyAACSMediaIdentifier(byte[] AACSMIResponse) { AACSMediaIdentifier? decoded = DecodeAACSMediaIdentifier(AACSMIResponse); + return PrettifyAACSMediaIdentifier(decoded); } public static AACSMediaKeyBlock? DecodeAACSMediaKeyBlock(byte[] AACSMKBResponse) { - if(AACSMKBResponse == null) return null; + if(AACSMKBResponse == null) + return null; - AACSMediaKeyBlock decoded = new AACSMediaKeyBlock(); + var decoded = new AACSMediaKeyBlock(); decoded.MediaKeyBlockPacks = new byte[AACSMKBResponse.Length - 4]; @@ -359,17 +202,20 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string PrettifyAACSMediaKeyBlock(AACSMediaKeyBlock? AACSMKBResponse) { - if(AACSMKBResponse == null) return null; + if(AACSMKBResponse == null) + return null; AACSMediaKeyBlock response = AACSMKBResponse.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); + + #if DEBUG + if(response.Reserved != 0) + sb.AppendFormat("Reserved = 0x{0:X2}", response.Reserved).AppendLine(); + #endif + sb.AppendFormat("Total number of media key blocks available to transfer {0}", response.TotalPacks). + AppendLine(); - #if DEBUG - if(response.Reserved != 0) sb.AppendFormat("Reserved = 0x{0:X2}", response.Reserved).AppendLine(); - #endif - sb.AppendFormat("Total number of media key blocks available to transfer {0}", response.TotalPacks) - .AppendLine(); sb.AppendFormat("AACS Media Key Blocks in hex follows:"); sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.MediaKeyBlockPacks, 80)); @@ -379,14 +225,16 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string PrettifyAACSMediaKeyBlock(byte[] AACSMKBResponse) { AACSMediaKeyBlock? decoded = DecodeAACSMediaKeyBlock(AACSMKBResponse); + return PrettifyAACSMediaKeyBlock(decoded); } public static AACSDataKeys? DecodeAACSDataKeys(byte[] AACSDKResponse) { - if(AACSDKResponse == null) return null; + if(AACSDKResponse == null) + return null; - AACSDataKeys decoded = new AACSDataKeys(); + var decoded = new AACSDataKeys(); decoded.DataKeys = new byte[AACSDKResponse.Length - 4]; @@ -400,16 +248,20 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string PrettifyAACSDataKeys(AACSDataKeys? AACSDKResponse) { - if(AACSDKResponse == null) return null; + if(AACSDKResponse == null) + return null; AACSDataKeys response = AACSDKResponse.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); - #if DEBUG - if(response.Reserved1 != 0) sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); - if(response.Reserved2 != 0) sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); - #endif + #if DEBUG + if(response.Reserved1 != 0) + sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); + + if(response.Reserved2 != 0) + sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); + #endif sb.AppendFormat("AACS Data Keys in hex follows:"); sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.DataKeys, 80)); @@ -419,21 +271,24 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string PrettifyAACSDataKeys(byte[] AACSDKResponse) { AACSDataKeys? decoded = DecodeAACSDataKeys(AACSDKResponse); + return PrettifyAACSDataKeys(decoded); } public static AACSLBAExtentsResponse? DecodeAACSLBAExtents(byte[] AACSLBAExtsResponse) { - if(AACSLBAExtsResponse == null) return null; + if(AACSLBAExtsResponse == null) + return null; - AACSLBAExtentsResponse decoded = new AACSLBAExtentsResponse + var decoded = new AACSLBAExtentsResponse { DataLength = BigEndianBitConverter.ToUInt16(AACSLBAExtsResponse, 0), Reserved = AACSLBAExtsResponse[2], MaxLBAExtents = AACSLBAExtsResponse[3] }; - if((AACSLBAExtsResponse.Length - 4) % 16 != 0) return decoded; + if((AACSLBAExtsResponse.Length - 4) % 16 != 0) + return decoded; decoded.Extents = new AACSLBAExtent[(AACSLBAExtsResponse.Length - 4) / 16]; @@ -450,17 +305,18 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string PrettifyAACSLBAExtents(AACSLBAExtentsResponse? AACSLBAExtsResponse) { - if(AACSLBAExtsResponse == null) return null; + if(AACSLBAExtsResponse == null) + return null; AACSLBAExtentsResponse response = AACSLBAExtsResponse.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); if(response.MaxLBAExtents == 0) - sb.AppendLine(response.DataLength > 2 - ? "Drive can store 256 LBA Extents" + sb.AppendLine(response.DataLength > 2 ? "Drive can store 256 LBA Extents" : "Drive cannot store LBA Extents"); - else sb.AppendFormat("Drive can store {0} LBA Extents", response.MaxLBAExtents).AppendLine(); + else + sb.AppendFormat("Drive can store {0} LBA Extents", response.MaxLBAExtents).AppendLine(); for(int i = 0; i < response.Extents.Length; i++) sb.AppendFormat("LBA Extent {0} starts at LBA {1} and goes for {2} sectors", i, @@ -472,7 +328,93 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string PrettifyAACSLBAExtents(byte[] AACSLBAExtsResponse) { AACSLBAExtentsResponse? decoded = DecodeAACSLBAExtents(AACSLBAExtsResponse); + return PrettifyAACSLBAExtents(decoded); } + + public struct AACSVolumeIdentifier + { + /// Bytes 0 to 1 Data length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Bytes 4 to end AACS volume identifier data + public byte[] VolumeIdentifier; + } + + public struct AACSMediaSerialNumber + { + /// Bytes 0 to 1 Data length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Bytes 4 to end AACS media serial number + public byte[] MediaSerialNumber; + } + + public struct AACSMediaIdentifier + { + /// Bytes 0 to 1 Data length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Bytes 4 to end AACS media identifier data + public byte[] MediaIdentifier; + } + + public struct AACSMediaKeyBlock + { + /// Bytes 0 to 1 Data length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved; + /// Byte 3 Number of MKB packs available to transfer + public byte TotalPacks; + /// Bytes 4 to end AACS media key block packs + public byte[] MediaKeyBlockPacks; + } + + public struct AACSDataKeys + { + /// Bytes 0 to 1 Data length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Bytes 4 to end AACS data keys + public byte[] DataKeys; + } + + public struct AACSLBAExtentsResponse + { + /// Bytes 0 to 1 Data Length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved; + /// + /// Byte 3 Number of LBA extents the drive can store. if(MaxLBAExtents == 0 && DataLength > 2), 256 + /// extents can be stored + /// + public byte MaxLBAExtents; + /// Bytes 4 to end LBA Extents + public AACSLBAExtent[] Extents; + } + + public struct AACSLBAExtent + { + /// Bytes 0 to 7 Reserved + public byte[] Reserved; + /// Bytes 8 to 11 Start LBA of extent + public uint StartLBA; + /// Bytes 12 to 15 Extent length + public uint LBACount; + } } } \ No newline at end of file diff --git a/SCSI/MMC/CPRM.cs b/SCSI/MMC/CPRM.cs index d870ebf..d1794d6 100644 --- a/SCSI/MMC/CPRM.cs +++ b/SCSI/MMC/CPRM.cs @@ -37,59 +37,23 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI.MMC { /// - /// Information from the following standards: - /// ANSI X3.304-1997 - /// T10/1048-D revision 9.0 - /// T10/1048-D revision 10a - /// T10/1228-D revision 7.0c - /// T10/1228-D revision 11a - /// T10/1363-D revision 10g - /// T10/1545-D revision 1d - /// T10/1545-D revision 5 - /// T10/1545-D revision 5a - /// T10/1675-D revision 2c - /// T10/1675-D revision 4 - /// T10/1836-D revision 2g + /// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a + /// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision + /// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] public static class CPRM { - public struct CPRMMediaKeyBlock - { - /// - /// Bytes 0 to 1 - /// Data Length - /// - public ushort DataLength; - /// - /// Byte 2 - /// Reserved - /// - public byte Reserved; - /// - /// Byte 3 - /// Number of MKB packs available to transfer - /// - public byte TotalPacks; - /// - /// Byte 4 - /// MKB Packs - /// - public byte[] MKBPackData; - } - public static CPRMMediaKeyBlock? DecodeCPRMMediaKeyBlock(byte[] CPRMMKBResponse) { - if(CPRMMKBResponse == null) return null; + if(CPRMMKBResponse == null) + return null; - CPRMMediaKeyBlock decoded = new CPRMMediaKeyBlock + var decoded = new CPRMMediaKeyBlock { MKBPackData = new byte[CPRMMKBResponse.Length - 4], - DataLength = BigEndianBitConverter.ToUInt16(CPRMMKBResponse, 0), - Reserved = CPRMMKBResponse[2], + DataLength = BigEndianBitConverter.ToUInt16(CPRMMKBResponse, 0), Reserved = CPRMMKBResponse[2], TotalPacks = CPRMMKBResponse[3] }; @@ -100,17 +64,20 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string PrettifyCPRMMediaKeyBlock(CPRMMediaKeyBlock? CPRMMKBResponse) { - if(CPRMMKBResponse == null) return null; + if(CPRMMKBResponse == null) + return null; CPRMMediaKeyBlock response = CPRMMKBResponse.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); + + #if DEBUG + if(response.Reserved != 0) + sb.AppendFormat("Reserved = 0x{0:X2}", response.Reserved).AppendLine(); + #endif + sb.AppendFormat("Total number of CPRM Media Key Blocks available to transfer: {0}", response.TotalPacks). + AppendLine(); - #if DEBUG - if(response.Reserved != 0) sb.AppendFormat("Reserved = 0x{0:X2}", response.Reserved).AppendLine(); - #endif - sb.AppendFormat("Total number of CPRM Media Key Blocks available to transfer: {0}", response.TotalPacks) - .AppendLine(); sb.AppendFormat("CPRM Media Key Blocks in hex follows:"); sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.MKBPackData, 80)); @@ -120,7 +87,20 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string PrettifyCPRMMediaKeyBlock(byte[] CPRMMKBResponse) { CPRMMediaKeyBlock? decoded = DecodeCPRMMediaKeyBlock(CPRMMKBResponse); + return PrettifyCPRMMediaKeyBlock(decoded); } + + public struct CPRMMediaKeyBlock + { + /// Bytes 0 to 1 Data Length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved; + /// Byte 3 Number of MKB packs available to transfer + public byte TotalPacks; + /// Byte 4 MKB Packs + public byte[] MKBPackData; + } } } \ No newline at end of file diff --git a/SCSI/MMC/DiscInformation.cs b/SCSI/MMC/DiscInformation.cs index 2694035..76528e6 100644 --- a/SCSI/MMC/DiscInformation.cs +++ b/SCSI/MMC/DiscInformation.cs @@ -37,257 +37,29 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI.MMC { /// - /// Information from the following standards: - /// ANSI X3.304-1997 - /// T10/1048-D revision 9.0 - /// T10/1048-D revision 10a - /// T10/1228-D revision 7.0c - /// T10/1228-D revision 11a - /// T10/1363-D revision 10g - /// T10/1545-D revision 1d - /// T10/1545-D revision 5 - /// T10/1545-D revision 5a - /// T10/1675-D revision 2c - /// T10/1675-D revision 4 - /// T10/1836-D revision 2g + /// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a + /// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision + /// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] public static class DiscInformation { - public struct StandardDiscInformation - { - /// - /// Bytes 0 to 1 - /// 32 + OPCTablesNumber*8 - /// - public ushort DataLength; - /// - /// Byte 2, bits 7 to 5 - /// 000b - /// - public byte DataType; - /// - /// Byte 2, bit 4 - /// If set, disc is erasable - /// - public bool Erasable; - /// - /// Byte 2, bits 3 to 2 - /// Status of last session - /// - public byte LastSessionStatus; - /// - /// Byte 2, bits 1 to 0 - /// Status of disc - /// - public byte DiscStatus; - /// - /// Byte 3 - /// Number of logical track that contains LBA 0 - /// - public byte FirstTrackNumber; - /// - /// Byte 9 (MSB) and byte 4 (LSB) - /// Number of sessions - /// - public ushort Sessions; - /// - /// Byte 10 (MSB) and byte 5 (LSB) - /// Number of first track in last session - /// - public ushort FirstTrackLastSession; - /// - /// Byte 11 (MSB) and byte 6 (LSB) - /// Number of last track in last session - /// - public ushort LastTrackLastSession; - /// - /// Byte 7, bit 7 - /// If set, DiscIdentification is valid - /// - public bool DID_V; - /// - /// Byte 7, bit 6 - /// If set, DiscBarcode is valid - /// - public bool DBC_V; - /// - /// Byte 7, bit 5 - /// If set, disc is unrestricted - /// - public bool URU; - /// - /// Byte 7, bit 4 - /// If set DiscApplicationCode is valid - /// - public bool DAC_V; - /// - /// Byte 7, bit 3 - /// Reserved - /// - public bool Reserved; - /// - /// Byte 7, bit 2 - /// Copy of dirty bit from MRW status - /// - public bool Dbit; - /// - /// Byte 7, bits 1 to 0 - /// Background format status - /// - public byte BGFormatStatus; - /// - /// Byte 8 - /// Disc type code - /// - public byte DiscType; - /// - /// Bytes 12 to 15 - /// Disc identification number from PMA - /// - public uint DiscIdentification; - /// - /// Bytes 16 to 19 - /// Last Session Lead-in Start Address (MSF for CD, LBA for others) - /// - public uint LastSessionLeadInStartLBA; - /// - /// Bytes 20 to 23 - /// Last Possible Lead-out Start Address (MSF for CD, LBA for others) - /// - public uint LastPossibleLeadOutStartLBA; - /// - /// Bytes 24 to 31 - /// Disc barcode - /// - public ulong DiscBarcode; - /// - /// Byte 32 - /// Disc application code - /// - public byte DiscApplicationCode; - /// - /// Byte 33 - /// How many OPC tables are - /// - public byte OPCTablesNumber; - /// - /// Bytes 34 to end - /// OPC tables (8 bytes each) - /// - public OPCTable[] OPCTables; - } - - public struct OPCTable - { - /// - /// Bytes 0 to 1 - /// kilobytes/sec this OPC table applies to - /// - public ushort Speed; - /// - /// Bytes 2 to 7 - /// OPC values - /// - public byte[] OPCValues; - } - - public struct TrackResourcesInformation - { - /// - /// Bytes 0 to 1 - /// 10 - /// - public ushort DataLength; - /// - /// Byte 2, bits 7 to 5 - /// 001b - /// - public byte DataType; - /// - /// Byte 2, bits 4 to 0 - /// Reserved - /// - public byte Reserved1; - /// - /// Byte 3 - /// Reserved - /// - public byte Reserved2; - /// - /// Bytes 4 to 5 - /// Maximum possible number of the tracks on the disc - /// - public ushort MaxTracks; - /// - /// Bytes 6 to 7 - /// Number of the assigned tracks on the disc - /// - public ushort AssignedTracks; - /// - /// Bytes 8 to 9 - /// Maximum possible number of appendable tracks on the disc - /// - public ushort MaxAppendableTracks; - /// - /// Bytes 10 to 11 - /// Current number of appendable tracks on the disc - /// - public ushort AppendableTracks; - } - - public struct POWResourcesInformation - { - /// - /// Bytes 0 to 1 - /// 14 - /// - public ushort DataLength; - /// - /// Byte 2, bits 7 to 5 - /// 010b - /// - public byte DataType; - /// - /// Byte 2, bits 4 to 0 - /// Reserved - /// - public byte Reserved1; - /// - /// Byte 3 - /// Reserved - /// - public byte Reserved2; - /// - /// Bytes 4 to 7 - /// Remaining POW replacements - /// - public uint RemainingPOWReplacements; - /// - /// Bytes 8 to 11 - /// Remaining POW reallocation map entries - /// - public uint RemainingPOWReallocation; - /// - /// Bytes 12 to 15 - /// Number of remaining POW updates - /// - public uint RemainingPOWUpdates; - } - public static StandardDiscInformation? Decode000b(byte[] response) { - if(response.Length < 34) return null; + if(response.Length < 34) + return null; - if((response[2] & 0xE0) != 0) return null; + if((response[2] & 0xE0) != 0) + return null; - StandardDiscInformation decoded = - new StandardDiscInformation {DataLength = (ushort)((response[0] << 8) + response[1])}; + var decoded = new StandardDiscInformation + { + DataLength = (ushort)((response[0] << 8) + response[1]) + }; - if(decoded.DataLength + 2 != response.Length) return null; + if(decoded.DataLength + 2 != response.Length) + return null; decoded.DataType = (byte)((response[2] & 0xE0) >> 5); decoded.Erasable |= (response[2] & 0x10) == 0x10; @@ -308,8 +80,10 @@ namespace DiscImageChef.Decoders.SCSI.MMC decoded.DiscIdentification = (uint)((response[12] << 24) + (response[13] << 16) + (response[14] << 8) + response[15]); + decoded.LastSessionLeadInStartLBA = (uint)((response[16] << 24) + (response[17] << 16) + (response[18] << 8) + response[19]); + decoded.LastPossibleLeadOutStartLBA = (uint)((response[20] << 24) + (response[21] << 16) + (response[22] << 8) + response[23]); @@ -321,9 +95,12 @@ namespace DiscImageChef.Decoders.SCSI.MMC decoded.DiscApplicationCode = response[32]; decoded.OPCTablesNumber = response[33]; - if(decoded.OPCTablesNumber <= 0 || response.Length != decoded.OPCTablesNumber * 8 + 34) return decoded; + if(decoded.OPCTablesNumber <= 0 || + response.Length != decoded.OPCTablesNumber * 8 + 34) + return decoded; decoded.OPCTables = new OPCTable[decoded.OPCTablesNumber]; + for(int i = 0; i < decoded.OPCTablesNumber; i++) { decoded.OPCTables[i].Speed = (ushort)((response[34 + i * 8 + 0] << 16) + response[34 + i * 8 + 1]); @@ -336,30 +113,37 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string Prettify000b(StandardDiscInformation? information) { - if(!information.HasValue) return null; + if(!information.HasValue) + return null; StandardDiscInformation decoded = information.Value; - if(decoded.DataType != 0) return null; + if(decoded.DataType != 0) + return null; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); switch(decoded.DiscType) { case 0x00: sb.AppendLine("Disc type declared as CD-DA or CD-ROM"); + break; case 0x10: sb.AppendLine("Disc type declared as CD-i"); + break; case 0x20: sb.AppendLine("Disc type declared as CD-ROM XA"); + break; case 0xFF: sb.AppendLine("Disc type is undefined"); + break; default: sb.AppendFormat("Unknown disc type {0:X2}h", decoded.DiscType).AppendLine(); + break; } @@ -367,30 +151,38 @@ namespace DiscImageChef.Decoders.SCSI.MMC { case 0: sb.AppendLine("Disc is empty"); + break; case 1: sb.AppendLine("Disc is incomplete"); + break; case 2: sb.AppendLine("Disc is finalized"); + break; } - if(decoded.Erasable) sb.AppendLine("Disc is erasable"); + if(decoded.Erasable) + sb.AppendLine("Disc is erasable"); switch(decoded.LastSessionStatus) { case 0: sb.AppendLine("Last session is empty"); + break; case 1: sb.AppendLine("Last session is incomplete"); + break; case 2: sb.AppendLine("Last session is damaged"); + break; case 3: sb.AppendLine("Last session is complete"); + break; } @@ -398,26 +190,31 @@ namespace DiscImageChef.Decoders.SCSI.MMC { case 1: sb.AppendLine("Media was being formatted in the background but it is stopped and incomplete"); + break; case 2: sb.AppendLine("Media is currently being formatted in the background"); + break; case 3: sb.AppendLine("Media background formatting has completed"); + break; } - if(decoded.Dbit) sb.AppendLine("MRW is dirty"); + if(decoded.Dbit) + sb.AppendLine("MRW is dirty"); sb.AppendFormat("First track on disc is track {0}", decoded.FirstTrackNumber).AppendLine(); sb.AppendFormat("Disc has {0} sessions", decoded.Sessions).AppendLine(); sb.AppendFormat("First track in last session is track {0}", decoded.FirstTrackLastSession).AppendLine(); sb.AppendFormat("Last track in last session is track {0}", decoded.LastTrackLastSession).AppendLine(); + sb.AppendFormat("Last session Lead-In address is {0} (as LBA) or {1:X2}:{2:X2}:{3:X2}", decoded.LastSessionLeadInStartLBA, (decoded.LastSessionLeadInStartLBA & 0xFF0000) >> 16, (decoded.LastSessionLeadInStartLBA & 0xFF00) >> 8, - decoded.LastSessionLeadInStartLBA & 0xFF) - .AppendLine(); + decoded.LastSessionLeadInStartLBA & 0xFF).AppendLine(); + sb.AppendFormat("Last possible Lead-Out address is {0} (as LBA) or {1:X2}:{2:X2}:{3:X2}", decoded.LastPossibleLeadOutStartLBA, (decoded.LastPossibleLeadOutStartLBA & 0xFF0000) >> 16, (decoded.LastPossibleLeadOutStartLBA & 0xFF00) >> 8, @@ -425,11 +222,17 @@ namespace DiscImageChef.Decoders.SCSI.MMC sb.AppendLine(decoded.URU ? "Disc is defined for unrestricted use" : "Disc is defined for restricted use"); - if(decoded.DID_V) sb.AppendFormat("Disc ID: {0:X6}", decoded.DiscIdentification & 0x00FFFFFF).AppendLine(); - if(decoded.DBC_V) sb.AppendFormat("Disc barcode: {0:X16}", decoded.DiscBarcode).AppendLine(); - if(decoded.DAC_V) sb.AppendFormat("Disc application code: {0}", decoded.DiscApplicationCode).AppendLine(); + if(decoded.DID_V) + sb.AppendFormat("Disc ID: {0:X6}", decoded.DiscIdentification & 0x00FFFFFF).AppendLine(); - if(decoded.OPCTables == null) return sb.ToString(); + if(decoded.DBC_V) + sb.AppendFormat("Disc barcode: {0:X16}", decoded.DiscBarcode).AppendLine(); + + if(decoded.DAC_V) + sb.AppendFormat("Disc application code: {0}", decoded.DiscApplicationCode).AppendLine(); + + if(decoded.OPCTables == null) + return sb.ToString(); foreach(OPCTable table in decoded.OPCTables) sb.AppendFormat("OPC values for {0}Kbit/sec.: {1}, {2}, {3}, {4}, {5}, {6}", table.Speed, @@ -441,14 +244,19 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static TrackResourcesInformation? Decode001b(byte[] response) { - if(response.Length != 12) return null; + if(response.Length != 12) + return null; - if((response[2] & 0xE0) != 0x20) return null; + if((response[2] & 0xE0) != 0x20) + return null; - TrackResourcesInformation decoded = - new TrackResourcesInformation {DataLength = (ushort)((response[0] << 8) + response[1])}; + var decoded = new TrackResourcesInformation + { + DataLength = (ushort)((response[0] << 8) + response[1]) + }; - if(decoded.DataLength + 2 != response.Length) return null; + if(decoded.DataLength + 2 != response.Length) + return null; decoded.DataType = (byte)((response[2] & 0xE0) >> 5); decoded.MaxTracks = (ushort)((response[4] << 8) + response[5]); @@ -461,18 +269,22 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string Prettify001b(TrackResourcesInformation? information) { - if(!information.HasValue) return null; + if(!information.HasValue) + return null; TrackResourcesInformation decoded = information.Value; - if(decoded.DataType != 1) return null; + if(decoded.DataType != 1) + return null; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendFormat("{0} maximum possible tracks on the disc", decoded.MaxTracks).AppendLine(); sb.AppendFormat("{0} assigned tracks on the disc", decoded.AssignedTracks).AppendLine(); - sb.AppendFormat("{0} maximum possible appendable tracks on the disc", decoded.AppendableTracks) - .AppendLine(); + + sb.AppendFormat("{0} maximum possible appendable tracks on the disc", decoded.AppendableTracks). + AppendLine(); + sb.AppendFormat("{0} current appendable tracks on the disc", decoded.MaxAppendableTracks).AppendLine(); return sb.ToString(); @@ -480,20 +292,28 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static POWResourcesInformation? Decode010b(byte[] response) { - if(response.Length != 16) return null; + if(response.Length != 16) + return null; - if((response[2] & 0xE0) != 0x40) return null; + if((response[2] & 0xE0) != 0x40) + return null; - POWResourcesInformation decoded = - new POWResourcesInformation {DataLength = (ushort)((response[0] << 8) + response[1])}; + var decoded = new POWResourcesInformation + { + DataLength = (ushort)((response[0] << 8) + response[1]) + }; - if(decoded.DataLength + 2 != response.Length) return null; + if(decoded.DataLength + 2 != response.Length) + return null; decoded.DataType = (byte)((response[2] & 0xE0) >> 5); + decoded.RemainingPOWReplacements = (ushort)((response[4] << 24) + (response[5] << 16) + (response[6] << 8) + response[7]); + decoded.RemainingPOWReallocation = (ushort)((response[8] << 24) + (response[9] << 16) + (response[10] << 8) + response[11]); + decoded.RemainingPOWUpdates = (ushort)((response[12] << 24) + (response[13] << 16) + (response[14] << 8) + response[15]); @@ -502,17 +322,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string Prettify010b(POWResourcesInformation? information) { - if(!information.HasValue) return null; + if(!information.HasValue) + return null; POWResourcesInformation decoded = information.Value; - if(decoded.DataType != 1) return null; + if(decoded.DataType != 1) + return null; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendFormat("{0} remaining POW replacements", decoded.RemainingPOWReplacements).AppendLine(); - sb.AppendFormat("{0} remaining POW reallocation map entries", decoded.RemainingPOWReallocation) - .AppendLine(); + + sb.AppendFormat("{0} remaining POW reallocation map entries", decoded.RemainingPOWReallocation). + AppendLine(); + sb.AppendFormat("{0} remaining POW updates", decoded.RemainingPOWUpdates).AppendLine(); return sb.ToString(); @@ -520,9 +344,11 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string Prettify(byte[] response) { - if(response == null) return null; + if(response == null) + return null; - if(response.Length < 12) return null; + if(response.Length < 12) + return null; switch(response[2] & 0xE0) { @@ -533,5 +359,103 @@ namespace DiscImageChef.Decoders.SCSI.MMC return null; } + + public struct StandardDiscInformation + { + /// Bytes 0 to 1 32 + OPCTablesNumber*8 + public ushort DataLength; + /// Byte 2, bits 7 to 5 000b + public byte DataType; + /// Byte 2, bit 4 If set, disc is erasable + public bool Erasable; + /// Byte 2, bits 3 to 2 Status of last session + public byte LastSessionStatus; + /// Byte 2, bits 1 to 0 Status of disc + public byte DiscStatus; + /// Byte 3 Number of logical track that contains LBA 0 + public byte FirstTrackNumber; + /// Byte 9 (MSB) and byte 4 (LSB) Number of sessions + public ushort Sessions; + /// Byte 10 (MSB) and byte 5 (LSB) Number of first track in last session + public ushort FirstTrackLastSession; + /// Byte 11 (MSB) and byte 6 (LSB) Number of last track in last session + public ushort LastTrackLastSession; + /// Byte 7, bit 7 If set, DiscIdentification is valid + public bool DID_V; + /// Byte 7, bit 6 If set, DiscBarcode is valid + public bool DBC_V; + /// Byte 7, bit 5 If set, disc is unrestricted + public bool URU; + /// Byte 7, bit 4 If set DiscApplicationCode is valid + public bool DAC_V; + /// Byte 7, bit 3 Reserved + public bool Reserved; + /// Byte 7, bit 2 Copy of dirty bit from MRW status + public bool Dbit; + /// Byte 7, bits 1 to 0 Background format status + public byte BGFormatStatus; + /// Byte 8 Disc type code + public byte DiscType; + /// Bytes 12 to 15 Disc identification number from PMA + public uint DiscIdentification; + /// Bytes 16 to 19 Last Session Lead-in Start Address (MSF for CD, LBA for others) + public uint LastSessionLeadInStartLBA; + /// Bytes 20 to 23 Last Possible Lead-out Start Address (MSF for CD, LBA for others) + public uint LastPossibleLeadOutStartLBA; + /// Bytes 24 to 31 Disc barcode + public ulong DiscBarcode; + /// Byte 32 Disc application code + public byte DiscApplicationCode; + /// Byte 33 How many OPC tables are + public byte OPCTablesNumber; + /// Bytes 34 to end OPC tables (8 bytes each) + public OPCTable[] OPCTables; + } + + public struct OPCTable + { + /// Bytes 0 to 1 kilobytes/sec this OPC table applies to + public ushort Speed; + /// Bytes 2 to 7 OPC values + public byte[] OPCValues; + } + + public struct TrackResourcesInformation + { + /// Bytes 0 to 1 10 + public ushort DataLength; + /// Byte 2, bits 7 to 5 001b + public byte DataType; + /// Byte 2, bits 4 to 0 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Bytes 4 to 5 Maximum possible number of the tracks on the disc + public ushort MaxTracks; + /// Bytes 6 to 7 Number of the assigned tracks on the disc + public ushort AssignedTracks; + /// Bytes 8 to 9 Maximum possible number of appendable tracks on the disc + public ushort MaxAppendableTracks; + /// Bytes 10 to 11 Current number of appendable tracks on the disc + public ushort AppendableTracks; + } + + public struct POWResourcesInformation + { + /// Bytes 0 to 1 14 + public ushort DataLength; + /// Byte 2, bits 7 to 5 010b + public byte DataType; + /// Byte 2, bits 4 to 0 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Bytes 4 to 7 Remaining POW replacements + public uint RemainingPOWReplacements; + /// Bytes 8 to 11 Remaining POW reallocation map entries + public uint RemainingPOWReallocation; + /// Bytes 12 to 15 Number of remaining POW updates + public uint RemainingPOWUpdates; + } } } \ No newline at end of file diff --git a/SCSI/MMC/Enums.cs b/SCSI/MMC/Enums.cs index e36fd88..c38b012 100644 --- a/SCSI/MMC/Enums.cs +++ b/SCSI/MMC/Enums.cs @@ -34,56 +34,38 @@ using System.Diagnostics.CodeAnalysis; namespace DiscImageChef.Decoders.SCSI.MMC { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal")] public enum FormatLayerTypeCodes : ushort { - CDLayer = 0x0008, - DVDLayer = 0x0010, - BDLayer = 0x0040, + CDLayer = 0x0008, DVDLayer = 0x0010, BDLayer = 0x0040, HDDVDLayer = 0x0050 } - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal")] public enum SessionStatusCodes : byte { - Empty = 0x00, - Incomplete = 0x01, - ReservedOrDamaged = 0x02, - Complete = 0x03 + Empty = 0x00, Incomplete = 0x01, ReservedOrDamaged = 0x02, + Complete = 0x03 } - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal")] public enum DiscStatusCodes : byte { - Empty = 0x00, - Incomplete = 0x01, - Finalized = 0x02, - Others = 0x03 + Empty = 0x00, Incomplete = 0x01, Finalized = 0x02, + Others = 0x03 } - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal")] public enum BGFormatStatusCodes : byte { - NoFormattable = 0x00, - IncompleteBackgroundFormat = 0x01, - BackgroundFormatInProgress = 0x02, - FormatComplete = 0x03 + NoFormattable = 0x00, IncompleteBackgroundFormat = 0x01, BackgroundFormatInProgress = 0x02, + FormatComplete = 0x03 } - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal")] public enum DiscTypeCodes : byte { - /// - /// Also valid for CD-DA, DVD and BD - /// - CDROM = 0x00, - CDi = 0x10, - CDROMXA = 0x20, - Undefined = 0xFF + /// Also valid for CD-DA, DVD and BD + CDROM = 0x00, CDi = 0x10, CDROMXA = 0x20, Undefined = 0xFF } } \ No newline at end of file diff --git a/SCSI/MMC/Features.cs b/SCSI/MMC/Features.cs index 55e65a9..f5c8b17 100644 --- a/SCSI/MMC/Features.cs +++ b/SCSI/MMC/Features.cs @@ -39,2139 +39,1082 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI.MMC { - /// - /// MMC Feature enumeration - /// + /// MMC Feature enumeration [SuppressMessage("ReSharper", "InconsistentNaming")] public enum FeatureNumber : ushort { - /// - /// Lists all profiles - /// - ProfileList = 0x0000, - /// - /// Mandatory behaviour - /// - Core = 0x0001, - /// - /// Operational changes - /// - Morphing = 0x0002, - /// - /// Removable medium - /// - Removable = 0x0003, - /// - /// Ability to control write protection status - /// - WriteProtect = 0x0004, - /// - /// Ability to read sectors with random addressing - /// - RandomRead = 0x0010, - /// - /// Reads on OSTA Multi-Read - /// - MultiRead = 0x001D, - /// - /// Able to read CD structures - /// - CDRead = 0x001E, - /// - /// Able to read DVD structures - /// - DVDRead = 0x001F, - /// - /// Ability to write sectors with random addressing - /// - RandomWrite = 0x0020, - /// - /// Ability to sequentially write - /// - IncrementalWrite = 0x0021, - /// - /// Support for media that requires erase before write - /// - SectorErasable = 0x0022, - /// - /// Supports formatting media - /// - Formattable = 0x0023, - /// - /// Ability to provide defect-free space - /// - HardwareDefectMgmt = 0x0024, - /// - /// Supports for write-once media in random order - /// - WriteOnce = 0x0025, - /// - /// Supports for media that shall be written from blocking boundaries - /// - RestrictedOverwrite = 0x0026, - /// - /// Supports high speed CD-RW - /// - CDRWCAV = 0x0027, - /// - /// Read and optionally write MRW - /// - MRW = 0x0028, - /// - /// Ability to control RECOVERED ERROR reporting - /// - EnDefectReport = 0x0029, - /// - /// Ability to recognize, read and optionally write DVD+RW - /// - DVDRWPlus = 0x002A, - /// - /// Ability to read DVD+R - /// - DVDRPlus = 0x002B, - RigidOverWrite = 0x002C, - /// - /// Ability to write CD in Track-at-Once - /// - CDTAO = 0x002D, - /// - /// Ability to write CD in Session-at-Once or RAW - /// - CDMastering = 0x002E, - /// - /// Ability to write DVD structures - /// - DVDRWrite = 0x002F, - /// - /// Ability to read DDCD - /// - DDCD = 0x0030, - /// - /// Ability to write DDCD-R - /// - DDCDR = 0x0031, - /// - /// Ability to write DDCD-RW - /// - DDCDRW = 0x0032, - /// - /// Ability to record in layer jump mode - /// - LayerJump = 0x0033, - /// - /// Ability to perform Layer Jump recording on Rigid Restricted Overwrite - /// - LJRigid = 0x0034, - /// - /// Ability to stop the long immediate operation - /// - StopLong = 0x0035, - /// - /// Ability to report CD-RW media sub-types supported for write - /// - CDRWMediaWrite = 0x0037, - /// - /// Logical block overwrite service on BD-R formatted as SRM+POW - /// - BDRPOW = 0x0038, - /// - /// Ability to read DVD+RW DL - /// - DVDRWDLPlus = 0x003A, - /// - /// Ability to read DVD+R DL - /// - DVDRDLPlus = 0x003B, - /// - /// Ability to read BD discs - /// - BDRead = 0x0040, - /// - /// Ability to write BD discs - /// - BDWrite = 0x0041, - /// - /// Timely, Safe Recording - /// - TSR = 0x0042, - /// - /// Ability to read HD DVD - /// - HDDVDRead = 0x0050, - /// - /// Ability to write HD DVD - /// - HDDVDWrite = 0x0051, - /// - /// Ability to write HD DVD-RW fragmented - /// - HDDVDRWFragment = 0x0052, - /// - /// Supports some Hybrid Discs - /// - Hybrid = 0x0080, - /// - /// Host and device directed power management - /// - PowerMgmt = 0x0100, - /// - /// Supports S.M.A.R.T. - /// - SMART = 0x0101, - /// - /// Single machanism multiple disc changer - /// - Changer = 0x0102, - /// - /// Ability to play CD audio to an analogue output - /// - CDAudioExt = 0x0103, - /// - /// Ability to accept new microcode - /// - MicrocodeUpgrade = 0x0104, - /// - /// Ability to respond to all commands within a specific time - /// - Timeout = 0x0105, - /// - /// Supports DVD CSS/CPPM - /// - CSS = 0x0106, - /// - /// Ability to read and write using host requested performance parameters - /// - RTS = 0x0107, - /// - /// Drive has a unique identifier - /// - DriveSerial = 0x0108, - /// - /// Ability to return unique Media Serial Number - /// - MediaSerial = 0x0109, - /// - /// Ability to read and/or write DCBs - /// - DCBs = 0x010A, - /// - /// Supports DVD CPRM - /// - CPRM = 0x010B, - /// - /// Firmware creation date report - /// - FirmwareInfo = 0x010C, - /// - /// Ability to decode and optionally encode AACS - /// - AACS = 0x010D, - /// - /// Ability to perform DVD CSS managed recording - /// - CSSManagedRec = 0x010E, - /// - /// Ability to decode and optionally encode VCPS - /// - VCPS = 0x0110, - /// - /// Supports SecurDisc - /// - SecurDisc = 0x0113, - /// - /// TCG Optical Security Subsystem Class - /// + /// Lists all profiles + ProfileList = 0x0000, /// Mandatory behaviour + Core = 0x0001, /// Operational changes + Morphing = 0x0002, /// Removable medium + Removable = 0x0003, /// Ability to control write protection status + WriteProtect = 0x0004, /// Ability to read sectors with random addressing + RandomRead = 0x0010, /// Reads on OSTA Multi-Read + MultiRead = 0x001D, /// Able to read CD structures + CDRead = 0x001E, /// Able to read DVD structures + DVDRead = 0x001F, /// Ability to write sectors with random addressing + RandomWrite = 0x0020, /// Ability to sequentially write + IncrementalWrite = 0x0021, /// Support for media that requires erase before write + SectorErasable = 0x0022, /// Supports formatting media + Formattable = 0x0023, /// Ability to provide defect-free space + HardwareDefectMgmt = 0x0024, /// Supports for write-once media in random order + WriteOnce = 0x0025, /// Supports for media that shall be written from blocking boundaries + RestrictedOverwrite = 0x0026, /// Supports high speed CD-RW + CDRWCAV = 0x0027, /// Read and optionally write MRW + MRW = 0x0028, /// Ability to control RECOVERED ERROR reporting + EnDefectReport = 0x0029, /// Ability to recognize, read and optionally write DVD+RW + DVDRWPlus = 0x002A, /// Ability to read DVD+R + DVDRPlus = 0x002B, RigidOverWrite = 0x002C, /// Ability to write CD in Track-at-Once + CDTAO = 0x002D, /// Ability to write CD in Session-at-Once or RAW + CDMastering = 0x002E, /// Ability to write DVD structures + DVDRWrite = 0x002F, /// Ability to read DDCD + DDCD = 0x0030, /// Ability to write DDCD-R + DDCDR = 0x0031, /// Ability to write DDCD-RW + DDCDRW = 0x0032, /// Ability to record in layer jump mode + LayerJump = 0x0033, /// Ability to perform Layer Jump recording on Rigid Restricted Overwrite + LJRigid = 0x0034, /// Ability to stop the long immediate operation + StopLong = 0x0035, /// Ability to report CD-RW media sub-types supported for write + CDRWMediaWrite = 0x0037, /// Logical block overwrite service on BD-R formatted as SRM+POW + BDRPOW = 0x0038, /// Ability to read DVD+RW DL + DVDRWDLPlus = 0x003A, /// Ability to read DVD+R DL + DVDRDLPlus = 0x003B, /// Ability to read BD discs + BDRead = 0x0040, /// Ability to write BD discs + BDWrite = 0x0041, /// Timely, Safe Recording + TSR = 0x0042, /// Ability to read HD DVD + HDDVDRead = 0x0050, /// Ability to write HD DVD + HDDVDWrite = 0x0051, /// Ability to write HD DVD-RW fragmented + HDDVDRWFragment = 0x0052, /// Supports some Hybrid Discs + Hybrid = 0x0080, /// Host and device directed power management + PowerMgmt = 0x0100, /// Supports S.M.A.R.T. + SMART = 0x0101, /// Single machanism multiple disc changer + Changer = 0x0102, /// Ability to play CD audio to an analogue output + CDAudioExt = 0x0103, /// Ability to accept new microcode + MicrocodeUpgrade = 0x0104, /// Ability to respond to all commands within a specific time + Timeout = 0x0105, /// Supports DVD CSS/CPPM + CSS = 0x0106, /// Ability to read and write using host requested performance parameters + RTS = 0x0107, /// Drive has a unique identifier + DriveSerial = 0x0108, /// Ability to return unique Media Serial Number + MediaSerial = 0x0109, /// Ability to read and/or write DCBs + DCBs = 0x010A, /// Supports DVD CPRM + CPRM = 0x010B, /// Firmware creation date report + FirmwareInfo = 0x010C, /// Ability to decode and optionally encode AACS + AACS = 0x010D, /// Ability to perform DVD CSS managed recording + CSSManagedRec = 0x010E, /// Ability to decode and optionally encode VCPS + VCPS = 0x0110, /// Supports SecurDisc + SecurDisc = 0x0113, /// TCG Optical Security Subsystem Class OSSC = 0x0142 } - /// - /// MMC Profile enumeration - /// + /// MMC Profile enumeration [SuppressMessage("ReSharper", "InconsistentNaming")] public enum ProfileNumber : ushort { - /// - /// Not to use - /// - Reserved = 0x0000, - /// - /// Non-removable disk profile - /// - NonRemovable = 0x0001, - /// - /// Rewritable with removable media - /// - Removable = 0x0002, - /// - /// Magneto-Optical with sector erase - /// - MOErasable = 0x0003, - /// - /// Optical write once - /// - OpticalWORM = 0x0004, - /// - /// Advance Storage - Magneto-Optical - /// - ASMO = 0x0005, - /// - /// Read-only Compact Disc - /// - CDROM = 0x0008, - /// - /// Write-once Compact Disc - /// - CDR = 0x0009, - /// - /// Re-writable Compact Disc - /// - CDRW = 0x000A, - /// - /// Read-only DVD - /// - DVDROM = 0x0010, - /// - /// Write-once sequentially recorded DVD-R - /// - DVDRSeq = 0x0011, - /// - /// DVD-RAM - /// - DVDRAM = 0x0012, - /// - /// Restricted overwrite DVD-RW - /// - DVDRWRes = 0x0013, - /// - /// Sequential recording DVD-RW - /// - DVDRWSeq = 0x0014, - /// - /// Sequential recording DVD-R DL - /// - DVDRDLSeq = 0x0015, - /// - /// Layer jump recording DVD-R DL - /// - DVDRDLJump = 0x0016, - /// - /// DVD-RW DL - /// - DVDRWDL = 0x0017, - /// - /// DVD-Download - /// - DVDDownload = 0x0018, - /// - /// DVD+RW - /// - DVDRWPlus = 0x001A, - /// - /// DVD+R - /// - DVDRPlus = 0x001B, - /// - /// DDCD-ROM - /// - DDCDROM = 0x0020, - /// - /// DDCD-R - /// - DDCDR = 0x0021, - /// - /// DDCD-RW - /// - DDCDRW = 0x0022, - /// - /// DVD+RW DL - /// - DVDRWDLPlus = 0x002A, - /// - /// DVD+R DL - /// - DVDRDLPlus = 0x002B, - /// - /// BD-ROM - /// - BDROM = 0x0040, - /// - /// BD-R SRM - /// - BDRSeq = 0x0041, - /// - /// BD-R RRM - /// - BDRRdm = 0x0042, - /// - /// BD-RE - /// - BDRE = 0x0043, - /// - /// HD DVD-ROM - /// - HDDVDROM = 0x0050, - /// - /// HD DVD-R - /// - HDDVDR = 0x0051, - /// - /// HD DVD-RAM - /// - HDDVDRAM = 0x0052, - /// - /// HD DVD-RW - /// - HDDVDRW = 0x0053, - /// - /// HD DVD-R DL - /// - HDDVDRDL = 0x0058, - /// - /// HD DVD-RW DL - /// - HDDVDRWDL = 0x005A, - /// - /// HDBurn CD-ROM - /// - HDBURNROM = 0x0080, - /// - /// HDBurn CD-R - /// - HDBURNR = 0x0081, - /// - /// HDBurn CD-RW - /// - HDBURNRW = 0x0082, - /// - /// Drive does not conform to any profiles - /// + /// Not to use + Reserved = 0x0000, /// Non-removable disk profile + NonRemovable = 0x0001, /// Rewritable with removable media + Removable = 0x0002, /// Magneto-Optical with sector erase + MOErasable = 0x0003, /// Optical write once + OpticalWORM = 0x0004, /// Advance Storage - Magneto-Optical + ASMO = 0x0005, /// Read-only Compact Disc + CDROM = 0x0008, /// Write-once Compact Disc + CDR = 0x0009, /// Re-writable Compact Disc + CDRW = 0x000A, /// Read-only DVD + DVDROM = 0x0010, /// Write-once sequentially recorded DVD-R + DVDRSeq = 0x0011, /// DVD-RAM + DVDRAM = 0x0012, /// Restricted overwrite DVD-RW + DVDRWRes = 0x0013, /// Sequential recording DVD-RW + DVDRWSeq = 0x0014, /// Sequential recording DVD-R DL + DVDRDLSeq = 0x0015, /// Layer jump recording DVD-R DL + DVDRDLJump = 0x0016, /// DVD-RW DL + DVDRWDL = 0x0017, /// DVD-Download + DVDDownload = 0x0018, /// DVD+RW + DVDRWPlus = 0x001A, /// DVD+R + DVDRPlus = 0x001B, /// DDCD-ROM + DDCDROM = 0x0020, /// DDCD-R + DDCDR = 0x0021, /// DDCD-RW + DDCDRW = 0x0022, /// DVD+RW DL + DVDRWDLPlus = 0x002A, /// DVD+R DL + DVDRDLPlus = 0x002B, /// BD-ROM + BDROM = 0x0040, /// BD-R SRM + BDRSeq = 0x0041, /// BD-R RRM + BDRRdm = 0x0042, /// BD-RE + BDRE = 0x0043, /// HD DVD-ROM + HDDVDROM = 0x0050, /// HD DVD-R + HDDVDR = 0x0051, /// HD DVD-RAM + HDDVDRAM = 0x0052, /// HD DVD-RW + HDDVDRW = 0x0053, /// HD DVD-R DL + HDDVDRDL = 0x0058, /// HD DVD-RW DL + HDDVDRWDL = 0x005A, /// HDBurn CD-ROM + HDBURNROM = 0x0080, /// HDBurn CD-R + HDBURNR = 0x0081, /// HDBurn CD-RW + HDBURNRW = 0x0082, /// Drive does not conform to any profiles Unconforming = 0xFFFF } [SuppressMessage("ReSharper", "InconsistentNaming")] public enum PhysicalInterfaces : uint { - /// - /// Unspecified physical interface - /// - Unspecified = 0, - /// - /// SCSI - /// - SCSI = 1, - /// - /// ATAPI - /// - ATAPI = 2, - /// - /// IEEE-1394/1995 - /// - IEEE1394 = 3, - /// - /// IEEE-1394A - /// - IEEE1394A = 4, - /// - /// Fibre Channel - /// - FC = 5, - /// - /// IEEE-1394B - /// - IEEE1394B = 6, - /// - /// Serial ATAPI - /// - SerialATAPI = 7, - /// - /// USB - /// - USB = 8, - /// - /// Vendor unique - /// + /// Unspecified physical interface + Unspecified = 0, /// SCSI + SCSI = 1, /// ATAPI + ATAPI = 2, /// IEEE-1394/1995 + IEEE1394 = 3, /// IEEE-1394A + IEEE1394A = 4, /// Fibre Channel + FC = 5, /// IEEE-1394B + IEEE1394B = 6, /// Serial ATAPI + SerialATAPI = 7, /// USB + USB = 8, /// Vendor unique Vendor = 0xFFFF } - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Profile { public ProfileNumber Number; public bool Current; } - /// - /// Profile List Feature (0000h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// Profile List Feature (0000h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0000 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// All supported profiles - /// + /// All supported profiles public Profile[] Profiles; } - /// - /// Core Feature (0001h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// Core Feature (0001h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0001 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// Currently in-use physical interface standard - /// + /// Currently in-use physical interface standard public PhysicalInterfaces PhysicalInterfaceStandard; - /// - /// Supports EVPD, Page Code and 16-bit Allocation Length as defined in SPC-3 - /// + /// Supports EVPD, Page Code and 16-bit Allocation Length as defined in SPC-3 public bool INQ2; - /// - /// Supports Device Busy Event - /// + /// Supports Device Busy Event public bool DBE; } - /// - /// Morphing Feature (0002h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// Morphing Feature (0002h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0002 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// Supports Operational Change Request/Nofitication Class Events - /// of GET EVENT/STATUS NOTIFICATION - /// + /// Supports Operational Change Request/Nofitication Class Events of GET EVENT/STATUS NOTIFICATION public bool OCEvent; - /// - /// Supports asynchronous GET EVENT/STATUS NOTIFICATION - /// + /// Supports asynchronous GET EVENT/STATUS NOTIFICATION public bool Async; } - /// - /// Removable Medium Feature (0003h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// Removable Medium Feature (0003h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0003 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// Mechanism type - /// + /// Mechanism type public byte LoadingMechanismType; - /// - /// Drive is able to load the medium - /// + /// Drive is able to load the medium public bool Load; - /// - /// Device can eject medium - /// + /// Device can eject medium public bool Eject; - /// - /// Device starts in medium ejection/insertion allow - /// + /// Device starts in medium ejection/insertion allow public bool PreventJumper; - /// - /// Reports Device Busy Class events during medium loading/unloading - /// + /// Reports Device Busy Class events during medium loading/unloading public bool DBML; - /// - /// Medium is currently locked - /// + /// Medium is currently locked public bool Lock; } - /// - /// Write Protect Feature (0004h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// Write Protect Feature (0004h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0004 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// Drive can read/write Disc Write Protect PAC on BD-R/-RE media - /// + /// Drive can read/write Disc Write Protect PAC on BD-R/-RE media public bool DWP; - /// - /// Supports reading/writing Write Inhibit DCB on DVD+RW media. - /// + /// Supports reading/writing Write Inhibit DCB on DVD+RW media. public bool WDCB; - /// - /// Supports PWP status - /// + /// Supports PWP status public bool SPWP; - /// - /// Supports SWPP bit of mode page 1Dh - /// + /// Supports SWPP bit of mode page 1Dh public bool SSWPP; } - /// - /// Random Readable Feature (0010h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// Random Readable Feature (0010h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0010 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// Bytes per logical block - /// + /// Bytes per logical block public uint LogicalBlockSize; - /// - /// Number of logical blocks per device readable unit - /// + /// Number of logical blocks per device readable unit public ushort Blocking; - /// - /// Read/Write Error Recovery page is present - /// + /// Read/Write Error Recovery page is present public bool PP; } - /// - /// Multi-Read Feature (001Dh) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// Multi-Read Feature (001Dh) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_001D { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; } - /// - /// CD Read Feature (001Eh) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// CD Read Feature (001Eh) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_001E { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// Supports DAP bit in READ CD and READ CD MSF - /// + /// Supports DAP bit in READ CD and READ CD MSF public bool DAP; - /// - /// Supports C2 Error Pointers - /// + /// Supports C2 Error Pointers public bool C2; - /// - /// Can read CD-Text with READ TOC/PMA/ATIP - /// + /// Can read CD-Text with READ TOC/PMA/ATIP public bool CDText; } - /// - /// DVD Read Feature (001Fh) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// DVD Read Feature (001Fh) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_001F { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// Compliant with DVD Multi Drive Read-only specifications - /// + /// Compliant with DVD Multi Drive Read-only specifications public bool MULTI110; - /// - /// Supports reading all DVD-RW DL - /// + /// Supports reading all DVD-RW DL public bool DualRW; - /// - /// Supports reading all DVD-R DL including remapping - /// + /// Supports reading all DVD-R DL including remapping public bool DualR; } - /// - /// Random Writable Feature (0020h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// Random Writable Feature (0020h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0020 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// Last logical block address - /// + /// Last logical block address public uint LastLBA; - /// - /// Bytes per logical block - /// + /// Bytes per logical block public uint LogicalBlockSize; - /// - /// Number of logical blocks per device readable unit - /// + /// Number of logical blocks per device readable unit public ushort Blocking; - /// - /// Read/Write Error Recovery page is present - /// + /// Read/Write Error Recovery page is present public bool PP; } - /// - /// Incremental Streaming Writable Feature (0021h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// Incremental Streaming Writable Feature (0021h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0021 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// Bitmask of supported data types - /// + /// Bitmask of supported data types public ushort DataTypeSupported; - /// - /// Can report Track Resources Information of READ DISC INFORMATION - /// + /// Can report Track Resources Information of READ DISC INFORMATION public bool TRIO; - /// - /// Supports Address Mode in RESERVE TRACK - /// + /// Supports Address Mode in RESERVE TRACK public bool ARSV; - /// - /// Zero loss linking - /// + /// Zero loss linking public bool BUF; - /// - /// Logical blocks per link - /// + /// Logical blocks per link public byte[] LinkSizes; } - /// - /// Sector Erasable Feature (0022h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// Sector Erasable Feature (0022h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0022 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; } - /// - /// Formattable Feature (0023h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// Formattable Feature (0023h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0023 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// Supports formatting BD-RE without spare area - /// + /// Supports formatting BD-RE without spare area public bool RENoSA; - /// - /// Supports expansion of the spare area on BD-RE - /// + /// Supports expansion of the spare area on BD-RE public bool Expand; - /// - /// Supports FORMAT type 30h sub-type 11b - /// + /// Supports FORMAT type 30h sub-type 11b public bool QCert; - /// - /// Supports FORMAT type 30h sub-type 10b - /// + /// Supports FORMAT type 30h sub-type 10b public bool Cert; - /// - /// Supports FORMAT type 18h - /// + /// Supports FORMAT type 18h public bool FRF; - /// - /// Supports FORMAT type 00h/32h sub-type 10b on BD-R - /// + /// Supports FORMAT type 00h/32h sub-type 10b on BD-R public bool RRM; } - /// - /// Hardware Defect Management Feature (0024h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// Hardware Defect Management Feature (0024h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0024 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// Supports READ DISC STRUCTURE with Format Code 0Ah (Spare Area Information) - /// + /// Supports READ DISC STRUCTURE with Format Code 0Ah (Spare Area Information) public bool SSA; } - /// - /// Write Once Feature (0025h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// Write Once Feature (0025h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0025 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// Bytes per logical block - /// + /// Bytes per logical block public uint LogicalBlockSize; - /// - /// Number of logical blocks per device readable unit - /// + /// Number of logical blocks per device readable unit public ushort Blocking; - /// - /// Read/Write Error Recovery page is present - /// + /// Read/Write Error Recovery page is present public bool PP; } - /// - /// Restricted Overwrite Feature (0026h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// Restricted Overwrite Feature (0026h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0026 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; } - /// - /// CD-RW CAV Write Feature (0027h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// CD-RW CAV Write Feature (0027h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0027 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; } - /// - /// MRW Feature (0028h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// MRW Feature (0028h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0028 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// Can read DVD+MRW discs - /// + /// Can read DVD+MRW discs public bool DVDPRead; - /// - /// Can write DVD+MRW discs - /// + /// Can write DVD+MRW discs public bool DVDPWrite; - /// - /// Can format and write to CD-MRW discs - /// + /// Can format and write to CD-MRW discs public bool Write; } - /// - /// Enhanced Defect Reporting Feature (0029h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// Enhanced Defect Reporting Feature (0029h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0029 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// Supports DRT-DM - /// + /// Supports DRT-DM public bool DRTDM; - /// - /// Maximum number of DBI cache zones device can handle separately - /// + /// Maximum number of DBI cache zones device can handle separately public byte DBICacheZones; - /// - /// Number of entries in worst case to case DBI overflow - /// + /// Number of entries in worst case to case DBI overflow public ushort Entries; } - /// - /// DVD+RW Feature (002Ah) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// DVD+RW Feature (002Ah) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_002A { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// Can format DVD+RW discs - /// + /// Can format DVD+RW discs public bool Write; - /// - /// FORMAT UNIT supports quick start formatting - /// + /// FORMAT UNIT supports quick start formatting public bool QuickStart; - /// - /// Drive only supports read compatibility stop - /// + /// Drive only supports read compatibility stop public bool CloseOnly; } - /// - /// DVD+R Feature (002Bh) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// DVD+R Feature (002Bh) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_002B { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// Can write DVD+R - /// + /// Can write DVD+R public bool Write; } - /// - /// Rigid Restricted Overwrite Feature (002Ch) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// Rigid Restricted Overwrite Feature (002Ch) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_002C { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// Can generate Defect Status Data during formatting - /// + /// Can generate Defect Status Data during formatting public bool DSDG; - /// - /// Can read Defect Status Data recorded on medium - /// + /// Can read Defect Status Data recorded on medium public bool DSDR; - /// - /// Supports writing on an intermediate state Session and quick formatting - /// + /// Supports writing on an intermediate state Session and quick formatting public bool Intermediate; - /// - /// Supports BLANK command types 00h and 01h - /// + /// Supports BLANK command types 00h and 01h public bool Blank; } - /// - /// CD Track at Once Feature (002Dh) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// CD Track at Once Feature (002Dh) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_002D { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// Supports zero loss linking - /// + /// Supports zero loss linking public bool BUF; - /// - /// Supports writing R-W subchannels in raw mode - /// + /// Supports writing R-W subchannels in raw mode public bool RWRaw; - /// - /// Supports writing R-W subchannels in packed mode - /// + /// Supports writing R-W subchannels in packed mode public bool RWPack; - /// - /// Can perform test writes - /// + /// Can perform test writes public bool TestWrite; - /// - /// Supports overwriting a TAO track with another - /// + /// Supports overwriting a TAO track with another public bool CDRW; - /// - /// Can write R-W subchannels with user provided data - /// + /// Can write R-W subchannels with user provided data public bool RWSubchannel; - /// - /// Bitmask of supported data types - /// + /// Bitmask of supported data types public ushort DataTypeSupported; } - /// - /// CD Mastering (Session at Once) Feature (002Eh) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// CD Mastering (Session at Once) Feature (002Eh) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_002E { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// Supports zero loss linking - /// + /// Supports zero loss linking public bool BUF; - /// - /// Can write in Session at Once - /// + /// Can write in Session at Once public bool SAO; - /// - /// Can write multi-session in RAW - /// + /// Can write multi-session in RAW public bool RAWMS; - /// - /// Can write in RAW - /// + /// Can write in RAW public bool RAW; - /// - /// Can perform test writes - /// + /// Can perform test writes public bool TestWrite; - /// - /// Can overwrite previously recorded data - /// + /// Can overwrite previously recorded data public bool CDRW; - /// - /// Can write R-W subchannels with user provided data - /// + /// Can write R-W subchannels with user provided data public bool RW; - /// - /// Maximum length of a Cue Sheet for Session at Once - /// + /// Maximum length of a Cue Sheet for Session at Once public uint MaxCueSheet; } - /// - /// DVD-R/-RW Write Feature (002Fh) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// DVD-R/-RW Write Feature (002Fh) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_002F { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// Buffer Under-run protection - /// + /// Buffer Under-run protection public bool BUF; - /// - /// Supports writing DVD-R DL - /// + /// Supports writing DVD-R DL public bool RDL; - /// - /// Test write - /// + /// Test write public bool TestWrite; - /// - /// Can write and erase DVD-RW - /// + /// Can write and erase DVD-RW public bool DVDRW; } - /// - /// Double Density CD Read Feature (0030h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// Double Density CD Read Feature (0030h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0030 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; } - /// - /// Double Density CD-R Write Feature (0031h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// Double Density CD-R Write Feature (0031h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0031 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// Test write - /// + /// Test write public bool TestWrite; } - /// - /// Double Density CD-RW Write Feature (0032h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// Double Density CD-RW Write Feature (0032h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0032 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// Supports quick formatting - /// + /// Supports quick formatting public bool Intermediate; - /// - /// Supports BLANK command - /// + /// Supports BLANK command public bool Blank; } - /// - /// Layer Jump Recording Feature (0033h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// Layer Jump Recording Feature (0033h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0033 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; public byte[] LinkSizes; } - /// - /// Stop Long Operation Feature (0035h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// Stop Long Operation Feature (0035h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0035 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; } - /// - /// CD-RW Media Write Support Feature (0037h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// CD-RW Media Write Support Feature (0037h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0037 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// Bitmask of supported CD-RW media sub-types - /// + /// Bitmask of supported CD-RW media sub-types public byte SubtypeSupport; } - /// - /// BD-R Pseudo-Overwrite (POW) Feature (0038h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// BD-R Pseudo-Overwrite (POW) Feature (0038h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0038 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; } - /// - /// DVD+RW Dual Layer Feature (003Ah) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// DVD+RW Dual Layer Feature (003Ah) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_003A { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// Can format DVD+RW DL discs - /// + /// Can format DVD+RW DL discs public bool Write; - /// - /// FORMAT UNIT supports quick start formatting - /// + /// FORMAT UNIT supports quick start formatting public bool QuickStart; - /// - /// Drive only supports read compatibility stop - /// + /// Drive only supports read compatibility stop public bool CloseOnly; } - /// - /// DVD+R Dual Layer Feature (003Bh) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// DVD+R Dual Layer Feature (003Bh) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_003B { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// Can format DVD+R DL discs - /// + /// Can format DVD+R DL discs public bool Write; - /// - /// FORMAT UNIT supports quick start formatting - /// + /// FORMAT UNIT supports quick start formatting public bool QuickStart; - /// - /// Drive only supports read compatibility stop - /// + /// Drive only supports read compatibility stop public bool CloseOnly; } - /// - /// BD Read Feature (0040h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// BD Read Feature (0040h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0040 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// Can read BCA - /// + /// Can read BCA public bool BCA; - /// - /// Supports reading BD-RE Ver.2 - /// + /// Supports reading BD-RE Ver.2 public bool RE2; - /// - /// Supports reading BD-RE Ver.1 - /// + /// Supports reading BD-RE Ver.1 public bool RE1; - /// - /// Obsolete - /// + /// Obsolete public bool OldRE; - /// - /// Supports reading BD-R Ver.1 - /// + /// Supports reading BD-R Ver.1 public bool R; - /// - /// Obsolete - /// + /// Obsolete public bool OldR; - /// - /// Supports reading BD-ROM Ver.1 - /// + /// Supports reading BD-ROM Ver.1 public bool ROM; - /// - /// Obsolete - /// + /// Obsolete public bool OldROM; } - /// - /// BD Write Feature (0041h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// BD Write Feature (0041h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0041 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// Supports verify not required - /// + /// Supports verify not required public bool SVNR; - /// - /// Supports writing BD-RE Ver.2 - /// + /// Supports writing BD-RE Ver.2 public bool RE2; - /// - /// Supports writing BD-RE Ver.1 - /// + /// Supports writing BD-RE Ver.1 public bool RE1; - /// - /// Obsolete - /// + /// Obsolete public bool OldRE; - /// - /// Supports writing BD-R Ver.1 - /// + /// Supports writing BD-R Ver.1 public bool R; - /// - /// Obsolete - /// + /// Obsolete public bool OldR; } - /// - /// TSR Feature (0042h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// TSR Feature (0042h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0042 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; } - /// - /// HD DVD Read Feature (0050h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// HD DVD Read Feature (0050h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0050 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// Can read HD DVD-R - /// + /// Can read HD DVD-R public bool HDDVDR; - /// - /// Can read HD DVD-RAM - /// + /// Can read HD DVD-RAM public bool HDDVDRAM; } - /// - /// HD DVD Write Feature (0051h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// HD DVD Write Feature (0051h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0051 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// Can write HD DVD-R - /// + /// Can write HD DVD-R public bool HDDVDR; - /// - /// Can write HD DVD-RAM - /// + /// Can write HD DVD-RAM public bool HDDVDRAM; } - /// - /// Hybrid Disc Feature (0080h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// Hybrid Disc Feature (0080h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0080 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// Reset immunity - /// + /// Reset immunity public bool RI; } - /// - /// Power Management Feature (0100h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// Power Management Feature (0100h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0100 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; } - /// - /// S.M.A.R.T. Feature (0101h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// S.M.A.R.T. Feature (0101h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0101 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// Mode Page 1Ch is present - /// + /// Mode Page 1Ch is present public bool PP; } - /// - /// Embedded Changer Feature (0102h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// Embedded Changer Feature (0102h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0102 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// Side change capable - /// + /// Side change capable public bool SCC; - /// - /// Supports Disc Present - /// + /// Supports Disc Present public bool SDP; - /// - /// Number of slots - 1 - /// + /// Number of slots - 1 public byte HighestSlotNumber; } - /// - /// CD Audio External Play Feature (0103h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// CD Audio External Play Feature (0103h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0103 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// Supports SCAN command - /// + /// Supports SCAN command public bool Scan; - /// - /// Separate Channel Mute - /// + /// Separate Channel Mute public bool SCM; - /// - /// Separate Volume - /// + /// Separate Volume public bool SV; - /// - /// Number of volume levels - /// + /// Number of volume levels public ushort VolumeLevels; } - /// - /// Microcode Upgrade Feature (0104h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// Microcode Upgrade Feature (0104h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0104 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// Supports validating 5-bit mode field of READ BUFFER and WRITE BUFFER commands. - /// + /// Supports validating 5-bit mode field of READ BUFFER and WRITE BUFFER commands. public bool M5; } - /// - /// Time-Out Feature (0105h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// Time-Out Feature (0105h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0105 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// Supports G3Enable bit and Group3 Timeout field in Mode Page 1Dh - /// + /// Supports G3Enable bit and Group3 Timeout field in Mode Page 1Dh public bool Group3; - /// - /// Indicates a unit of block length, in sectors, corresponding to increase a unit of Group 3 time unit - /// + /// Indicates a unit of block length, in sectors, corresponding to increase a unit of Group 3 time unit public ushort UnitLength; } - /// - /// DVD-CSS Feature (0106h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// DVD-CSS Feature (0106h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0106 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// CSS version - /// + /// CSS version public byte CSSVersion; } - /// - /// Real Time Streaming Feature (0107h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// Real Time Streaming Feature (0107h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0107 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// Supports Set Minimum Performance bit in SET STREAMING - /// + /// Supports Set Minimum Performance bit in SET STREAMING public bool SMP; - /// - /// Supports READ BUFFER CAPACITY with block bit set - /// + /// Supports READ BUFFER CAPACITY with block bit set public bool RBCB; - /// - /// Supports SET CD SPEED - /// + /// Supports SET CD SPEED public bool SCS; - /// - /// Has Mode Page 2Ah with Speed Performance Descriptors - /// + /// Has Mode Page 2Ah with Speed Performance Descriptors public bool MP2A; - /// - /// Supports type 03h of GET PERFORMANCE - /// + /// Supports type 03h of GET PERFORMANCE public bool WSPD; - /// - /// Supports stream recording - /// + /// Supports stream recording public bool SW; } - /// - /// Drive serial number (0108h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// Drive serial number (0108h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0108 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// Drive serial number - /// + /// Drive serial number public string Serial; } - /// - /// Media Serial Number Feature (0109h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// Media Serial Number Feature (0109h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0109 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; } - /// - /// Disc Control Blocks Feature (010Ah) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// Disc Control Blocks Feature (010Ah) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_010A { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; public uint[] DCBs; } - /// - /// DVD CPRM Feature (010Bh) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// DVD CPRM Feature (010Bh) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_010B { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// CPRM version - /// + /// CPRM version public byte CPRMVersion; } - /// - /// Firmware Information Feature (010Ch) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// Firmware Information Feature (010Ch) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_010C { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; public ushort Century; public ushort Year; @@ -2182,162 +1125,93 @@ namespace DiscImageChef.Decoders.SCSI.MMC public ushort Second; } - /// - /// AACS Feature (010Dh) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// AACS Feature (010Dh) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_010D { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// Drive supports reading drive certificate - /// + /// Drive supports reading drive certificate public bool RDC; - /// - /// Drive can read media key block of CPRM - /// + /// Drive can read media key block of CPRM public bool RMC; - /// - /// Drive can write bus encrypted blocks - /// + /// Drive can write bus encrypted blocks public bool WBE; - /// - /// Drive supports bus encryption - /// + /// Drive supports bus encryption public bool BEC; - /// - /// Drive supports generating the binding nonce - /// + /// Drive supports generating the binding nonce public bool BNG; - /// - /// Blocks required to store the binding nonce for the media - /// + /// Blocks required to store the binding nonce for the media public byte BindNonceBlocks; - /// - /// Maximum number of AGIDs supported concurrently - /// + /// Maximum number of AGIDs supported concurrently public byte AGIDs; - /// - /// AACS version - /// + /// AACS version public byte AACSVersion; } - /// - /// DVD CSS Managed Recording Feature (010Eh) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// DVD CSS Managed Recording Feature (010Eh) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_010E { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// Maximum number of Scramble Extent information entries in a single SEND DISC STRUCTURE - /// + /// Maximum number of Scramble Extent information entries in a single SEND DISC STRUCTURE public byte MaxScrambleExtent; } - /// - /// SecurDisc Feature (0113h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// SecurDisc Feature (0113h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0113 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; } - /// - /// OSSC Feature (0142h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// OSSC Feature (0142h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0142 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; - /// - /// Supports PSA updates on write-once media - /// + /// Supports PSA updates on write-once media public bool PSAU; - /// - /// Supports linked OSPBs - /// + /// Supports linked OSPBs public bool LOSPB; - /// - /// Restricted to recording only OSSC disc format - /// + /// Restricted to recording only OSSC disc format public bool ME; public ushort[] Profiles; } - /// - /// VCPS Feature (0110h) - /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + /// VCPS Feature (0110h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct Feature_0110 { - /// - /// Feature version - /// + /// Feature version public byte Version; - /// - /// Feature is persistent - /// + /// Feature is persistent public bool Persistent; - /// - /// Feature is currently in use - /// + /// Feature is currently in use public bool Current; } @@ -2345,17 +1219,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC { public static Feature_0000? Decode_0000(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 4) return null; + if(feature.Length < 4) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0000) return null; + if(number != 0x0000) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0000 decoded = new Feature_0000(); + var decoded = new Feature_0000(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -2363,9 +1241,14 @@ namespace DiscImageChef.Decoders.SCSI.MMC int offset = 4; List listProfiles = new List(); + while(offset < feature.Length) { - Profile prof = new Profile {Number = (ProfileNumber)((feature[offset] << 8) + feature[offset + 1])}; + var prof = new Profile + { + Number = (ProfileNumber)((feature[offset] << 8) + feature[offset + 1]) + }; + prof.Current |= (feature[offset + 2] & 0x01) == 0x01; listProfiles.Add(prof); offset += 4; @@ -2378,17 +1261,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_0001? Decode_0001(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 8) return null; + if(feature.Length < 8) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0001) return null; + if(number != 0x0001) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0001 decoded = new Feature_0001(); + var decoded = new Feature_0001(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -2397,26 +1284,34 @@ namespace DiscImageChef.Decoders.SCSI.MMC decoded.PhysicalInterfaceStandard = (PhysicalInterfaces)((feature[4] << 24) + (feature[5] << 16) + (feature[6] << 8) + feature[7]); - if(decoded.Version >= 1 && feature.Length >= 12) decoded.DBE |= (feature[8] & 0x01) == 0x01; + if(decoded.Version >= 1 && + feature.Length >= 12) + decoded.DBE |= (feature[8] & 0x01) == 0x01; - if(decoded.Version >= 2 && feature.Length >= 12) decoded.INQ2 |= (feature[8] & 0x02) == 0x02; + if(decoded.Version >= 2 && + feature.Length >= 12) + decoded.INQ2 |= (feature[8] & 0x02) == 0x02; return decoded; } public static Feature_0002? Decode_0002(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 8) return null; + if(feature.Length < 8) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0002) return null; + if(number != 0x0002) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0002 decoded = new Feature_0002(); + var decoded = new Feature_0002(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -2424,24 +1319,29 @@ namespace DiscImageChef.Decoders.SCSI.MMC decoded.Async |= (feature[4] & 0x01) == 0x01; - if(decoded.Version >= 1) decoded.OCEvent |= (feature[4] & 0x02) == 0x02; + if(decoded.Version >= 1) + decoded.OCEvent |= (feature[4] & 0x02) == 0x02; return decoded; } public static Feature_0003? Decode_0003(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 8) return null; + if(feature.Length < 8) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0003) return null; + if(number != 0x0003) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0003 decoded = new Feature_0003(); + var decoded = new Feature_0003(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -2452,7 +1352,8 @@ namespace DiscImageChef.Decoders.SCSI.MMC decoded.PreventJumper |= (feature[4] & 0x04) == 0x04; decoded.Lock |= (feature[4] & 0x01) == 0x01; - if(decoded.Version < 2) return decoded; + if(decoded.Version < 2) + return decoded; decoded.Load |= (feature[4] & 0x10) == 0x10; decoded.DBML |= (feature[4] & 0x02) == 0x02; @@ -2462,17 +1363,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_0004? Decode_0004(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 8) return null; + if(feature.Length < 8) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0004) return null; + if(number != 0x0004) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0004 decoded = new Feature_0004(); + var decoded = new Feature_0004(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -2481,26 +1386,32 @@ namespace DiscImageChef.Decoders.SCSI.MMC decoded.SPWP |= (feature[4] & 0x02) == 0x02; decoded.SSWPP |= (feature[4] & 0x01) == 0x01; - if(decoded.Version >= 1) decoded.WDCB |= (feature[4] & 0x04) == 0x04; + if(decoded.Version >= 1) + decoded.WDCB |= (feature[4] & 0x04) == 0x04; - if(decoded.Version >= 2) decoded.DWP |= (feature[4] & 0x08) == 0x08; + if(decoded.Version >= 2) + decoded.DWP |= (feature[4] & 0x08) == 0x08; return decoded; } public static Feature_0010? Decode_0010(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 12) return null; + if(feature.Length < 12) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0010) return null; + if(number != 0x0010) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0010 decoded = new Feature_0010(); + var decoded = new Feature_0010(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -2508,8 +1419,10 @@ namespace DiscImageChef.Decoders.SCSI.MMC decoded.LogicalBlockSize = (uint)((feature[4] << 24) + (feature[5] << 16) + (feature[6] << 8) + feature[7]); + decoded.Blocking = (ushort)((feature[8] << 8) + feature[9]); + decoded.PP |= (feature[10] & 0x01) == 0x01; return decoded; @@ -2517,17 +1430,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_001D? Decode_001D(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 4) return null; + if(feature.Length < 4) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x001D) return null; + if(number != 0x001D) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_001D decoded = new Feature_001D(); + var decoded = new Feature_001D(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -2538,17 +1455,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_001E? Decode_001E(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 8) return null; + if(feature.Length < 8) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x001E) return null; + if(number != 0x001E) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_001E decoded = new Feature_001E(); + var decoded = new Feature_001E(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -2560,64 +1481,79 @@ namespace DiscImageChef.Decoders.SCSI.MMC decoded.CDText |= (feature[4] & 0x01) == 0x01; } - if(decoded.Version >= 2) decoded.DAP |= (feature[4] & 0x80) == 0x80; + if(decoded.Version >= 2) + decoded.DAP |= (feature[4] & 0x80) == 0x80; return decoded; } public static Feature_001F? Decode_001F(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 4) return null; + if(feature.Length < 4) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x001F) return null; + if(number != 0x001F) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_001F decoded = new Feature_001F(); + var decoded = new Feature_001F(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; decoded.Version = (byte)((feature[2] & 0x3C) >> 2); - if(decoded.Version >= 2 && feature.Length >= 8) + if(decoded.Version >= 2 && + feature.Length >= 8) { decoded.MULTI110 |= (feature[4] & 0x01) == 0x01; decoded.DualR |= (feature[6] & 0x01) == 0x01; } // TODO: Check this - if(decoded.Version >= 2 && feature.Length >= 8) decoded.DualRW |= (feature[6] & 0x02) == 0x02; + if(decoded.Version >= 2 && + feature.Length >= 8) + decoded.DualRW |= (feature[6] & 0x02) == 0x02; return decoded; } public static Feature_0020? Decode_0020(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 16) return null; + if(feature.Length < 16) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0020) return null; + if(number != 0x0020) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0020 decoded = new Feature_0020(); + var decoded = new Feature_0020(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; decoded.Version = (byte)((feature[2] & 0x3C) >> 2); - if(decoded.Version < 1) return decoded; + if(decoded.Version < 1) + return decoded; decoded.LastLBA = (uint)((feature[4] << 24) + (feature[5] << 16) + (feature[6] << 8) + feature[7]); + decoded.LogicalBlockSize = (uint)((feature[8] << 24) + (feature[9] << 16) + (feature[10] << 8) + feature[11]); + decoded.Blocking = (ushort)((feature[12] << 8) + feature[13]); decoded.PP |= (feature[14] & 0x01) == 0x01; @@ -2626,17 +1562,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_0021? Decode_0021(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 8) return null; + if(feature.Length < 8) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0021) return null; + if(number != 0x0021) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0021 decoded = new Feature_0021(); + var decoded = new Feature_0021(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -2647,10 +1587,13 @@ namespace DiscImageChef.Decoders.SCSI.MMC decoded.DataTypeSupported = (ushort)((feature[4] << 8) + feature[5]); decoded.BUF |= (feature[6] & 0x01) == 0x01; decoded.LinkSizes = new byte[feature[7]]; - if(feature.Length > feature[7] + 8) Array.Copy(feature, 8, decoded.LinkSizes, 0, feature[7]); + + if(feature.Length > feature[7] + 8) + Array.Copy(feature, 8, decoded.LinkSizes, 0, feature[7]); } - if(decoded.Version < 3) return decoded; + if(decoded.Version < 3) + return decoded; decoded.TRIO |= (feature[6] & 0x04) == 0x04; decoded.ARSV |= (feature[6] & 0x02) == 0x02; @@ -2660,17 +1603,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_0022? Decode_0022(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 4) return null; + if(feature.Length < 4) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0022) return null; + if(number != 0x0022) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0022 decoded = new Feature_0022(); + var decoded = new Feature_0022(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -2681,23 +1628,28 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_0023? Decode_0023(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 4) return null; + if(feature.Length < 4) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0023) return null; + if(number != 0x0023) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0023 decoded = new Feature_0023(); + var decoded = new Feature_0023(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; decoded.Version = (byte)((feature[2] & 0x3C) >> 2); - if(decoded.Version >= 1 && feature.Length >= 12) + if(decoded.Version >= 1 && + feature.Length >= 12) { decoded.RENoSA |= (feature[4] & 0x08) == 0x08; decoded.Expand |= (feature[4] & 0x04) == 0x04; @@ -2706,47 +1658,59 @@ namespace DiscImageChef.Decoders.SCSI.MMC decoded.RRM |= (feature[8] & 0x01) == 0x01; } - if(decoded.Version >= 2 && feature.Length >= 12) decoded.FRF |= (feature[4] & 0x80) == 0x80; + if(decoded.Version >= 2 && + feature.Length >= 12) + decoded.FRF |= (feature[4] & 0x80) == 0x80; return decoded; } public static Feature_0024? Decode_0024(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 4) return null; + if(feature.Length < 4) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0024) return null; + if(number != 0x0024) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0024 decoded = new Feature_0024(); + var decoded = new Feature_0024(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; decoded.Version = (byte)((feature[2] & 0x3C) >> 2); - if(decoded.Version >= 1 && feature.Length >= 8) decoded.SSA |= (feature[4] & 0x80) == 0x80; + if(decoded.Version >= 1 && + feature.Length >= 8) + decoded.SSA |= (feature[4] & 0x80) == 0x80; return decoded; } public static Feature_0025? Decode_0025(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 12) return null; + if(feature.Length < 12) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0025) return null; + if(number != 0x0025) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0025 decoded = new Feature_0025(); + var decoded = new Feature_0025(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -2754,8 +1718,10 @@ namespace DiscImageChef.Decoders.SCSI.MMC decoded.LogicalBlockSize = (uint)((feature[4] << 24) + (feature[5] << 16) + (feature[6] << 8) + feature[7]); + decoded.Blocking = (ushort)((feature[8] << 8) + feature[9]); + decoded.PP |= (feature[10] & 0x01) == 0x01; return decoded; @@ -2763,17 +1729,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_0026? Decode_0026(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 4) return null; + if(feature.Length < 4) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0026) return null; + if(number != 0x0026) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0026 decoded = new Feature_0026(); + var decoded = new Feature_0026(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -2784,17 +1754,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_0027? Decode_0027(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 8) return null; + if(feature.Length < 8) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0027) return null; + if(number != 0x0027) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0027 decoded = new Feature_0027(); + var decoded = new Feature_0027(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -2805,17 +1779,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_0028? Decode_0028(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 8) return null; + if(feature.Length < 8) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0028) return null; + if(number != 0x0028) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0028 decoded = new Feature_0028(); + var decoded = new Feature_0028(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -2823,7 +1801,8 @@ namespace DiscImageChef.Decoders.SCSI.MMC decoded.Write |= (feature[4] & 0x01) == 0x01; - if(decoded.Version < 1) return decoded; + if(decoded.Version < 1) + return decoded; decoded.DVDPWrite |= (feature[4] & 0x04) == 0x04; decoded.DVDPRead |= (feature[4] & 0x02) == 0x02; @@ -2833,17 +1812,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_0029? Decode_0029(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 8) return null; + if(feature.Length < 8) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0029) return null; + if(number != 0x0029) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0029 decoded = new Feature_0029(); + var decoded = new Feature_0029(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -2858,17 +1841,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_002A? Decode_002A(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 8) return null; + if(feature.Length < 8) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x002A) return null; + if(number != 0x002A) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_002A decoded = new Feature_002A(); + var decoded = new Feature_002A(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -2877,24 +1864,29 @@ namespace DiscImageChef.Decoders.SCSI.MMC decoded.Write |= (feature[4] & 0x01) == 0x01; decoded.CloseOnly |= (feature[5] & 0x01) == 0x01; - if(decoded.Version >= 1) decoded.QuickStart |= (feature[5] & 0x02) == 0x02; + if(decoded.Version >= 1) + decoded.QuickStart |= (feature[5] & 0x02) == 0x02; return decoded; } public static Feature_002B? Decode_002B(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 8) return null; + if(feature.Length < 8) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x002B) return null; + if(number != 0x002B) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_002B decoded = new Feature_002B(); + var decoded = new Feature_002B(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -2907,17 +1899,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_002C? Decode_002C(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 8) return null; + if(feature.Length < 8) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x002C) return null; + if(number != 0x002C) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_002C decoded = new Feature_002C(); + var decoded = new Feature_002C(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -2933,17 +1929,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_002D? Decode_002D(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 8) return null; + if(feature.Length < 8) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x002D) return null; + if(number != 0x002D) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_002D decoded = new Feature_002D(); + var decoded = new Feature_002D(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -2954,7 +1954,8 @@ namespace DiscImageChef.Decoders.SCSI.MMC decoded.RWSubchannel |= (feature[4] & 0x01) == 0x01; decoded.DataTypeSupported = (ushort)((feature[6] << 8) + feature[7]); - if(decoded.Version < 2) return decoded; + if(decoded.Version < 2) + return decoded; decoded.BUF |= (feature[4] & 0x40) == 0x40; decoded.RWRaw |= (feature[4] & 0x10) == 0x10; @@ -2965,17 +1966,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_002E? Decode_002E(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 8) return null; + if(feature.Length < 8) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x002E) return null; + if(number != 0x002E) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_002E decoded = new Feature_002E(); + var decoded = new Feature_002E(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -2989,24 +1994,29 @@ namespace DiscImageChef.Decoders.SCSI.MMC decoded.RW |= (feature[4] & 0x01) == 0x01; decoded.MaxCueSheet = (uint)((feature[5] << 16) + (feature[6] << 8) + feature[7]); - if(decoded.Version >= 1) decoded.BUF |= (feature[4] & 0x40) == 0x40; + if(decoded.Version >= 1) + decoded.BUF |= (feature[4] & 0x40) == 0x40; return decoded; } public static Feature_002F? Decode_002F(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 8) return null; + if(feature.Length < 8) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x002F) return null; + if(number != 0x002F) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_002F decoded = new Feature_002F(); + var decoded = new Feature_002F(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -3015,26 +2025,32 @@ namespace DiscImageChef.Decoders.SCSI.MMC decoded.BUF |= (feature[4] & 0x40) == 0x40; decoded.TestWrite |= (feature[4] & 0x04) == 0x04; - if(decoded.Version >= 1) decoded.DVDRW |= (feature[4] & 0x02) == 0x02; + if(decoded.Version >= 1) + decoded.DVDRW |= (feature[4] & 0x02) == 0x02; - if(decoded.Version >= 2) decoded.RDL |= (feature[4] & 0x08) == 0x08; + if(decoded.Version >= 2) + decoded.RDL |= (feature[4] & 0x08) == 0x08; return decoded; } public static Feature_0030? Decode_0030(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 4) return null; + if(feature.Length < 4) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0030) return null; + if(number != 0x0030) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0030 decoded = new Feature_0030(); + var decoded = new Feature_0030(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -3045,17 +2061,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_0031? Decode_0031(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 8) return null; + if(feature.Length < 8) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0031) return null; + if(number != 0x0031) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0031 decoded = new Feature_0031(); + var decoded = new Feature_0031(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -3068,17 +2088,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_0032? Decode_0032(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 8) return null; + if(feature.Length < 8) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0032) return null; + if(number != 0x0032) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0032 decoded = new Feature_0032(); + var decoded = new Feature_0032(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -3092,23 +2116,29 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_0033? Decode_0033(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 8) return null; + if(feature.Length < 8) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0033) return null; + if(number != 0x0033) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0033 decoded = new Feature_0033(); + var decoded = new Feature_0033(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; decoded.Version = (byte)((feature[2] & 0x3C) >> 2); - if(feature[7] <= 0 || feature.Length <= feature[7] + 8) return decoded; + if(feature[7] <= 0 || + feature.Length <= feature[7] + 8) + return decoded; decoded.LinkSizes = new byte[feature[7]]; Array.Copy(feature, 8, decoded.LinkSizes, 0, feature[7]); @@ -3118,17 +2148,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_0035? Decode_0035(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 4) return null; + if(feature.Length < 4) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0035) return null; + if(number != 0x0035) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0035 decoded = new Feature_0035(); + var decoded = new Feature_0035(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -3139,17 +2173,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_0037? Decode_0037(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 8) return null; + if(feature.Length < 8) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0037) return null; + if(number != 0x0037) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0037 decoded = new Feature_0037(); + var decoded = new Feature_0037(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -3162,17 +2200,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_0038? Decode_0038(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 8) return null; + if(feature.Length < 8) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0038) return null; + if(number != 0x0038) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0038 decoded = new Feature_0038(); + var decoded = new Feature_0038(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -3183,17 +2225,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_003A? Decode_003A(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 8) return null; + if(feature.Length < 8) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x003A) return null; + if(number != 0x003A) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_003A decoded = new Feature_003A(); + var decoded = new Feature_003A(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -3208,17 +2254,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_003B? Decode_003B(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 8) return null; + if(feature.Length < 8) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x003B) return null; + if(number != 0x003B) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_003B decoded = new Feature_003B(); + var decoded = new Feature_003B(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -3231,17 +2281,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_0040? Decode_0040(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 32) return null; + if(feature.Length < 32) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0040) return null; + if(number != 0x0040) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0040 decoded = new Feature_0040(); + var decoded = new Feature_0040(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -3251,7 +2305,8 @@ namespace DiscImageChef.Decoders.SCSI.MMC decoded.OldR |= (feature[17] & 0x01) == 0x01; decoded.OldROM |= (feature[25] & 0x01) == 0x01; - if(decoded.Version < 1) return decoded; + if(decoded.Version < 1) + return decoded; decoded.BCA |= (feature[4] & 0x01) == 0x01; decoded.RE2 |= (feature[9] & 0x04) == 0x04; @@ -3264,17 +2319,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_0041? Decode_0041(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 24) return null; + if(feature.Length < 24) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0041) return null; + if(number != 0x0041) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0041 decoded = new Feature_0041(); + var decoded = new Feature_0041(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -3284,7 +2343,8 @@ namespace DiscImageChef.Decoders.SCSI.MMC decoded.OldRE |= (feature[9] & 0x01) == 0x01; decoded.OldR |= (feature[17] & 0x01) == 0x01; - if(decoded.Version < 1) return decoded; + if(decoded.Version < 1) + return decoded; decoded.RE2 |= (feature[9] & 0x04) == 0x04; decoded.RE1 |= (feature[9] & 0x02) == 0x02; @@ -3295,17 +2355,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_0042? Decode_0042(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 4) return null; + if(feature.Length < 4) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0042) return null; + if(number != 0x0042) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0042 decoded = new Feature_0042(); + var decoded = new Feature_0042(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -3316,17 +2380,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_0050? Decode_0050(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 8) return null; + if(feature.Length < 8) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0050) return null; + if(number != 0x0050) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0050 decoded = new Feature_0050(); + var decoded = new Feature_0050(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -3340,17 +2408,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_0051? Decode_0051(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 8) return null; + if(feature.Length < 8) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0051) return null; + if(number != 0x0051) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0051 decoded = new Feature_0051(); + var decoded = new Feature_0051(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -3364,17 +2436,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_0080? Decode_0080(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 8) return null; + if(feature.Length < 8) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0080) return null; + if(number != 0x0080) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0080 decoded = new Feature_0080(); + var decoded = new Feature_0080(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -3387,17 +2463,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_0100? Decode_0100(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 4) return null; + if(feature.Length < 4) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0100) return null; + if(number != 0x0100) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0100 decoded = new Feature_0100(); + var decoded = new Feature_0100(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -3408,17 +2488,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_0101? Decode_0101(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 8) return null; + if(feature.Length < 8) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0101) return null; + if(number != 0x0101) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0101 decoded = new Feature_0101(); + var decoded = new Feature_0101(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -3431,17 +2515,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_0102? Decode_0102(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 4) return null; + if(feature.Length < 4) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0102) return null; + if(number != 0x0102) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0102 decoded = new Feature_0102(); + var decoded = new Feature_0102(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -3456,17 +2544,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_0103? Decode_0103(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 8) return null; + if(feature.Length < 8) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0103) return null; + if(number != 0x0103) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0103 decoded = new Feature_0103(); + var decoded = new Feature_0103(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -3482,46 +2574,58 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_0104? Decode_0104(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 4) return null; + if(feature.Length < 4) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0104) return null; + if(number != 0x0104) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0104 decoded = new Feature_0104(); + var decoded = new Feature_0104(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; decoded.Version = (byte)((feature[2] & 0x3C) >> 2); - if(decoded.Version >= 1 && feature.Length >= 8) decoded.M5 |= (feature[4] & 0x01) == 0x01; + if(decoded.Version >= 1 && + feature.Length >= 8) + decoded.M5 |= (feature[4] & 0x01) == 0x01; return decoded; } public static Feature_0105? Decode_0105(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 4) return null; + if(feature.Length < 4) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0105) return null; + if(number != 0x0105) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0105 decoded = new Feature_0105(); + var decoded = new Feature_0105(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; decoded.Version = (byte)((feature[2] & 0x3C) >> 2); - if(decoded.Version < 1 || feature.Length < 8) return decoded; + if(decoded.Version < 1 || + feature.Length < 8) + return decoded; decoded.Group3 |= (feature[4] & 0x01) == 0x01; decoded.UnitLength = (ushort)((feature[6] << 8) + feature[7]); @@ -3531,17 +2635,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_0106? Decode_0106(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 8) return null; + if(feature.Length < 8) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0106) return null; + if(number != 0x0106) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0106 decoded = new Feature_0106(); + var decoded = new Feature_0106(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -3554,23 +2662,28 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_0107? Decode_0107(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 4) return null; + if(feature.Length < 4) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0107) return null; + if(number != 0x0107) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0107 decoded = new Feature_0107(); + var decoded = new Feature_0107(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; decoded.Version = (byte)((feature[2] & 0x3C) >> 2); - if(decoded.Version >= 3 && feature.Length >= 8) + if(decoded.Version >= 3 && + feature.Length >= 8) { decoded.RBCB |= (feature[4] & 0x10) == 0x10; decoded.SCS |= (feature[4] & 0x08) == 0x08; @@ -3579,7 +2692,9 @@ namespace DiscImageChef.Decoders.SCSI.MMC decoded.SW |= (feature[4] & 0x01) == 0x01; } - if(decoded.Version < 5 || feature.Length < 8) return decoded; + if(decoded.Version < 5 || + feature.Length < 8) + return decoded; decoded.SMP |= (feature[4] & 0x20) == 0x20; decoded.RBCB |= (feature[4] & 0x10) == 0x10; @@ -3589,17 +2704,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_0108? Decode_0108(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 4) return null; + if(feature.Length < 4) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0108) return null; + if(number != 0x0108) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0108 decoded = new Feature_0108(); + var decoded = new Feature_0108(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -3614,17 +2733,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_0109? Decode_0109(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 4) return null; + if(feature.Length < 4) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0109) return null; + if(number != 0x0109) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0109 decoded = new Feature_0109(); + var decoded = new Feature_0109(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -3635,23 +2758,28 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_010A? Decode_010A(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 8) return null; + if(feature.Length < 8) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x010A) return null; + if(number != 0x010A) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_010A decoded = new Feature_010A(); + var decoded = new Feature_010A(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; decoded.Version = (byte)((feature[2] & 0x3C) >> 2); decoded.DCBs = new uint[feature[3] / 4]; + for(int i = 0; i < decoded.DCBs.Length; i++) decoded.DCBs[i] = (uint)((feature[0 + 4 + i * 4] << 24) + (feature[1 + 4 + i * 4] << 16) + (feature[2 + 4 + i * 4] << 8) + feature[3 + 4 + i * 4]); @@ -3661,17 +2789,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_010B? Decode_010B(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 4) return null; + if(feature.Length < 4) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x010B) return null; + if(number != 0x010B) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_010B decoded = new Feature_010B(); + var decoded = new Feature_010B(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -3684,17 +2816,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_010C? Decode_010C(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 20) return null; + if(feature.Length < 20) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x010C) return null; + if(number != 0x010C) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_010C decoded = new Feature_010C(); + var decoded = new Feature_010C(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -3713,17 +2849,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_010D? Decode_010D(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 8) return null; + if(feature.Length < 8) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x010D) return null; + if(number != 0x010D) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_010D decoded = new Feature_010D(); + var decoded = new Feature_010D(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -3734,7 +2874,8 @@ namespace DiscImageChef.Decoders.SCSI.MMC decoded.AGIDs = (byte)(feature[6] & 0x0F); decoded.AACSVersion = feature[7]; - if(decoded.Version < 2) return decoded; + if(decoded.Version < 2) + return decoded; decoded.RDC |= (feature[4] & 0x10) == 0x10; decoded.RMC |= (feature[4] & 0x08) == 0x08; @@ -3746,17 +2887,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_010E? Decode_010E(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 8) return null; + if(feature.Length < 8) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x010E) return null; + if(number != 0x010E) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_010E decoded = new Feature_010E(); + var decoded = new Feature_010E(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -3769,17 +2914,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_0110? Decode_0110(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 8) return null; + if(feature.Length < 8) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0110) return null; + if(number != 0x0110) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0110 decoded = new Feature_0110(); + var decoded = new Feature_0110(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -3790,17 +2939,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_0113? Decode_0113(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 4) return null; + if(feature.Length < 4) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0113) return null; + if(number != 0x0113) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0113 decoded = new Feature_0113(); + var decoded = new Feature_0113(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -3811,17 +2964,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static Feature_0142? Decode_0142(byte[] feature) { - if(feature == null) return null; + if(feature == null) + return null; - if(feature.Length < 6) return null; + if(feature.Length < 6) + return null; ushort number = (ushort)((feature[0] << 8) + feature[1]); - if(number != 0x0142) return null; + if(number != 0x0142) + return null; - if(feature[3] + 4 != feature.Length) return null; + if(feature[3] + 4 != feature.Length) + return null; - Feature_0142 decoded = new Feature_0142(); + var decoded = new Feature_0142(); decoded.Current |= (feature[2] & 0x01) == 0x01; decoded.Persistent |= (feature[2] & 0x02) == 0x02; @@ -3831,7 +2988,9 @@ namespace DiscImageChef.Decoders.SCSI.MMC decoded.LOSPB |= (feature[4] & 0x40) == 0x40; decoded.ME |= (feature[4] & 0x01) == 0x01; decoded.Profiles = new ushort[feature[5]]; - if(feature[5] * 2 + 6 != feature.Length) return decoded; + + if(feature[5] * 2 + 6 != feature.Length) + return decoded; for(int i = 0; i < feature[5]; i++) decoded.Profiles[i] = (ushort)((feature[0 + 6 + 2 * i] << 8) + feature[1 + 6 + 2 * i]); @@ -3841,13 +3000,16 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string Prettify_0000(Feature_0000? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_0000 ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_0000 ftr = feature.Value; + var sb = new StringBuilder(); sb.AppendLine("MMC Supported Profiles:"); - if(ftr.Profiles == null) return sb.ToString(); + + if(ftr.Profiles == null) + return sb.ToString(); foreach(Profile prof in ftr.Profiles) { @@ -3855,128 +3017,170 @@ namespace DiscImageChef.Decoders.SCSI.MMC { case ProfileNumber.Reserved: sb.Append("\tDrive reported a reserved profile number"); + break; case ProfileNumber.NonRemovable: sb.Append("\tDrive supports non-removable changeable media"); + break; case ProfileNumber.Removable: sb.Append("\tDrive supports rewritable and removable media"); + break; case ProfileNumber.MOErasable: sb.Append("\tDrive supports Magnet-Optical media"); + break; case ProfileNumber.OpticalWORM: sb.Append("\tDrive supports optical write-once media"); + break; case ProfileNumber.ASMO: sb.Append("\tDrive supports Advanced Storage - Magneto-Optical"); + break; case ProfileNumber.CDROM: sb.Append("\tDrive supports CD-ROM"); + break; case ProfileNumber.CDR: sb.Append("\tDrive supports CD-R"); + break; case ProfileNumber.CDRW: sb.Append("\tDrive supports CD-RW"); + break; case ProfileNumber.DVDROM: sb.Append("\tDrive supports DVD-ROM"); + break; case ProfileNumber.DVDRSeq: sb.Append("\tDrive supports DVD-R"); + break; case ProfileNumber.DVDRAM: sb.Append("\tDrive supports DVD-RAM"); + break; case ProfileNumber.DVDRWRes: sb.Append("\tDrive supports restricted overwrite DVD-RW"); + break; case ProfileNumber.DVDRWSeq: sb.Append("\tDrive supports sequentially recorded DVD-RW"); + break; case ProfileNumber.DVDRDLSeq: sb.Append("\tDrive supports sequentially recorded DVD-R DL"); + break; case ProfileNumber.DVDRDLJump: sb.Append("\tDrive supports layer jump recorded DVD-R DL"); + break; case ProfileNumber.DVDRWDL: sb.Append("\tDrive supports DVD-RW DL"); + break; case ProfileNumber.DVDDownload: sb.Append("\tDrive supports DVD-Download"); + break; case ProfileNumber.DVDRWPlus: sb.Append("\tDrive supports DVD+RW"); + break; case ProfileNumber.DVDRPlus: sb.Append("\tDrive supports DVD+R"); + break; case ProfileNumber.DDCDROM: sb.Append("\tDrive supports DDCD-ROM"); + break; case ProfileNumber.DDCDR: sb.Append("\tDrive supports DDCD-R"); + break; case ProfileNumber.DDCDRW: sb.Append("\tDrive supports DDCD-RW"); + break; case ProfileNumber.DVDRWDLPlus: sb.Append("\tDrive supports DVD+RW DL"); + break; case ProfileNumber.DVDRDLPlus: sb.Append("\tDrive supports DVD+R DL"); + break; case ProfileNumber.BDROM: sb.Append("\tDrive supports BD-ROM"); + break; case ProfileNumber.BDRSeq: sb.Append("\tDrive supports BD-R SRM"); + break; case ProfileNumber.BDRRdm: sb.Append("\tDrive supports BD-R RRM"); + break; case ProfileNumber.BDRE: sb.Append("\tDrive supports BD-RE"); + break; case ProfileNumber.HDDVDROM: sb.Append("\tDrive supports HD DVD-ROM"); + break; case ProfileNumber.HDDVDR: sb.Append("\tDrive supports HD DVD-R"); + break; case ProfileNumber.HDDVDRAM: sb.Append("\tDrive supports HD DVD-RAM"); + break; case ProfileNumber.HDDVDRW: sb.Append("\tDrive supports HD DVD-RW"); + break; case ProfileNumber.HDDVDRDL: sb.Append("\tDrive supports HD DVD-R DL"); + break; case ProfileNumber.HDDVDRWDL: sb.Append("\tDrive supports HD DVD-RW DL"); + break; case ProfileNumber.HDBURNROM: sb.Append("\tDrive supports HDBurn CD-ROM"); + break; case ProfileNumber.HDBURNR: sb.Append("\tDrive supports HDBurn CD-R"); + break; case ProfileNumber.HDBURNRW: sb.Append("\tDrive supports HDBurn CD-RW"); + break; case ProfileNumber.Unconforming: sb.Append("\tDrive is not conforming to any profile"); + break; default: sb.AppendFormat("\tDrive informs of unknown profile 0x{0:X4}", (ushort)prof.Number); + break; } - if(prof.Current) sb.AppendLine(" (current)"); - else sb.AppendLine(); + if(prof.Current) + sb.AppendLine(" (current)"); + else + sb.AppendLine(); } return sb.ToString(); @@ -3984,52 +3188,67 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string Prettify_0001(Feature_0001? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_0001 ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_0001 ftr = feature.Value; + var sb = new StringBuilder(); sb.AppendLine("MMC Core Feature:"); sb.Append("\tDrive uses "); + switch(ftr.PhysicalInterfaceStandard) { case PhysicalInterfaces.Unspecified: sb.AppendLine("an unspecified physical interface"); + break; case PhysicalInterfaces.SCSI: sb.AppendLine("SCSI interface"); + break; case PhysicalInterfaces.ATAPI: sb.AppendLine("ATAPI interface"); + break; case PhysicalInterfaces.IEEE1394: sb.AppendLine("IEEE-1394 interface"); + break; case PhysicalInterfaces.IEEE1394A: sb.AppendLine("IEEE-1394A interface"); + break; case PhysicalInterfaces.FC: sb.AppendLine("Fibre Channel interface"); + break; case PhysicalInterfaces.IEEE1394B: sb.AppendLine("IEEE-1394B interface"); + break; case PhysicalInterfaces.SerialATAPI: sb.AppendLine("Serial ATAPI interface"); + break; case PhysicalInterfaces.USB: sb.AppendLine("USB interface"); + break; case PhysicalInterfaces.Vendor: sb.AppendLine("a vendor unique interface"); + break; default: - sb.AppendFormat("an unknown interface with code {0}", (uint)ftr.PhysicalInterfaceStandard) - .AppendLine(); + sb.AppendFormat("an unknown interface with code {0}", (uint)ftr.PhysicalInterfaceStandard). + AppendLine(); + break; } - if(ftr.DBE) sb.AppendLine("\tDrive supports Device Busy events"); + if(ftr.DBE) + sb.AppendLine("\tDrive supports Device Busy events"); + if(ftr.INQ2) sb.AppendLine("\tDrive supports EVPD, Page Code and 16-bit Allocation Length as described in SPC-3"); @@ -4038,28 +3257,30 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string Prettify_0002(Feature_0002? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_0002 ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_0002 ftr = feature.Value; + var sb = new StringBuilder(); sb.AppendLine("MMC Morphing:"); - sb.AppendLine(ftr.Async - ? "\tDrive supports polling and asynchronous GET EVENT STATUS NOTIFICATION" + sb.AppendLine(ftr.Async ? "\tDrive supports polling and asynchronous GET EVENT STATUS NOTIFICATION" : "\tDrive supports only polling GET EVENT STATUS NOTIFICATION"); - if(ftr.OCEvent) sb.AppendLine("\tDrive supports operational change request / notification class events"); + if(ftr.OCEvent) + sb.AppendLine("\tDrive supports operational change request / notification class events"); return sb.ToString(); } public static string Prettify_0003(Feature_0003? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_0003 ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_0003 ftr = feature.Value; + var sb = new StringBuilder(); sb.AppendLine("MMC Removable Medium:"); @@ -4067,65 +3288,95 @@ namespace DiscImageChef.Decoders.SCSI.MMC { case 0: sb.AppendLine("\tDrive uses media caddy"); + break; case 1: sb.AppendLine("\tDrive uses a tray"); + break; case 2: sb.AppendLine("\tDrive is pop-up"); + break; case 4: sb.AppendLine("\tDrive is a changer with individually changeable discs"); + break; case 5: sb.AppendLine("\tDrive is a changer using cartridges"); + break; default: - sb.AppendFormat("\tDrive uses unknown loading mechanism type {0}", ftr.LoadingMechanismType) - .AppendLine(); + sb.AppendFormat("\tDrive uses unknown loading mechanism type {0}", ftr.LoadingMechanismType). + AppendLine(); + break; } - if(ftr.Lock) sb.AppendLine("\tDrive can lock media"); - if(ftr.PreventJumper) sb.AppendLine("\tDrive power ups locked"); - if(ftr.Eject) sb.AppendLine("\tDrive can eject media"); - if(ftr.Load) sb.AppendLine("\tDrive can load media"); - if(ftr.DBML) sb.AppendLine("\tDrive reports Device Busy Class events during medium loading/unloading"); + if(ftr.Lock) + sb.AppendLine("\tDrive can lock media"); + + if(ftr.PreventJumper) + sb.AppendLine("\tDrive power ups locked"); + + if(ftr.Eject) + sb.AppendLine("\tDrive can eject media"); + + if(ftr.Load) + sb.AppendLine("\tDrive can load media"); + + if(ftr.DBML) + sb.AppendLine("\tDrive reports Device Busy Class events during medium loading/unloading"); return sb.ToString(); } public static string Prettify_0004(Feature_0004? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_0004 ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_0004 ftr = feature.Value; + var sb = new StringBuilder(); sb.AppendLine("MMC Write Protect:"); - if(ftr.DWP) sb.AppendLine("\tDrive supports reading/writing the Disc Write Protect PAC on BD-R/-RE media"); - if(ftr.WDCB) sb.AppendLine("\tDrive supports writing the Write Inhibit DCB on DVD+RW media"); - if(ftr.SPWP) sb.AppendLine("\tDrive supports set/release of PWP status"); - if(ftr.SSWPP) sb.AppendLine("\tDrive supports the SWPP bit of the Timeout and Protect mode page"); + if(ftr.DWP) + sb.AppendLine("\tDrive supports reading/writing the Disc Write Protect PAC on BD-R/-RE media"); + + if(ftr.WDCB) + sb.AppendLine("\tDrive supports writing the Write Inhibit DCB on DVD+RW media"); + + if(ftr.SPWP) + sb.AppendLine("\tDrive supports set/release of PWP status"); + + if(ftr.SSWPP) + sb.AppendLine("\tDrive supports the SWPP bit of the Timeout and Protect mode page"); return sb.ToString(); } public static string Prettify_0010(Feature_0010? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_0010 ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_0010 ftr = feature.Value; + var sb = new StringBuilder(); sb.Append("MMC Random Readable"); - if(ftr.Current) sb.Append(" (current)"); + + if(ftr.Current) + sb.Append(" (current)"); + sb.AppendLine(":"); - if(ftr.PP) sb.AppendLine("\tDrive shall report Read/Write Error Recovery mode page"); + if(ftr.PP) + sb.AppendLine("\tDrive shall report Read/Write Error Recovery mode page"); + if(ftr.LogicalBlockSize > 0) sb.AppendFormat("\t{0} bytes per logical block", ftr.LogicalBlockSize).AppendLine(); + if(ftr.Blocking > 1) sb.AppendFormat("\t{0} logical blocks per media readable unit", ftr.Blocking).AppendLine(); @@ -4133,102 +3384,167 @@ namespace DiscImageChef.Decoders.SCSI.MMC } public static string Prettify_001D(Feature_001D? feature) => - !feature.HasValue - ? null + !feature.HasValue ? null : "Drive claims capability to read all CD formats according to OSTA Multi-Read Specification\n"; public static string Prettify_001E(Feature_001E? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_001E ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_001E ftr = feature.Value; + var sb = new StringBuilder(); sb.Append("MMC CD Read"); - if(ftr.Current) sb.Append(" (current)"); + + if(ftr.Current) + sb.Append(" (current)"); + sb.AppendLine(":"); - if(ftr.DAP) sb.AppendLine("\tDrive supports the DAP bit in the READ CD and READ CD MSF commands"); - if(ftr.C2) sb.AppendLine("\tDrive supports C2 Error Pointers"); - if(ftr.CDText) sb.AppendLine("\tDrive can return CD-Text from Lead-In"); + if(ftr.DAP) + sb.AppendLine("\tDrive supports the DAP bit in the READ CD and READ CD MSF commands"); + + if(ftr.C2) + sb.AppendLine("\tDrive supports C2 Error Pointers"); + + if(ftr.CDText) + sb.AppendLine("\tDrive can return CD-Text from Lead-In"); return sb.ToString(); } public static string Prettify_001F(Feature_001F? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_001F ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_001F ftr = feature.Value; + var sb = new StringBuilder(); sb.Append("MMC DVD Read"); - if(ftr.Current) sb.Append(" (current)"); + + if(ftr.Current) + sb.Append(" (current)"); + sb.AppendLine(":"); sb.AppendLine("\tDrive can read DVD media"); - if(ftr.DualR) sb.AppendLine("\tDrive can read DVD-R DL from all recording modes"); - if(ftr.DualRW) sb.AppendLine("\tDrive can read DVD-RW DL from all recording modes"); - if(ftr.MULTI110) sb.AppendLine("\tDrive conforms to DVD Multi Drive Read-only Specifications"); + if(ftr.DualR) + sb.AppendLine("\tDrive can read DVD-R DL from all recording modes"); + + if(ftr.DualRW) + sb.AppendLine("\tDrive can read DVD-RW DL from all recording modes"); + + if(ftr.MULTI110) + sb.AppendLine("\tDrive conforms to DVD Multi Drive Read-only Specifications"); return sb.ToString(); } public static string Prettify_0020(Feature_0020? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_0020 ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_0020 ftr = feature.Value; + var sb = new StringBuilder(); sb.Append("MMC Random Writable:"); - if(ftr.Current) sb.Append(" (current)"); + + if(ftr.Current) + sb.Append(" (current)"); + sb.AppendLine(":"); - if(ftr.PP) sb.AppendLine("\tDrive shall report Read/Write Error Recovery mode page"); + if(ftr.PP) + sb.AppendLine("\tDrive shall report Read/Write Error Recovery mode page"); + if(ftr.LogicalBlockSize > 0) sb.AppendFormat("\t{0} bytes per logical block", ftr.LogicalBlockSize).AppendLine(); + if(ftr.Blocking > 1) sb.AppendFormat("\t{0} logical blocks per media writable unit", ftr.Blocking).AppendLine(); - if(ftr.LastLBA > 0) sb.AppendFormat("\tLast adressable logical block is {0}", ftr.LastLBA).AppendLine(); + + if(ftr.LastLBA > 0) + sb.AppendFormat("\tLast adressable logical block is {0}", ftr.LastLBA).AppendLine(); return sb.ToString(); } public static string Prettify_0021(Feature_0021? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_0021 ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_0021 ftr = feature.Value; + var sb = new StringBuilder(); sb.AppendLine("MMC Incremental Streaming Writable:"); if(ftr.DataTypeSupported > 0) { sb.Append("\tDrive supports data block types:"); - if((ftr.DataTypeSupported & 0x0001) == 0x0001) sb.Append(" 0"); - if((ftr.DataTypeSupported & 0x0002) == 0x0002) sb.Append(" 1"); - if((ftr.DataTypeSupported & 0x0004) == 0x0004) sb.Append(" 2"); - if((ftr.DataTypeSupported & 0x0008) == 0x0008) sb.Append(" 3"); - if((ftr.DataTypeSupported & 0x0010) == 0x0010) sb.Append(" 4"); - if((ftr.DataTypeSupported & 0x0020) == 0x0020) sb.Append(" 5"); - if((ftr.DataTypeSupported & 0x0040) == 0x0040) sb.Append(" 6"); - if((ftr.DataTypeSupported & 0x0080) == 0x0080) sb.Append(" 7"); - if((ftr.DataTypeSupported & 0x0100) == 0x0100) sb.Append(" 8"); - if((ftr.DataTypeSupported & 0x0200) == 0x0200) sb.Append(" 9"); - if((ftr.DataTypeSupported & 0x0400) == 0x0400) sb.Append(" 10"); - if((ftr.DataTypeSupported & 0x0800) == 0x0800) sb.Append(" 11"); - if((ftr.DataTypeSupported & 0x1000) == 0x1000) sb.Append(" 12"); - if((ftr.DataTypeSupported & 0x2000) == 0x2000) sb.Append(" 13"); - if((ftr.DataTypeSupported & 0x4000) == 0x4000) sb.Append(" 14"); - if((ftr.DataTypeSupported & 0x8000) == 0x8000) sb.Append(" 15"); + + if((ftr.DataTypeSupported & 0x0001) == 0x0001) + sb.Append(" 0"); + + if((ftr.DataTypeSupported & 0x0002) == 0x0002) + sb.Append(" 1"); + + if((ftr.DataTypeSupported & 0x0004) == 0x0004) + sb.Append(" 2"); + + if((ftr.DataTypeSupported & 0x0008) == 0x0008) + sb.Append(" 3"); + + if((ftr.DataTypeSupported & 0x0010) == 0x0010) + sb.Append(" 4"); + + if((ftr.DataTypeSupported & 0x0020) == 0x0020) + sb.Append(" 5"); + + if((ftr.DataTypeSupported & 0x0040) == 0x0040) + sb.Append(" 6"); + + if((ftr.DataTypeSupported & 0x0080) == 0x0080) + sb.Append(" 7"); + + if((ftr.DataTypeSupported & 0x0100) == 0x0100) + sb.Append(" 8"); + + if((ftr.DataTypeSupported & 0x0200) == 0x0200) + sb.Append(" 9"); + + if((ftr.DataTypeSupported & 0x0400) == 0x0400) + sb.Append(" 10"); + + if((ftr.DataTypeSupported & 0x0800) == 0x0800) + sb.Append(" 11"); + + if((ftr.DataTypeSupported & 0x1000) == 0x1000) + sb.Append(" 12"); + + if((ftr.DataTypeSupported & 0x2000) == 0x2000) + sb.Append(" 13"); + + if((ftr.DataTypeSupported & 0x4000) == 0x4000) + sb.Append(" 14"); + + if((ftr.DataTypeSupported & 0x8000) == 0x8000) + sb.Append(" 15"); + sb.AppendLine(); } - if(ftr.TRIO) sb.AppendLine("\tDrive claims support to report Track Resources Information"); - if(ftr.ARSV) sb.AppendLine("\tDrive supports address mode reservation on the RESERVE TRACK command"); - if(ftr.BUF) sb.AppendLine("\tDrive is capable of zero loss linking"); + if(ftr.TRIO) + sb.AppendLine("\tDrive claims support to report Track Resources Information"); + + if(ftr.ARSV) + sb.AppendLine("\tDrive supports address mode reservation on the RESERVE TRACK command"); + + if(ftr.BUF) + sb.AppendLine("\tDrive is capable of zero loss linking"); return sb.ToString(); } @@ -4238,52 +3554,74 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string Prettify_0023(Feature_0023? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_0023 ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_0023 ftr = feature.Value; + var sb = new StringBuilder(); sb.AppendLine("MMC Formattable:"); sb.AppendLine("\tDrive can format media into logical blocks"); - if(ftr.RENoSA) sb.AppendLine("\tDrive can format BD-RE with no spares allocated"); - if(ftr.Expand) sb.AppendLine("\tDrive can expand the spare area on a formatted BD-RE disc"); - if(ftr.QCert) sb.AppendLine("\tDrive can format BD-RE discs with quick certification"); - if(ftr.Cert) sb.AppendLine("\tDrive can format BD-RE discs with full certification"); - if(ftr.FRF) sb.AppendLine("\tDrive can fast re-format BD-RE discs"); - if(ftr.RRM) sb.AppendLine("\tDrive can format BD-R discs with RRM format"); + if(ftr.RENoSA) + sb.AppendLine("\tDrive can format BD-RE with no spares allocated"); + + if(ftr.Expand) + sb.AppendLine("\tDrive can expand the spare area on a formatted BD-RE disc"); + + if(ftr.QCert) + sb.AppendLine("\tDrive can format BD-RE discs with quick certification"); + + if(ftr.Cert) + sb.AppendLine("\tDrive can format BD-RE discs with full certification"); + + if(ftr.FRF) + sb.AppendLine("\tDrive can fast re-format BD-RE discs"); + + if(ftr.RRM) + sb.AppendLine("\tDrive can format BD-R discs with RRM format"); return sb.ToString(); } public static string Prettify_0024(Feature_0024? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_0024 ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_0024 ftr = feature.Value; + var sb = new StringBuilder(); sb.AppendLine("MMC Hardware Defect Management:"); sb.AppendLine("\tDrive shall be able to provide a defect-free contiguous address space"); - if(ftr.SSA) sb.AppendLine("\tDrive can return Spare Area Information"); + + if(ftr.SSA) + sb.AppendLine("\tDrive can return Spare Area Information"); return sb.ToString(); } public static string Prettify_0025(Feature_0025? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_0025 ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_0025 ftr = feature.Value; + var sb = new StringBuilder(); sb.Append("MMC Write Once"); - if(ftr.Current) sb.Append(" (current)"); + + if(ftr.Current) + sb.Append(" (current)"); + sb.AppendLine(":"); - if(ftr.PP) sb.AppendLine("\tDrive shall report Read/Write Error Recovery mode page"); + if(ftr.PP) + sb.AppendLine("\tDrive shall report Read/Write Error Recovery mode page"); + if(ftr.LogicalBlockSize > 0) sb.AppendFormat("\t{0} bytes per logical block", ftr.LogicalBlockSize).AppendLine(); + if(ftr.Blocking > 1) sb.AppendFormat("\t{0} logical blocks per media writable unit", ftr.Blocking).AppendLine(); @@ -4291,50 +3629,67 @@ namespace DiscImageChef.Decoders.SCSI.MMC } public static string Prettify_0026(Feature_0026? feature) => - !feature.HasValue - ? null + !feature.HasValue ? null : "Drive shall have the ability to overwrite logical blocks only in fixed sets at a time\n"; public static string Prettify_0027(Feature_0027? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_0027 ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_0027 ftr = feature.Value; + var sb = new StringBuilder(); sb.Append("Drive can write High-Speed CD-RW"); - if(ftr.Current) sb.AppendLine(" (current)"); - else sb.AppendLine(); + + if(ftr.Current) + sb.AppendLine(" (current)"); + else + sb.AppendLine(); return sb.ToString(); } public static string Prettify_0028(Feature_0028? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_0028 ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_0028 ftr = feature.Value; + var sb = new StringBuilder(); - if(ftr.Write && ftr.DVDPRead && ftr.DVDPWrite) sb.Append("Drive can read and write CD-MRW and DVD+MRW"); - else if(ftr.DVDPRead && ftr.DVDPWrite) sb.Append("Drive can read and write DVD+MRW"); - else if(ftr.Write && ftr.DVDPRead) sb.Append("Drive and read DVD+MRW and read and write CD-MRW"); - else if(ftr.Write) sb.Append("Drive can read and write CD-MRW"); - else if(ftr.DVDPRead) sb.Append("Drive can read CD-MRW and DVD+MRW"); - else sb.Append("Drive can read CD-MRW"); + if(ftr.Write && + ftr.DVDPRead && + ftr.DVDPWrite) + sb.Append("Drive can read and write CD-MRW and DVD+MRW"); + else if(ftr.DVDPRead && + ftr.DVDPWrite) + sb.Append("Drive can read and write DVD+MRW"); + else if(ftr.Write && + ftr.DVDPRead) + sb.Append("Drive and read DVD+MRW and read and write CD-MRW"); + else if(ftr.Write) + sb.Append("Drive can read and write CD-MRW"); + else if(ftr.DVDPRead) + sb.Append("Drive can read CD-MRW and DVD+MRW"); + else + sb.Append("Drive can read CD-MRW"); - if(ftr.Current) sb.AppendLine(" (current)"); - else sb.AppendLine(); + if(ftr.Current) + sb.AppendLine(" (current)"); + else + sb.AppendLine(); return sb.ToString(); } public static string Prettify_0029(Feature_0029? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_0029 ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_0029 ftr = feature.Value; + var sb = new StringBuilder(); sb.AppendLine("MMC Enhanced Defect Reporting Feature:"); @@ -4342,33 +3697,44 @@ namespace DiscImageChef.Decoders.SCSI.MMC if(ftr.DBICacheZones > 0) sb.AppendFormat("\tDrive has {0} DBI cache zones", ftr.DBICacheZones).AppendLine(); - if(ftr.Entries > 0) sb.AppendFormat("\tDrive has {0} DBI entries", ftr.Entries).AppendLine(); + + if(ftr.Entries > 0) + sb.AppendFormat("\tDrive has {0} DBI entries", ftr.Entries).AppendLine(); return sb.ToString(); } public static string Prettify_002A(Feature_002A? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_002A ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_002A ftr = feature.Value; + var sb = new StringBuilder(); if(ftr.Write) { sb.Append("Drive can read and write DVD+RW"); - if(ftr.Current) sb.AppendLine(" (current)"); - else sb.AppendLine(); - sb.AppendLine(ftr.CloseOnly - ? "\tDrive supports only the read compatibility stop" + + if(ftr.Current) + sb.AppendLine(" (current)"); + else + sb.AppendLine(); + + sb.AppendLine(ftr.CloseOnly ? "\tDrive supports only the read compatibility stop" : "\tDrive supports both forms of background format stopping"); - if(ftr.QuickStart) sb.AppendLine("\tDrive can do a quick start formatting"); + + if(ftr.QuickStart) + sb.AppendLine("\tDrive can do a quick start formatting"); } else { sb.Append("Drive can read DVD+RW"); - if(ftr.Current) sb.AppendLine(" (current)"); - else sb.AppendLine(); + + if(ftr.Current) + sb.AppendLine(" (current)"); + else + sb.AppendLine(); } return sb.ToString(); @@ -4376,22 +3742,29 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string Prettify_002B(Feature_002B? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_002B ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_002B ftr = feature.Value; + var sb = new StringBuilder(); if(ftr.Write) { sb.Append("Drive can read and write DVD+R"); - if(ftr.Current) sb.AppendLine(" (current)"); - else sb.AppendLine(); + + if(ftr.Current) + sb.AppendLine(" (current)"); + else + sb.AppendLine(); } else { sb.Append("Drive can read DVD+R"); - if(ftr.Current) sb.AppendLine(" (current)"); - else sb.AppendLine(); + + if(ftr.Current) + sb.AppendLine(" (current)"); + else + sb.AppendLine(); } return sb.ToString(); @@ -4399,62 +3772,113 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string Prettify_002C(Feature_002C? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_002C ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_002C ftr = feature.Value; + var sb = new StringBuilder(); sb.Append("MMC Rigid Restricted Overwrite"); sb.AppendLine(ftr.Current ? " (current):" : ":"); - if(ftr.Blank) sb.AppendLine("\tDrive supports the BLANK command"); + if(ftr.Blank) + sb.AppendLine("\tDrive supports the BLANK command"); + if(ftr.Intermediate) sb.AppendLine("\tDrive supports writing on an intermediate state session and quick formatting"); - if(ftr.DSDR) sb.AppendLine("\tDrive can read Defect Status data recorded on the medium"); - if(ftr.DSDG) sb.AppendLine("\tDrive can generate Defect Status data during formatting"); + + if(ftr.DSDR) + sb.AppendLine("\tDrive can read Defect Status data recorded on the medium"); + + if(ftr.DSDG) + sb.AppendLine("\tDrive can generate Defect Status data during formatting"); return sb.ToString(); } public static string Prettify_002D(Feature_002D? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_002D ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_002D ftr = feature.Value; + var sb = new StringBuilder(); sb.AppendLine("Drive can write CDs in Track at Once Mode:"); if(ftr.RWSubchannel) { sb.AppendLine("\tDrive can write user provided data in the R-W subchannels"); - if(ftr.RWRaw) sb.AppendLine("\tDrive accepts RAW R-W subchannel data"); - if(ftr.RWPack) sb.AppendLine("\tDrive accepts Packed R-W subchannel data"); + + if(ftr.RWRaw) + sb.AppendLine("\tDrive accepts RAW R-W subchannel data"); + + if(ftr.RWPack) + sb.AppendLine("\tDrive accepts Packed R-W subchannel data"); } - if(ftr.CDRW) sb.AppendLine("\tDrive can overwrite a TAO track with another in CD-RWs"); - if(ftr.TestWrite) sb.AppendLine("\tDrive can do a test writing"); - if(ftr.BUF) sb.AppendLine("\tDrive supports zero loss linking"); + if(ftr.CDRW) + sb.AppendLine("\tDrive can overwrite a TAO track with another in CD-RWs"); - if(ftr.DataTypeSupported <= 0) return sb.ToString(); + if(ftr.TestWrite) + sb.AppendLine("\tDrive can do a test writing"); + + if(ftr.BUF) + sb.AppendLine("\tDrive supports zero loss linking"); + + if(ftr.DataTypeSupported <= 0) + return sb.ToString(); sb.Append("\tDrive supports data block types:"); - if((ftr.DataTypeSupported & 0x0001) == 0x0001) sb.Append(" 0"); - if((ftr.DataTypeSupported & 0x0002) == 0x0002) sb.Append(" 1"); - if((ftr.DataTypeSupported & 0x0004) == 0x0004) sb.Append(" 2"); - if((ftr.DataTypeSupported & 0x0008) == 0x0008) sb.Append(" 3"); - if((ftr.DataTypeSupported & 0x0010) == 0x0010) sb.Append(" 4"); - if((ftr.DataTypeSupported & 0x0020) == 0x0020) sb.Append(" 5"); - if((ftr.DataTypeSupported & 0x0040) == 0x0040) sb.Append(" 6"); - if((ftr.DataTypeSupported & 0x0080) == 0x0080) sb.Append(" 7"); - if((ftr.DataTypeSupported & 0x0100) == 0x0100) sb.Append(" 8"); - if((ftr.DataTypeSupported & 0x0200) == 0x0200) sb.Append(" 9"); - if((ftr.DataTypeSupported & 0x0400) == 0x0400) sb.Append(" 10"); - if((ftr.DataTypeSupported & 0x0800) == 0x0800) sb.Append(" 11"); - if((ftr.DataTypeSupported & 0x1000) == 0x1000) sb.Append(" 12"); - if((ftr.DataTypeSupported & 0x2000) == 0x2000) sb.Append(" 13"); - if((ftr.DataTypeSupported & 0x4000) == 0x4000) sb.Append(" 14"); - if((ftr.DataTypeSupported & 0x8000) == 0x8000) sb.Append(" 15"); + + if((ftr.DataTypeSupported & 0x0001) == 0x0001) + sb.Append(" 0"); + + if((ftr.DataTypeSupported & 0x0002) == 0x0002) + sb.Append(" 1"); + + if((ftr.DataTypeSupported & 0x0004) == 0x0004) + sb.Append(" 2"); + + if((ftr.DataTypeSupported & 0x0008) == 0x0008) + sb.Append(" 3"); + + if((ftr.DataTypeSupported & 0x0010) == 0x0010) + sb.Append(" 4"); + + if((ftr.DataTypeSupported & 0x0020) == 0x0020) + sb.Append(" 5"); + + if((ftr.DataTypeSupported & 0x0040) == 0x0040) + sb.Append(" 6"); + + if((ftr.DataTypeSupported & 0x0080) == 0x0080) + sb.Append(" 7"); + + if((ftr.DataTypeSupported & 0x0100) == 0x0100) + sb.Append(" 8"); + + if((ftr.DataTypeSupported & 0x0200) == 0x0200) + sb.Append(" 9"); + + if((ftr.DataTypeSupported & 0x0400) == 0x0400) + sb.Append(" 10"); + + if((ftr.DataTypeSupported & 0x0800) == 0x0800) + sb.Append(" 11"); + + if((ftr.DataTypeSupported & 0x1000) == 0x1000) + sb.Append(" 12"); + + if((ftr.DataTypeSupported & 0x2000) == 0x2000) + sb.Append(" 13"); + + if((ftr.DataTypeSupported & 0x4000) == 0x4000) + sb.Append(" 14"); + + if((ftr.DataTypeSupported & 0x8000) == 0x8000) + sb.Append(" 15"); + sb.AppendLine(); return sb.ToString(); @@ -4462,44 +3886,67 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string Prettify_002E(Feature_002E? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_002E ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_002E ftr = feature.Value; + var sb = new StringBuilder(); - if(ftr.SAO && !ftr.RAW) sb.AppendLine("Drive can write CDs in Session at Once Mode:"); - else if(!ftr.SAO && ftr.RAW) sb.AppendLine("Drive can write CDs in raw Mode:"); - else sb.AppendLine("Drive can write CDs in Session at Once and in Raw Modes:"); + if(ftr.SAO && + !ftr.RAW) + sb.AppendLine("Drive can write CDs in Session at Once Mode:"); + else if(!ftr.SAO && + ftr.RAW) + sb.AppendLine("Drive can write CDs in raw Mode:"); + else + sb.AppendLine("Drive can write CDs in Session at Once and in Raw Modes:"); - if(ftr.RAW && ftr.RAWMS) sb.AppendLine("\tDrive can write multi-session CDs in raw mode"); + if(ftr.RAW && + ftr.RAWMS) + sb.AppendLine("\tDrive can write multi-session CDs in raw mode"); - if(ftr.RW) sb.AppendLine("\tDrive can write user provided data in the R-W subchannels"); + if(ftr.RW) + sb.AppendLine("\tDrive can write user provided data in the R-W subchannels"); - if(ftr.CDRW) sb.AppendLine("\tDrive can write CD-RWs"); - if(ftr.TestWrite) sb.AppendLine("\tDrive can do a test writing"); - if(ftr.BUF) sb.AppendLine("\tDrive supports zero loss linking"); + if(ftr.CDRW) + sb.AppendLine("\tDrive can write CD-RWs"); + + if(ftr.TestWrite) + sb.AppendLine("\tDrive can do a test writing"); + + if(ftr.BUF) + sb.AppendLine("\tDrive supports zero loss linking"); if(ftr.MaxCueSheet > 0) - sb.AppendFormat("\tDrive supports a maximum of {0} bytes in a single cue sheet", ftr.MaxCueSheet) - .AppendLine(); + sb.AppendFormat("\tDrive supports a maximum of {0} bytes in a single cue sheet", ftr.MaxCueSheet). + AppendLine(); return sb.ToString(); } public static string Prettify_002F(Feature_002F? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_002F ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_002F ftr = feature.Value; + var sb = new StringBuilder(); - if(ftr.DVDRW && ftr.RDL) sb.AppendLine("Drive supports writing DVD-R, DVD-RW and DVD-R DL"); - else if(ftr.RDL) sb.AppendLine("Drive supports writing DVD-R and DVD-R DL"); - else if(ftr.DVDRW) sb.AppendLine("Drive supports writing DVD-R and DVD-RW"); - else sb.AppendLine("Drive supports writing DVD-R"); + if(ftr.DVDRW && + ftr.RDL) + sb.AppendLine("Drive supports writing DVD-R, DVD-RW and DVD-R DL"); + else if(ftr.RDL) + sb.AppendLine("Drive supports writing DVD-R and DVD-R DL"); + else if(ftr.DVDRW) + sb.AppendLine("Drive supports writing DVD-R and DVD-RW"); + else + sb.AppendLine("Drive supports writing DVD-R"); - if(ftr.TestWrite) sb.AppendLine("\tDrive can do a test writing"); - if(ftr.BUF) sb.AppendLine("\tDrive supports zero loss linking"); + if(ftr.TestWrite) + sb.AppendLine("\tDrive can do a test writing"); + + if(ftr.BUF) + sb.AppendLine("\tDrive supports zero loss linking"); return sb.ToString(); } @@ -4509,43 +3956,51 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string Prettify_0031(Feature_0031? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_0031 ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_0031 ftr = feature.Value; + var sb = new StringBuilder(); sb.AppendLine("Drive supports writing DDCD-R"); - if(ftr.TestWrite) sb.AppendLine("\tDrive can do a test writing"); + if(ftr.TestWrite) + sb.AppendLine("\tDrive can do a test writing"); return sb.ToString(); } public static string Prettify_0032(Feature_0032? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_0032 ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_0032 ftr = feature.Value; + var sb = new StringBuilder(); sb.AppendLine("Drive supports writing DDCD-RW"); - if(ftr.Blank) sb.AppendLine("\tDrive supports the BLANK command"); - if(ftr.Intermediate) sb.AppendLine("\tDrive supports quick formatting"); + if(ftr.Blank) + sb.AppendLine("\tDrive supports the BLANK command"); + + if(ftr.Intermediate) + sb.AppendLine("\tDrive supports quick formatting"); return sb.ToString(); } public static string Prettify_0033(Feature_0033? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_0033 ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_0033 ftr = feature.Value; + var sb = new StringBuilder(); sb.AppendLine("MMC Layer Jump Recording:"); - if(ftr.LinkSizes == null) return sb.ToString(); + if(ftr.LinkSizes == null) + return sb.ToString(); foreach(byte link in ftr.LinkSizes) sb.AppendFormat("\tCurrent media has a {0} bytes link available", link).AppendLine(); @@ -4558,23 +4013,43 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string Prettify_0037(Feature_0037? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_0037 ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_0037 ftr = feature.Value; + var sb = new StringBuilder(); sb.AppendLine("Drive can write CD-RW"); - if(ftr.SubtypeSupport <= 0) return sb.ToString(); + + if(ftr.SubtypeSupport <= 0) + return sb.ToString(); sb.Append("\tDrive supports CD-RW subtypes"); - if((ftr.SubtypeSupport & 0x01) == 0x01) sb.Append(" 0"); - if((ftr.SubtypeSupport & 0x02) == 0x02) sb.Append(" 1"); - if((ftr.SubtypeSupport & 0x04) == 0x04) sb.Append(" 2"); - if((ftr.SubtypeSupport & 0x08) == 0x08) sb.Append(" 3"); - if((ftr.SubtypeSupport & 0x10) == 0x10) sb.Append(" 4"); - if((ftr.SubtypeSupport & 0x20) == 0x20) sb.Append(" 5"); - if((ftr.SubtypeSupport & 0x40) == 0x40) sb.Append(" 6"); - if((ftr.SubtypeSupport & 0x80) == 0x80) sb.Append(" 7"); + + if((ftr.SubtypeSupport & 0x01) == 0x01) + sb.Append(" 0"); + + if((ftr.SubtypeSupport & 0x02) == 0x02) + sb.Append(" 1"); + + if((ftr.SubtypeSupport & 0x04) == 0x04) + sb.Append(" 2"); + + if((ftr.SubtypeSupport & 0x08) == 0x08) + sb.Append(" 3"); + + if((ftr.SubtypeSupport & 0x10) == 0x10) + sb.Append(" 4"); + + if((ftr.SubtypeSupport & 0x20) == 0x20) + sb.Append(" 5"); + + if((ftr.SubtypeSupport & 0x40) == 0x40) + sb.Append(" 6"); + + if((ftr.SubtypeSupport & 0x80) == 0x80) + sb.Append(" 7"); + sb.AppendLine(); return sb.ToString(); @@ -4585,26 +4060,35 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string Prettify_003A(Feature_003A? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_003A ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_003A ftr = feature.Value; + var sb = new StringBuilder(); if(ftr.Write) { sb.Append("Drive can read and write DVD+RW DL"); - if(ftr.Current) sb.AppendLine(" (current)"); - else sb.AppendLine(); - sb.AppendLine(ftr.CloseOnly - ? "\tDrive supports only the read compatibility stop" + + if(ftr.Current) + sb.AppendLine(" (current)"); + else + sb.AppendLine(); + + sb.AppendLine(ftr.CloseOnly ? "\tDrive supports only the read compatibility stop" : "\tDrive supports both forms of background format stopping"); - if(ftr.QuickStart) sb.AppendLine("\tDrive can do a quick start formatting"); + + if(ftr.QuickStart) + sb.AppendLine("\tDrive can do a quick start formatting"); } else { sb.Append("Drive can read DVD+RW DL"); - if(ftr.Current) sb.AppendLine(" (current)"); - else sb.AppendLine(); + + if(ftr.Current) + sb.AppendLine(" (current)"); + else + sb.AppendLine(); } return sb.ToString(); @@ -4612,22 +4096,29 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string Prettify_003B(Feature_003B? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_003B ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_003B ftr = feature.Value; + var sb = new StringBuilder(); if(ftr.Write) { sb.Append("Drive can read and write DVD+R DL"); - if(ftr.Current) sb.AppendLine(" (current)"); - else sb.AppendLine(); + + if(ftr.Current) + sb.AppendLine(" (current)"); + else + sb.AppendLine(); } else { sb.Append("Drive can read DVD+R DL"); - if(ftr.Current) sb.AppendLine(" (current)"); - else sb.AppendLine(); + + if(ftr.Current) + sb.AppendLine(" (current)"); + else + sb.AppendLine(); } return sb.ToString(); @@ -4635,99 +4126,144 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string Prettify_0040(Feature_0040? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_0040 ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_0040 ftr = feature.Value; + var sb = new StringBuilder(); sb.Append("MMC BD Read"); sb.AppendLine(ftr.Current ? " (current):" : ":"); - if(ftr.OldROM) sb.AppendLine("\tDrive can read BD-ROM pre-1.0"); - if(ftr.ROM) sb.AppendLine("\tDrive can read BD-ROM Ver.1"); - if(ftr.OldR) sb.AppendLine("\tDrive can read BD-R pre-1.0"); - if(ftr.R) sb.AppendLine("\tDrive can read BD-R Ver.1"); - if(ftr.OldRE) sb.AppendLine("\tDrive can read BD-RE pre-1.0"); - if(ftr.RE1) sb.AppendLine("\tDrive can read BD-RE Ver.1"); - if(ftr.RE2) sb.AppendLine("\tDrive can read BD-RE Ver.2"); + if(ftr.OldROM) + sb.AppendLine("\tDrive can read BD-ROM pre-1.0"); - if(ftr.BCA) sb.AppendLine("\tDrive can read BD's Burst Cutting Area"); + if(ftr.ROM) + sb.AppendLine("\tDrive can read BD-ROM Ver.1"); + + if(ftr.OldR) + sb.AppendLine("\tDrive can read BD-R pre-1.0"); + + if(ftr.R) + sb.AppendLine("\tDrive can read BD-R Ver.1"); + + if(ftr.OldRE) + sb.AppendLine("\tDrive can read BD-RE pre-1.0"); + + if(ftr.RE1) + sb.AppendLine("\tDrive can read BD-RE Ver.1"); + + if(ftr.RE2) + sb.AppendLine("\tDrive can read BD-RE Ver.2"); + + if(ftr.BCA) + sb.AppendLine("\tDrive can read BD's Burst Cutting Area"); return sb.ToString(); } public static string Prettify_0041(Feature_0041? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_0041 ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_0041 ftr = feature.Value; + var sb = new StringBuilder(); sb.Append("MMC BD Write"); sb.AppendLine(ftr.Current ? " (current):" : ":"); - if(ftr.OldR) sb.AppendLine("\tDrive can write BD-R pre-1.0"); - if(ftr.R) sb.AppendLine("\tDrive can write BD-R Ver.1"); - if(ftr.OldRE) sb.AppendLine("\tDrive can write BD-RE pre-1.0"); - if(ftr.RE1) sb.AppendLine("\tDrive can write BD-RE Ver.1"); - if(ftr.RE2) sb.AppendLine("\tDrive can write BD-RE Ver.2"); + if(ftr.OldR) + sb.AppendLine("\tDrive can write BD-R pre-1.0"); - if(ftr.SVNR) sb.AppendLine("\tDrive supports write without verify requirement"); + if(ftr.R) + sb.AppendLine("\tDrive can write BD-R Ver.1"); + + if(ftr.OldRE) + sb.AppendLine("\tDrive can write BD-RE pre-1.0"); + + if(ftr.RE1) + sb.AppendLine("\tDrive can write BD-RE Ver.1"); + + if(ftr.RE2) + sb.AppendLine("\tDrive can write BD-RE Ver.2"); + + if(ftr.SVNR) + sb.AppendLine("\tDrive supports write without verify requirement"); return sb.ToString(); } public static string Prettify_0042(Feature_0042? feature) => - !feature.HasValue - ? null + !feature.HasValue ? null : "Drive is able to detect and report defective writable unit and behave accordinly\n"; public static string Prettify_0050(Feature_0050? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_0050 ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_0050 ftr = feature.Value; + var sb = new StringBuilder(); - if(ftr.HDDVDR && ftr.HDDVDRAM) sb.Append("Drive can read HD DVD-ROM, HD DVD-RW, HD DVD-R and HD DVD-RAM"); - else if(ftr.HDDVDR) sb.Append("Drive can read HD DVD-ROM, HD DVD-RW and HD DVD-R"); - else if(ftr.HDDVDRAM) sb.Append("Drive can read HD DVD-ROM, HD DVD-RW and HD DVD-RAM"); - else sb.Append("Drive can read HD DVD-ROM and HD DVD-RW"); + if(ftr.HDDVDR && + ftr.HDDVDRAM) + sb.Append("Drive can read HD DVD-ROM, HD DVD-RW, HD DVD-R and HD DVD-RAM"); + else if(ftr.HDDVDR) + sb.Append("Drive can read HD DVD-ROM, HD DVD-RW and HD DVD-R"); + else if(ftr.HDDVDRAM) + sb.Append("Drive can read HD DVD-ROM, HD DVD-RW and HD DVD-RAM"); + else + sb.Append("Drive can read HD DVD-ROM and HD DVD-RW"); - if(ftr.Current) sb.AppendLine(" (current)"); - else sb.AppendLine(); + if(ftr.Current) + sb.AppendLine(" (current)"); + else + sb.AppendLine(); return sb.ToString(); } public static string Prettify_0051(Feature_0051? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_0051 ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_0051 ftr = feature.Value; + var sb = new StringBuilder(); - if(ftr.HDDVDR && ftr.HDDVDRAM) sb.Append("Drive can write HD DVD-RW, HD DVD-R and HD DVD-RAM"); - else if(ftr.HDDVDR) sb.Append("Drive can write HD DVD-RW and HD DVD-R"); - else if(ftr.HDDVDRAM) sb.Append("Drive can write HD DVD-RW and HD DVD-RAM"); - else sb.Append("Drive can write HD DVD-RW"); + if(ftr.HDDVDR && + ftr.HDDVDRAM) + sb.Append("Drive can write HD DVD-RW, HD DVD-R and HD DVD-RAM"); + else if(ftr.HDDVDR) + sb.Append("Drive can write HD DVD-RW and HD DVD-R"); + else if(ftr.HDDVDRAM) + sb.Append("Drive can write HD DVD-RW and HD DVD-RAM"); + else + sb.Append("Drive can write HD DVD-RW"); - if(ftr.Current) sb.AppendLine(" (current)"); - else sb.AppendLine(); + if(ftr.Current) + sb.AppendLine(" (current)"); + else + sb.AppendLine(); return sb.ToString(); } public static string Prettify_0080(Feature_0080? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_0080 ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_0080 ftr = feature.Value; + var sb = new StringBuilder(); sb.Append("Drive is able to access Hybrid discs"); - if(ftr.Current) sb.AppendLine(" (current)"); - else sb.AppendLine(); + + if(ftr.Current) + sb.AppendLine(" (current)"); + else + sb.AppendLine(); if(ftr.RI) sb.AppendLine("\tDrive is able to maintain the online format layer through reset and power cycling"); @@ -4740,28 +4276,35 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string Prettify_0101(Feature_0101? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_0101 ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_0101 ftr = feature.Value; + var sb = new StringBuilder(); sb.AppendLine("Drive supports S.M.A.R.T."); - if(ftr.PP) sb.AppendLine("\tDrive supports the Informational Exceptions Control mode page 1Ch"); + + if(ftr.PP) + sb.AppendLine("\tDrive supports the Informational Exceptions Control mode page 1Ch"); return sb.ToString(); } public static string Prettify_0102(Feature_0102? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_0102 ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_0102 ftr = feature.Value; + var sb = new StringBuilder(); sb.AppendLine("MMC Embedded Changer:"); - if(ftr.SCC) sb.AppendLine("\tDrive can change disc side"); - if(ftr.SDP) sb.AppendLine("\tDrive is able to report slots contents after a reset or change"); + if(ftr.SCC) + sb.AppendLine("\tDrive can change disc side"); + + if(ftr.SDP) + sb.AppendLine("\tDrive is able to report slots contents after a reset or change"); sb.AppendFormat("\tDrive has {0} slots", ftr.HighestSlotNumber + 1).AppendLine(); @@ -4770,16 +4313,22 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string Prettify_0103(Feature_0103? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_0103 ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_0103 ftr = feature.Value; + var sb = new StringBuilder(); sb.AppendLine("Drive has an analogue audio output"); - if(ftr.Scan) sb.AppendLine("\tDrive supports the SCAN command"); - if(ftr.SCM) sb.AppendLine("\tDrive is able to mute channels separately"); - if(ftr.SV) sb.AppendLine("\tDrive supports separate volume per channel"); + if(ftr.Scan) + sb.AppendLine("\tDrive supports the SCAN command"); + + if(ftr.SCM) + sb.AppendLine("\tDrive is able to mute channels separately"); + + if(ftr.SV) + sb.AppendLine("\tDrive supports separate volume per channel"); sb.AppendFormat("\tDrive has {0} volume levels", ftr.VolumeLevels + 1).AppendLine(); @@ -4788,12 +4337,14 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string Prettify_0104(Feature_0104? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_0104 ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_0104 ftr = feature.Value; + var sb = new StringBuilder(); sb.AppendLine("Drive supports Microcode Upgrade"); + if(ftr.M5) sb.AppendLine("Drive supports validating the 5-bit Mode of the READ BUFFER and WRITE BUFFER commands"); @@ -4802,16 +4353,19 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string Prettify_0105(Feature_0105? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_0105 ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_0105 ftr = feature.Value; + var sb = new StringBuilder(); sb.AppendLine("Drive supports Timeout & Protect mode page 1Dh"); - if(!ftr.Group3) return sb.ToString(); + if(!ftr.Group3) + return sb.ToString(); sb.AppendLine("\tDrive supports the Group3 in Timeout & Protect mode page 1Dh"); + if(ftr.UnitLength > 0) sb.AppendFormat("\tDrive has {0} increase of Group 3 time unit", ftr.UnitLength).AppendLine(); @@ -4820,45 +4374,60 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string Prettify_0106(Feature_0106? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_0106 ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_0106 ftr = feature.Value; + var sb = new StringBuilder(); sb.AppendFormat("Drive supports DVD CSS/CPPM version {0}", ftr.CSSVersion); - if(ftr.Current) sb.AppendLine(" and current disc is encrypted"); - else sb.AppendLine(); + + if(ftr.Current) + sb.AppendLine(" and current disc is encrypted"); + else + sb.AppendLine(); return sb.ToString(); } public static string Prettify_0107(Feature_0107? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_0107 ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_0107 ftr = feature.Value; + var sb = new StringBuilder(); sb.AppendLine("MMC Real Time Streaming:"); - if(ftr.SMP) sb.AppendLine("\tDrive supports Set Minimum Performance with the SET STREAMING command"); - if(ftr.RBCB) sb.AppendLine("\tDrive supports the block bit in the READ BUFFER CAPACITY command"); - if(ftr.SCS) sb.AppendLine("\tDrive supports the SET CD SPEED command"); + if(ftr.SMP) + sb.AppendLine("\tDrive supports Set Minimum Performance with the SET STREAMING command"); + + if(ftr.RBCB) + sb.AppendLine("\tDrive supports the block bit in the READ BUFFER CAPACITY command"); + + if(ftr.SCS) + sb.AppendLine("\tDrive supports the SET CD SPEED command"); + if(ftr.MP2A) sb.AppendLine("\tDrive supports the Write Speed Performance Descriptor Blocks in the MMC mode page 2Ah"); + if(ftr.WSPD) sb.AppendLine("\tDrive supports the Write Speed data of GET PERFORMANCE and the WRC field of SET STREAMING"); - if(ftr.SW) sb.AppendLine("\tDrive supports stream recording"); + + if(ftr.SW) + sb.AppendLine("\tDrive supports stream recording"); return sb.ToString(); } public static string Prettify_0108(Feature_0108? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_0108 ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_0108 ftr = feature.Value; + var sb = new StringBuilder(); sb.AppendFormat("Drive serial number: {0}", ftr.Serial).AppendLine(); @@ -4870,38 +4439,46 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string Prettify_010A(Feature_010A? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_010A ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_010A ftr = feature.Value; + var sb = new StringBuilder(); - if(ftr.DCBs == null) return sb.ToString(); + if(ftr.DCBs == null) + return sb.ToString(); - foreach(uint dcb in ftr.DCBs) sb.AppendFormat("Drive supports DCB {0:X8}h", dcb).AppendLine(); + foreach(uint dcb in ftr.DCBs) + sb.AppendFormat("Drive supports DCB {0:X8}h", dcb).AppendLine(); return sb.ToString(); } public static string Prettify_010B(Feature_010B? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_010B ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_010B ftr = feature.Value; + var sb = new StringBuilder(); sb.AppendFormat("Drive supports DVD CPRM version {0}", ftr.CPRMVersion); - if(ftr.Current) sb.AppendLine(" and current disc is or can be encrypted"); - else sb.AppendLine(); + + if(ftr.Current) + sb.AppendLine(" and current disc is or can be encrypted"); + else + sb.AppendLine(); return sb.ToString(); } public static string Prettify_010C(Feature_010C? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_010C ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_010C ftr = feature.Value; + var sb = new StringBuilder(); byte[] temp = new byte[4]; temp[0] = (byte)((ftr.Century & 0xFF00) >> 8); @@ -4932,8 +4509,8 @@ namespace DiscImageChef.Decoders.SCSI.MMC try { - DateTime fwDate = new DateTime(int.Parse(syear), int.Parse(smonth), int.Parse(sday), int.Parse(shour), - int.Parse(sminute), int.Parse(ssecond), DateTimeKind.Utc); + var fwDate = new DateTime(int.Parse(syear), int.Parse(smonth), int.Parse(sday), int.Parse(shour), + int.Parse(sminute), int.Parse(ssecond), DateTimeKind.Utc); sb.AppendFormat("Drive firmware is dated {0}", fwDate).AppendLine(); } @@ -4949,56 +4526,75 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string Prettify_010D(Feature_010D? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_010D ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_010D ftr = feature.Value; + var sb = new StringBuilder(); sb.AppendFormat("Drive supports AACS version {0}", ftr.AACSVersion); - if(ftr.Current) sb.AppendLine(" and current disc is encrypted"); - else sb.AppendLine(); - if(ftr.RDC) sb.AppendLine("\tDrive supports reading the Drive Certificate"); - if(ftr.RMC) sb.AppendLine("\tDrive supports reading Media Key Block of CPRM"); - if(ftr.WBE) sb.AppendLine("\tDrive supports writing with bus encryption"); - if(ftr.BEC) sb.AppendLine("\tDrive supports bus encryption"); + if(ftr.Current) + sb.AppendLine(" and current disc is encrypted"); + else + sb.AppendLine(); + + if(ftr.RDC) + sb.AppendLine("\tDrive supports reading the Drive Certificate"); + + if(ftr.RMC) + sb.AppendLine("\tDrive supports reading Media Key Block of CPRM"); + + if(ftr.WBE) + sb.AppendLine("\tDrive supports writing with bus encryption"); + + if(ftr.BEC) + sb.AppendLine("\tDrive supports bus encryption"); + if(ftr.BNG) { sb.AppendLine("\tDrive supports generating the binding nonce"); + if(ftr.BindNonceBlocks > 0) - sb.AppendFormat("\t{0} media blocks are required for the binding nonce", ftr.BindNonceBlocks) - .AppendLine(); + sb.AppendFormat("\t{0} media blocks are required for the binding nonce", ftr.BindNonceBlocks). + AppendLine(); } - if(ftr.AGIDs > 0) sb.AppendFormat("\tDrive supports {0} AGIDs concurrently", ftr.AGIDs).AppendLine(); + if(ftr.AGIDs > 0) + sb.AppendFormat("\tDrive supports {0} AGIDs concurrently", ftr.AGIDs).AppendLine(); return sb.ToString(); } public static string Prettify_010E(Feature_010E? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_010E ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_010E ftr = feature.Value; + var sb = new StringBuilder(); sb.Append("Drive supports DVD-Download"); - if(ftr.Current) sb.AppendLine(" (current)"); - else sb.AppendLine(); + + if(ftr.Current) + sb.AppendLine(" (current)"); + else + sb.AppendLine(); if(ftr.MaxScrambleExtent > 0) - sb.AppendFormat("\tMaximum {0} scranble extent information entries", ftr.MaxScrambleExtent) - .AppendLine(); + sb.AppendFormat("\tMaximum {0} scranble extent information entries", ftr.MaxScrambleExtent). + AppendLine(); return sb.ToString(); } public static string Prettify_0110(Feature_0110? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_0110 ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_0110 ftr = feature.Value; + var sb = new StringBuilder(); sb.AppendLine(ftr.Current ? "Drive and currently inserted media support VCPS" : "Drive supports VCPS"); @@ -5007,13 +4603,13 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string Prettify_0113(Feature_0113? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_0113 ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_0113 ftr = feature.Value; + var sb = new StringBuilder(); - sb.AppendLine(ftr.Current - ? "Drive and currently inserted media support SecurDisc" + sb.AppendLine(ftr.Current ? "Drive and currently inserted media support SecurDisc" : "Drive supports SecurDisc"); return sb.ToString(); @@ -5021,19 +4617,28 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string Prettify_0142(Feature_0142? feature) { - if(!feature.HasValue) return null; + if(!feature.HasValue) + return null; - Feature_0142 ftr = feature.Value; - StringBuilder sb = new StringBuilder(); + Feature_0142 ftr = feature.Value; + var sb = new StringBuilder(); sb.AppendLine("Drive supports the Trusted Computing Group Optical Security Subsystem Class"); - if(ftr.Current) sb.AppendLine("\tCurrent media is initialized with TCG OSSC"); - if(ftr.PSAU) sb.AppendLine("\tDrive supports PSA updates on write-once media"); - if(ftr.LOSPB) sb.AppendLine("\tDrive supports linked OSPBs"); - if(ftr.ME) sb.AppendLine("\tDrive will only record on the OSSC Disc Format"); + if(ftr.Current) + sb.AppendLine("\tCurrent media is initialized with TCG OSSC"); - if(ftr.Profiles == null) return sb.ToString(); + if(ftr.PSAU) + sb.AppendLine("\tDrive supports PSA updates on write-once media"); + + if(ftr.LOSPB) + sb.AppendLine("\tDrive supports linked OSPBs"); + + if(ftr.ME) + sb.AppendLine("\tDrive will only record on the OSSC Disc Format"); + + if(ftr.Profiles == null) + return sb.ToString(); for(int i = 0; i < ftr.Profiles.Length; i++) sb.AppendFormat("\tProfile {0}: {1}", i, ftr.Profiles[i]).AppendLine(); @@ -5159,22 +4764,26 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static SeparatedFeatures Separate(byte[] response) { - SeparatedFeatures dec = new SeparatedFeatures + var dec = new SeparatedFeatures { DataLength = (uint)((response[0] << 24) + (response[1] << 16) + (response[2] << 8) + response[4]), CurrentProfile = (ushort)((response[6] << 8) + response[7]) }; + uint offset = 8; List descLst = new List(); while(offset + 4 < response.Length) { - FeatureDescriptor desc = new FeatureDescriptor + var desc = new FeatureDescriptor { Code = (ushort)((response[offset + 0] << 8) + response[offset + 1]), Data = new byte[response[offset + 3] + 4] }; - if(desc.Data.Length + offset > response.Length) desc.Data = new byte[response.Length - offset]; + + if(desc.Data.Length + offset > response.Length) + desc.Data = new byte[response.Length - offset]; + Array.Copy(response, offset, desc.Data, 0, desc.Data.Length); offset += (uint)desc.Data.Length; @@ -5186,18 +4795,16 @@ namespace DiscImageChef.Decoders.SCSI.MMC return dec; } - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct FeatureDescriptor { public ushort Code; public byte[] Data; } - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct SeparatedFeatures { public uint DataLength; diff --git a/SCSI/MMC/Hybrid.cs b/SCSI/MMC/Hybrid.cs index ffa8fd2..f3f505c 100644 --- a/SCSI/MMC/Hybrid.cs +++ b/SCSI/MMC/Hybrid.cs @@ -36,90 +36,29 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI.MMC { /// - /// Information from the following standards: - /// ANSI X3.304-1997 - /// T10/1048-D revision 9.0 - /// T10/1048-D revision 10a - /// T10/1228-D revision 7.0c - /// T10/1228-D revision 11a - /// T10/1363-D revision 10g - /// T10/1545-D revision 1d - /// T10/1545-D revision 5 - /// T10/1545-D revision 5a - /// T10/1675-D revision 2c - /// T10/1675-D revision 4 - /// T10/1836-D revision 2g + /// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a + /// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision + /// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] public static class Hybrid { - public struct RecognizedFormatLayers - { - /// - /// Bytes 0 to 1 - /// Data Length - /// - public ushort DataLength; - /// - /// Byte 2 - /// Reserved - /// - public byte Reserved1; - /// - /// Byte 3 - /// Reserved - /// - public byte Reserved2; - /// - /// Byte 4 - /// Number of format layers in hybrid disc identified by drive - /// - public byte NumberOfLayers; - /// - /// Byte 5, bits 7 to 6 - /// Reserved - /// - public byte Reserved3; - /// - /// Byte 5, bits 5 to 4 - /// Layer no. used when disc is inserted - /// - public byte DefaultFormatLayer; - /// - /// Byte 5, bits 3 to 2 - /// Reserved - /// - public byte Reserved4; - /// - /// Byte 5, bits 1 to 0 - /// Layer no. currently in use - /// - public byte OnlineFormatLayer; - /// - /// Bytes 6 to end - /// Recognized format layers - /// - public ushort[] FormatLayers; - } - public static RecognizedFormatLayers? DecodeFormatLayers(byte[] FormatLayersResponse) { - if(FormatLayersResponse == null) return null; + if(FormatLayersResponse == null) + return null; - if(FormatLayersResponse.Length < 8) return null; + if(FormatLayersResponse.Length < 8) + return null; - RecognizedFormatLayers decoded = new RecognizedFormatLayers + var decoded = new RecognizedFormatLayers { DataLength = BigEndianBitConverter.ToUInt16(FormatLayersResponse, 0), - Reserved1 = FormatLayersResponse[2], - Reserved2 = FormatLayersResponse[3], - NumberOfLayers = FormatLayersResponse[4], - Reserved3 = (byte)((FormatLayersResponse[5] & 0xC0) >> 6), - DefaultFormatLayer = (byte)((FormatLayersResponse[5] & 0x30) >> 4), - Reserved4 = (byte)((FormatLayersResponse[5] & 0x0C) >> 2), + Reserved1 = FormatLayersResponse[2], Reserved2 = FormatLayersResponse[3], + NumberOfLayers = FormatLayersResponse[4], Reserved3 = (byte)((FormatLayersResponse[5] & 0xC0) >> 6), + DefaultFormatLayer = (byte)((FormatLayersResponse[5] & 0x30) >> 4), + Reserved4 = (byte)((FormatLayersResponse[5] & 0x0C) >> 2), OnlineFormatLayer = (byte)(FormatLayersResponse[5] & 0x03), FormatLayers = new ushort[(FormatLayersResponse.Length - 6) / 2] }; @@ -132,55 +71,81 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string PrettifyFormatLayers(RecognizedFormatLayers? FormatLayersResponse) { - if(FormatLayersResponse == null) return null; + if(FormatLayersResponse == null) + return null; RecognizedFormatLayers response = FormatLayersResponse.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendFormat("{0} format layers recognized", response.NumberOfLayers); for(int i = 0; i < response.FormatLayers.Length; i++) switch(response.FormatLayers[i]) { - case (ushort)FormatLayerTypeCodes.BDLayer: + case(ushort)FormatLayerTypeCodes.BDLayer: { sb.AppendFormat("Layer {0} is of type Blu-ray", i).AppendLine(); - if(response.DefaultFormatLayer == i) sb.AppendLine("This is the default layer."); - if(response.OnlineFormatLayer == i) sb.AppendLine("This is the layer actually in use."); + + if(response.DefaultFormatLayer == i) + sb.AppendLine("This is the default layer."); + + if(response.OnlineFormatLayer == i) + sb.AppendLine("This is the layer actually in use."); + break; } - case (ushort)FormatLayerTypeCodes.CDLayer: + case(ushort)FormatLayerTypeCodes.CDLayer: { sb.AppendFormat("Layer {0} is of type CD", i).AppendLine(); - if(response.DefaultFormatLayer == i) sb.AppendLine("This is the default layer."); - if(response.OnlineFormatLayer == i) sb.AppendLine("This is the layer actually in use."); + + if(response.DefaultFormatLayer == i) + sb.AppendLine("This is the default layer."); + + if(response.OnlineFormatLayer == i) + sb.AppendLine("This is the layer actually in use."); + break; } - case (ushort)FormatLayerTypeCodes.DVDLayer: + case(ushort)FormatLayerTypeCodes.DVDLayer: { sb.AppendFormat("Layer {0} is of type DVD", i).AppendLine(); - if(response.DefaultFormatLayer == i) sb.AppendLine("This is the default layer."); - if(response.OnlineFormatLayer == i) sb.AppendLine("This is the layer actually in use."); + + if(response.DefaultFormatLayer == i) + sb.AppendLine("This is the default layer."); + + if(response.OnlineFormatLayer == i) + sb.AppendLine("This is the layer actually in use."); + break; } - case (ushort)FormatLayerTypeCodes.HDDVDLayer: + case(ushort)FormatLayerTypeCodes.HDDVDLayer: { sb.AppendFormat("Layer {0} is of type HD DVD", i).AppendLine(); - if(response.DefaultFormatLayer == i) sb.AppendLine("This is the default layer."); - if(response.OnlineFormatLayer == i) sb.AppendLine("This is the layer actually in use."); + + if(response.DefaultFormatLayer == i) + sb.AppendLine("This is the default layer."); + + if(response.OnlineFormatLayer == i) + sb.AppendLine("This is the layer actually in use."); + break; } default: { - sb.AppendFormat("Layer {0} is of unknown type 0x{1:X4}", i, response.FormatLayers[i]) - .AppendLine(); - if(response.DefaultFormatLayer == i) sb.AppendLine("This is the default layer."); - if(response.OnlineFormatLayer == i) sb.AppendLine("This is the layer actually in use."); + sb.AppendFormat("Layer {0} is of unknown type 0x{1:X4}", i, response.FormatLayers[i]). + AppendLine(); + + if(response.DefaultFormatLayer == i) + sb.AppendLine("This is the default layer."); + + if(response.OnlineFormatLayer == i) + sb.AppendLine("This is the layer actually in use."); + break; } } @@ -191,7 +156,30 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string PrettifyFormatLayers(byte[] FormatLayersResponse) { RecognizedFormatLayers? decoded = DecodeFormatLayers(FormatLayersResponse); + return PrettifyFormatLayers(decoded); } + + public struct RecognizedFormatLayers + { + /// Bytes 0 to 1 Data Length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Byte 4 Number of format layers in hybrid disc identified by drive + public byte NumberOfLayers; + /// Byte 5, bits 7 to 6 Reserved + public byte Reserved3; + /// Byte 5, bits 5 to 4 Layer no. used when disc is inserted + public byte DefaultFormatLayer; + /// Byte 5, bits 3 to 2 Reserved + public byte Reserved4; + /// Byte 5, bits 1 to 0 Layer no. currently in use + public byte OnlineFormatLayer; + /// Bytes 6 to end Recognized format layers + public ushort[] FormatLayers; + } } } \ No newline at end of file diff --git a/SCSI/MMC/WriteProtect.cs b/SCSI/MMC/WriteProtect.cs index d237d61..2858eca 100644 --- a/SCSI/MMC/WriteProtect.cs +++ b/SCSI/MMC/WriteProtect.cs @@ -37,101 +37,29 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI.MMC { /// - /// Information from the following standards: - /// ANSI X3.304-1997 - /// T10/1048-D revision 9.0 - /// T10/1048-D revision 10a - /// T10/1228-D revision 7.0c - /// T10/1228-D revision 11a - /// T10/1363-D revision 10g - /// T10/1545-D revision 1d - /// T10/1545-D revision 5 - /// T10/1545-D revision 5a - /// T10/1675-D revision 2c - /// T10/1675-D revision 4 - /// T10/1836-D revision 2g + /// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a + /// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision + /// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g /// - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] public static class WriteProtect { - public struct WriteProtectionStatus - { - /// - /// Bytes 0 to 1 - /// Data Length - /// - public ushort DataLength; - /// - /// Byte 2 - /// Reserved - /// - public byte Reserved1; - /// - /// Byte 3 - /// Reserved - /// - public byte Reserved2; - /// - /// Byte 4, bits 7 to 4 - /// Reserved - /// - public byte Reserved3; - /// - /// Byte 4, bit 3 - /// Writing inhibited by media specific reason - /// - public bool MSWI; - /// - /// Byte 4, bit 2 - /// Cartridge sets write protection - /// - public bool CWP; - /// - /// Byte 4, bit 1 - /// Media surface sets write protection - /// - public bool PWP; - /// - /// Byte 4, bit 0 - /// Software write protection until power down - /// - public bool SWPP; - /// - /// Byte 5 - /// Reserved - /// - public byte Reserved4; - /// - /// Byte 6 - /// Reserved - /// - public byte Reserved5; - /// - /// Byte 7 - /// Reserved - /// - public byte Reserved6; - } - public static WriteProtectionStatus? DecodeWriteProtectionStatus(byte[] WPSResponse) { - if(WPSResponse == null) return null; + if(WPSResponse == null) + return null; - WriteProtectionStatus decoded = new WriteProtectionStatus + var decoded = new WriteProtectionStatus { - DataLength = BigEndianBitConverter.ToUInt16(WPSResponse, 0), - Reserved1 = WPSResponse[2], + DataLength = BigEndianBitConverter.ToUInt16(WPSResponse, 0), Reserved1 = WPSResponse[2], Reserved2 = WPSResponse[3], Reserved3 = (byte)((WPSResponse[4] & 0xF0) >> 4), MSWI = Convert.ToBoolean(WPSResponse[4] & 0x08), CWP = Convert.ToBoolean(WPSResponse[4] & 0x04), PWP = Convert.ToBoolean(WPSResponse[4] & 0x02), SWPP = Convert.ToBoolean(WPSResponse[4] & 0x01), - Reserved4 = WPSResponse[5], - Reserved5 = WPSResponse[6], + Reserved4 = WPSResponse[5], Reserved5 = WPSResponse[6], Reserved6 = WPSResponse[7] }; @@ -140,25 +68,44 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string PrettifyWriteProtectionStatus(WriteProtectionStatus? WPSResponse) { - if(WPSResponse == null) return null; + if(WPSResponse == null) + return null; WriteProtectionStatus response = WPSResponse.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); - if(response.MSWI) sb.AppendLine("Writing inhibited by media specific reason"); - if(response.CWP) sb.AppendLine("Cartridge sets write protection"); - if(response.PWP) sb.AppendLine("Media surface sets write protection"); - if(response.SWPP) sb.AppendLine("Software write protection is set until power down"); + if(response.MSWI) + sb.AppendLine("Writing inhibited by media specific reason"); - #if DEBUG - if(response.Reserved1 != 0) sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); - if(response.Reserved2 != 0) sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); - if(response.Reserved3 != 0) sb.AppendFormat("Reserved3 = 0x{0:X2}", response.Reserved3).AppendLine(); - if(response.Reserved4 != 0) sb.AppendFormat("Reserved4 = 0x{0:X2}", response.Reserved4).AppendLine(); - if(response.Reserved5 != 0) sb.AppendFormat("Reserved5 = 0x{0:X2}", response.Reserved5).AppendLine(); - if(response.Reserved6 != 0) sb.AppendFormat("Reserved6 = 0x{0:X2}", response.Reserved6).AppendLine(); - #endif + if(response.CWP) + sb.AppendLine("Cartridge sets write protection"); + + if(response.PWP) + sb.AppendLine("Media surface sets write protection"); + + if(response.SWPP) + sb.AppendLine("Software write protection is set until power down"); + + #if DEBUG + if(response.Reserved1 != 0) + sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); + + if(response.Reserved2 != 0) + sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); + + if(response.Reserved3 != 0) + sb.AppendFormat("Reserved3 = 0x{0:X2}", response.Reserved3).AppendLine(); + + if(response.Reserved4 != 0) + sb.AppendFormat("Reserved4 = 0x{0:X2}", response.Reserved4).AppendLine(); + + if(response.Reserved5 != 0) + sb.AppendFormat("Reserved5 = 0x{0:X2}", response.Reserved5).AppendLine(); + + if(response.Reserved6 != 0) + sb.AppendFormat("Reserved6 = 0x{0:X2}", response.Reserved6).AppendLine(); + #endif return sb.ToString(); } @@ -166,7 +113,34 @@ namespace DiscImageChef.Decoders.SCSI.MMC public static string PrettifyWriteProtectionStatus(byte[] WPSResponse) { WriteProtectionStatus? decoded = DecodeWriteProtectionStatus(WPSResponse); + return PrettifyWriteProtectionStatus(decoded); } + + public struct WriteProtectionStatus + { + /// Bytes 0 to 1 Data Length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Byte 4, bits 7 to 4 Reserved + public byte Reserved3; + /// Byte 4, bit 3 Writing inhibited by media specific reason + public bool MSWI; + /// Byte 4, bit 2 Cartridge sets write protection + public bool CWP; + /// Byte 4, bit 1 Media surface sets write protection + public bool PWP; + /// Byte 4, bit 0 Software write protection until power down + public bool SWPP; + /// Byte 5 Reserved + public byte Reserved4; + /// Byte 6 Reserved + public byte Reserved5; + /// Byte 7 Reserved + public byte Reserved6; + } } } \ No newline at end of file diff --git a/SCSI/Modes/00_SFF.cs b/SCSI/Modes/00_SFF.cs index 267badb..01442b6 100644 --- a/SCSI/Modes/00_SFF.cs +++ b/SCSI/Modes/00_SFF.cs @@ -35,52 +35,41 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Modes { #region Mode Page 0x00: Drive Operation Mode page - /// - /// Drive Operation Mode page - /// Page code 0x00 - /// 4 bytes in INF-8070 - /// + /// Drive Operation Mode page Page code 0x00 4 bytes in INF-8070 public struct ModePage_00_SFF { - /// - /// Parameters can be saved - /// + /// Parameters can be saved public bool PS; - /// - /// Select LUN Mode - /// + /// Select LUN Mode public bool SLM; - /// - /// Select LUN for rewritable - /// + /// Select LUN for rewritable public bool SLR; - /// - /// Disable verify for WRITE - /// + /// Disable verify for WRITE public bool DVW; - /// - /// Disable deferred error - /// + /// Disable deferred error public bool DDE; } public static ModePage_00_SFF? DecodeModePage_00_SFF(byte[] pageResponse) { - if((pageResponse?[0] & 0x40) == 0x40) return null; + if((pageResponse?[0] & 0x40) == 0x40) + return null; - if((pageResponse?[0] & 0x3F) != 0x00) return null; + if((pageResponse?[0] & 0x3F) != 0x00) + return null; - if(pageResponse[1] + 2 != pageResponse.Length) return null; + if(pageResponse[1] + 2 != pageResponse.Length) + return null; - if(pageResponse.Length < 4) return null; + if(pageResponse.Length < 4) + return null; - ModePage_00_SFF decoded = new ModePage_00_SFF(); + var decoded = new ModePage_00_SFF(); decoded.PS |= (pageResponse[0] & 0x80) == 0x80; @@ -98,19 +87,25 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyModePage_00_SFF(ModePage_00_SFF? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; ModePage_00_SFF page = modePage.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendLine("SCSI Drive Operation Mode page:"); - if(page.PS) sb.AppendLine("\tParameters can be saved"); + if(page.PS) + sb.AppendLine("\tParameters can be saved"); - if(page.DVW) sb.AppendLine("\tVerifying after writing is disabled"); - if(page.DDE) sb.AppendLine("\tDrive will abort when a writing error is detected"); + if(page.DVW) + sb.AppendLine("\tVerifying after writing is disabled"); - if(!page.SLM) return sb.ToString(); + if(page.DDE) + sb.AppendLine("\tDrive will abort when a writing error is detected"); + + if(!page.SLM) + return sb.ToString(); sb.Append("\tDrive has two LUNs with rewritable being "); sb.AppendLine(page.SLR ? "LUN 1" : "LUN 0"); diff --git a/SCSI/Modes/01.cs b/SCSI/Modes/01.cs index 00bc8f8..300986c 100644 --- a/SCSI/Modes/01.cs +++ b/SCSI/Modes/01.cs @@ -35,159 +35,10 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Modes { - #region Mode Page 0x01: Read-write error recovery page - /// - /// Disconnect-reconnect page - /// Page code 0x01 - /// 12 bytes in SCSI-2, SBC-1, SBC-2 - /// - public struct ModePage_01 - { - /// - /// Parameters can be saved - /// - public bool PS; - /// - /// Automatic Write Reallocation Enabled - /// - public bool AWRE; - /// - /// Automatic Read Reallocation Enabled - /// - public bool ARRE; - /// - /// Transfer block - /// - public bool TB; - /// - /// Read continuous - /// - public bool RC; - /// - /// Enable early recovery - /// - public bool EER; - /// - /// Post error reporting - /// - public bool PER; - /// - /// Disable transfer on error - /// - public bool DTE; - /// - /// Disable correction - /// - public bool DCR; - /// - /// How many times to retry a read operation - /// - public byte ReadRetryCount; - /// - /// How many bits of largest data burst error is maximum to apply error correction on it - /// - public byte CorrectionSpan; - /// - /// Offset to move the heads - /// - public sbyte HeadOffsetCount; - /// - /// Incremental position to which the recovered data strobe shall be adjusted - /// - public sbyte DataStrobeOffsetCount; - /// - /// How many times to retry a write operation - /// - public byte WriteRetryCount; - /// - /// Maximum time in ms to use in data error recovery procedures - /// - public ushort RecoveryTimeLimit; - - /// - /// Logical block provisioning error reporting is enabled - /// - public bool LBPERE; - } - - public static ModePage_01? DecodeModePage_01(byte[] pageResponse) - { - if((pageResponse?[0] & 0x40) == 0x40) return null; - - if((pageResponse?[0] & 0x3F) != 0x01) return null; - - if(pageResponse[1] + 2 != pageResponse.Length) return null; - - if(pageResponse.Length < 8) return null; - - ModePage_01 decoded = new ModePage_01(); - - decoded.PS |= (pageResponse[0] & 0x80) == 0x80; - decoded.AWRE |= (pageResponse[2] & 0x80) == 0x80; - decoded.ARRE |= (pageResponse[2] & 0x40) == 0x40; - decoded.TB |= (pageResponse[2] & 0x20) == 0x20; - decoded.RC |= (pageResponse[2] & 0x10) == 0x10; - decoded.EER |= (pageResponse[2] & 0x08) == 0x08; - decoded.PER |= (pageResponse[2] & 0x04) == 0x04; - decoded.DTE |= (pageResponse[2] & 0x02) == 0x02; - decoded.DCR |= (pageResponse[2] & 0x01) == 0x01; - - decoded.ReadRetryCount = pageResponse[3]; - decoded.CorrectionSpan = pageResponse[4]; - decoded.HeadOffsetCount = (sbyte)pageResponse[5]; - decoded.DataStrobeOffsetCount = (sbyte)pageResponse[6]; - - if(pageResponse.Length < 12) return decoded; - - decoded.WriteRetryCount = pageResponse[8]; - decoded.RecoveryTimeLimit = (ushort)((pageResponse[10] << 8) + pageResponse[11]); - decoded.LBPERE |= (pageResponse[7] & 0x80) == 0x80; - - return decoded; - } - - public static string PrettifyModePage_01(byte[] pageResponse) => - PrettifyModePage_01(DecodeModePage_01(pageResponse)); - - public static string PrettifyModePage_01(ModePage_01? modePage) - { - if(!modePage.HasValue) return null; - - ModePage_01 page = modePage.Value; - StringBuilder sb = new StringBuilder(); - - sb.AppendLine("SCSI Read-write error recovery page:"); - - if(page.PS) sb.AppendLine("\tParameters can be saved"); - - if(page.AWRE) sb.AppendLine("\tAutomatic write reallocation is enabled"); - if(page.ARRE) sb.AppendLine("\tAutomatic read reallocation is enabled"); - if(page.TB) - sb.AppendLine("\tData not recovered within limits shall be transferred back before a CHECK CONDITION"); - if(page.RC) - sb.AppendLine("\tDrive will transfer the entire requested length without delaying to perform error recovery"); - if(page.EER) sb.AppendLine("\tDrive will use the most expedient form of error recovery first"); - if(page.PER) sb.AppendLine("\tDrive shall report recovered errors"); - if(page.DTE) sb.AppendLine("\tTransfer will be terminated upon error detection"); - if(page.DCR) sb.AppendLine("\tError correction is disabled"); - if(page.ReadRetryCount > 0) - sb.AppendFormat("\tDrive will repeat read operations {0} times", page.ReadRetryCount).AppendLine(); - if(page.WriteRetryCount > 0) - sb.AppendFormat("\tDrive will repeat write operations {0} times", page.WriteRetryCount).AppendLine(); - if(page.RecoveryTimeLimit > 0) - sb.AppendFormat("\tDrive will employ a maximum of {0} ms to recover data", page.RecoveryTimeLimit) - .AppendLine(); - if(page.LBPERE) sb.AppendLine("Logical block provisioning error reporting is enabled"); - - return sb.ToString(); - } - #endregion Mode Page 0x01: Read-write error recovery page - public static byte[] EncodeModePage_01(ModePage_01 page) { byte[] pg = new byte[8]; @@ -195,15 +46,32 @@ namespace DiscImageChef.Decoders.SCSI pg[0] = 0x01; pg[1] = 6; - if(page.PS) pg[0] += 0x80; - if(page.AWRE) pg[2] += 0x80; - if(page.ARRE) pg[2] += 0x40; - if(page.TB) pg[2] += 0x20; - if(page.RC) pg[2] += 0x10; - if(page.EER) pg[2] += 0x08; - if(page.PER) pg[2] += 0x04; - if(page.DTE) pg[2] += 0x02; - if(page.DCR) pg[2] += 0x01; + if(page.PS) + pg[0] += 0x80; + + if(page.AWRE) + pg[2] += 0x80; + + if(page.ARRE) + pg[2] += 0x40; + + if(page.TB) + pg[2] += 0x20; + + if(page.RC) + pg[2] += 0x10; + + if(page.EER) + pg[2] += 0x08; + + if(page.PER) + pg[2] += 0x04; + + if(page.DTE) + pg[2] += 0x02; + + if(page.DCR) + pg[2] += 0x01; pg[3] = page.ReadRetryCount; pg[4] = page.CorrectionSpan; @@ -220,5 +88,142 @@ namespace DiscImageChef.Decoders.SCSI return pg; } + + #region Mode Page 0x01: Read-write error recovery page + /// Disconnect-reconnect page Page code 0x01 12 bytes in SCSI-2, SBC-1, SBC-2 + public struct ModePage_01 + { + /// Parameters can be saved + public bool PS; + /// Automatic Write Reallocation Enabled + public bool AWRE; + /// Automatic Read Reallocation Enabled + public bool ARRE; + /// Transfer block + public bool TB; + /// Read continuous + public bool RC; + /// Enable early recovery + public bool EER; + /// Post error reporting + public bool PER; + /// Disable transfer on error + public bool DTE; + /// Disable correction + public bool DCR; + /// How many times to retry a read operation + public byte ReadRetryCount; + /// How many bits of largest data burst error is maximum to apply error correction on it + public byte CorrectionSpan; + /// Offset to move the heads + public sbyte HeadOffsetCount; + /// Incremental position to which the recovered data strobe shall be adjusted + public sbyte DataStrobeOffsetCount; + /// How many times to retry a write operation + public byte WriteRetryCount; + /// Maximum time in ms to use in data error recovery procedures + public ushort RecoveryTimeLimit; + + /// Logical block provisioning error reporting is enabled + public bool LBPERE; + } + + public static ModePage_01? DecodeModePage_01(byte[] pageResponse) + { + if((pageResponse?[0] & 0x40) == 0x40) + return null; + + if((pageResponse?[0] & 0x3F) != 0x01) + return null; + + if(pageResponse[1] + 2 != pageResponse.Length) + return null; + + if(pageResponse.Length < 8) + return null; + + var decoded = new ModePage_01(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + decoded.AWRE |= (pageResponse[2] & 0x80) == 0x80; + decoded.ARRE |= (pageResponse[2] & 0x40) == 0x40; + decoded.TB |= (pageResponse[2] & 0x20) == 0x20; + decoded.RC |= (pageResponse[2] & 0x10) == 0x10; + decoded.EER |= (pageResponse[2] & 0x08) == 0x08; + decoded.PER |= (pageResponse[2] & 0x04) == 0x04; + decoded.DTE |= (pageResponse[2] & 0x02) == 0x02; + decoded.DCR |= (pageResponse[2] & 0x01) == 0x01; + + decoded.ReadRetryCount = pageResponse[3]; + decoded.CorrectionSpan = pageResponse[4]; + decoded.HeadOffsetCount = (sbyte)pageResponse[5]; + decoded.DataStrobeOffsetCount = (sbyte)pageResponse[6]; + + if(pageResponse.Length < 12) + return decoded; + + decoded.WriteRetryCount = pageResponse[8]; + decoded.RecoveryTimeLimit = (ushort)((pageResponse[10] << 8) + pageResponse[11]); + decoded.LBPERE |= (pageResponse[7] & 0x80) == 0x80; + + return decoded; + } + + public static string PrettifyModePage_01(byte[] pageResponse) => + PrettifyModePage_01(DecodeModePage_01(pageResponse)); + + public static string PrettifyModePage_01(ModePage_01? modePage) + { + if(!modePage.HasValue) + return null; + + ModePage_01 page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("SCSI Read-write error recovery page:"); + + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + if(page.AWRE) + sb.AppendLine("\tAutomatic write reallocation is enabled"); + + if(page.ARRE) + sb.AppendLine("\tAutomatic read reallocation is enabled"); + + if(page.TB) + sb.AppendLine("\tData not recovered within limits shall be transferred back before a CHECK CONDITION"); + + if(page.RC) + sb.AppendLine("\tDrive will transfer the entire requested length without delaying to perform error recovery"); + + if(page.EER) + sb.AppendLine("\tDrive will use the most expedient form of error recovery first"); + + if(page.PER) + sb.AppendLine("\tDrive shall report recovered errors"); + + if(page.DTE) + sb.AppendLine("\tTransfer will be terminated upon error detection"); + + if(page.DCR) + sb.AppendLine("\tError correction is disabled"); + + if(page.ReadRetryCount > 0) + sb.AppendFormat("\tDrive will repeat read operations {0} times", page.ReadRetryCount).AppendLine(); + + if(page.WriteRetryCount > 0) + sb.AppendFormat("\tDrive will repeat write operations {0} times", page.WriteRetryCount).AppendLine(); + + if(page.RecoveryTimeLimit > 0) + sb.AppendFormat("\tDrive will employ a maximum of {0} ms to recover data", page.RecoveryTimeLimit). + AppendLine(); + + if(page.LBPERE) + sb.AppendLine("Logical block provisioning error reporting is enabled"); + + return sb.ToString(); + } + #endregion Mode Page 0x01: Read-write error recovery page } } \ No newline at end of file diff --git a/SCSI/Modes/01_MMC.cs b/SCSI/Modes/01_MMC.cs index c94e6d1..03c5776 100644 --- a/SCSI/Modes/01_MMC.cs +++ b/SCSI/Modes/01_MMC.cs @@ -35,59 +35,73 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Modes { + public static byte[] EncodeModePage_01_MMC(ModePage_01_MMC page) + { + byte[] pg = new byte[12]; + + pg[0] = 0x01; + pg[1] = 10; + + if(page.PS) + pg[0] += 0x80; + + pg[2] = page.Parameter; + pg[3] = page.ReadRetryCount; + + // This is from a newer version of SCSI unknown what happen for drives expecting an 8 byte page + + pg[8] = page.WriteRetryCount; + pg[10] = (byte)((page.RecoveryTimeLimit & 0xFF00) << 8); + pg[11] = (byte)(page.RecoveryTimeLimit & 0xFF); + + return pg; + } + #region Mode Page 0x01: Read error recovery page for MultiMedia Devices /// - /// Read error recovery page for MultiMedia Devices - /// Page code 0x01 - /// 8 bytes in SCSI-2, MMC-1 - /// 12 bytes in MMC-2, MMC-3 + /// Read error recovery page for MultiMedia Devices Page code 0x01 8 bytes in SCSI-2, MMC-1 12 bytes in MMC-2, + /// MMC-3 /// public struct ModePage_01_MMC { - /// - /// Parameters can be saved - /// + /// Parameters can be saved public bool PS; - /// - /// Error recovery parameter - /// + /// Error recovery parameter public byte Parameter; - /// - /// How many times to retry a read operation - /// + /// How many times to retry a read operation public byte ReadRetryCount; - /// - /// How many times to retry a write operation - /// + /// How many times to retry a write operation public byte WriteRetryCount; - /// - /// Maximum time in ms to use in data error recovery procedures - /// + /// Maximum time in ms to use in data error recovery procedures public ushort RecoveryTimeLimit; } public static ModePage_01_MMC? DecodeModePage_01_MMC(byte[] pageResponse) { - if((pageResponse?[0] & 0x40) == 0x40) return null; + if((pageResponse?[0] & 0x40) == 0x40) + return null; - if((pageResponse?[0] & 0x3F) != 0x01) return null; + if((pageResponse?[0] & 0x3F) != 0x01) + return null; - if(pageResponse[1] + 2 != pageResponse.Length) return null; + if(pageResponse[1] + 2 != pageResponse.Length) + return null; - if(pageResponse.Length < 8) return null; + if(pageResponse.Length < 8) + return null; - ModePage_01_MMC decoded = new ModePage_01_MMC(); + var decoded = new ModePage_01_MMC(); decoded.PS |= (pageResponse[0] & 0x80) == 0x80; decoded.Parameter = pageResponse[2]; decoded.ReadRetryCount = pageResponse[3]; - if(pageResponse.Length < 12) return decoded; + if(pageResponse.Length < 12) + return decoded; decoded.WriteRetryCount = pageResponse[8]; decoded.RecoveryTimeLimit = (ushort)((pageResponse[10] << 8) + pageResponse[11]); @@ -100,14 +114,17 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyModePage_01_MMC(ModePage_01_MMC? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; ModePage_01_MMC page = modePage.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendLine("SCSI Read error recovery page for MultiMedia Devices:"); - if(page.PS) sb.AppendLine("\tParameters can be saved"); + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + if(page.ReadRetryCount > 0) sb.AppendFormat("\tDrive will repeat read operations {0} times", page.ReadRetryCount).AppendLine(); @@ -121,8 +138,10 @@ namespace DiscImageChef.Decoders.SCSI string UnrecCIRCAbort = "\tUnrecovered CIRC errors will return CHECK CONDITION."; string UnrecECCNotAbort = "\tUnrecovered ECC errors will not abort the transfer."; string UnrecCIRCNotAbort = "\tUnrecovered CIRC errors will not abort the transfer."; + string UnrecECCAbortData = "\tUnrecovered ECC errors will return CHECK CONDITION and the uncorrected data."; + string UnrecCIRCAbortData = "\tUnrecovered CIRC errors will return CHECK CONDITION and the uncorrected data."; @@ -130,51 +149,67 @@ namespace DiscImageChef.Decoders.SCSI { case 0x00: sb.AppendLine(AllUsed + RecoveredNotReported + UnrecECCAbort); + break; case 0x01: sb.AppendLine(CIRCRetriesUsed + RecoveredNotReported + UnrecCIRCAbort); + break; case 0x04: sb.AppendLine(AllUsed + RecoveredReported + UnrecECCAbort); + break; case 0x05: sb.AppendLine(CIRCRetriesUsed + RecoveredReported + UnrecCIRCAbort); + break; case 0x06: sb.AppendLine(AllUsed + RecoveredAbort + UnrecECCAbort); + break; case 0x07: sb.AppendLine(RetriesUsed + RecoveredAbort + UnrecCIRCAbort); + break; case 0x10: sb.AppendLine(AllUsed + RecoveredNotReported + UnrecECCNotAbort); + break; case 0x11: sb.AppendLine(CIRCRetriesUsed + RecoveredNotReported + UnrecCIRCNotAbort); + break; case 0x14: sb.AppendLine(AllUsed + RecoveredReported + UnrecECCNotAbort); + break; case 0x15: sb.AppendLine(CIRCRetriesUsed + RecoveredReported + UnrecCIRCNotAbort); + break; case 0x20: sb.AppendLine(AllUsed + RecoveredNotReported + UnrecECCAbortData); + break; case 0x21: sb.AppendLine(CIRCRetriesUsed + RecoveredNotReported + UnrecCIRCAbortData); + break; case 0x24: sb.AppendLine(AllUsed + RecoveredReported + UnrecECCAbortData); + break; case 0x25: sb.AppendLine(CIRCRetriesUsed + RecoveredReported + UnrecCIRCAbortData); + break; case 0x26: sb.AppendLine(AllUsed + RecoveredAbort + UnrecECCAbortData); + break; case 0x27: sb.AppendLine(RetriesUsed + RecoveredAbort + UnrecCIRCAbortData); + break; case 0x30: goto case 0x10; case 0x31: goto case 0x11; @@ -182,37 +217,19 @@ namespace DiscImageChef.Decoders.SCSI case 0x35: goto case 0x15; default: sb.AppendFormat("Unknown recovery parameter 0x{0:X2}", page.Parameter).AppendLine(); + break; } if(page.WriteRetryCount > 0) sb.AppendFormat("\tDrive will repeat write operations {0} times", page.WriteRetryCount).AppendLine(); + if(page.RecoveryTimeLimit > 0) - sb.AppendFormat("\tDrive will employ a maximum of {0} ms to recover data", page.RecoveryTimeLimit) - .AppendLine(); + sb.AppendFormat("\tDrive will employ a maximum of {0} ms to recover data", page.RecoveryTimeLimit). + AppendLine(); return sb.ToString(); } #endregion Mode Page 0x01: Read error recovery page for MultiMedia Devices - - public static byte[] EncodeModePage_01_MMC(ModePage_01_MMC page) - { - byte[] pg = new byte[12]; - - pg[0] = 0x01; - pg[1] = 10; - - if(page.PS) pg[0] += 0x80; - pg[2] = page.Parameter; - pg[3] = page.ReadRetryCount; - - // This is from a newer version of SCSI unknown what happen for drives expecting an 8 byte page - - pg[8] = page.WriteRetryCount; - pg[10] = (byte)((page.RecoveryTimeLimit & 0xFF00) << 8); - pg[11] = (byte)(page.RecoveryTimeLimit & 0xFF); - - return pg; - } } } \ No newline at end of file diff --git a/SCSI/Modes/02.cs b/SCSI/Modes/02.cs index bd0ce87..1b9f113 100644 --- a/SCSI/Modes/02.cs +++ b/SCSI/Modes/02.cs @@ -35,82 +35,59 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Modes { #region Mode Page 0x02: Disconnect-reconnect page - /// - /// Disconnect-reconnect page - /// Page code 0x02 - /// 16 bytes in SCSI-2, SPC-1, SPC-2, SPC-3, SPC-4, SPC-5 - /// + /// Disconnect-reconnect page Page code 0x02 16 bytes in SCSI-2, SPC-1, SPC-2, SPC-3, SPC-4, SPC-5 public struct ModePage_02 { - /// - /// Parameters can be saved - /// + /// Parameters can be saved public bool PS; - /// - /// How full should be the buffer prior to attempting a reselection - /// + /// How full should be the buffer prior to attempting a reselection public byte BufferFullRatio; - /// - /// How empty should be the buffer prior to attempting a reselection - /// + /// How empty should be the buffer prior to attempting a reselection public byte BufferEmptyRatio; - /// - /// Max. time in 100 µs increments that the target is permitted to assert BSY without a REQ/ACK - /// + /// Max. time in 100 µs increments that the target is permitted to assert BSY without a REQ/ACK public ushort BusInactivityLimit; - /// - /// Min. time in 100 µs increments to wait after releasing the bus before attempting reselection - /// + /// Min. time in 100 µs increments to wait after releasing the bus before attempting reselection public ushort DisconnectTimeLimit; /// /// Max. time in 100 µs increments allowed to use the bus before disconnecting, if granted the privilege and not /// restricted by /// public ushort ConnectTimeLimit; - /// - /// Maximum amount of data before disconnecting in 512 bytes increments - /// + /// Maximum amount of data before disconnecting in 512 bytes increments public ushort MaxBurstSize; - /// - /// Data transfer disconnect control - /// + /// Data transfer disconnect control public byte DTDC; - /// - /// Target shall not transfer data for a command during the same interconnect tenancy - /// + /// Target shall not transfer data for a command during the same interconnect tenancy public bool DIMM; - /// - /// Wether to use fair or unfair arbitration when requesting an interconnect tenancy - /// + /// Wether to use fair or unfair arbitration when requesting an interconnect tenancy public byte FairArbitration; - /// - /// Max. ammount of data in 512 bytes increments that may be transferred for a command along with the command - /// + /// Max. ammount of data in 512 bytes increments that may be transferred for a command along with the command public ushort FirstBurstSize; - /// - /// Target is allowed to re-order the data transfer - /// + /// Target is allowed to re-order the data transfer public bool EMDP; } public static ModePage_02? DecodeModePage_02(byte[] pageResponse) { - if((pageResponse?[0] & 0x40) == 0x40) return null; + if((pageResponse?[0] & 0x40) == 0x40) + return null; - if((pageResponse?[0] & 0x3F) != 0x02) return null; + if((pageResponse?[0] & 0x3F) != 0x02) + return null; - if(pageResponse[1] + 2 != pageResponse.Length) return null; + if(pageResponse[1] + 2 != pageResponse.Length) + return null; - if(pageResponse.Length < 12) return null; + if(pageResponse.Length < 12) + return null; - ModePage_02 decoded = new ModePage_02(); + var decoded = new ModePage_02(); decoded.PS |= (pageResponse[0] & 0x80) == 0x80; decoded.BufferFullRatio = pageResponse[2]; @@ -128,7 +105,8 @@ namespace DiscImageChef.Decoders.SCSI decoded.DTDC = (byte)(pageResponse[12] & 0x07); } - if(pageResponse.Length >= 16) decoded.FirstBurstSize = (ushort)((pageResponse[14] << 8) + pageResponse[15]); + if(pageResponse.Length >= 16) + decoded.FirstBurstSize = (ushort)((pageResponse[14] << 8) + pageResponse[15]); return decoded; } @@ -138,55 +116,70 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyModePage_02(ModePage_02? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; - ModePage_02 page = modePage.Value; - StringBuilder sb = new StringBuilder(); + ModePage_02 page = modePage.Value; + var sb = new StringBuilder(); sb.AppendLine("SCSI Disconnect-Reconnect mode page:"); - if(page.PS) sb.AppendLine("\tParameters can be saved"); + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + if(page.BufferFullRatio > 0) sb.AppendFormat("\t{0} ratio of buffer that shall be full prior to attempting a reselection", page.BufferFullRatio).AppendLine(); + if(page.BufferEmptyRatio > 0) sb.AppendFormat("\t{0} ratio of buffer that shall be empty prior to attempting a reselection", page.BufferEmptyRatio).AppendLine(); + if(page.BusInactivityLimit > 0) sb.AppendFormat("\t{0} µs maximum permitted to assert BSY without a REQ/ACK handshake", page.BusInactivityLimit * 100).AppendLine(); + if(page.DisconnectTimeLimit > 0) sb.AppendFormat("\t{0} µs maximum permitted wait after releasing the bus before attempting reselection", page.DisconnectTimeLimit * 100).AppendLine(); + if(page.ConnectTimeLimit > 0) - sb - .AppendFormat("\t{0} µs allowed to use the bus before disconnecting, if granted the privilege and not restricted", + sb. + AppendFormat("\t{0} µs allowed to use the bus before disconnecting, if granted the privilege and not restricted", page.ConnectTimeLimit * 100).AppendLine(); + if(page.MaxBurstSize > 0) - sb.AppendFormat("\t{0} bytes maximum can be transferred before disconnecting", page.MaxBurstSize * 512) - .AppendLine(); + sb.AppendFormat("\t{0} bytes maximum can be transferred before disconnecting", page.MaxBurstSize * 512). + AppendLine(); + if(page.FirstBurstSize > 0) - sb - .AppendFormat("\t{0} bytes maximum can be transferred for a command along with the disconnect command", + sb. + AppendFormat("\t{0} bytes maximum can be transferred for a command along with the disconnect command", page.FirstBurstSize * 512).AppendLine(); if(page.DIMM) sb.AppendLine("\tTarget shall not transfer data for a command during the same interconnect tenancy"); - if(page.EMDP) sb.AppendLine("\tTarget is allowed to re-order the data transfer"); + + if(page.EMDP) + sb.AppendLine("\tTarget is allowed to re-order the data transfer"); switch(page.DTDC) { case 0: sb.AppendLine("\tData transfer disconnect control is not used"); + break; case 1: sb.AppendLine("\tAll data for a command shall be transferred within a single interconnect tenancy"); + break; case 3: sb.AppendLine("\tAll data and the response for a command shall be transferred within a single interconnect tenancy"); + break; default: sb.AppendFormat("\tReserved data transfer disconnect control value {0}", page.DTDC).AppendLine(); + break; } diff --git a/SCSI/Modes/03.cs b/SCSI/Modes/03.cs index 3ff1776..5032e94 100644 --- a/SCSI/Modes/03.cs +++ b/SCSI/Modes/03.cs @@ -35,89 +35,62 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Modes { #region Mode Page 0x03: Format device page - /// - /// Disconnect-reconnect page - /// Page code 0x03 - /// 24 bytes in SCSI-2, SBC-1 - /// + /// Disconnect-reconnect page Page code 0x03 24 bytes in SCSI-2, SBC-1 public struct ModePage_03 { - /// - /// Parameters can be saved - /// + /// Parameters can be saved public bool PS; - /// - /// Tracks per zone to use in dividing the capacity for the purpose of allocating alternate sectors - /// + /// Tracks per zone to use in dividing the capacity for the purpose of allocating alternate sectors public ushort TracksPerZone; - /// - /// Number of sectors per zone that shall be reserved for defect handling - /// + /// Number of sectors per zone that shall be reserved for defect handling public ushort AltSectorsPerZone; - /// - /// Number of tracks per zone that shall be reserved for defect handling - /// + /// Number of tracks per zone that shall be reserved for defect handling public ushort AltTracksPerZone; - /// - /// Number of tracks per LUN that shall be reserved for defect handling - /// + /// Number of tracks per LUN that shall be reserved for defect handling public ushort AltTracksPerLun; - /// - /// Number of physical sectors per track - /// + /// Number of physical sectors per track public ushort SectorsPerTrack; - /// - /// Bytes per physical sector - /// + /// Bytes per physical sector public ushort BytesPerSector; - /// - /// Interleave value, target dependent - /// + /// Interleave value, target dependent public ushort Interleave; - /// - /// Sectors between last block of one track and first block of the next - /// + /// Sectors between last block of one track and first block of the next public ushort TrackSkew; - /// - /// Sectors between last block of a cylinder and first block of the next one - /// + /// Sectors between last block of a cylinder and first block of the next one public ushort CylinderSkew; - /// - /// Soft-sectored - /// + /// Soft-sectored public bool SSEC; - /// - /// Hard-sectored - /// + /// Hard-sectored public bool HSEC; - /// - /// Removable - /// + /// Removable public bool RMB; /// - /// If set, address are allocated progressively in a surface before going to the next. - /// Otherwise, it goes by cylinders + /// If set, address are allocated progressively in a surface before going to the next. Otherwise, it goes by + /// cylinders /// public bool SURF; } public static ModePage_03? DecodeModePage_03(byte[] pageResponse) { - if((pageResponse?[0] & 0x40) == 0x40) return null; + if((pageResponse?[0] & 0x40) == 0x40) + return null; - if((pageResponse?[0] & 0x3F) != 0x03) return null; + if((pageResponse?[0] & 0x3F) != 0x03) + return null; - if(pageResponse[1] + 2 != pageResponse.Length) return null; + if(pageResponse[1] + 2 != pageResponse.Length) + return null; - if(pageResponse.Length < 24) return null; + if(pageResponse.Length < 24) + return null; - ModePage_03 decoded = new ModePage_03(); + var decoded = new ModePage_03(); decoded.PS |= (pageResponse[0] & 0x80) == 0x80; decoded.TracksPerZone = (ushort)((pageResponse[2] << 8) + pageResponse[3]); @@ -142,34 +115,49 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyModePage_03(ModePage_03? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; - ModePage_03 page = modePage.Value; - StringBuilder sb = new StringBuilder(); + ModePage_03 page = modePage.Value; + var sb = new StringBuilder(); sb.AppendLine("SCSI Format device page:"); - if(page.PS) sb.AppendLine("\tParameters can be saved"); + if(page.PS) + sb.AppendLine("\tParameters can be saved"); - sb - .AppendFormat("\t{0} tracks per zone to use in dividing the capacity for the purpose of allocating alternate sectors", + sb. + AppendFormat("\t{0} tracks per zone to use in dividing the capacity for the purpose of allocating alternate sectors", page.TracksPerZone).AppendLine(); - sb.AppendFormat("\t{0} sectors per zone that shall be reserved for defect handling", page.AltSectorsPerZone) - .AppendLine(); - sb.AppendFormat("\t{0} tracks per zone that shall be reserved for defect handling", page.AltTracksPerZone) - .AppendLine(); - sb.AppendFormat("\t{0} tracks per LUN that shall be reserved for defect handling", page.AltTracksPerLun) - .AppendLine(); + + sb.AppendFormat("\t{0} sectors per zone that shall be reserved for defect handling", + page.AltSectorsPerZone).AppendLine(); + + sb.AppendFormat("\t{0} tracks per zone that shall be reserved for defect handling", page.AltTracksPerZone). + AppendLine(); + + sb.AppendFormat("\t{0} tracks per LUN that shall be reserved for defect handling", page.AltTracksPerLun). + AppendLine(); + sb.AppendFormat("\t{0} physical sectors per track", page.SectorsPerTrack).AppendLine(); sb.AppendFormat("\t{0} Bytes per physical sector", page.BytesPerSector).AppendLine(); sb.AppendFormat("\tTarget-dependent interleave value is {0}", page.Interleave).AppendLine(); - sb.AppendFormat("\t{0} sectors between last block of one track and first block of the next", page.TrackSkew) - .AppendLine(); + + sb.AppendFormat("\t{0} sectors between last block of one track and first block of the next", + page.TrackSkew).AppendLine(); + sb.AppendFormat("\t{0} sectors between last block of a cylinder and first block of the next one", page.CylinderSkew).AppendLine(); - if(page.SSEC) sb.AppendLine("\tDrive supports soft-sectoring format"); - if(page.HSEC) sb.AppendLine("\tDrive supports hard-sectoring format"); - if(page.RMB) sb.AppendLine("\tDrive media is removable"); + + if(page.SSEC) + sb.AppendLine("\tDrive supports soft-sectoring format"); + + if(page.HSEC) + sb.AppendLine("\tDrive supports hard-sectoring format"); + + if(page.RMB) + sb.AppendLine("\tDrive media is removable"); + sb.AppendLine(page.SURF ? "\tSector addressing is progressively incremented in one surface before going to the next" : "\tSector addressing is progressively incremented in one cylinder before going to the next"); diff --git a/SCSI/Modes/04.cs b/SCSI/Modes/04.cs index 052e775..992ffae 100644 --- a/SCSI/Modes/04.cs +++ b/SCSI/Modes/04.cs @@ -35,81 +35,63 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Modes { #region Mode Page 0x04: Rigid disk drive geometry page - /// - /// Disconnect-reconnect page - /// Page code 0x04 - /// 24 bytes in SCSI-2, SBC-1 - /// + /// Disconnect-reconnect page Page code 0x04 24 bytes in SCSI-2, SBC-1 public struct ModePage_04 { - /// - /// Parameters can be saved - /// + /// Parameters can be saved public bool PS; - /// - /// Cylinders used for data storage - /// + /// Cylinders used for data storage public uint Cylinders; - /// - /// Heads for reading and/or writing - /// + /// Heads for reading and/or writing public byte Heads; - /// - /// Cylinder where write precompensation starts - /// + /// Cylinder where write precompensation starts public uint WritePrecompCylinder; - /// - /// Cylinder where write current reduction starts - /// + /// Cylinder where write current reduction starts public uint WriteReduceCylinder; - /// - /// Step rate in 100 ns units - /// + /// Step rate in 100 ns units public ushort DriveStepRate; - /// - /// Cylinder where the heads park - /// + /// Cylinder where the heads park public int LandingCylinder; - /// - /// Rotational position locking - /// + /// Rotational position locking public byte RPL; - /// - /// Rotational skew to apply when synchronized - /// + /// Rotational skew to apply when synchronized public byte RotationalOffset; - /// - /// Medium speed in rpm - /// + /// Medium speed in rpm public ushort MediumRotationRate; } public static ModePage_04? DecodeModePage_04(byte[] pageResponse) { - if((pageResponse?[0] & 0x40) == 0x40) return null; + if((pageResponse?[0] & 0x40) == 0x40) + return null; - if((pageResponse?[0] & 0x3F) != 0x04) return null; + if((pageResponse?[0] & 0x3F) != 0x04) + return null; - if(pageResponse[1] + 2 != pageResponse.Length) return null; + if(pageResponse[1] + 2 != pageResponse.Length) + return null; - if(pageResponse.Length < 20) return null; + if(pageResponse.Length < 20) + return null; - ModePage_04 decoded = new ModePage_04(); + var decoded = new ModePage_04(); decoded.PS |= (pageResponse[0] & 0x80) == 0x80; decoded.Cylinders = (uint)((pageResponse[2] << 16) + (pageResponse[3] << 8) + pageResponse[4]); decoded.Heads = pageResponse[5]; decoded.WritePrecompCylinder = (uint)((pageResponse[6] << 16) + (pageResponse[7] << 8) + pageResponse[8]); + decoded.WriteReduceCylinder = (uint)((pageResponse[9] << 16) + (pageResponse[10] << 8) + pageResponse[11]); + decoded.DriveStepRate = (ushort)((pageResponse[12] << 8) + pageResponse[13]); + decoded.LandingCylinder = (pageResponse[14] << 16) + (pageResponse[15] << 8) + pageResponse[16]; decoded.RPL = (byte)(pageResponse[17] & 0x03); decoded.RotationalOffset = pageResponse[18]; @@ -125,23 +107,28 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyModePage_04(ModePage_04? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; - ModePage_04 page = modePage.Value; - StringBuilder sb = new StringBuilder(); + ModePage_04 page = modePage.Value; + var sb = new StringBuilder(); sb.AppendLine("SCSI Rigid disk drive geometry page:"); - if(page.PS) sb.AppendLine("\tParameters can be saved"); + if(page.PS) + sb.AppendLine("\tParameters can be saved"); sb.AppendFormat("\t{0} heads", page.Heads).AppendLine(); sb.AppendFormat("\t{0} cylinders", page.Cylinders).AppendLine(); + if(page.WritePrecompCylinder < page.Cylinders) - sb.AppendFormat("\tWrite pre-compensation starts at cylinder {0}", page.WritePrecompCylinder) - .AppendLine(); + sb.AppendFormat("\tWrite pre-compensation starts at cylinder {0}", page.WritePrecompCylinder). + AppendLine(); + if(page.WriteReduceCylinder < page.Cylinders) - sb.AppendFormat("\tWrite current reduction starts at cylinder {0}", page.WriteReduceCylinder) - .AppendLine(); + sb.AppendFormat("\tWrite current reduction starts at cylinder {0}", page.WriteReduceCylinder). + AppendLine(); + if(page.DriveStepRate > 0) sb.AppendFormat("\tDrive steps in {0} ns", (uint)page.DriveStepRate * 100).AppendLine(); @@ -154,15 +141,19 @@ namespace DiscImageChef.Decoders.SCSI { case 0: sb.AppendLine("\tSpindle synchronization is disable or unsupported"); + break; case 1: sb.AppendLine("\tTarget operates as a synchronized-spindle slave"); + break; case 2: sb.AppendLine("\tTarget operates as a synchronized-spindle master"); + break; case 3: sb.AppendLine("\tTarget operates as a synchronized-spindle master control"); + break; } diff --git a/SCSI/Modes/05.cs b/SCSI/Modes/05.cs index e9a229f..baad679 100644 --- a/SCSI/Modes/05.cs +++ b/SCSI/Modes/05.cs @@ -35,137 +35,87 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Modes { #region Mode Page 0x05: Flexible disk page - /// - /// Disconnect-reconnect page - /// Page code 0x05 - /// 32 bytes in SCSI-2, SBC-1 - /// + /// Disconnect-reconnect page Page code 0x05 32 bytes in SCSI-2, SBC-1 public struct ModePage_05 { - /// - /// Parameters can be saved - /// + /// Parameters can be saved public bool PS; - /// - /// Data rate of peripheral device on kbit/s - /// + /// Data rate of peripheral device on kbit/s public ushort TransferRate; - /// - /// Heads for reading and/or writing - /// + /// Heads for reading and/or writing public byte Heads; - /// - /// Sectors per revolution per head - /// + /// Sectors per revolution per head public byte SectorsPerTrack; - /// - /// Bytes of data per sector - /// + /// Bytes of data per sector public ushort BytesPerSector; - /// - /// Cylinders used for data storage - /// + /// Cylinders used for data storage public ushort Cylinders; - /// - /// Cylinder where write precompensation starts - /// + /// Cylinder where write precompensation starts public ushort WritePrecompCylinder; - /// - /// Cylinder where write current reduction starts - /// + /// Cylinder where write current reduction starts public ushort WriteReduceCylinder; - /// - /// Step rate in 100 μs units - /// + /// Step rate in 100 μs units public ushort DriveStepRate; - /// - /// Width of step pulse in μs - /// + /// Width of step pulse in μs public byte DriveStepPulse; - /// - /// Head settle time in 100 μs units - /// + /// Head settle time in 100 μs units public ushort HeadSettleDelay; /// - /// If is true, specified in 1/10s of a - /// second the time waiting for read status before aborting medium - /// access. Otherwise, indicates time to way before medimum access - /// after motor on signal is asserted. + /// If is true, specified in 1/10s of a second the time waiting for read status before + /// aborting medium access. Otherwise, indicates time to way before medimum access after motor on signal is asserted. /// public byte MotorOnDelay; /// - /// Time in 1/10s of a second to wait before releasing the motor on - /// signal after an idle condition. 0xFF means to never release the - /// signal + /// Time in 1/10s of a second to wait before releasing the motor on signal after an idle condition. 0xFF means to + /// never release the signal /// public byte MotorOffDelay; - /// - /// Specifies if a signal indicates that the medium is ready to be accessed - /// + /// Specifies if a signal indicates that the medium is ready to be accessed public bool TRDY; - /// - /// If true sectors start with one. Otherwise, they start with zero. - /// + /// If true sectors start with one. Otherwise, they start with zero. public bool SSN; - /// - /// If true specifies that motor on shall remain released. - /// + /// If true specifies that motor on shall remain released. public bool MO; - /// - /// Number of additional step pulses per cylinder. - /// + /// Number of additional step pulses per cylinder. public byte SPC; - /// - /// Write compensation value - /// + /// Write compensation value public byte WriteCompensation; - /// - /// Head loading time in ms. - /// + /// Head loading time in ms. public byte HeadLoadDelay; - /// - /// Head unloading time in ms. - /// + /// Head unloading time in ms. public byte HeadUnloadDelay; - /// - /// Description of shugart's bus pin 34 usage - /// + /// Description of shugart's bus pin 34 usage public byte Pin34; - /// - /// Description of shugart's bus pin 2 usage - /// + /// Description of shugart's bus pin 2 usage public byte Pin2; - /// - /// Description of shugart's bus pin 4 usage - /// + /// Description of shugart's bus pin 4 usage public byte Pin4; - /// - /// Description of shugart's bus pin 1 usage - /// + /// Description of shugart's bus pin 1 usage public byte Pin1; - /// - /// Medium speed in rpm - /// + /// Medium speed in rpm public ushort MediumRotationRate; } public static ModePage_05? DecodeModePage_05(byte[] pageResponse) { - if((pageResponse?[0] & 0x40) == 0x40) return null; + if((pageResponse?[0] & 0x40) == 0x40) + return null; - if((pageResponse?[0] & 0x3F) != 0x05) return null; + if((pageResponse?[0] & 0x3F) != 0x05) + return null; - if(pageResponse[1] + 2 != pageResponse.Length) return null; + if(pageResponse[1] + 2 != pageResponse.Length) + return null; - if(pageResponse.Length < 32) return null; + if(pageResponse.Length < 32) + return null; - ModePage_05 decoded = new ModePage_05(); + var decoded = new ModePage_05(); decoded.PS |= (pageResponse[0] & 0x80) == 0x80; decoded.TransferRate = (ushort)((pageResponse[2] << 8) + pageResponse[3]); @@ -201,57 +151,73 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyModePage_05(ModePage_05? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; - ModePage_05 page = modePage.Value; - StringBuilder sb = new StringBuilder(); + ModePage_05 page = modePage.Value; + var sb = new StringBuilder(); sb.AppendLine("SCSI Flexible disk page:"); - if(page.PS) sb.AppendLine("\tParameters can be saved"); + if(page.PS) + sb.AppendLine("\tParameters can be saved"); sb.AppendFormat("\tTransfer rate: {0} kbit/s", page.TransferRate).AppendLine(); sb.AppendFormat("\t{0} heads", page.Heads).AppendLine(); sb.AppendFormat("\t{0} cylinders", page.Cylinders).AppendLine(); sb.AppendFormat("\t{0} sectors per track", page.SectorsPerTrack).AppendLine(); sb.AppendFormat("\t{0} bytes per sector", page.BytesPerSector).AppendLine(); + if(page.WritePrecompCylinder < page.Cylinders) - sb.AppendFormat("\tWrite pre-compensation starts at cylinder {0}", page.WritePrecompCylinder) - .AppendLine(); + sb.AppendFormat("\tWrite pre-compensation starts at cylinder {0}", page.WritePrecompCylinder). + AppendLine(); + if(page.WriteReduceCylinder < page.Cylinders) - sb.AppendFormat("\tWrite current reduction starts at cylinder {0}", page.WriteReduceCylinder) - .AppendLine(); + sb.AppendFormat("\tWrite current reduction starts at cylinder {0}", page.WriteReduceCylinder). + AppendLine(); + if(page.DriveStepRate > 0) sb.AppendFormat("\tDrive steps in {0} μs", (uint)page.DriveStepRate * 100).AppendLine(); + if(page.DriveStepPulse > 0) sb.AppendFormat("\tEach step pulse is {0} ms", page.DriveStepPulse).AppendLine(); + if(page.HeadSettleDelay > 0) sb.AppendFormat("\tHeads settles in {0} μs", (uint)page.HeadSettleDelay * 100).AppendLine(); if(!page.TRDY) - sb - .AppendFormat("\tTarget shall wait {0} seconds before attempting to access the medium after motor on is asserted", + sb. + AppendFormat("\tTarget shall wait {0} seconds before attempting to access the medium after motor on is asserted", (double)page.MotorOnDelay * 10).AppendLine(); else - sb - .AppendFormat("\tTarget shall wait {0} seconds after drive is ready before aborting medium access attemps", + sb. + AppendFormat("\tTarget shall wait {0} seconds after drive is ready before aborting medium access attemps", (double)page.MotorOnDelay * 10).AppendLine(); if(page.MotorOffDelay != 0xFF) - sb - .AppendFormat("\tTarget shall wait {0} seconds before releasing the motor on signal after becoming idle", + sb. + AppendFormat("\tTarget shall wait {0} seconds before releasing the motor on signal after becoming idle", (double)page.MotorOffDelay * 10).AppendLine(); - else sb.AppendLine("\tTarget shall never release the motor on signal"); + else + sb.AppendLine("\tTarget shall never release the motor on signal"); - if(page.TRDY) sb.AppendLine("\tThere is a drive ready signal"); - if(page.SSN) sb.AppendLine("\tSectors start at 1"); - if(page.MO) sb.AppendLine("\tThe motor on signal shall remain released"); + if(page.TRDY) + sb.AppendLine("\tThere is a drive ready signal"); + + if(page.SSN) + sb.AppendLine("\tSectors start at 1"); + + if(page.MO) + sb.AppendLine("\tThe motor on signal shall remain released"); sb.AppendFormat("\tDrive needs to do {0} step pulses per cylinder", page.SPC + 1).AppendLine(); if(page.WriteCompensation > 0) sb.AppendFormat("\tWrite pre-compensation is {0}", page.WriteCompensation).AppendLine(); - if(page.HeadLoadDelay > 0) sb.AppendFormat("\tHead takes {0} ms to load", page.HeadLoadDelay).AppendLine(); + + if(page.HeadLoadDelay > 0) + sb.AppendFormat("\tHead takes {0} ms to load", page.HeadLoadDelay).AppendLine(); + if(page.HeadUnloadDelay > 0) sb.AppendFormat("\tHead takes {0} ms to unload", page.HeadUnloadDelay).AppendLine(); @@ -262,18 +228,22 @@ namespace DiscImageChef.Decoders.SCSI { case 0: sb.AppendLine("\tPin 34 is unconnected"); + break; case 1: sb.Append("\tPin 34 indicates drive is ready when active "); sb.Append((page.Pin34 & 0x08) == 0x08 ? "high" : "low"); + break; case 2: sb.Append("\tPin 34 indicates disk has changed when active "); sb.Append((page.Pin34 & 0x08) == 0x08 ? "high" : "low"); + break; default: sb.AppendFormat("\tPin 34 indicates unknown function {0} when active ", page.Pin34 & 0x07); sb.Append((page.Pin34 & 0x08) == 0x08 ? "high" : "low"); + break; } @@ -281,22 +251,27 @@ namespace DiscImageChef.Decoders.SCSI { case 0: sb.AppendLine("\tPin 4 is unconnected"); + break; case 1: sb.Append("\tPin 4 indicates drive is in use when active "); sb.Append((page.Pin4 & 0x08) == 0x08 ? "high" : "low"); + break; case 2: sb.Append("\tPin 4 indicates eject when active "); sb.Append((page.Pin4 & 0x08) == 0x08 ? "high" : "low"); + break; case 3: sb.Append("\tPin 4 indicates head load when active "); sb.Append((page.Pin4 & 0x08) == 0x08 ? "high" : "low"); + break; default: sb.AppendFormat("\tPin 4 indicates unknown function {0} when active ", page.Pin4 & 0x07); sb.Append((page.Pin4 & 0x08) == 0x08 ? "high" : "low"); + break; } @@ -304,10 +279,12 @@ namespace DiscImageChef.Decoders.SCSI { case 0: sb.AppendLine("\tPin 2 is unconnected"); + break; default: sb.AppendFormat("\tPin 2 indicates unknown function {0} when active ", page.Pin2 & 0x07); sb.Append((page.Pin2 & 0x08) == 0x08 ? "high" : "low"); + break; } @@ -315,14 +292,17 @@ namespace DiscImageChef.Decoders.SCSI { case 0: sb.AppendLine("\tPin 1 is unconnected"); + break; case 1: sb.Append("\tPin 1 indicates disk change reset when active "); sb.Append((page.Pin1 & 0x08) == 0x08 ? "high" : "low"); + break; default: sb.AppendFormat("\tPin 1 indicates unknown function {0} when active ", page.Pin1 & 0x07); sb.Append((page.Pin1 & 0x08) == 0x08 ? "high" : "low"); + break; } diff --git a/SCSI/Modes/06.cs b/SCSI/Modes/06.cs index 1cc4bc0..6bdaf9a 100644 --- a/SCSI/Modes/06.cs +++ b/SCSI/Modes/06.cs @@ -35,40 +35,35 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Modes { #region Mode Page 0x06: Optical memory page - /// - /// Optical memory page - /// Page code 0x06 - /// 4 bytes in SCSI-2 - /// + /// Optical memory page Page code 0x06 4 bytes in SCSI-2 public struct ModePage_06 { - /// - /// Parameters can be saved - /// + /// Parameters can be saved public bool PS; - /// - /// Report updated block read - /// + /// Report updated block read public bool RUBR; } public static ModePage_06? DecodeModePage_06(byte[] pageResponse) { - if((pageResponse?[0] & 0x40) == 0x40) return null; + if((pageResponse?[0] & 0x40) == 0x40) + return null; - if((pageResponse?[0] & 0x3F) != 0x06) return null; + if((pageResponse?[0] & 0x3F) != 0x06) + return null; - if(pageResponse[1] + 2 != pageResponse.Length) return null; + if(pageResponse[1] + 2 != pageResponse.Length) + return null; - if(pageResponse.Length < 4) return null; + if(pageResponse.Length < 4) + return null; - ModePage_06 decoded = new ModePage_06(); + var decoded = new ModePage_06(); decoded.PS |= (pageResponse[0] & 0x80) == 0x80; decoded.RUBR |= (pageResponse[2] & 0x01) == 0x01; @@ -81,15 +76,19 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyModePage_06(ModePage_06? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; - ModePage_06 page = modePage.Value; - StringBuilder sb = new StringBuilder(); + ModePage_06 page = modePage.Value; + var sb = new StringBuilder(); sb.AppendLine("SCSI optical memory:"); - if(page.PS) sb.AppendLine("\tParameters can be saved"); - if(page.RUBR) sb.AppendLine("\tOn reading an updated block drive will return RECOVERED ERROR"); + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + if(page.RUBR) + sb.AppendLine("\tOn reading an updated block drive will return RECOVERED ERROR"); return sb.ToString(); } diff --git a/SCSI/Modes/07.cs b/SCSI/Modes/07.cs index 6e6e8e2..5697a8f 100644 --- a/SCSI/Modes/07.cs +++ b/SCSI/Modes/07.cs @@ -35,65 +35,47 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] public static partial class Modes { #region Mode Page 0x07: Verify error recovery page - /// - /// Disconnect-reconnect page - /// Page code 0x07 - /// 12 bytes in SCSI-2, SBC-1, SBC-2 - /// + /// Disconnect-reconnect page Page code 0x07 12 bytes in SCSI-2, SBC-1, SBC-2 public struct ModePage_07 { - /// - /// Parameters can be saved - /// + /// Parameters can be saved public bool PS; - /// - /// Enable early recovery - /// + /// Enable early recovery public bool EER; - /// - /// Post error reporting - /// + /// Post error reporting public bool PER; - /// - /// Disable transfer on error - /// + /// Disable transfer on error public bool DTE; - /// - /// Disable correction - /// + /// Disable correction public bool DCR; - /// - /// How many times to retry a verify operation - /// + /// How many times to retry a verify operation public byte VerifyRetryCount; - /// - /// How many bits of largest data burst error is maximum to apply error correction on it - /// + /// How many bits of largest data burst error is maximum to apply error correction on it public byte CorrectionSpan; - /// - /// Maximum time in ms to use in data error recovery procedures - /// + /// Maximum time in ms to use in data error recovery procedures public ushort RecoveryTimeLimit; } public static ModePage_07? DecodeModePage_07(byte[] pageResponse) { - if((pageResponse?[0] & 0x40) == 0x40) return null; + if((pageResponse?[0] & 0x40) == 0x40) + return null; - if((pageResponse?[0] & 0x3F) != 0x07) return null; + if((pageResponse?[0] & 0x3F) != 0x07) + return null; - if(pageResponse[1] + 2 != pageResponse.Length) return null; + if(pageResponse[1] + 2 != pageResponse.Length) + return null; - if(pageResponse.Length < 12) return null; + if(pageResponse.Length < 12) + return null; - ModePage_07 decoded = new ModePage_07(); + var decoded = new ModePage_07(); decoded.PS |= (pageResponse[0] & 0x80) == 0x80; decoded.EER |= (pageResponse[2] & 0x08) == 0x08; @@ -113,24 +95,35 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyModePage_07(ModePage_07? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; - ModePage_07 page = modePage.Value; - StringBuilder sb = new StringBuilder(); + ModePage_07 page = modePage.Value; + var sb = new StringBuilder(); sb.AppendLine("SCSI Verify error recovery page:"); - if(page.PS) sb.AppendLine("\tParameters can be saved"); + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + if(page.EER) + sb.AppendLine("\tDrive will use the most expedient form of error recovery first"); + + if(page.PER) + sb.AppendLine("\tDrive shall report recovered errors"); + + if(page.DTE) + sb.AppendLine("\tTransfer will be terminated upon error detection"); + + if(page.DCR) + sb.AppendLine("\tError correction is disabled"); - if(page.EER) sb.AppendLine("\tDrive will use the most expedient form of error recovery first"); - if(page.PER) sb.AppendLine("\tDrive shall report recovered errors"); - if(page.DTE) sb.AppendLine("\tTransfer will be terminated upon error detection"); - if(page.DCR) sb.AppendLine("\tError correction is disabled"); if(page.VerifyRetryCount > 0) sb.AppendFormat("\tDrive will repeat verify operations {0} times", page.VerifyRetryCount).AppendLine(); + if(page.RecoveryTimeLimit > 0) - sb.AppendFormat("\tDrive will employ a maximum of {0} ms to recover data", page.RecoveryTimeLimit) - .AppendLine(); + sb.AppendFormat("\tDrive will employ a maximum of {0} ms to recover data", page.RecoveryTimeLimit). + AppendLine(); return sb.ToString(); } diff --git a/SCSI/Modes/07_MMC.cs b/SCSI/Modes/07_MMC.cs index a743362..1d06734 100644 --- a/SCSI/Modes/07_MMC.cs +++ b/SCSI/Modes/07_MMC.cs @@ -35,44 +35,37 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Modes { #region Mode Page 0x07: Verify error recovery page for MultiMedia Devices - /// - /// Verify error recovery page for MultiMedia Devices - /// Page code 0x07 - /// 8 bytes in SCSI-2, MMC-1 - /// + /// Verify error recovery page for MultiMedia Devices Page code 0x07 8 bytes in SCSI-2, MMC-1 public struct ModePage_07_MMC { - /// - /// Parameters can be saved - /// + /// Parameters can be saved public bool PS; - /// - /// Error recovery parameter - /// + /// Error recovery parameter public byte Parameter; - /// - /// How many times to retry a verify operation - /// + /// How many times to retry a verify operation public byte VerifyRetryCount; } public static ModePage_07_MMC? DecodeModePage_07_MMC(byte[] pageResponse) { - if((pageResponse?[0] & 0x40) == 0x40) return null; + if((pageResponse?[0] & 0x40) == 0x40) + return null; - if((pageResponse?[0] & 0x3F) != 0x07) return null; + if((pageResponse?[0] & 0x3F) != 0x07) + return null; - if(pageResponse[1] + 2 != pageResponse.Length) return null; + if(pageResponse[1] + 2 != pageResponse.Length) + return null; - if(pageResponse.Length < 8) return null; + if(pageResponse.Length < 8) + return null; - ModePage_07_MMC decoded = new ModePage_07_MMC(); + var decoded = new ModePage_07_MMC(); decoded.PS |= (pageResponse[0] & 0x80) == 0x80; decoded.Parameter = pageResponse[2]; @@ -86,14 +79,17 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyModePage_07_MMC(ModePage_07_MMC? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; ModePage_07_MMC page = modePage.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendLine("SCSI Verify error recovery page for MultiMedia Devices:"); - if(page.PS) sb.AppendLine("\tParameters can be saved"); + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + if(page.VerifyRetryCount > 0) sb.AppendFormat("\tDrive will repeat verify operations {0} times", page.VerifyRetryCount).AppendLine(); @@ -107,8 +103,10 @@ namespace DiscImageChef.Decoders.SCSI string UnrecCIRCAbort = "\tUnrecovered CIRC errors will return CHECK CONDITION."; string UnrecECCNotAbort = "\tUnrecovered ECC errors will not abort the transfer."; string UnrecCIRCNotAbort = "\tUnrecovered CIRC errors will not abort the transfer."; + string UnrecECCAbortData = "\tUnrecovered ECC errors will return CHECK CONDITION and the uncorrected data."; + string UnrecCIRCAbortData = "\tUnrecovered CIRC errors will return CHECK CONDITION and the uncorrected data."; @@ -116,51 +114,67 @@ namespace DiscImageChef.Decoders.SCSI { case 0x00: sb.AppendLine(AllUsed + RecoveredNotReported + UnrecECCAbort); + break; case 0x01: sb.AppendLine(CIRCRetriesUsed + RecoveredNotReported + UnrecCIRCAbort); + break; case 0x04: sb.AppendLine(AllUsed + RecoveredReported + UnrecECCAbort); + break; case 0x05: sb.AppendLine(CIRCRetriesUsed + RecoveredReported + UnrecCIRCAbort); + break; case 0x06: sb.AppendLine(AllUsed + RecoveredAbort + UnrecECCAbort); + break; case 0x07: sb.AppendLine(RetriesUsed + RecoveredAbort + UnrecCIRCAbort); + break; case 0x10: sb.AppendLine(AllUsed + RecoveredNotReported + UnrecECCNotAbort); + break; case 0x11: sb.AppendLine(CIRCRetriesUsed + RecoveredNotReported + UnrecCIRCNotAbort); + break; case 0x14: sb.AppendLine(AllUsed + RecoveredReported + UnrecECCNotAbort); + break; case 0x15: sb.AppendLine(CIRCRetriesUsed + RecoveredReported + UnrecCIRCNotAbort); + break; case 0x20: sb.AppendLine(AllUsed + RecoveredNotReported + UnrecECCAbortData); + break; case 0x21: sb.AppendLine(CIRCRetriesUsed + RecoveredNotReported + UnrecCIRCAbortData); + break; case 0x24: sb.AppendLine(AllUsed + RecoveredReported + UnrecECCAbortData); + break; case 0x25: sb.AppendLine(CIRCRetriesUsed + RecoveredReported + UnrecCIRCAbortData); + break; case 0x26: sb.AppendLine(AllUsed + RecoveredAbort + UnrecECCAbortData); + break; case 0x27: sb.AppendLine(RetriesUsed + RecoveredAbort + UnrecCIRCAbortData); + break; case 0x30: goto case 0x10; case 0x31: goto case 0x11; @@ -168,6 +182,7 @@ namespace DiscImageChef.Decoders.SCSI case 0x35: goto case 0x15; default: sb.AppendFormat("Unknown recovery parameter 0x{0:X2}", page.Parameter).AppendLine(); + break; } diff --git a/SCSI/Modes/08.cs b/SCSI/Modes/08.cs index 70a8a8e..b5b797d 100644 --- a/SCSI/Modes/08.cs +++ b/SCSI/Modes/08.cs @@ -35,104 +35,56 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Modes { #region Mode Page 0x08: Caching page - /// - /// Disconnect-reconnect page - /// Page code 0x08 - /// 12 bytes in SCSI-2 - /// 20 bytes in SBC-1, SBC-2, SBC-3 - /// + /// Disconnect-reconnect page Page code 0x08 12 bytes in SCSI-2 20 bytes in SBC-1, SBC-2, SBC-3 public struct ModePage_08 { - /// - /// Parameters can be saved - /// + /// Parameters can be saved public bool PS; - /// - /// true if write cache is enabled - /// + /// true if write cache is enabled public bool WCE; - /// - /// Multiplication factor - /// + /// Multiplication factor public bool MF; - /// - /// true if read cache is enabled - /// + /// true if read cache is enabled public bool RCD; - /// - /// Advices on reading-cache retention priority - /// + /// Advices on reading-cache retention priority public byte DemandReadRetentionPrio; - /// - /// Advices on writing-cache retention priority - /// + /// Advices on writing-cache retention priority public byte WriteRetentionPriority; - /// - /// If requested read blocks are more than this, no pre-fetch is done - /// + /// If requested read blocks are more than this, no pre-fetch is done public ushort DisablePreFetch; - /// - /// Minimum pre-fetch - /// + /// Minimum pre-fetch public ushort MinimumPreFetch; - /// - /// Maximum pre-fetch - /// + /// Maximum pre-fetch public ushort MaximumPreFetch; - /// - /// Upper limit on maximum pre-fetch value - /// + /// Upper limit on maximum pre-fetch value public ushort MaximumPreFetchCeiling; - /// - /// Manual cache controlling - /// + /// Manual cache controlling public bool IC; - /// - /// Abort pre-fetch - /// + /// Abort pre-fetch public bool ABPF; - /// - /// Caching analysis permitted - /// + /// Caching analysis permitted public bool CAP; - /// - /// Pre-fetch over discontinuities - /// + /// Pre-fetch over discontinuities public bool Disc; - /// - /// is to be used to control caching segmentation - /// + /// is to be used to control caching segmentation public bool Size; - /// - /// Force sequential write - /// + /// Force sequential write public bool FSW; - /// - /// Logical block cache segment size - /// + /// Logical block cache segment size public bool LBCSS; - /// - /// Disable read-ahead - /// + /// Disable read-ahead public bool DRA; - /// - /// How many segments should the cache be divided upon - /// + /// How many segments should the cache be divided upon public byte CacheSegments; - /// - /// How many bytes should the cache be divided upon - /// + /// How many bytes should the cache be divided upon public ushort CacheSegmentSize; - /// - /// How many bytes should be used as a buffer when all other cached data cannot be evicted - /// + /// How many bytes should be used as a buffer when all other cached data cannot be evicted public uint NonCacheSegmentSize; public bool NV_DIS; @@ -140,15 +92,19 @@ namespace DiscImageChef.Decoders.SCSI public static ModePage_08? DecodeModePage_08(byte[] pageResponse) { - if((pageResponse?[0] & 0x40) == 0x40) return null; + if((pageResponse?[0] & 0x40) == 0x40) + return null; - if((pageResponse?[0] & 0x3F) != 0x08) return null; + if((pageResponse?[0] & 0x3F) != 0x08) + return null; - if(pageResponse[1] + 2 != pageResponse.Length) return null; + if(pageResponse[1] + 2 != pageResponse.Length) + return null; - if(pageResponse.Length < 12) return null; + if(pageResponse.Length < 12) + return null; - ModePage_08 decoded = new ModePage_08(); + var decoded = new ModePage_08(); decoded.PS |= (pageResponse[0] & 0x80) == 0x80; decoded.WCE |= (pageResponse[2] & 0x04) == 0x04; @@ -162,7 +118,8 @@ namespace DiscImageChef.Decoders.SCSI decoded.MaximumPreFetch = (ushort)((pageResponse[8] << 8) + pageResponse[9]); decoded.MaximumPreFetchCeiling = (ushort)((pageResponse[10] << 8) + pageResponse[11]); - if(pageResponse.Length < 20) return decoded; + if(pageResponse.Length < 20) + return decoded; decoded.IC |= (pageResponse[2] & 0x80) == 0x80; decoded.ABPF |= (pageResponse[2] & 0x40) == 0x40; @@ -188,31 +145,41 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyModePage_08(ModePage_08? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; - ModePage_08 page = modePage.Value; - StringBuilder sb = new StringBuilder(); + ModePage_08 page = modePage.Value; + var sb = new StringBuilder(); sb.AppendLine("SCSI Caching mode page:"); - if(page.PS) sb.AppendLine("\tParameters can be saved"); - if(page.RCD) sb.AppendLine("\tRead-cache is enabled"); - if(page.WCE) sb.AppendLine("\tWrite-cache is enabled"); + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + if(page.RCD) + sb.AppendLine("\tRead-cache is enabled"); + + if(page.WCE) + sb.AppendLine("\tWrite-cache is enabled"); switch(page.DemandReadRetentionPrio) { case 0: sb.AppendLine("\tDrive does not distinguish between cached read data"); + break; case 1: sb.AppendLine("\tData put by READ commands should be evicted from cache sooner than data put in read cache by other means"); + break; case 0xF: sb.AppendLine("\tData put by READ commands should not be evicted if there is data cached by other means that can be evicted"); + break; default: - sb.AppendFormat("\tUnknown demand read retention priority value {0}", page.DemandReadRetentionPrio) - .AppendLine(); + sb.AppendFormat("\tUnknown demand read retention priority value {0}", page.DemandReadRetentionPrio). + AppendLine(); + break; } @@ -220,61 +187,76 @@ namespace DiscImageChef.Decoders.SCSI { case 0: sb.AppendLine("\tDrive does not distinguish between cached write data"); + break; case 1: sb.AppendLine("\tData put by WRITE commands should be evicted from cache sooner than data put in write cache by other means"); + break; case 0xF: sb.AppendLine("\tData put by WRITE commands should not be evicted if there is data cached by other means that can be evicted"); + break; default: - sb.AppendFormat("\tUnknown demand write retention priority value {0}", page.DemandReadRetentionPrio) - .AppendLine(); + sb.AppendFormat("\tUnknown demand write retention priority value {0}", + page.DemandReadRetentionPrio).AppendLine(); + break; } - if(page.DRA) sb.AppendLine("\tRead-ahead is disabled"); + if(page.DRA) + sb.AppendLine("\tRead-ahead is disabled"); else { - if(page.MF) sb.AppendLine("\tPre-fetch values indicate a block multiplier"); + if(page.MF) + sb.AppendLine("\tPre-fetch values indicate a block multiplier"); - if(page.DisablePreFetch == 0) sb.AppendLine("\tNo pre-fetch will be done"); + if(page.DisablePreFetch == 0) + sb.AppendLine("\tNo pre-fetch will be done"); else { sb.AppendFormat("\tPre-fetch will be done for READ commands of {0} blocks or less", page.DisablePreFetch).AppendLine(); if(page.MinimumPreFetch > 0) - sb.AppendFormat("At least {0} blocks will be always pre-fetched", page.MinimumPreFetch) - .AppendLine(); + sb.AppendFormat("At least {0} blocks will be always pre-fetched", page.MinimumPreFetch). + AppendLine(); + if(page.MaximumPreFetch > 0) - sb.AppendFormat("\tA maximum of {0} blocks will be pre-fetched", page.MaximumPreFetch) - .AppendLine(); + sb.AppendFormat("\tA maximum of {0} blocks will be pre-fetched", page.MaximumPreFetch). + AppendLine(); + if(page.MaximumPreFetchCeiling > 0) - sb - .AppendFormat("\tA maximum of {0} blocks will be pre-fetched even if it is commanded to pre-fetch more", + sb. + AppendFormat("\tA maximum of {0} blocks will be pre-fetched even if it is commanded to pre-fetch more", page.MaximumPreFetchCeiling).AppendLine(); if(page.IC) sb.AppendLine("\tDevice should use number of cache segments or cache segment size for caching"); - if(page.ABPF) sb.AppendLine("\tPre-fetch should be aborted upong receiving a new command"); - if(page.CAP) sb.AppendLine("\tCaching analysis is permitted"); + + if(page.ABPF) + sb.AppendLine("\tPre-fetch should be aborted upong receiving a new command"); + + if(page.CAP) + sb.AppendLine("\tCaching analysis is permitted"); + if(page.Disc) sb.AppendLine("\tPre-fetch can continue across discontinuities (such as cylinders or tracks)"); } } - if(page.FSW) sb.AppendLine("\tDrive should not reorder the sequence of write commands to be faster"); + if(page.FSW) + sb.AppendLine("\tDrive should not reorder the sequence of write commands to be faster"); if(page.Size) { if(page.CacheSegmentSize > 0) if(page.LBCSS) - sb.AppendFormat("\tDrive cache segments should be {0} blocks long", page.CacheSegmentSize) - .AppendLine(); + sb.AppendFormat("\tDrive cache segments should be {0} blocks long", page.CacheSegmentSize). + AppendLine(); else - sb.AppendFormat("\tDrive cache segments should be {0} bytes long", page.CacheSegmentSize) - .AppendLine(); + sb.AppendFormat("\tDrive cache segments should be {0} bytes long", page.CacheSegmentSize). + AppendLine(); } else { @@ -283,11 +265,12 @@ namespace DiscImageChef.Decoders.SCSI } if(page.NonCacheSegmentSize > 0) - sb - .AppendFormat("\tDrive shall allocate {0} bytes to buffer even when all cached data cannot be evicted", + sb. + AppendFormat("\tDrive shall allocate {0} bytes to buffer even when all cached data cannot be evicted", page.NonCacheSegmentSize).AppendLine(); - if(page.NV_DIS) sb.AppendLine("\tNon-Volatile cache is disabled"); + if(page.NV_DIS) + sb.AppendLine("\tNon-Volatile cache is disabled"); return sb.ToString(); } diff --git a/SCSI/Modes/0A.cs b/SCSI/Modes/0A.cs index fb0c183..1283a3c 100644 --- a/SCSI/Modes/0A.cs +++ b/SCSI/Modes/0A.cs @@ -35,147 +35,95 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Modes { #region Mode Page 0x0A: Control mode page - /// - /// Control mode page - /// Page code 0x0A - /// 8 bytes in SCSI-2 - /// 12 bytes in SPC-1, SPC-2, SPC-3, SPC-4, SPC-5 - /// + /// Control mode page Page code 0x0A 8 bytes in SCSI-2 12 bytes in SPC-1, SPC-2, SPC-3, SPC-4, SPC-5 public struct ModePage_0A { - /// - /// Parameters can be saved - /// + /// Parameters can be saved public bool PS; - /// - /// If set, target shall report log exception conditions - /// + /// If set, target shall report log exception conditions public bool RLEC; - /// - /// Queue algorithm modifier - /// + /// Queue algorithm modifier public byte QueueAlgorithm; /// - /// If set all remaining suspended I/O processes shall be aborted after the contingent allegiance condition or extended - /// contingent allegiance condition + /// If set all remaining suspended I/O processes shall be aborted after the contingent allegiance condition or + /// extended contingent allegiance condition /// public byte QErr; - /// - /// Tagged queuing is disabled - /// + /// Tagged queuing is disabled public bool DQue; - /// - /// Extended Contingent Allegiance is enabled - /// + /// Extended Contingent Allegiance is enabled public bool EECA; - /// - /// Target may issue an asynchronous event notification upon completing its initialization - /// + /// Target may issue an asynchronous event notification upon completing its initialization public bool RAENP; - /// - /// Target may issue an asynchronous event notification instead of a unit attention condition - /// + /// Target may issue an asynchronous event notification instead of a unit attention condition public bool UAAENP; - /// - /// Target may issue an asynchronous event notification instead of a deferred error - /// + /// Target may issue an asynchronous event notification instead of a deferred error public bool EAENP; - /// - /// Minimum time in ms after initialization before attempting asynchronous event notifications - /// + /// Minimum time in ms after initialization before attempting asynchronous event notifications public ushort ReadyAENHoldOffPeriod; - /// - /// Global logging target save disabled - /// + /// Global logging target save disabled public bool GLTSD; - /// - /// CHECK CONDITION should be reported rather than a long busy condition - /// + /// CHECK CONDITION should be reported rather than a long busy condition public bool RAC; - /// - /// Software write protect is active - /// + /// Software write protect is active public bool SWP; - /// - /// Maximum time in 100 ms units allowed to remain busy. 0xFFFF == unlimited. - /// + /// Maximum time in 100 ms units allowed to remain busy. 0xFFFF == unlimited. public ushort BusyTimeoutPeriod; - /// - /// Task set type - /// + /// Task set type public byte TST; - /// - /// Tasks aborted by other initiator's actions should be terminated with TASK ABORTED - /// + /// Tasks aborted by other initiator's actions should be terminated with TASK ABORTED public bool TAS; - /// - /// Action to be taken when a medium is inserted - /// + /// Action to be taken when a medium is inserted public byte AutoloadMode; - /// - /// Time in seconds to complete an extended self-test - /// + /// Time in seconds to complete an extended self-test public byte ExtendedSelfTestCompletionTime; - /// - /// All tasks received in nexus with ACA ACTIVE is set and an ACA condition is established shall terminate - /// + /// All tasks received in nexus with ACA ACTIVE is set and an ACA condition is established shall terminate public bool TMF_ONLY; /// /// Device shall return descriptor format sense data when returning sense data in the same transactions as a CHECK /// CONDITION /// public bool D_SENSE; - /// - /// Unit attention interlocks control - /// + /// Unit attention interlocks control public byte UA_INTLCK_CTRL; - /// - /// LOGICAL BLOCK APPLICATION TAG should not be modified - /// + /// LOGICAL BLOCK APPLICATION TAG should not be modified public bool ATO; - /// - /// Protector information checking is disabled - /// + /// Protector information checking is disabled public bool DPICZ; - /// - /// No unit attention on release - /// + /// No unit attention on release public bool NUAR; - /// - /// Application Tag mode page is enabled - /// + /// Application Tag mode page is enabled public bool ATMPE; - /// - /// Abort any write command without protection information - /// + /// Abort any write command without protection information public bool RWWP; - /// - /// Supportes block lengths and protection information - /// + /// Supportes block lengths and protection information public bool SBLP; } public static ModePage_0A? DecodeModePage_0A(byte[] pageResponse) { - if((pageResponse?[0] & 0x40) == 0x40) return null; + if((pageResponse?[0] & 0x40) == 0x40) + return null; - if((pageResponse?[0] & 0x3F) != 0x0A) return null; + if((pageResponse?[0] & 0x3F) != 0x0A) + return null; - if(pageResponse[1] + 2 != pageResponse.Length) return null; + if(pageResponse[1] + 2 != pageResponse.Length) + return null; - if(pageResponse.Length < 8) return null; + if(pageResponse.Length < 8) + return null; - ModePage_0A decoded = new ModePage_0A(); + var decoded = new ModePage_0A(); decoded.PS |= (pageResponse[0] & 0x80) == 0x80; decoded.RLEC |= (pageResponse[2] & 0x01) == 0x01; @@ -191,7 +139,8 @@ namespace DiscImageChef.Decoders.SCSI decoded.ReadyAENHoldOffPeriod = (ushort)((pageResponse[6] << 8) + pageResponse[7]); - if(pageResponse.Length < 10) return decoded; + if(pageResponse.Length < 10) + return decoded; // SPC-1 decoded.GLTSD |= (pageResponse[2] & 0x02) == 0x02; @@ -228,49 +177,84 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyModePage_0A(ModePage_0A? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; - ModePage_0A page = modePage.Value; - StringBuilder sb = new StringBuilder(); + ModePage_0A page = modePage.Value; + var sb = new StringBuilder(); sb.AppendLine("SCSI Control mode page:"); - if(page.PS) sb.AppendLine("\tParameters can be saved"); - if(page.RLEC) sb.AppendLine("\tIf set, target shall report log exception conditions"); - if(page.DQue) sb.AppendLine("\tTagged queuing is disabled"); - if(page.EECA) sb.AppendLine("\tExtended Contingent Allegiance is enabled"); + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + if(page.RLEC) + sb.AppendLine("\tIf set, target shall report log exception conditions"); + + if(page.DQue) + sb.AppendLine("\tTagged queuing is disabled"); + + if(page.EECA) + sb.AppendLine("\tExtended Contingent Allegiance is enabled"); + if(page.RAENP) sb.AppendLine("\tTarget may issue an asynchronous event notification upon completing its initialization"); + if(page.UAAENP) sb.AppendLine("\tTarget may issue an asynchronous event notification instead of a unit attention condition"); + if(page.EAENP) sb.AppendLine("\tTarget may issue an asynchronous event notification instead of a deferred error"); - if(page.GLTSD) sb.AppendLine("\tGlobal logging target save disabled"); - if(page.RAC) sb.AppendLine("\tCHECK CONDITION should be reported rather than a long busy condition"); - if(page.SWP) sb.AppendLine("\tSoftware write protect is active"); + + if(page.GLTSD) + sb.AppendLine("\tGlobal logging target save disabled"); + + if(page.RAC) + sb.AppendLine("\tCHECK CONDITION should be reported rather than a long busy condition"); + + if(page.SWP) + sb.AppendLine("\tSoftware write protect is active"); + if(page.TAS) sb.AppendLine("\tTasks aborted by other initiator's actions should be terminated with TASK ABORTED"); + if(page.TMF_ONLY) sb.AppendLine("\tAll tasks received in nexus with ACA ACTIVE is set and an ACA condition is established shall terminate"); + if(page.D_SENSE) sb.AppendLine("\tDevice shall return descriptor format sense data when returning sense data in the same transactions as a CHECK CONDITION"); - if(page.ATO) sb.AppendLine("\tLOGICAL BLOCK APPLICATION TAG should not be modified"); - if(page.DPICZ) sb.AppendLine("\tProtector information checking is disabled"); - if(page.NUAR) sb.AppendLine("\tNo unit attention on release"); - if(page.ATMPE) sb.AppendLine("\tApplication Tag mode page is enabled"); - if(page.RWWP) sb.AppendLine("\tAbort any write command without protection information"); - if(page.SBLP) sb.AppendLine("\tSupportes block lengths and protection information"); + + if(page.ATO) + sb.AppendLine("\tLOGICAL BLOCK APPLICATION TAG should not be modified"); + + if(page.DPICZ) + sb.AppendLine("\tProtector information checking is disabled"); + + if(page.NUAR) + sb.AppendLine("\tNo unit attention on release"); + + if(page.ATMPE) + sb.AppendLine("\tApplication Tag mode page is enabled"); + + if(page.RWWP) + sb.AppendLine("\tAbort any write command without protection information"); + + if(page.SBLP) + sb.AppendLine("\tSupportes block lengths and protection information"); switch(page.TST) { case 0: sb.AppendLine("\tThe logical unit maintains one task set for all nexuses"); + break; case 1: sb.AppendLine("\tThe logical unit maintains separate task sets for each nexus"); + break; default: sb.AppendFormat("\tUnknown Task set type {0}", page.TST).AppendLine(); + break; } @@ -278,12 +262,15 @@ namespace DiscImageChef.Decoders.SCSI { case 0: sb.AppendLine("\tCommands should be sent strictly ordered"); + break; case 1: sb.AppendLine("\tCommands can be reordered in any manner"); + break; default: sb.AppendFormat("\tUnknown Queue Algorithm Modifier {0}", page.QueueAlgorithm).AppendLine(); + break; } @@ -291,15 +278,19 @@ namespace DiscImageChef.Decoders.SCSI { case 0: sb.AppendLine("\tIf ACA is established, the task set commands shall resume after it is cleared, otherwise they shall terminate with CHECK CONDITION"); + break; case 1: sb.AppendLine("\tAll the affected commands in the task set shall be aborted when CHECK CONDITION is returned"); + break; case 3: sb.AppendLine("\tAffected commands in the task set belonging with the CHECK CONDITION nexus shall be aborted"); + break; default: sb.AppendLine("\tReserved QErr value 2 is set"); + break; } @@ -307,15 +298,19 @@ namespace DiscImageChef.Decoders.SCSI { case 0: sb.AppendLine("\tLUN shall clear unit attention condition reported in the same nexus"); + break; case 2: sb.AppendLine("\tLUN shall not clear unit attention condition reported in the same nexus"); + break; case 3: sb.AppendLine("\tLUN shall not clear unit attention condition reported in the same nexus and shall establish a unit attention condition for the initiator"); + break; default: sb.AppendLine("\tReserved UA_INTLCK_CTRL value 1 is set"); + break; } @@ -323,15 +318,19 @@ namespace DiscImageChef.Decoders.SCSI { case 0: sb.AppendLine("\tOn medium insertion, it shall be loaded for full access"); + break; case 1: sb.AppendLine("\tOn medium insertion, it shall be loaded for auxiliary memory access only"); + break; case 2: sb.AppendLine("\tOn medium insertion, it shall not be loaded"); + break; default: sb.AppendFormat("\tReserved autoload mode {0} set", page.AutoloadMode).AppendLine(); + break; } @@ -343,8 +342,8 @@ namespace DiscImageChef.Decoders.SCSI if(page.BusyTimeoutPeriod == 0xFFFF) sb.AppendLine("\tThere is no limit on the maximum time that is allowed to remain busy"); else - sb.AppendFormat("\tA maximum of {0} ms are allowed to remain busy", page.BusyTimeoutPeriod * 100) - .AppendLine(); + sb.AppendFormat("\tA maximum of {0} ms are allowed to remain busy", page.BusyTimeoutPeriod * 100). + AppendLine(); if(page.ExtendedSelfTestCompletionTime > 0) sb.AppendFormat("\t{0} seconds to complete extended self-test", page.ExtendedSelfTestCompletionTime); @@ -354,58 +353,44 @@ namespace DiscImageChef.Decoders.SCSI #endregion Mode Page 0x0A: Control mode page #region Mode Page 0x0A subpage 0x01: Control Extension mode page - /// - /// Control Extension mode page - /// Page code 0x0A - /// Subpage code 0x01 - /// 32 bytes in SPC-3, SPC-4, SPC-5 - /// + /// Control Extension mode page Page code 0x0A Subpage code 0x01 32 bytes in SPC-3, SPC-4, SPC-5 public struct ModePage_0A_S01 { - /// - /// Parameters can be saved - /// + /// Parameters can be saved public bool PS; - /// - /// Timestamp outside this standard - /// + /// Timestamp outside this standard public bool TCMOS; - /// - /// SCSI precedence - /// + /// SCSI precedence public bool SCSIP; - /// - /// Implicit Asymmetric Logical Unit Access Enabled - /// + /// Implicit Asymmetric Logical Unit Access Enabled public bool IALUAE; - /// - /// Initial task priority - /// + /// Initial task priority public byte InitialPriority; - /// - /// Device life control disabled - /// + /// Device life control disabled public bool DLC; - /// - /// Maximum size of SENSE data in bytes - /// + /// Maximum size of SENSE data in bytes public byte MaximumSenseLength; } public static ModePage_0A_S01? DecodeModePage_0A_S01(byte[] pageResponse) { - if((pageResponse?[0] & 0x40) != 0x40) return null; + if((pageResponse?[0] & 0x40) != 0x40) + return null; - if((pageResponse[0] & 0x3F) != 0x0A) return null; + if((pageResponse[0] & 0x3F) != 0x0A) + return null; - if(pageResponse[1] != 0x01) return null; + if(pageResponse[1] != 0x01) + return null; - if((pageResponse[2] << 8) + pageResponse[3] + 4 != pageResponse.Length) return null; + if((pageResponse[2] << 8) + pageResponse[3] + 4 != pageResponse.Length) + return null; - if(pageResponse.Length < 32) return null; + if(pageResponse.Length < 32) + return null; - ModePage_0A_S01 decoded = new ModePage_0A_S01(); + var decoded = new ModePage_0A_S01(); decoded.PS |= (pageResponse[0] & 0x80) == 0x80; @@ -423,29 +408,34 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyModePage_0A_S01(ModePage_0A_S01? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; ModePage_0A_S01 page = modePage.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendLine("SCSI Control extension page:"); - if(page.PS) sb.AppendLine("\tParameters can be saved"); + if(page.PS) + sb.AppendLine("\tParameters can be saved"); if(page.TCMOS) { sb.Append("\tTimestamp can be initialized by methods outside of the SCSI standards"); - if(page.SCSIP) sb.Append(", but SCSI's SET TIMESTAMP shall take precedence over them"); + if(page.SCSIP) + sb.Append(", but SCSI's SET TIMESTAMP shall take precedence over them"); sb.AppendLine(); } - if(page.IALUAE) sb.AppendLine("\tImplicit Asymmetric Logical Unit Access is enabled"); + if(page.IALUAE) + sb.AppendLine("\tImplicit Asymmetric Logical Unit Access is enabled"); sb.AppendFormat("\tInitial priority is {0}", page.InitialPriority).AppendLine(); - if(page.DLC) sb.AppendLine("\tDevice will not degrade performance to extend its life"); + if(page.DLC) + sb.AppendLine("\tDevice will not degrade performance to extend its life"); if(page.MaximumSenseLength > 0) sb.AppendFormat("\tMaximum sense data would be {0} bytes", page.MaximumSenseLength).AppendLine(); diff --git a/SCSI/Modes/0B.cs b/SCSI/Modes/0B.cs index 263e784..fdabe47 100644 --- a/SCSI/Modes/0B.cs +++ b/SCSI/Modes/0B.cs @@ -35,22 +35,15 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Modes { #region Mode Page 0x0B: Medium types supported page - /// - /// Disconnect-reconnect page - /// Page code 0x0B - /// 8 bytes in SCSI-2 - /// + /// Disconnect-reconnect page Page code 0x0B 8 bytes in SCSI-2 public struct ModePage_0B { - /// - /// Parameters can be saved - /// + /// Parameters can be saved public bool PS; public MediumTypes MediumType1; public MediumTypes MediumType2; @@ -60,15 +53,19 @@ namespace DiscImageChef.Decoders.SCSI public static ModePage_0B? DecodeModePage_0B(byte[] pageResponse) { - if((pageResponse?[0] & 0x40) == 0x40) return null; + if((pageResponse?[0] & 0x40) == 0x40) + return null; - if((pageResponse?[0] & 0x3F) != 0x0B) return null; + if((pageResponse?[0] & 0x3F) != 0x0B) + return null; - if(pageResponse[1] + 2 != pageResponse.Length) return null; + if(pageResponse[1] + 2 != pageResponse.Length) + return null; - if(pageResponse.Length < 8) return null; + if(pageResponse.Length < 8) + return null; - ModePage_0B decoded = new ModePage_0B(); + var decoded = new ModePage_0B(); decoded.PS |= (pageResponse[0] & 0x80) == 0x80; decoded.MediumType1 = (MediumTypes)pageResponse[4]; @@ -84,27 +81,32 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyModePage_0B(ModePage_0B? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; - ModePage_0B page = modePage.Value; - StringBuilder sb = new StringBuilder(); + ModePage_0B page = modePage.Value; + var sb = new StringBuilder(); sb.AppendLine("SCSI Medium types supported page:"); - if(page.PS) sb.AppendLine("\tParameters can be saved"); + if(page.PS) + sb.AppendLine("\tParameters can be saved"); if(page.MediumType1 != MediumTypes.Default) - sb.AppendFormat("Supported medium type one: {0}", GetMediumTypeDescription(page.MediumType1)) - .AppendLine(); + sb.AppendFormat("Supported medium type one: {0}", GetMediumTypeDescription(page.MediumType1)). + AppendLine(); + if(page.MediumType2 != MediumTypes.Default) - sb.AppendFormat("Supported medium type two: {0}", GetMediumTypeDescription(page.MediumType2)) - .AppendLine(); + sb.AppendFormat("Supported medium type two: {0}", GetMediumTypeDescription(page.MediumType2)). + AppendLine(); + if(page.MediumType3 != MediumTypes.Default) - sb.AppendFormat("Supported medium type three: {0}", GetMediumTypeDescription(page.MediumType3)) - .AppendLine(); + sb.AppendFormat("Supported medium type three: {0}", GetMediumTypeDescription(page.MediumType3)). + AppendLine(); + if(page.MediumType4 != MediumTypes.Default) - sb.AppendFormat("Supported medium type four: {0}", GetMediumTypeDescription(page.MediumType4)) - .AppendLine(); + sb.AppendFormat("Supported medium type four: {0}", GetMediumTypeDescription(page.MediumType4)). + AppendLine(); return sb.ToString(); } diff --git a/SCSI/Modes/0D.cs b/SCSI/Modes/0D.cs index 7b5dfec..6fe53fd 100644 --- a/SCSI/Modes/0D.cs +++ b/SCSI/Modes/0D.cs @@ -35,48 +35,39 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Modes { #region Mode Page 0x0D: CD-ROM parameteres page - /// - /// CD-ROM parameteres page - /// Page code 0x0D - /// 8 bytes in SCSI-2, MMC-1, MMC-2, MMC-3 - /// + /// CD-ROM parameteres page Page code 0x0D 8 bytes in SCSI-2, MMC-1, MMC-2, MMC-3 public struct ModePage_0D { - /// - /// Parameters can be saved - /// + /// Parameters can be saved public bool PS; - /// - /// Time the drive shall remain in hold track state after seek or read - /// + /// Time the drive shall remain in hold track state after seek or read public byte InactivityTimerMultiplier; - /// - /// Seconds per Minute - /// + /// Seconds per Minute public ushort SecondsPerMinute; - /// - /// Frames per Second - /// + /// Frames per Second public ushort FramesPerSecond; } public static ModePage_0D? DecodeModePage_0D(byte[] pageResponse) { - if((pageResponse?[0] & 0x40) == 0x40) return null; + if((pageResponse?[0] & 0x40) == 0x40) + return null; - if((pageResponse?[0] & 0x3F) != 0x0D) return null; + if((pageResponse?[0] & 0x3F) != 0x0D) + return null; - if(pageResponse[1] + 2 != pageResponse.Length) return null; + if(pageResponse[1] + 2 != pageResponse.Length) + return null; - if(pageResponse.Length < 8) return null; + if(pageResponse.Length < 8) + return null; - ModePage_0D decoded = new ModePage_0D(); + var decoded = new ModePage_0D(); decoded.PS |= (pageResponse[0] & 0x80) == 0x80; decoded.InactivityTimerMultiplier = (byte)(pageResponse[3] & 0xF); @@ -91,68 +82,88 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyModePage_0D(ModePage_0D? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; - ModePage_0D page = modePage.Value; - StringBuilder sb = new StringBuilder(); + ModePage_0D page = modePage.Value; + var sb = new StringBuilder(); sb.AppendLine("SCSI CD-ROM parameters page:"); - if(page.PS) sb.AppendLine("\tParameters can be saved"); + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + switch(page.InactivityTimerMultiplier) { case 0: sb.AppendLine("\tDrive will remain in track hold state a vendor-specified time after a seek or read"); + break; case 1: sb.AppendLine("\tDrive will remain in track hold state 125 ms after a seek or read"); + break; case 2: sb.AppendLine("\tDrive will remain in track hold state 250 ms after a seek or read"); + break; case 3: sb.AppendLine("\tDrive will remain in track hold state 500 ms after a seek or read"); + break; case 4: sb.AppendLine("\tDrive will remain in track hold state 1 second after a seek or read"); + break; case 5: sb.AppendLine("\tDrive will remain in track hold state 2 seconds after a seek or read"); + break; case 6: sb.AppendLine("\tDrive will remain in track hold state 4 seconds after a seek or read"); + break; case 7: sb.AppendLine("\tDrive will remain in track hold state 8 seconds after a seek or read"); + break; case 8: sb.AppendLine("\tDrive will remain in track hold state 16 seconds after a seek or read"); + break; case 9: sb.AppendLine("\tDrive will remain in track hold state 32 seconds after a seek or read"); + break; case 10: sb.AppendLine("\tDrive will remain in track hold state 1 minute after a seek or read"); + break; case 11: sb.AppendLine("\tDrive will remain in track hold state 2 minutes after a seek or read"); + break; case 12: sb.AppendLine("\tDrive will remain in track hold state 4 minutes after a seek or read"); + break; case 13: sb.AppendLine("\tDrive will remain in track hold state 8 minutes after a seek or read"); + break; case 14: sb.AppendLine("\tDrive will remain in track hold state 16 minutes after a seek or read"); + break; case 15: sb.AppendLine("\tDrive will remain in track hold state 32 minutes after a seek or read"); + break; } if(page.SecondsPerMinute > 0) sb.AppendFormat("\tEach minute has {0} seconds", page.SecondsPerMinute).AppendLine(); + if(page.FramesPerSecond > 0) sb.AppendFormat("\tEach second has {0} frames", page.FramesPerSecond).AppendLine(); diff --git a/SCSI/Modes/0E.cs b/SCSI/Modes/0E.cs index ac9aae1..1229c95 100644 --- a/SCSI/Modes/0E.cs +++ b/SCSI/Modes/0E.cs @@ -35,88 +35,59 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Modes { #region Mode Page 0x0E: CD-ROM audio control parameters page - /// - /// CD-ROM audio control parameters - /// Page code 0x0E - /// 16 bytes in SCSI-2, MMC-1, MMC-2, MMC-3 - /// + /// CD-ROM audio control parameters Page code 0x0E 16 bytes in SCSI-2, MMC-1, MMC-2, MMC-3 public struct ModePage_0E { - /// - /// Parameters can be saved - /// + /// Parameters can be saved public bool PS; - /// - /// Return status as soon as playback operation starts - /// + /// Return status as soon as playback operation starts public bool Immed; - /// - /// Stop on track crossing - /// + /// Stop on track crossing public bool SOTC; - /// - /// Indicates is valid - /// + /// Indicates is valid public bool APRVal; - /// - /// Multiplier for - /// + /// Multiplier for public byte LBAFormat; - /// - /// LBAs per second of audio - /// + /// LBAs per second of audio public ushort BlocksPerSecondOfAudio; - /// - /// Channels output on this port - /// + /// Channels output on this port public byte OutputPort0ChannelSelection; - /// - /// Volume level for this port - /// + /// Volume level for this port public byte OutputPort0Volume; - /// - /// Channels output on this port - /// + /// Channels output on this port public byte OutputPort1ChannelSelection; - /// - /// Volume level for this port - /// + /// Volume level for this port public byte OutputPort1Volume; - /// - /// Channels output on this port - /// + /// Channels output on this port public byte OutputPort2ChannelSelection; - /// - /// Volume level for this port - /// + /// Volume level for this port public byte OutputPort2Volume; - /// - /// Channels output on this port - /// + /// Channels output on this port public byte OutputPort3ChannelSelection; - /// - /// Volume level for this port - /// + /// Volume level for this port public byte OutputPort3Volume; } public static ModePage_0E? DecodeModePage_0E(byte[] pageResponse) { - if((pageResponse?[0] & 0x40) == 0x40) return null; + if((pageResponse?[0] & 0x40) == 0x40) + return null; - if((pageResponse?[0] & 0x3F) != 0x0E) return null; + if((pageResponse?[0] & 0x3F) != 0x0E) + return null; - if(pageResponse[1] + 2 != pageResponse.Length) return null; + if(pageResponse[1] + 2 != pageResponse.Length) + return null; - if(pageResponse.Length < 16) return null; + if(pageResponse.Length < 16) + return null; - ModePage_0E decoded = new ModePage_0E(); + var decoded = new ModePage_0E(); decoded.PS |= (pageResponse[0] & 0x80) == 0x80; decoded.Immed |= (pageResponse[2] & 0x04) == 0x04; @@ -141,24 +112,31 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyModePage_0E(ModePage_0E? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; - ModePage_0E page = modePage.Value; - StringBuilder sb = new StringBuilder(); + ModePage_0E page = modePage.Value; + var sb = new StringBuilder(); sb.AppendLine("SCSI CD-ROM audio control parameters page:"); - if(page.PS) sb.AppendLine("\tParameters can be saved"); - sb.AppendLine(page.Immed - ? "\tDrive will return from playback command immediately" + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + sb.AppendLine(page.Immed ? "\tDrive will return from playback command immediately" : "\tDrive will return from playback command when playback ends"); - if(page.SOTC) sb.AppendLine("\tDrive will stop playback on track end"); + + if(page.SOTC) + sb.AppendLine("\tDrive will stop playback on track end"); if(page.APRVal) { double blocks; - if(page.LBAFormat == 8) blocks = page.BlocksPerSecondOfAudio * (1 / 256); - else blocks = page.BlocksPerSecondOfAudio; + + if(page.LBAFormat == 8) + blocks = page.BlocksPerSecondOfAudio * (1 / 256); + else + blocks = page.BlocksPerSecondOfAudio; sb.AppendFormat("\tThere are {0} blocks per each second of audio", blocks).AppendLine(); } @@ -166,21 +144,32 @@ namespace DiscImageChef.Decoders.SCSI if(page.OutputPort0ChannelSelection > 0) { sb.Append("\tOutput port 0 has channels "); - if((page.OutputPort0ChannelSelection & 0x01) == 0x01) sb.Append("0 "); - if((page.OutputPort0ChannelSelection & 0x02) == 0x02) sb.Append("1 "); - if((page.OutputPort0ChannelSelection & 0x04) == 0x04) sb.Append("2 "); - if((page.OutputPort0ChannelSelection & 0x08) == 0x08) sb.Append("3 "); + + if((page.OutputPort0ChannelSelection & 0x01) == 0x01) + sb.Append("0 "); + + if((page.OutputPort0ChannelSelection & 0x02) == 0x02) + sb.Append("1 "); + + if((page.OutputPort0ChannelSelection & 0x04) == 0x04) + sb.Append("2 "); + + if((page.OutputPort0ChannelSelection & 0x08) == 0x08) + sb.Append("3 "); switch(page.OutputPort0Volume) { case 0: sb.AppendLine("muted"); + break; case 0xFF: sb.AppendLine("at maximum volume"); + break; default: sb.AppendFormat("at volume {0}", page.OutputPort0Volume).AppendLine(); + break; } } @@ -188,21 +177,32 @@ namespace DiscImageChef.Decoders.SCSI if(page.OutputPort1ChannelSelection > 0) { sb.Append("\tOutput port 1 has channels "); - if((page.OutputPort1ChannelSelection & 0x01) == 0x01) sb.Append("0 "); - if((page.OutputPort1ChannelSelection & 0x02) == 0x02) sb.Append("1 "); - if((page.OutputPort1ChannelSelection & 0x04) == 0x04) sb.Append("2 "); - if((page.OutputPort1ChannelSelection & 0x08) == 0x08) sb.Append("3 "); + + if((page.OutputPort1ChannelSelection & 0x01) == 0x01) + sb.Append("0 "); + + if((page.OutputPort1ChannelSelection & 0x02) == 0x02) + sb.Append("1 "); + + if((page.OutputPort1ChannelSelection & 0x04) == 0x04) + sb.Append("2 "); + + if((page.OutputPort1ChannelSelection & 0x08) == 0x08) + sb.Append("3 "); switch(page.OutputPort1Volume) { case 0: sb.AppendLine("muted"); + break; case 0xFF: sb.AppendLine("at maximum volume"); + break; default: sb.AppendFormat("at volume {0}", page.OutputPort1Volume).AppendLine(); + break; } } @@ -210,43 +210,66 @@ namespace DiscImageChef.Decoders.SCSI if(page.OutputPort2ChannelSelection > 0) { sb.Append("\tOutput port 2 has channels "); - if((page.OutputPort2ChannelSelection & 0x01) == 0x01) sb.Append("0 "); - if((page.OutputPort2ChannelSelection & 0x02) == 0x02) sb.Append("1 "); - if((page.OutputPort2ChannelSelection & 0x04) == 0x04) sb.Append("2 "); - if((page.OutputPort2ChannelSelection & 0x08) == 0x08) sb.Append("3 "); + + if((page.OutputPort2ChannelSelection & 0x01) == 0x01) + sb.Append("0 "); + + if((page.OutputPort2ChannelSelection & 0x02) == 0x02) + sb.Append("1 "); + + if((page.OutputPort2ChannelSelection & 0x04) == 0x04) + sb.Append("2 "); + + if((page.OutputPort2ChannelSelection & 0x08) == 0x08) + sb.Append("3 "); switch(page.OutputPort2Volume) { case 0: sb.AppendLine("muted"); + break; case 0xFF: sb.AppendLine("at maximum volume"); + break; default: sb.AppendFormat("at volume {0}", page.OutputPort2Volume).AppendLine(); + break; } } - if(page.OutputPort3ChannelSelection <= 0) return sb.ToString(); + if(page.OutputPort3ChannelSelection <= 0) + return sb.ToString(); sb.Append("\tOutput port 3 has channels "); - if((page.OutputPort3ChannelSelection & 0x01) == 0x01) sb.Append("0 "); - if((page.OutputPort3ChannelSelection & 0x02) == 0x02) sb.Append("1 "); - if((page.OutputPort3ChannelSelection & 0x04) == 0x04) sb.Append("2 "); - if((page.OutputPort3ChannelSelection & 0x08) == 0x08) sb.Append("3 "); + + if((page.OutputPort3ChannelSelection & 0x01) == 0x01) + sb.Append("0 "); + + if((page.OutputPort3ChannelSelection & 0x02) == 0x02) + sb.Append("1 "); + + if((page.OutputPort3ChannelSelection & 0x04) == 0x04) + sb.Append("2 "); + + if((page.OutputPort3ChannelSelection & 0x08) == 0x08) + sb.Append("3 "); switch(page.OutputPort3Volume) { case 0: sb.AppendLine("muted"); + break; case 0xFF: sb.AppendLine("at maximum volume"); + break; default: sb.AppendFormat("at volume {0}", page.OutputPort3Volume).AppendLine(); + break; } diff --git a/SCSI/Modes/0F.cs b/SCSI/Modes/0F.cs index 662a9d7..8e42f0d 100644 --- a/SCSI/Modes/0F.cs +++ b/SCSI/Modes/0F.cs @@ -35,60 +35,45 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Modes { #region Mode Page 0x0F: Data compression page - /// - /// Data compression page - /// Page code 0x0F - /// 16 bytes in SSC-1, SSC-2, SSC-3 - /// + /// Data compression page Page code 0x0F 16 bytes in SSC-1, SSC-2, SSC-3 public struct ModePage_0F { - /// - /// Parameters can be saved - /// + /// Parameters can be saved public bool PS; - /// - /// Data compression enabled - /// + /// Data compression enabled public bool DCE; - /// - /// Data compression capable - /// + /// Data compression capable public bool DCC; - /// - /// Data decompression enabled - /// + /// Data decompression enabled public bool DDE; - /// - /// Report exception on decompression - /// + /// Report exception on decompression public byte RED; - /// - /// Compression algorithm - /// + /// Compression algorithm public uint CompressionAlgo; - /// - /// Decompression algorithm - /// + /// Decompression algorithm public uint DecompressionAlgo; } public static ModePage_0F? DecodeModePage_0F(byte[] pageResponse) { - if((pageResponse?[0] & 0x40) == 0x40) return null; + if((pageResponse?[0] & 0x40) == 0x40) + return null; - if((pageResponse?[0] & 0x3F) != 0x0F) return null; + if((pageResponse?[0] & 0x3F) != 0x0F) + return null; - if(pageResponse[1] + 2 != pageResponse.Length) return null; + if(pageResponse[1] + 2 != pageResponse.Length) + return null; - if(pageResponse.Length < 16) return null; + if(pageResponse.Length < 16) + return null; - ModePage_0F decoded = new ModePage_0F(); + var decoded = new ModePage_0F(); decoded.PS |= (pageResponse[0] & 0x80) == 0x80; @@ -99,6 +84,7 @@ namespace DiscImageChef.Decoders.SCSI decoded.CompressionAlgo = (uint)((pageResponse[4] << 24) + (pageResponse[5] << 16) + (pageResponse[6] << 8) + pageResponse[7]); + decoded.DecompressionAlgo = (uint)((pageResponse[8] << 24) + (pageResponse[9] << 16) + (pageResponse[10] << 8) + pageResponse[11]); @@ -110,43 +96,54 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyModePage_0F(ModePage_0F? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; - ModePage_0F page = modePage.Value; - StringBuilder sb = new StringBuilder(); + ModePage_0F page = modePage.Value; + var sb = new StringBuilder(); sb.AppendLine("SCSI Data compression page:"); - if(page.PS) sb.AppendLine("\tParameters can be saved"); + if(page.PS) + sb.AppendLine("\tParameters can be saved"); if(page.DCC) { sb.AppendLine("\tDrive supports data compression"); + if(page.DCE) { sb.Append("\tData compression is enabled with "); + switch(page.CompressionAlgo) { case 3: sb.AppendLine("IBM ALDC with 512 byte buffer"); + break; case 4: sb.AppendLine("IBM ALDC with 1024 byte buffer"); + break; case 5: sb.AppendLine("IBM ALDC with 2048 byte buffer"); + break; case 0x10: sb.AppendLine("IBM IDRC"); + break; case 0x20: sb.AppendLine("DCLZ"); + break; case 0xFF: sb.AppendLine("an unregistered compression algorithm"); + break; default: sb.AppendFormat("an unknown algorithm coded {0}", page.CompressionAlgo).AppendLine(); + break; } } @@ -154,32 +151,42 @@ namespace DiscImageChef.Decoders.SCSI if(page.DDE) { sb.AppendLine("\tData decompression is enabled"); - if(page.DecompressionAlgo == 0) sb.AppendLine("\tLast data read was uncompressed"); + + if(page.DecompressionAlgo == 0) + sb.AppendLine("\tLast data read was uncompressed"); else { sb.Append("\tLast data read was compressed with "); + switch(page.CompressionAlgo) { case 3: sb.AppendLine("IBM ALDC with 512 byte buffer"); + break; case 4: sb.AppendLine("IBM ALDC with 1024 byte buffer"); + break; case 5: sb.AppendLine("IBM ALDC with 2048 byte buffer"); + break; case 0x10: sb.AppendLine("IBM IDRC"); + break; case 0x20: sb.AppendLine("DCLZ"); + break; case 0xFF: sb.AppendLine("an unregistered compression algorithm"); + break; default: sb.AppendFormat("an unknown algorithm coded {0}", page.CompressionAlgo).AppendLine(); + break; } } @@ -187,7 +194,8 @@ namespace DiscImageChef.Decoders.SCSI sb.AppendFormat("\tReport exception on compression is set to {0}", page.RED).AppendLine(); } - else sb.AppendLine("\tDrive does not support data compression"); + else + sb.AppendLine("\tDrive does not support data compression"); return sb.ToString(); } diff --git a/SCSI/Modes/10.cs b/SCSI/Modes/10.cs index 4bc2f22..3405c9a 100644 --- a/SCSI/Modes/10.cs +++ b/SCSI/Modes/10.cs @@ -35,66 +35,57 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Modes { #region Mode Page 0x10: XOR control mode page - /// - /// XOR control mode page - /// Page code 0x10 - /// 24 bytes in SBC-1, SBC-2 - /// + /// XOR control mode page Page code 0x10 24 bytes in SBC-1, SBC-2 public struct ModePage_10 { - /// - /// Parameters can be saved - /// + /// Parameters can be saved public bool PS; - /// - /// Disables XOR operations - /// + /// Disables XOR operations public bool XORDIS; - /// - /// Maximum transfer length in blocks for a XOR command - /// + /// Maximum transfer length in blocks for a XOR command public uint MaxXorWrite; - /// - /// Maximum regenerate length in blocks - /// + /// Maximum regenerate length in blocks public uint MaxRegenSize; - /// - /// Maximum transfer length in blocks for READ during a rebuild - /// + /// Maximum transfer length in blocks for READ during a rebuild public uint MaxRebuildRead; - /// - /// Minimum time in ms between READs during a rebuild - /// + /// Minimum time in ms between READs during a rebuild public ushort RebuildDelay; } public static ModePage_10? DecodeModePage_10(byte[] pageResponse) { - if((pageResponse?[0] & 0x40) == 0x40) return null; + if((pageResponse?[0] & 0x40) == 0x40) + return null; - if((pageResponse?[0] & 0x3F) != 0x10) return null; + if((pageResponse?[0] & 0x3F) != 0x10) + return null; - if(pageResponse[1] + 2 != pageResponse.Length) return null; + if(pageResponse[1] + 2 != pageResponse.Length) + return null; - if(pageResponse.Length < 24) return null; + if(pageResponse.Length < 24) + return null; - ModePage_10 decoded = new ModePage_10(); + var decoded = new ModePage_10(); decoded.PS |= (pageResponse[0] & 0x80) == 0x80; decoded.XORDIS |= (pageResponse[2] & 0x02) == 0x02; + decoded.MaxXorWrite = (uint)((pageResponse[4] << 24) + (pageResponse[5] << 16) + (pageResponse[6] << 8) + pageResponse[7]); + decoded.MaxRegenSize = (uint)((pageResponse[12] << 24) + (pageResponse[13] << 16) + (pageResponse[14] << 8) + pageResponse[15]); + decoded.MaxRebuildRead = (uint)((pageResponse[16] << 24) + (pageResponse[17] << 16) + (pageResponse[18] << 8) + pageResponse[19]); + decoded.RebuildDelay = (ushort)((pageResponse[22] << 8) + pageResponse[23]); return decoded; @@ -105,27 +96,33 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyModePage_10(ModePage_10? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; - ModePage_10 page = modePage.Value; - StringBuilder sb = new StringBuilder(); + ModePage_10 page = modePage.Value; + var sb = new StringBuilder(); sb.AppendLine("SCSI XOR control mode page:"); - if(page.PS) sb.AppendLine("\tParameters can be saved"); + if(page.PS) + sb.AppendLine("\tParameters can be saved"); - if(page.XORDIS) sb.AppendLine("\tXOR operations are disabled"); + if(page.XORDIS) + sb.AppendLine("\tXOR operations are disabled"); else { if(page.MaxXorWrite > 0) sb.AppendFormat("\tDrive accepts a maximum of {0} blocks in a single XOR WRITE command", page.MaxXorWrite).AppendLine(); + if(page.MaxRegenSize > 0) sb.AppendFormat("\tDrive accepts a maximum of {0} blocks in a REGENERATE command", page.MaxRegenSize).AppendLine(); + if(page.MaxRebuildRead > 0) sb.AppendFormat("\tDrive accepts a maximum of {0} blocks in a READ command during rebuild", page.MaxRebuildRead).AppendLine(); + if(page.RebuildDelay > 0) sb.AppendFormat("\tDrive needs a minimum of {0} ms between READ commands during rebuild", page.RebuildDelay).AppendLine(); diff --git a/SCSI/Modes/10_SSC.cs b/SCSI/Modes/10_SSC.cs index 71bd239..57b5fed 100644 --- a/SCSI/Modes/10_SSC.cs +++ b/SCSI/Modes/10_SSC.cs @@ -35,146 +35,91 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Modes { #region Mode Page 0x10: Device configuration page - /// - /// Device configuration page - /// Page code 0x10 - /// 16 bytes in SCSI-2, SSC-1, SSC-2, SSC-3 - /// + /// Device configuration page Page code 0x10 16 bytes in SCSI-2, SSC-1, SSC-2, SSC-3 public struct ModePage_10_SSC { - /// - /// Parameters can be saved - /// + /// Parameters can be saved public bool PS; - /// - /// Used in mode select to change partition to one specified in - /// + /// Used in mode select to change partition to one specified in public bool CAP; - /// - /// Used in mode select to change format to one specified in - /// + /// Used in mode select to change format to one specified in public bool CAF; - /// - /// Active format, vendor-specific - /// + /// Active format, vendor-specific public byte ActiveFormat; - /// - /// Current logical partition - /// + /// Current logical partition public byte ActivePartition; - /// - /// How full the buffer shall be before writing to medium - /// + /// How full the buffer shall be before writing to medium public byte WriteBufferFullRatio; - /// - /// How empty the buffer shall be before reading more data from the medium - /// + /// How empty the buffer shall be before reading more data from the medium public byte ReadBufferEmptyRatio; - /// - /// Delay in 100 ms before buffered data is forcefully written to the medium even before buffer is full - /// + /// Delay in 100 ms before buffered data is forcefully written to the medium even before buffer is full public ushort WriteDelayTime; - /// - /// Drive supports recovering data from buffer - /// + /// Drive supports recovering data from buffer public bool DBR; - /// - /// Medium has block IDs - /// + /// Medium has block IDs public bool BIS; - /// - /// Drive recognizes and reports setmarks - /// + /// Drive recognizes and reports setmarks public bool RSmk; - /// - /// Drive selects best speed - /// + /// Drive selects best speed public bool AVC; - /// - /// If drive should stop pre-reading on filemarks - /// + /// If drive should stop pre-reading on filemarks public byte SOCF; - /// - /// If set, recovered buffer data is LIFO, otherwise, FIFO - /// + /// If set, recovered buffer data is LIFO, otherwise, FIFO public bool RBO; - /// - /// Report early warnings - /// + /// Report early warnings public bool REW; - /// - /// Inter-block gap - /// + /// Inter-block gap public byte GapSize; - /// - /// End-of-Data format - /// + /// End-of-Data format public byte EODDefined; - /// - /// EOD generation enabled - /// + /// EOD generation enabled public bool EEG; - /// - /// Synchronize data to medium on early warning - /// + /// Synchronize data to medium on early warning public bool SEW; - /// - /// Bytes to reduce buffer size on early warning - /// + /// Bytes to reduce buffer size on early warning public uint BufferSizeEarlyWarning; - /// - /// Selected data compression algorithm - /// + /// Selected data compression algorithm public byte SelectedCompression; - /// - /// Soft write protect - /// + /// Soft write protect public bool SWP; - /// - /// Associated write protect - /// + /// Associated write protect public bool ASOCWP; - /// - /// Persistent write protect - /// + /// Persistent write protect public bool PERSWP; - /// - /// Permanent write protect - /// + /// Permanent write protect public bool PRMWP; public bool BAML; public bool BAM; public byte RewindOnReset; - /// - /// How drive shall respond to detection of compromised WORM medium integrity - /// + /// How drive shall respond to detection of compromised WORM medium integrity public byte WTRE; - /// - /// Respond to commands only if a reservation exists - /// + /// Respond to commands only if a reservation exists public bool OIR; } public static ModePage_10_SSC? DecodeModePage_10_SSC(byte[] pageResponse) { - if((pageResponse?[0] & 0x40) == 0x40) return null; + if((pageResponse?[0] & 0x40) == 0x40) + return null; - if((pageResponse?[0] & 0x3F) != 0x10) return null; + if((pageResponse?[0] & 0x3F) != 0x10) + return null; - if(pageResponse[1] + 2 != pageResponse.Length) return null; + if(pageResponse[1] + 2 != pageResponse.Length) + return null; - if(pageResponse.Length < 16) return null; + if(pageResponse.Length < 16) + return null; - ModePage_10_SSC decoded = new ModePage_10_SSC(); + var decoded = new ModePage_10_SSC(); decoded.PS |= (pageResponse[0] & 0x80) == 0x80; decoded.CAP |= (pageResponse[2] & 0x40) == 0x40; @@ -193,8 +138,10 @@ namespace DiscImageChef.Decoders.SCSI decoded.EEG |= (pageResponse[10] & 0x10) == 0x10; decoded.SEW |= (pageResponse[10] & 0x08) == 0x08; decoded.SOCF = (byte)((pageResponse[8] & 0x0C) >> 2); + decoded.BufferSizeEarlyWarning = (uint)((pageResponse[11] << 16) + (pageResponse[12] << 8) + pageResponse[13]); + decoded.SelectedCompression = pageResponse[14]; decoded.SWP |= (pageResponse[10] & 0x04) == 0x04; @@ -218,54 +165,70 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyModePage_10_SSC(ModePage_10_SSC? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; ModePage_10_SSC page = modePage.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendLine("SCSI Device configuration page:"); - if(page.PS) sb.AppendLine("\tParameters can be saved"); + if(page.PS) + sb.AppendLine("\tParameters can be saved"); sb.AppendFormat("\tActive format: {0}", page.ActiveFormat).AppendLine(); sb.AppendFormat("\tActive partition: {0}", page.ActivePartition).AppendLine(); + sb.AppendFormat("\tWrite buffer shall have a full ratio of {0} before being flushed to medium", page.WriteBufferFullRatio).AppendLine(); + sb.AppendFormat("\tRead buffer shall have an empty ratio of {0} before more data is read from medium", page.ReadBufferEmptyRatio).AppendLine(); - sb - .AppendFormat("\tDrive will delay {0} ms before buffered data is forcefully written to the medium even before buffer is full", + + sb. + AppendFormat("\tDrive will delay {0} ms before buffered data is forcefully written to the medium even before buffer is full", page.WriteDelayTime * 100).AppendLine(); + if(page.DBR) { sb.AppendLine("\tDrive supports recovering data from buffer"); - sb.AppendLine(page.RBO - ? "\tRecovered buffer data comes in LIFO order" + + sb.AppendLine(page.RBO ? "\tRecovered buffer data comes in LIFO order" : "\tRecovered buffer data comes in FIFO order"); } - if(page.BIS) sb.AppendLine("\tMedium supports block IDs"); - if(page.RSmk) sb.AppendLine("\tDrive reports setmarks"); + if(page.BIS) + sb.AppendLine("\tMedium supports block IDs"); + + if(page.RSmk) + sb.AppendLine("\tDrive reports setmarks"); + switch(page.SOCF) { case 0: sb.AppendLine("\tDrive will pre-read until buffer is full"); + break; case 1: sb.AppendLine("\tDrive will pre-read until one filemark is detected"); + break; case 2: sb.AppendLine("\tDrive will pre-read until two filemark is detected"); + break; case 3: sb.AppendLine("\tDrive will pre-read until three filemark is detected"); + break; } if(page.REW) { sb.AppendLine("\tDrive reports early warnings"); - if(page.SEW) sb.AppendLine("\tDrive will synchronize buffer to medium on early warnings"); + + if(page.SEW) + sb.AppendLine("\tDrive will synchronize buffer to medium on early warnings"); } switch(page.GapSize) @@ -273,6 +236,7 @@ namespace DiscImageChef.Decoders.SCSI case 0: break; case 1: sb.AppendLine("\tInter-block gap is long enough to support update in place"); + break; case 2: case 3: @@ -288,46 +252,60 @@ namespace DiscImageChef.Decoders.SCSI case 13: case 14: case 15: - sb.AppendFormat("\tInter-block gap is {0} times the device's defined gap size", page.GapSize) - .AppendLine(); + sb.AppendFormat("\tInter-block gap is {0} times the device's defined gap size", page.GapSize). + AppendLine(); + break; default: sb.AppendFormat("\tInter-block gap is unknown value {0}", page.GapSize).AppendLine(); + break; } - if(page.EEG) sb.AppendLine("\tDrive generates end-of-data"); + if(page.EEG) + sb.AppendLine("\tDrive generates end-of-data"); switch(page.SelectedCompression) { case 0: sb.AppendLine("\tDrive does not use compression"); + break; case 1: sb.AppendLine("\tDrive uses default compression"); + break; default: sb.AppendFormat("\tDrive uses unknown compression {0}", page.SelectedCompression).AppendLine(); + break; } - if(page.SWP) sb.AppendLine("\tSoftware write protect is enabled"); - if(page.ASOCWP) sb.AppendLine("\tAssociated write protect is enabled"); - if(page.PERSWP) sb.AppendLine("\tPersistent write protect is enabled"); - if(page.PRMWP) sb.AppendLine("\tPermanent write protect is enabled"); + if(page.SWP) + sb.AppendLine("\tSoftware write protect is enabled"); + + if(page.ASOCWP) + sb.AppendLine("\tAssociated write protect is enabled"); + + if(page.PERSWP) + sb.AppendLine("\tPersistent write protect is enabled"); + + if(page.PRMWP) + sb.AppendLine("\tPermanent write protect is enabled"); if(page.BAML) - sb.AppendLine(page.BAM - ? "\tDrive operates using explicit address mode" + sb.AppendLine(page.BAM ? "\tDrive operates using explicit address mode" : "\tDrive operates using implicit address mode"); switch(page.RewindOnReset) { case 1: sb.AppendLine("\tDrive shall position to beginning of default data partition on reset"); + break; case 2: sb.AppendLine("\tDrive shall maintain its position on reset"); + break; } @@ -335,13 +313,16 @@ namespace DiscImageChef.Decoders.SCSI { case 1: sb.AppendLine("\tDrive will do nothing on WORM tampered medium"); + break; case 2: sb.AppendLine("\tDrive will return CHECK CONDITION on WORM tampered medium"); + break; } - if(page.OIR) sb.AppendLine("\tDrive will only respond to commands if it has received a reservation"); + if(page.OIR) + sb.AppendLine("\tDrive will only respond to commands if it has received a reservation"); return sb.ToString(); } diff --git a/SCSI/Modes/11.cs b/SCSI/Modes/11.cs index 28b83a7..711e44f 100644 --- a/SCSI/Modes/11.cs +++ b/SCSI/Modes/11.cs @@ -36,111 +36,71 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Modes { #region Mode Page 0x11: Medium partition page (1) public enum PartitionSizeUnitOfMeasures : byte { - /// - /// Partition size is measures in bytes - /// - Bytes = 0, - /// - /// Partition size is measures in Kilobytes - /// - Kilobytes = 1, - /// - /// Partition size is measures in Megabytes - /// - Megabytes = 2, - /// - /// Partition size is 10eUNITS bytes - /// + /// Partition size is measures in bytes + Bytes = 0, /// Partition size is measures in Kilobytes + Kilobytes = 1, /// Partition size is measures in Megabytes + Megabytes = 2, /// Partition size is 10eUNITS bytes Exponential = 3 } public enum MediumFormatRecognitionValues : byte { - /// - /// Logical unit is incapable of format or partition recognition - /// - Incapable = 0, - /// - /// Logical unit is capable of format recognition only - /// - FormatCapable = 1, - /// - /// Logical unit is capable of partition recognition only - /// - PartitionCapable = 2, - /// - /// Logical unit is capable of both format and partition recognition - /// + /// Logical unit is incapable of format or partition recognition + Incapable = 0, /// Logical unit is capable of format recognition only + FormatCapable = 1, /// Logical unit is capable of partition recognition only + PartitionCapable = 2, /// Logical unit is capable of both format and partition recognition Capable = 3 } - /// - /// Medium partition page(1) - /// Page code 0x11 - /// + /// Medium partition page(1) Page code 0x11 public struct ModePage_11 { - /// - /// Parameters can be saved - /// + /// Parameters can be saved public bool PS; - /// - /// Maximum number of additional partitions supported - /// + /// Maximum number of additional partitions supported public byte MaxAdditionalPartitions; - /// - /// Number of additional partitions to be defined for a volume - /// + /// Number of additional partitions to be defined for a volume public byte AdditionalPartitionsDefined; - /// - /// Device defines partitions based on its fixed definition - /// + /// Device defines partitions based on its fixed definition public bool FDP; - /// - /// Device should divide medium according to the additional partitions defined field using sizes defined by device - /// + /// Device should divide medium according to the additional partitions defined field using sizes defined by device public bool SDP; - /// - /// Initiator defines number and size of partitions - /// + /// Initiator defines number and size of partitions public bool IDP; - /// - /// Defines the unit on which the partition sizes are defined - /// + /// Defines the unit on which the partition sizes are defined public PartitionSizeUnitOfMeasures PSUM; public bool POFM; public bool CLEAR; public bool ADDP; - /// - /// Defines the capabilities for the unit to recognize media partitions and format - /// + /// Defines the capabilities for the unit to recognize media partitions and format public MediumFormatRecognitionValues MediumFormatRecognition; public byte PartitionUnits; - /// - /// Array of partition sizes in units defined above - /// + /// Array of partition sizes in units defined above public ushort[] PartitionSizes; } public static ModePage_11? DecodeModePage_11(byte[] pageResponse) { - if((pageResponse?[0] & 0x40) == 0x40) return null; + if((pageResponse?[0] & 0x40) == 0x40) + return null; - if((pageResponse?[0] & 0x3F) != 0x11) return null; + if((pageResponse?[0] & 0x3F) != 0x11) + return null; - if(pageResponse[1] + 2 != pageResponse.Length) return null; + if(pageResponse[1] + 2 != pageResponse.Length) + return null; - if(pageResponse.Length < 8) return null; + if(pageResponse.Length < 8) + return null; - ModePage_11 decoded = new ModePage_11(); + var decoded = new ModePage_11(); decoded.PS |= (pageResponse[0] & 0x80) == 0x80; @@ -171,30 +131,42 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyModePage_11(ModePage_11? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; - ModePage_11 page = modePage.Value; - StringBuilder sb = new StringBuilder(); + ModePage_11 page = modePage.Value; + var sb = new StringBuilder(); sb.AppendLine("SCSI medium partition page:"); - if(page.PS) sb.AppendLine("\tParameters can be saved"); + if(page.PS) + sb.AppendLine("\tParameters can be saved"); sb.AppendFormat("\t{0} maximum additional partitions", page.MaxAdditionalPartitions).AppendLine(); sb.AppendFormat("\t{0} additional partitions defined", page.AdditionalPartitionsDefined).AppendLine(); - if(page.FDP) sb.AppendLine("\tPartitions are fixed under device definitions"); - if(page.SDP) sb.AppendLine("\tNumber of partitions can be defined but their size is defined by the device"); - if(page.IDP) sb.AppendLine("\tNumber and size of partitions can be manually defined"); + if(page.FDP) + sb.AppendLine("\tPartitions are fixed under device definitions"); + + if(page.SDP) + sb.AppendLine("\tNumber of partitions can be defined but their size is defined by the device"); + + if(page.IDP) + sb.AppendLine("\tNumber and size of partitions can be manually defined"); + if(page.POFM) sb.AppendLine("\tPartition parameters will not be applied until a FORMAT MEDIUM command is received"); - if(!page.CLEAR && !page.ADDP) + + if(!page.CLEAR && + !page.ADDP) sb.AppendLine("\tDevice may erase any or all partitions on MODE SELECT for partitioning"); - else if(page.CLEAR && !page.ADDP) + else if(page.CLEAR && + !page.ADDP) sb.AppendLine("\tDevice shall erase all partitions on MODE SELECT for partitioning"); else if(!page.CLEAR) sb.AppendLine("\tDevice shall not erase any partition on MODE SELECT for partitioning"); - else sb.AppendLine("\tDevice shall erase all partitions differing on size on MODE SELECT for partitioning"); + else + sb.AppendLine("\tDevice shall erase all partitions differing on size on MODE SELECT for partitioning"); string measure; @@ -203,23 +175,29 @@ namespace DiscImageChef.Decoders.SCSI case PartitionSizeUnitOfMeasures.Bytes: sb.AppendLine("\tPartitions are defined in bytes"); measure = "bytes"; + break; case PartitionSizeUnitOfMeasures.Kilobytes: sb.AppendLine("\tPartitions are defined in kilobytes"); measure = "kilobytes"; + break; case PartitionSizeUnitOfMeasures.Megabytes: sb.AppendLine("\tPartitions are defined in megabytes"); measure = "megabytes"; + break; case PartitionSizeUnitOfMeasures.Exponential: - sb.AppendFormat("\tPartitions are defined in units of {0} bytes", Math.Pow(10, page.PartitionUnits)) - .AppendLine(); + sb.AppendFormat("\tPartitions are defined in units of {0} bytes", + Math.Pow(10, page.PartitionUnits)).AppendLine(); + measure = $"units of {Math.Pow(10, page.PartitionUnits)} bytes"; + break; default: sb.AppendFormat("\tUnknown partition size unit code {0}", (byte)page.PSUM).AppendLine(); measure = "units"; + break; } @@ -227,19 +205,24 @@ namespace DiscImageChef.Decoders.SCSI { case MediumFormatRecognitionValues.Capable: sb.AppendLine("\tDevice is capable of recognizing both medium partitions and format"); + break; case MediumFormatRecognitionValues.FormatCapable: sb.AppendLine("\tDevice is capable of recognizing medium format"); + break; case MediumFormatRecognitionValues.PartitionCapable: sb.AppendLine("\tDevice is capable of recognizing medium partitions"); + break; case MediumFormatRecognitionValues.Incapable: sb.AppendLine("\tDevice is not capable of recognizing neither medium partitions nor format"); + break; default: - sb.AppendFormat("\tUnknown medium recognition code {0}", (byte)page.MediumFormatRecognition) - .AppendLine(); + sb.AppendFormat("\tUnknown medium recognition code {0}", (byte)page.MediumFormatRecognition). + AppendLine(); + break; } diff --git a/SCSI/Modes/12_13_14.cs b/SCSI/Modes/12_13_14.cs index abce554..1ad80ea 100644 --- a/SCSI/Modes/12_13_14.cs +++ b/SCSI/Modes/12_13_14.cs @@ -35,42 +35,40 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Modes { #region Mode Pages 0x12, 0x13, 0x14: Medium partition page (2-4) - /// - /// Medium partition page (2-4) - /// Page codes 0x12, 0x13 and 0x14 - /// + /// Medium partition page (2-4) Page codes 0x12, 0x13 and 0x14 public struct ModePage_12_13_14 { - /// - /// Parameters can be saved - /// + /// Parameters can be saved public bool PS; - /// - /// Array of partition sizes in units defined in mode page 11 - /// + /// Array of partition sizes in units defined in mode page 11 public ushort[] PartitionSizes; } public static ModePage_12_13_14? DecodeModePage_12_13_14(byte[] pageResponse) { - if(pageResponse == null) return null; + if(pageResponse == null) + return null; - if((pageResponse[0] & 0x40) == 0x40) return null; + if((pageResponse[0] & 0x40) == 0x40) + return null; - if((pageResponse[0] & 0x3F) != 0x12 && (pageResponse[0] & 0x3F) != 0x13 && - (pageResponse[0] & 0x3F) != 0x14) return null; + if((pageResponse[0] & 0x3F) != 0x12 && + (pageResponse[0] & 0x3F) != 0x13 && + (pageResponse[0] & 0x3F) != 0x14) + return null; - if(pageResponse[1] + 2 != pageResponse.Length) return null; + if(pageResponse[1] + 2 != pageResponse.Length) + return null; - if(pageResponse.Length < 2) return null; + if(pageResponse.Length < 2) + return null; - ModePage_12_13_14 decoded = new ModePage_12_13_14(); + var decoded = new ModePage_12_13_14(); decoded.PS |= (pageResponse[0] & 0x80) == 0x80; @@ -90,14 +88,16 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyModePage_12_13_14(ModePage_12_13_14? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; ModePage_12_13_14 page = modePage.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendLine("SCSI medium partition page (extra):"); - if(page.PS) sb.AppendLine("\tParameters can be saved"); + if(page.PS) + sb.AppendLine("\tParameters can be saved"); sb.AppendFormat("\tMedium has defined {0} partitions", page.PartitionSizes.Length).AppendLine(); diff --git a/SCSI/Modes/1A.cs b/SCSI/Modes/1A.cs index 5c0fa97..653563b 100644 --- a/SCSI/Modes/1A.cs +++ b/SCSI/Modes/1A.cs @@ -35,68 +35,38 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Modes { #region Mode Page 0x1A: Power condition page - /// - /// Power condition page - /// Page code 0x1A - /// 12 bytes in SPC-1, SPC-2, SPC-3, SPC-4 - /// 40 bytes in SPC-5 - /// + /// Power condition page Page code 0x1A 12 bytes in SPC-1, SPC-2, SPC-3, SPC-4 40 bytes in SPC-5 public struct ModePage_1A { - /// - /// Parameters can be saved - /// + /// Parameters can be saved public bool PS; - /// - /// Idle timer activated - /// + /// Idle timer activated public bool Idle; - /// - /// Standby timer activated - /// + /// Standby timer activated public bool Standby; - /// - /// Idle timer - /// + /// Idle timer public uint IdleTimer; - /// - /// Standby timer - /// + /// Standby timer public uint StandbyTimer; - /// - /// Interactions between background functions and power management - /// + /// Interactions between background functions and power management public byte PM_BG_Precedence; - /// - /// Standby timer Y activated - /// + /// Standby timer Y activated public bool Standby_Y; - /// - /// Idle timer B activated - /// + /// Idle timer B activated public bool Idle_B; - /// - /// Idle timer C activated - /// + /// Idle timer C activated public bool Idle_C; - /// - /// Idle timer B - /// + /// Idle timer B public uint IdleTimer_B; - /// - /// Idle timer C - /// + /// Idle timer C public uint IdleTimer_C; - /// - /// Standby timer Y - /// + /// Standby timer Y public uint StandbyTimer_Y; public byte CCF_Idle; public byte CCF_Standby; @@ -105,15 +75,19 @@ namespace DiscImageChef.Decoders.SCSI public static ModePage_1A? DecodeModePage_1A(byte[] pageResponse) { - if((pageResponse?[0] & 0x40) == 0x40) return null; + if((pageResponse?[0] & 0x40) == 0x40) + return null; - if((pageResponse?[0] & 0x3F) != 0x1A) return null; + if((pageResponse?[0] & 0x3F) != 0x1A) + return null; - if(pageResponse[1] + 2 != pageResponse.Length) return null; + if(pageResponse[1] + 2 != pageResponse.Length) + return null; - if(pageResponse.Length < 12) return null; + if(pageResponse.Length < 12) + return null; - ModePage_1A decoded = new ModePage_1A(); + var decoded = new ModePage_1A(); decoded.PS |= (pageResponse[0] & 0x80) == 0x80; @@ -122,10 +96,12 @@ namespace DiscImageChef.Decoders.SCSI decoded.IdleTimer = (uint)((pageResponse[4] << 24) + (pageResponse[5] << 16) + (pageResponse[6] << 8) + pageResponse[7]); + decoded.StandbyTimer = (uint)((pageResponse[8] << 24) + (pageResponse[9] << 16) + (pageResponse[10] << 8) + pageResponse[11]); - if(pageResponse.Length < 40) return decoded; + if(pageResponse.Length < 40) + return decoded; decoded.PM_BG_Precedence = (byte)((pageResponse[2] & 0xC0) >> 6); decoded.Standby_Y |= (pageResponse[2] & 0x01) == 0x01; @@ -134,8 +110,10 @@ namespace DiscImageChef.Decoders.SCSI decoded.IdleTimer_B = (uint)((pageResponse[12] << 24) + (pageResponse[13] << 16) + (pageResponse[14] << 8) + pageResponse[15]); + decoded.IdleTimer_C = (uint)((pageResponse[16] << 24) + (pageResponse[17] << 16) + (pageResponse[18] << 8) + pageResponse[19]); + decoded.StandbyTimer_Y = (uint)((pageResponse[20] << 24) + (pageResponse[21] << 16) + (pageResponse[22] << 8) + pageResponse[23]); @@ -151,44 +129,60 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyModePage_1A(ModePage_1A? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; - ModePage_1A page = modePage.Value; - StringBuilder sb = new StringBuilder(); + ModePage_1A page = modePage.Value; + var sb = new StringBuilder(); sb.AppendLine("SCSI Power condition page:"); - if(page.PS) sb.AppendLine("\tParameters can be saved"); + if(page.PS) + sb.AppendLine("\tParameters can be saved"); - if(page.Standby && page.StandbyTimer > 0 || page.Standby_Y && page.StandbyTimer_Y > 0) + if(page.Standby && page.StandbyTimer > 0 || + page.Standby_Y && page.StandbyTimer_Y > 0) { - if(page.Standby && page.StandbyTimer > 0) + if(page.Standby && + page.StandbyTimer > 0) sb.AppendFormat("\tStandby timer Z is set to {0} ms", page.StandbyTimer * 100).AppendLine(); - if(page.Standby_Y && page.StandbyTimer_Y > 0) + + if(page.Standby_Y && + page.StandbyTimer_Y > 0) sb.AppendFormat("\tStandby timer Y is set to {0} ms", page.StandbyTimer_Y * 100).AppendLine(); } - else sb.AppendLine("\tDrive will not enter standy mode"); + else + sb.AppendLine("\tDrive will not enter standy mode"); - if(page.Idle && page.IdleTimer > 0 || page.Idle_B && page.IdleTimer_B > 0 || + if(page.Idle && page.IdleTimer > 0 || + page.Idle_B && page.IdleTimer_B > 0 || page.Idle_C && page.IdleTimer_C > 0) { - if(page.Idle && page.IdleTimer > 0) + if(page.Idle && + page.IdleTimer > 0) sb.AppendFormat("\tIdle timer A is set to {0} ms", page.IdleTimer * 100).AppendLine(); - if(page.Idle_B && page.IdleTimer_B > 0) + + if(page.Idle_B && + page.IdleTimer_B > 0) sb.AppendFormat("\tIdle timer B is set to {0} ms", page.IdleTimer_B * 100).AppendLine(); - if(page.Idle_C && page.IdleTimer_C > 0) + + if(page.Idle_C && + page.IdleTimer_C > 0) sb.AppendFormat("\tIdle timer C is set to {0} ms", page.IdleTimer_C * 100).AppendLine(); } - else sb.AppendLine("\tDrive will not enter idle mode"); + else + sb.AppendLine("\tDrive will not enter idle mode"); switch(page.PM_BG_Precedence) { case 0: break; case 1: sb.AppendLine("\tPerforming background functions take precedence over maintaining low power conditions"); + break; case 2: sb.AppendLine("\tMaintaining low power conditions take precedence over performing background functions"); + break; } @@ -197,41 +191,35 @@ namespace DiscImageChef.Decoders.SCSI #endregion Mode Page 0x1A: Power condition page #region Mode Page 0x1A subpage 0x01: Power Consumption mode page - /// - /// Power Consumption mode page - /// Page code 0x1A - /// Subpage code 0x01 - /// 16 bytes in SPC-5 - /// + /// Power Consumption mode page Page code 0x1A Subpage code 0x01 16 bytes in SPC-5 public struct ModePage_1A_S01 { - /// - /// Parameters can be saved - /// + /// Parameters can be saved public bool PS; - /// - /// Active power level - /// + /// Active power level public byte ActiveLevel; - /// - /// Power Consumption VPD identifier in use - /// + /// Power Consumption VPD identifier in use public byte PowerConsumptionIdentifier; } public static ModePage_1A_S01? DecodeModePage_1A_S01(byte[] pageResponse) { - if((pageResponse?[0] & 0x40) != 0x40) return null; + if((pageResponse?[0] & 0x40) != 0x40) + return null; - if((pageResponse[0] & 0x3F) != 0x1A) return null; + if((pageResponse[0] & 0x3F) != 0x1A) + return null; - if(pageResponse[1] != 0x01) return null; + if(pageResponse[1] != 0x01) + return null; - if((pageResponse[2] << 8) + pageResponse[3] + 4 != pageResponse.Length) return null; + if((pageResponse[2] << 8) + pageResponse[3] + 4 != pageResponse.Length) + return null; - if(pageResponse.Length < 16) return null; + if(pageResponse.Length < 16) + return null; - ModePage_1A_S01 decoded = new ModePage_1A_S01(); + var decoded = new ModePage_1A_S01(); decoded.PS |= (pageResponse[0] & 0x80) == 0x80; decoded.ActiveLevel = (byte)(pageResponse[6] & 0x03); @@ -245,29 +233,35 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyModePage_1A_S01(ModePage_1A_S01? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; ModePage_1A_S01 page = modePage.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendLine("SCSI Power Consumption page:"); - if(page.PS) sb.AppendLine("\tParameters can be saved"); + if(page.PS) + sb.AppendLine("\tParameters can be saved"); switch(page.ActiveLevel) { case 0: sb.AppendFormat("\tDevice power consumption is dictated by identifier {0} of Power Consumption VPD", page.PowerConsumptionIdentifier).AppendLine(); + break; case 1: sb.AppendLine("\tDevice is in highest relative power consumption level"); + break; case 2: sb.AppendLine("\tDevice is in intermediate relative power consumption level"); + break; case 3: sb.AppendLine("\tDevice is in lowest relative power consumption level"); + break; } diff --git a/SCSI/Modes/1B.cs b/SCSI/Modes/1B.cs index 01ede31..fa28d3f 100644 --- a/SCSI/Modes/1B.cs +++ b/SCSI/Modes/1B.cs @@ -35,56 +35,43 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Modes { #region Mode Page 0x1B: Removable Block Access Capabilities page - /// - /// Removable Block Access Capabilities page - /// Page code 0x1B - /// 12 bytes in INF-8070 - /// + /// Removable Block Access Capabilities page Page code 0x1B 12 bytes in INF-8070 public struct ModePage_1B { - /// - /// Parameters can be saved - /// + /// Parameters can be saved public bool PS; - /// - /// Supports reporting progress of format - /// + /// Supports reporting progress of format public bool SRFP; - /// - /// Non-CD Optical Device - /// + /// Non-CD Optical Device public bool NCD; - /// - /// Phase change dual device supporting a CD and a Non-CD Optical devices - /// + /// Phase change dual device supporting a CD and a Non-CD Optical devices public bool SML; - /// - /// Total number of LUNs - /// + /// Total number of LUNs public byte TLUN; - /// - /// System Floppy Type device - /// + /// System Floppy Type device public bool SFLP; } public static ModePage_1B? DecodeModePage_1B(byte[] pageResponse) { - if((pageResponse?[0] & 0x40) == 0x40) return null; + if((pageResponse?[0] & 0x40) == 0x40) + return null; - if((pageResponse?[0] & 0x3F) != 0x1B) return null; + if((pageResponse?[0] & 0x3F) != 0x1B) + return null; - if(pageResponse[1] + 2 != pageResponse.Length) return null; + if(pageResponse[1] + 2 != pageResponse.Length) + return null; - if(pageResponse.Length < 12) return null; + if(pageResponse.Length < 12) + return null; - ModePage_1B decoded = new ModePage_1B(); + var decoded = new ModePage_1B(); decoded.PS |= (pageResponse[0] & 0x80) == 0x80; decoded.SFLP |= (pageResponse[2] & 0x80) == 0x80; @@ -102,20 +89,31 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyModePage_1B(ModePage_1B? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; - ModePage_1B page = modePage.Value; - StringBuilder sb = new StringBuilder(); + ModePage_1B page = modePage.Value; + var sb = new StringBuilder(); sb.AppendLine("SCSI Removable Block Access Capabilities page:"); - if(page.PS) sb.AppendLine("\tParameters can be saved"); + if(page.PS) + sb.AppendLine("\tParameters can be saved"); - if(page.SFLP) sb.AppendLine("\tDrive can be used as a system floppy device"); - if(page.SRFP) sb.AppendLine("\tDrive supports reporting progress of format"); - if(page.NCD) sb.AppendLine("\tDrive is a Non-CD Optical Device"); - if(page.SML) sb.AppendLine("\tDevice is a dual device supporting CD and Non-CD Optical"); - if(page.TLUN > 0) sb.AppendFormat("\tDrive supports {0} LUNs", page.TLUN).AppendLine(); + if(page.SFLP) + sb.AppendLine("\tDrive can be used as a system floppy device"); + + if(page.SRFP) + sb.AppendLine("\tDrive supports reporting progress of format"); + + if(page.NCD) + sb.AppendLine("\tDrive is a Non-CD Optical Device"); + + if(page.SML) + sb.AppendLine("\tDevice is a dual device supporting CD and Non-CD Optical"); + + if(page.TLUN > 0) + sb.AppendFormat("\tDrive supports {0} LUNs", page.TLUN).AppendLine(); return sb.ToString(); } diff --git a/SCSI/Modes/1C.cs b/SCSI/Modes/1C.cs index 4064fc0..49ba095 100644 --- a/SCSI/Modes/1C.cs +++ b/SCSI/Modes/1C.cs @@ -35,78 +35,55 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Modes { #region Mode Page 0x1C: Informational exceptions control page - /// - /// Informational exceptions control page - /// Page code 0x1C - /// 12 bytes in SPC-1, SPC-2, SPC-3, SPC-4 - /// + /// Informational exceptions control page Page code 0x1C 12 bytes in SPC-1, SPC-2, SPC-3, SPC-4 public struct ModePage_1C { - /// - /// Parameters can be saved - /// + /// Parameters can be saved public bool PS; - /// - /// Informational exception operations should not affect performance - /// + /// Informational exception operations should not affect performance public bool Perf; - /// - /// Disable informational exception operations - /// + /// Disable informational exception operations public bool DExcpt; - /// - /// Create a test device failure at next interval time - /// + /// Create a test device failure at next interval time public bool Test; - /// - /// Log informational exception conditions - /// + /// Log informational exception conditions public bool LogErr; - /// - /// Method of reporting informational exceptions - /// + /// Method of reporting informational exceptions public byte MRIE; - /// - /// 100 ms period to report an informational exception condition - /// + /// 100 ms period to report an informational exception condition public uint IntervalTimer; - /// - /// How many times to report informational exceptions - /// + /// How many times to report informational exceptions public uint ReportCount; - /// - /// Enable background functions - /// + /// Enable background functions public bool EBF; - /// - /// Warning reporting enabled - /// + /// Warning reporting enabled public bool EWasc; - /// - /// Enable reporting of background self-test errors - /// + /// Enable reporting of background self-test errors public bool EBACKERR; } public static ModePage_1C? DecodeModePage_1C(byte[] pageResponse) { - if((pageResponse?[0] & 0x40) == 0x40) return null; + if((pageResponse?[0] & 0x40) == 0x40) + return null; - if((pageResponse?[0] & 0x3F) != 0x1C) return null; + if((pageResponse?[0] & 0x3F) != 0x1C) + return null; - if(pageResponse[1] + 2 != pageResponse.Length) return null; + if(pageResponse[1] + 2 != pageResponse.Length) + return null; - if(pageResponse.Length < 8) return null; + if(pageResponse.Length < 8) + return null; - ModePage_1C decoded = new ModePage_1C(); + var decoded = new ModePage_1C(); decoded.PS |= (pageResponse[0] & 0x80) == 0x80; @@ -137,16 +114,19 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyModePage_1C(ModePage_1C? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; - ModePage_1C page = modePage.Value; - StringBuilder sb = new StringBuilder(); + ModePage_1C page = modePage.Value; + var sb = new StringBuilder(); sb.AppendLine("SCSI Informational exceptions control page:"); - if(page.PS) sb.AppendLine("\tParameters can be saved"); + if(page.PS) + sb.AppendLine("\tParameters can be saved"); - if(page.DExcpt) sb.AppendLine("\tInformational exceptions are disabled"); + if(page.DExcpt) + sb.AppendLine("\tInformational exceptions are disabled"); else { sb.AppendLine("\tInformational exceptions are enabled"); @@ -155,33 +135,46 @@ namespace DiscImageChef.Decoders.SCSI { case 0: sb.AppendLine("\tNo reporting of informational exception condition"); + break; case 1: sb.AppendLine("\tAsynchronous event reporting of informational exceptions"); + break; case 2: sb.AppendLine("\tGenerate unit attention on informational exceptions"); + break; case 3: sb.AppendLine("\tConditionally generate recovered error on informational exceptions"); + break; case 4: sb.AppendLine("\tUnconditionally generate recovered error on informational exceptions"); + break; case 5: sb.AppendLine("\tGenerate no sense on informational exceptions"); + break; case 6: sb.AppendLine("\tOnly report informational exception condition on request"); + break; default: sb.AppendFormat("\tUnknown method of reporting {0}", page.MRIE).AppendLine(); + break; } - if(page.Perf) sb.AppendLine("\tInformational exceptions reporting should not affect drive performance"); - if(page.Test) sb.AppendLine("\tA test informational exception will raise on next timer"); - if(page.LogErr) sb.AppendLine("\tDrive shall log informational exception conditions"); + if(page.Perf) + sb.AppendLine("\tInformational exceptions reporting should not affect drive performance"); + + if(page.Test) + sb.AppendLine("\tA test informational exception will raise on next timer"); + + if(page.LogErr) + sb.AppendLine("\tDrive shall log informational exception conditions"); if(page.IntervalTimer > 0) if(page.IntervalTimer == 0xFFFFFFFF) @@ -194,74 +187,61 @@ namespace DiscImageChef.Decoders.SCSI page.ReportCount); } - if(page.EWasc) sb.AppendLine("\tWarning reporting is enabled"); - if(page.EBF) sb.AppendLine("\tBackground functions are enabled"); - if(page.EBACKERR) sb.AppendLine("\tDrive will report background self-test errors"); + if(page.EWasc) + sb.AppendLine("\tWarning reporting is enabled"); + + if(page.EBF) + sb.AppendLine("\tBackground functions are enabled"); + + if(page.EBACKERR) + sb.AppendLine("\tDrive will report background self-test errors"); return sb.ToString(); } #endregion Mode Page 0x1C: Informational exceptions control page #region Mode Page 0x1C subpage 0x01: Background Control mode page - /// - /// Background Control mode page - /// Page code 0x1A - /// Subpage code 0x01 - /// 16 bytes in SPC-5 - /// + /// Background Control mode page Page code 0x1A Subpage code 0x01 16 bytes in SPC-5 public struct ModePage_1C_S01 { - /// - /// Parameters can be saved - /// + /// Parameters can be saved public bool PS; - /// - /// Suspend on log full - /// + /// Suspend on log full public bool S_L_Full; - /// - /// Log only when intervention required - /// + /// Log only when intervention required public bool LOWIR; - /// - /// Enable background medium scan - /// + /// Enable background medium scan public bool En_Bms; - /// - /// Enable background pre-scan - /// + /// Enable background pre-scan public bool En_Ps; - /// - /// Time in hours between background medium scans - /// + /// Time in hours between background medium scans public ushort BackgroundScanInterval; - /// - /// Maximum time in hours for a background pre-scan to complete - /// + /// Maximum time in hours for a background pre-scan to complete public ushort BackgroundPrescanTimeLimit; - /// - /// Minimum time in ms being idle before resuming a background scan - /// + /// Minimum time in ms being idle before resuming a background scan public ushort MinIdleBeforeBgScan; - /// - /// Maximum time in ms to start processing commands while performing a background scan - /// + /// Maximum time in ms to start processing commands while performing a background scan public ushort MaxTimeSuspendBgScan; } public static ModePage_1C_S01? DecodeModePage_1C_S01(byte[] pageResponse) { - if((pageResponse?[0] & 0x40) != 0x40) return null; + if((pageResponse?[0] & 0x40) != 0x40) + return null; - if((pageResponse[0] & 0x3F) != 0x1C) return null; + if((pageResponse[0] & 0x3F) != 0x1C) + return null; - if(pageResponse[1] != 0x01) return null; + if(pageResponse[1] != 0x01) + return null; - if((pageResponse[2] << 8) + pageResponse[3] + 4 != pageResponse.Length) return null; + if((pageResponse[2] << 8) + pageResponse[3] + 4 != pageResponse.Length) + return null; - if(pageResponse.Length < 16) return null; + if(pageResponse.Length < 16) + return null; - ModePage_1C_S01 decoded = new ModePage_1C_S01(); + var decoded = new ModePage_1C_S01(); decoded.PS |= (pageResponse[0] & 0x80) == 0x80; @@ -283,19 +263,28 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyModePage_1C_S01(ModePage_1C_S01? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; ModePage_1C_S01 page = modePage.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendLine("SCSI Background Control page:"); - if(page.PS) sb.AppendLine("\tParameters can be saved"); + if(page.PS) + sb.AppendLine("\tParameters can be saved"); - if(page.S_L_Full) sb.AppendLine("\tBackground scans will be halted if log is full"); - if(page.LOWIR) sb.AppendLine("\tBackground scans will only be logged if they require intervention"); - if(page.En_Bms) sb.AppendLine("\tBackground medium scans are enabled"); - if(page.En_Ps) sb.AppendLine("\tBackground pre-scans are enabled"); + if(page.S_L_Full) + sb.AppendLine("\tBackground scans will be halted if log is full"); + + if(page.LOWIR) + sb.AppendLine("\tBackground scans will only be logged if they require intervention"); + + if(page.En_Bms) + sb.AppendLine("\tBackground medium scans are enabled"); + + if(page.En_Ps) + sb.AppendLine("\tBackground pre-scans are enabled"); if(page.BackgroundScanInterval > 0) sb.AppendFormat("\t{0} hours shall be between the start of a background scan operation and the next", @@ -310,8 +299,8 @@ namespace DiscImageChef.Decoders.SCSI page.MinIdleBeforeBgScan).AppendLine(); if(page.MaxTimeSuspendBgScan > 0) - sb - .AppendFormat("\tAt most {0} ms must be before suspending a background scan operation and processing received commands", + sb. + AppendFormat("\tAt most {0} ms must be before suspending a background scan operation and processing received commands", page.MaxTimeSuspendBgScan).AppendLine(); return sb.ToString(); diff --git a/SCSI/Modes/1C_SFF.cs b/SCSI/Modes/1C_SFF.cs index 3707e6b..f6afaad 100644 --- a/SCSI/Modes/1C_SFF.cs +++ b/SCSI/Modes/1C_SFF.cs @@ -35,48 +35,39 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Modes { #region Mode Page 0x1C: Timer & Protect page - /// - /// Timer & Protect page - /// Page code 0x1C - /// 8 bytes in INF-8070 - /// + /// Timer & Protect page Page code 0x1C 8 bytes in INF-8070 public struct ModePage_1C_SFF { - /// - /// Parameters can be saved - /// + /// Parameters can be saved public bool PS; - /// - /// Time the device shall remain in the current state after seek, read or write operation - /// + /// Time the device shall remain in the current state after seek, read or write operation public byte InactivityTimeMultiplier; - /// - /// Disabled until power cycle - /// + /// Disabled until power cycle public bool DISP; - /// - /// Software Write Protect until Power-down - /// + /// Software Write Protect until Power-down public bool SWPP; } public static ModePage_1C_SFF? DecodeModePage_1C_SFF(byte[] pageResponse) { - if((pageResponse?[0] & 0x40) == 0x40) return null; + if((pageResponse?[0] & 0x40) == 0x40) + return null; - if((pageResponse?[0] & 0x3F) != 0x1C) return null; + if((pageResponse?[0] & 0x3F) != 0x1C) + return null; - if(pageResponse[1] + 2 != pageResponse.Length) return null; + if(pageResponse[1] + 2 != pageResponse.Length) + return null; - if(pageResponse.Length < 8) return null; + if(pageResponse.Length < 8) + return null; - ModePage_1C_SFF decoded = new ModePage_1C_SFF(); + var decoded = new ModePage_1C_SFF(); decoded.PS |= (pageResponse[0] & 0x80) == 0x80; decoded.DISP |= (pageResponse[2] & 0x02) == 0x02; @@ -92,67 +83,88 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyModePage_1C_SFF(ModePage_1C_SFF? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; ModePage_1C_SFF page = modePage.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendLine("SCSI Timer & Protect page:"); - if(page.PS) sb.AppendLine("\tParameters can be saved"); + if(page.PS) + sb.AppendLine("\tParameters can be saved"); - if(page.DISP) sb.AppendLine("\tDrive is disabled until power is cycled"); - if(page.SWPP) sb.AppendLine("\tDrive is software write-protected until powered down"); + if(page.DISP) + sb.AppendLine("\tDrive is disabled until power is cycled"); + + if(page.SWPP) + sb.AppendLine("\tDrive is software write-protected until powered down"); switch(page.InactivityTimeMultiplier) { case 0: sb.AppendLine("\tDrive will remain in same status a vendor-specified time after a seek, read or write operation"); + break; case 1: sb.AppendLine("\tDrive will remain in same status 125 ms after a seek, read or write operation"); + break; case 2: sb.AppendLine("\tDrive will remain in same status 250 ms after a seek, read or write operation"); + break; case 3: sb.AppendLine("\tDrive will remain in same status 500 ms after a seek, read or write operation"); + break; case 4: sb.AppendLine("\tDrive will remain in same status 1 second after a seek, read or write operation"); + break; case 5: sb.AppendLine("\tDrive will remain in same status 2 seconds after a seek, read or write operation"); + break; case 6: sb.AppendLine("\tDrive will remain in same status 4 seconds after a seek, read or write operation"); + break; case 7: sb.AppendLine("\tDrive will remain in same status 8 seconds after a seek, read or write operation"); + break; case 8: sb.AppendLine("\tDrive will remain in same status 16 seconds after a seek, read or write operation"); + break; case 9: sb.AppendLine("\tDrive will remain in same status 32 seconds after a seek, read or write operation"); + break; case 10: sb.AppendLine("\tDrive will remain in same status 1 minute after a seek, read or write operation"); + break; case 11: sb.AppendLine("\tDrive will remain in same status 2 minutes after a seek, read or write operation"); + break; case 12: sb.AppendLine("\tDrive will remain in same status 4 minutes after a seek, read or write operation"); + break; case 13: sb.AppendLine("\tDrive will remain in same status 8 minutes after a seek, read or write operation"); + break; case 14: sb.AppendLine("\tDrive will remain in same status 16 minutes after a seek, read or write operation"); + break; case 15: sb.AppendLine("\tDrive will remain in same status 32 minutes after a seek, read or write operation"); + break; } diff --git a/SCSI/Modes/1D.cs b/SCSI/Modes/1D.cs index bc119d7..3781f06 100644 --- a/SCSI/Modes/1D.cs +++ b/SCSI/Modes/1D.cs @@ -35,17 +35,14 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Modes { #region Mode Page 0x1D: Medium Configuration Mode Page public struct ModePage_1D { - /// - /// Parameters can be saved - /// + /// Parameters can be saved public bool PS; public bool WORMM; public byte WormModeLabelRestrictions; @@ -54,15 +51,19 @@ namespace DiscImageChef.Decoders.SCSI public static ModePage_1D? DecodeModePage_1D(byte[] pageResponse) { - if((pageResponse?[0] & 0x40) == 0x40) return null; + if((pageResponse?[0] & 0x40) == 0x40) + return null; - if((pageResponse?[0] & 0x3F) != 0x1D) return null; + if((pageResponse?[0] & 0x3F) != 0x1D) + return null; - if(pageResponse[1] + 2 != pageResponse.Length) return null; + if(pageResponse[1] + 2 != pageResponse.Length) + return null; - if(pageResponse.Length < 32) return null; + if(pageResponse.Length < 32) + return null; - ModePage_1D decoded = new ModePage_1D(); + var decoded = new ModePage_1D(); decoded.PS |= (pageResponse[0] & 0x80) == 0x80; decoded.WORMM |= (pageResponse[2] & 0x01) == 0x01; @@ -77,31 +78,38 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyModePage_1D(ModePage_1D? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; - ModePage_1D page = modePage.Value; - StringBuilder sb = new StringBuilder(); + ModePage_1D page = modePage.Value; + var sb = new StringBuilder(); sb.AppendLine("SCSI Medium Configuration Mode Page:"); - if(page.PS) sb.AppendLine("\tParameters can be saved"); + if(page.PS) + sb.AppendLine("\tParameters can be saved"); - if(page.WORMM) sb.AppendLine("\tDrive is operating in WORM mode"); + if(page.WORMM) + sb.AppendLine("\tDrive is operating in WORM mode"); switch(page.WormModeLabelRestrictions) { case 0: sb.AppendLine("\tDrive does not allow any logical blocks to be overwritten"); + break; case 1: sb.AppendLine("\tDrive allows a tape header to be overwritten"); + break; case 2: sb.AppendLine("\tDrive allows all format labels to be overwritten"); + break; default: - sb.AppendFormat("\tUnknown WORM mode label restrictions code {0}", page.WormModeLabelRestrictions) - .AppendLine(); + sb.AppendFormat("\tUnknown WORM mode label restrictions code {0}", page.WormModeLabelRestrictions). + AppendLine(); + break; } @@ -109,13 +117,16 @@ namespace DiscImageChef.Decoders.SCSI { case 2: sb.AppendLine("\tDrive allows any number of filemarks immediately preceding EOD to be overwritten except filemark closes to BOP"); + break; case 3: sb.AppendLine("\tDrive allows any number of filemarks immediately preceding EOD to be overwritten"); + break; default: sb.AppendFormat("\tUnknown WORM mode filemark restrictions code {0}", page.WormModeLabelRestrictions).AppendLine(); + break; } diff --git a/SCSI/Modes/21_Certance.cs b/SCSI/Modes/21_Certance.cs index 5270858..b3c49e8 100644 --- a/SCSI/Modes/21_Certance.cs +++ b/SCSI/Modes/21_Certance.cs @@ -35,17 +35,14 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Modes { #region Certance Mode Page 0x21: Drive Capabilities Control Mode page public struct Certance_ModePage_21 { - /// - /// Parameters can be saved - /// + /// Parameters can be saved public bool PS; public byte OperatingSystemsSupport; public byte FirmwareTestControl2; @@ -59,15 +56,19 @@ namespace DiscImageChef.Decoders.SCSI public static Certance_ModePage_21? DecodeCertanceModePage_21(byte[] pageResponse) { - if((pageResponse?[0] & 0x40) == 0x40) return null; + if((pageResponse?[0] & 0x40) == 0x40) + return null; - if((pageResponse?[0] & 0x3F) != 0x21) return null; + if((pageResponse?[0] & 0x3F) != 0x21) + return null; - if(pageResponse[1] + 2 != pageResponse.Length) return null; + if(pageResponse[1] + 2 != pageResponse.Length) + return null; - if(pageResponse.Length != 9) return null; + if(pageResponse.Length != 9) + return null; - Certance_ModePage_21 decoded = new Certance_ModePage_21(); + var decoded = new Certance_ModePage_21(); decoded.PS |= (pageResponse[0] & 0x80) == 0x80; decoded.OperatingSystemsSupport = pageResponse[2]; @@ -87,23 +88,27 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyCertanceModePage_21(Certance_ModePage_21? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; Certance_ModePage_21 page = modePage.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendLine("Certance Drive Capabilities Control Mode Page:"); - if(page.PS) sb.AppendLine("\tParameters can be saved"); + if(page.PS) + sb.AppendLine("\tParameters can be saved"); switch(page.OperatingSystemsSupport) { case 0: sb.AppendLine("\tOperating systems support is standard LTO"); + break; default: - sb.AppendFormat("\tOperating systems support is unknown code {0}", page.OperatingSystemsSupport) - .AppendLine(); + sb.AppendFormat("\tOperating systems support is unknown code {0}", page.OperatingSystemsSupport). + AppendLine(); + break; } @@ -112,15 +117,19 @@ namespace DiscImageChef.Decoders.SCSI { case 0: sb.AppendLine("\tFactory test code is disabled"); + break; case 1: sb.AppendLine("\tFactory test code 1 is disabled"); + break; case 2: sb.AppendLine("\tFactory test code 2 is disabled"); + break; default: sb.AppendFormat("\tUnknown factory test code {0}", page.FirmwareTestControl).AppendLine(); + break; } @@ -128,12 +137,15 @@ namespace DiscImageChef.Decoders.SCSI { case 0: sb.AppendLine("\tPower-On Self-Test is enabled"); + break; case 1: sb.AppendLine("\tPower-On Self-Test is disable"); + break; default: sb.AppendFormat("\tUnknown Power-On Self-Test code {0}", page.ExtendedPOSTMode).AppendLine(); + break; } @@ -141,37 +153,48 @@ namespace DiscImageChef.Decoders.SCSI { case 0: sb.AppendLine("\tCompression is controlled using mode pages 0Fh and 10h"); + break; case 1: sb.AppendLine("\tCompression is enabled and not controllable"); + break; case 2: sb.AppendLine("\tCompression is disabled and not controllable"); + break; default: sb.AppendFormat("\tUnknown compression control code {0}", page.DataCompressionControl).AppendLine(); + break; } - if(page.HostUnloadOverride) sb.AppendLine("\tSCSI UNLOAD command will not eject the cartridge"); + if(page.HostUnloadOverride) + sb.AppendLine("\tSCSI UNLOAD command will not eject the cartridge"); sb.Append("\tHow should tapes be unloaded in a power cycle, tape incompatibility, firmware download or cleaning end: "); + switch(page.AutoUnloadMode) { case 0: sb.AppendLine("\tTape will stay threaded at beginning"); + break; case 1: sb.AppendLine("\tTape will be unthreaded"); + break; case 2: sb.AppendLine("\tTape will be unthreaded and unloaded"); + break; case 3: sb.AppendLine("\tData tapes will be threaded at beginning, rest will be unloaded"); + break; default: sb.AppendFormat("\tUnknown auto unload code {0}", page.AutoUnloadMode).AppendLine(); + break; } diff --git a/SCSI/Modes/22_Certance.cs b/SCSI/Modes/22_Certance.cs index e3b8ccc..9d532b0 100644 --- a/SCSI/Modes/22_Certance.cs +++ b/SCSI/Modes/22_Certance.cs @@ -35,18 +35,14 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] public static partial class Modes { #region Certance Mode Page 0x22: Interface Control Mode Page public struct Certance_ModePage_22 { - /// - /// Parameters can be saved - /// + /// Parameters can be saved public bool PS; public byte BaudRate; public byte CmdFwd; @@ -63,15 +59,19 @@ namespace DiscImageChef.Decoders.SCSI public static Certance_ModePage_22? DecodeCertanceModePage_22(byte[] pageResponse) { - if((pageResponse?[0] & 0x40) == 0x40) return null; + if((pageResponse?[0] & 0x40) == 0x40) + return null; - if((pageResponse?[0] & 0x3F) != 0x22) return null; + if((pageResponse?[0] & 0x3F) != 0x22) + return null; - if(pageResponse[1] + 2 != pageResponse.Length) return null; + if(pageResponse[1] + 2 != pageResponse.Length) + return null; - if(pageResponse.Length != 16) return null; + if(pageResponse.Length != 16) + return null; - Certance_ModePage_22 decoded = new Certance_ModePage_22(); + var decoded = new Certance_ModePage_22(); decoded.PS |= (pageResponse[0] & 0x80) == 0x80; decoded.BaudRate = pageResponse[2]; @@ -94,14 +94,16 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyCertanceModePage_22(Certance_ModePage_22? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; Certance_ModePage_22 page = modePage.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendLine("Certance Interface Control Mode Page:"); - if(page.PS) sb.AppendLine("\tParameters can be saved"); + if(page.PS) + sb.AppendLine("\tParameters can be saved"); switch(page.BaudRate) { @@ -109,38 +111,46 @@ namespace DiscImageChef.Decoders.SCSI case 1: case 2: sb.AppendLine("\tLibrary interface will operate at 9600 baud on next reset"); + break; case 3: sb.AppendLine("\tLibrary interface will operate at 19200 baud on next reset"); + break; case 4: sb.AppendLine("\tLibrary interface will operate at 38400 baud on next reset"); + break; case 5: sb.AppendLine("\tLibrary interface will operate at 57600 baud on next reset"); + break; case 6: sb.AppendLine("\tLibrary interface will operate at 115200 baud on next reset"); + break; default: sb.AppendFormat("\tUnknown library interface baud rate code {0}", page.BaudRate).AppendLine(); + break; } - sb.AppendLine(page.StopBits - ? "Library interface transmits 2 stop bits per byte" + sb.AppendLine(page.StopBits ? "Library interface transmits 2 stop bits per byte" : "Library interface transmits 1 stop bits per byte"); switch(page.CmdFwd) { case 0: sb.AppendLine("\tCommand forwarding is disabled"); + break; case 1: sb.AppendLine("\tCommand forwarding is enabled"); + break; default: sb.AppendFormat("\tUnknown command forwarding code {0}", page.CmdFwd).AppendLine(); + break; } @@ -148,26 +158,29 @@ namespace DiscImageChef.Decoders.SCSI { case 0: sb.AppendLine("\tPort A link is down"); + break; case 3: sb.AppendLine("\tPort A uses Parallel SCSI Ultra-160 interface"); + break; default: sb.AppendFormat("\tUnknown port A transport type code {0}", page.PortATransportType).AppendLine(); + break; } if(page.PortATransportType > 0) sb.AppendFormat("\tDrive responds to SCSI ID {0}", page.PortAPresentSelectionID).AppendLine(); - sb.AppendFormat("\tDrive will respond to SCSI ID {0} on Port A enabling", page.NextSelectionID) - .AppendLine(); + sb.AppendFormat("\tDrive will respond to SCSI ID {0} on Port A enabling", page.NextSelectionID). + AppendLine(); + sb.AppendFormat("\tDrive jumpers choose SCSI ID {0}", page.JumperedSelectionID).AppendLine(); sb.AppendLine(page.PortAEnabled ? "\tSCSI port is enabled" : "\tSCSI port is disabled"); - sb.AppendLine(page.PortAEnabledOnPower - ? "\tSCSI port will be enabled on next power up" + sb.AppendLine(page.PortAEnabledOnPower ? "\tSCSI port will be enabled on next power up" : "\tSCSI port will be disabled on next power up"); return sb.ToString(); diff --git a/SCSI/Modes/24_IBM.cs b/SCSI/Modes/24_IBM.cs index 625abf1..0ea2f93 100644 --- a/SCSI/Modes/24_IBM.cs +++ b/SCSI/Modes/24_IBM.cs @@ -35,17 +35,14 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Modes { #region IBM Mode Page 0x24: Drive Capabilities Control Mode page public struct IBM_ModePage_24 { - /// - /// Parameters can be saved - /// + /// Parameters can be saved public bool PS; public byte ModeControl; public byte VelocitySetting; @@ -55,15 +52,19 @@ namespace DiscImageChef.Decoders.SCSI public static IBM_ModePage_24? DecodeIBMModePage_24(byte[] pageResponse) { - if((pageResponse?[0] & 0x40) == 0x40) return null; + if((pageResponse?[0] & 0x40) == 0x40) + return null; - if((pageResponse?[0] & 0x3F) != 0x24) return null; + if((pageResponse?[0] & 0x3F) != 0x24) + return null; - if(pageResponse[1] + 2 != pageResponse.Length) return null; + if(pageResponse[1] + 2 != pageResponse.Length) + return null; - if(pageResponse.Length != 8) return null; + if(pageResponse.Length != 8) + return null; - IBM_ModePage_24 decoded = new IBM_ModePage_24(); + var decoded = new IBM_ModePage_24(); decoded.PS |= (pageResponse[0] & 0x80) == 0x80; decoded.ModeControl = pageResponse[2]; @@ -79,22 +80,27 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyIBMModePage_24(IBM_ModePage_24? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; IBM_ModePage_24 page = modePage.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendLine("IBM Vendor-Specific Control Mode Page:"); - if(page.PS) sb.AppendLine("\tParameters can be saved"); + if(page.PS) + sb.AppendLine("\tParameters can be saved"); - sb.AppendFormat("\tVendor-specific mode control: {0}", page.ModeControl); + sb.AppendFormat("\tVendor-specific mode control: {0}", page.ModeControl); sb.AppendFormat("\tVendor-specific velocity setting: {0}", page.VelocitySetting); - if(!page.EncryptionCapable) return sb.ToString(); + if(!page.EncryptionCapable) + return sb.ToString(); sb.AppendLine("\tDrive supports encryption"); - if(page.EncryptionEnabled) sb.AppendLine("\tDrive has encryption enabled"); + + if(page.EncryptionEnabled) + sb.AppendLine("\tDrive has encryption enabled"); return sb.ToString(); } diff --git a/SCSI/Modes/2A.cs b/SCSI/Modes/2A.cs index 0055d41..061f85e 100644 --- a/SCSI/Modes/2A.cs +++ b/SCSI/Modes/2A.cs @@ -39,116 +39,63 @@ using Newtonsoft.Json; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] public static partial class Modes { #region Mode Page 0x2A: CD-ROM capabilities page /// - /// CD-ROM capabilities page - /// Page code 0x2A - /// 16 bytes in OB-U0077C - /// 20 bytes in SFF-8020i - /// 22 bytes in MMC-1 - /// 26 bytes in MMC-2 - /// Variable bytes in MMC-3 + /// CD-ROM capabilities page Page code 0x2A 16 bytes in OB-U0077C 20 bytes in SFF-8020i 22 bytes in MMC-1 26 bytes + /// in MMC-2 Variable bytes in MMC-3 /// public class ModePage_2A { public ModePage_2A_WriteDescriptor[] WriteSpeedPerformanceDescriptors; - /// - /// Parameters can be saved - /// + /// Parameters can be saved public bool PS { get; set; } - /// - /// Drive supports multi-session and/or Photo-CD - /// + /// Drive supports multi-session and/or Photo-CD public bool MultiSession { get; set; } - /// - /// Drive is capable of reading sectors in Mode 2 Form 2 format - /// + /// Drive is capable of reading sectors in Mode 2 Form 2 format public bool Mode2Form2 { get; set; } - /// - /// Drive is capable of reading sectors in Mode 2 Form 1 format - /// + /// Drive is capable of reading sectors in Mode 2 Form 1 format public bool Mode2Form1 { get; set; } - /// - /// Drive is capable of playing audio - /// + /// Drive is capable of playing audio public bool AudioPlay { get; set; } - /// - /// Drive can return the ISRC - /// + /// Drive can return the ISRC public bool ISRC { get; set; } - /// - /// Drive can return the media catalogue number - /// + /// Drive can return the media catalogue number public bool UPC { get; set; } - /// - /// Drive can return C2 pointers - /// + /// Drive can return C2 pointers public bool C2Pointer { get; set; } - /// - /// Drive can read, deinterlave and correct R-W subchannels - /// + /// Drive can read, deinterlave and correct R-W subchannels public bool DeinterlaveSubchannel { get; set; } - /// - /// Drive can read interleaved and uncorrected R-W subchannels - /// + /// Drive can read interleaved and uncorrected R-W subchannels public bool Subchannel { get; set; } - /// - /// Drive can continue from a loss of streaming on audio reading - /// + /// Drive can continue from a loss of streaming on audio reading public bool AccurateCDDA { get; set; } - /// - /// Audio can be read as digital data - /// + /// Audio can be read as digital data public bool CDDACommand { get; set; } - /// - /// Loading Mechanism Type - /// + /// Loading Mechanism Type public byte LoadingMechanism { get; set; } - /// - /// Drive can eject discs - /// + /// Drive can eject discs public bool Eject { get; set; } - /// - /// Drive's optional prevent jumper status - /// + /// Drive's optional prevent jumper status public bool PreventJumper { get; set; } - /// - /// Current lock status - /// + /// Current lock status public bool LockState { get; set; } - /// - /// Drive can lock media - /// + /// Drive can lock media public bool Lock { get; set; } - /// - /// Each channel can be muted independently - /// + /// Each channel can be muted independently public bool SeparateChannelMute { get; set; } - /// - /// Each channel's volume can be controlled independently - /// + /// Each channel's volume can be controlled independently public bool SeparateChannelVolume { get; set; } - /// - /// Maximum drive speed in Kbytes/second - /// + /// Maximum drive speed in Kbytes/second public ushort MaximumSpeed { get; set; } - /// - /// Supported volume levels - /// + /// Supported volume levels public ushort SupportedVolumeLevels { get; set; } - /// - /// Buffer size in Kbytes - /// + /// Buffer size in Kbytes public ushort BufferSize { get; set; } - /// - /// Current drive speed in Kbytes/second - /// + /// Current drive speed in Kbytes/second public ushort CurrentSpeed { get; set; } public bool Method2 { get; set; } @@ -185,8 +132,7 @@ namespace DiscImageChef.Decoders.SCSI public byte RotationControlSelected { get; set; } public ushort CurrentWriteSpeedSelected { get; set; } - [JsonIgnore] - [Key] + [JsonIgnore, Key] public int Id { get; set; } } @@ -198,15 +144,19 @@ namespace DiscImageChef.Decoders.SCSI public static ModePage_2A DecodeModePage_2A(byte[] pageResponse) { - if((pageResponse?[0] & 0x40) == 0x40) return null; + if((pageResponse?[0] & 0x40) == 0x40) + return null; - if((pageResponse?[0] & 0x3F) != 0x2A) return null; + if((pageResponse?[0] & 0x3F) != 0x2A) + return null; - if(pageResponse[1] + 2 != pageResponse.Length) return null; + if(pageResponse[1] + 2 != pageResponse.Length) + return null; - if(pageResponse.Length < 16) return null; + if(pageResponse.Length < 16) + return null; - ModePage_2A decoded = new ModePage_2A(); + var decoded = new ModePage_2A(); decoded.PS |= (pageResponse[0] & 0x80) == 0x80; @@ -237,7 +187,8 @@ namespace DiscImageChef.Decoders.SCSI decoded.BufferSize = (ushort)((pageResponse[12] << 8) + pageResponse[13]); decoded.CurrentSpeed = (ushort)((pageResponse[14] << 8) + pageResponse[15]); - if(pageResponse.Length < 20) return decoded; + if(pageResponse.Length < 20) + return decoded; decoded.Method2 |= (pageResponse[2] & 0x04) == 0x04; decoded.ReadCDRW |= (pageResponse[2] & 0x02) == 0x02; @@ -258,7 +209,8 @@ namespace DiscImageChef.Decoders.SCSI decoded.RCK |= (pageResponse[17] & 0x04) == 0x04; decoded.BCK |= (pageResponse[17] & 0x02) == 0x02; - if(pageResponse.Length < 22) return decoded; + if(pageResponse.Length < 22) + return decoded; decoded.TestWrite |= (pageResponse[3] & 0x04) == 0x04; decoded.MaxWriteSpeed = (ushort)((pageResponse[18] << 8) + pageResponse[19]); @@ -266,7 +218,8 @@ namespace DiscImageChef.Decoders.SCSI decoded.ReadBarcode |= (pageResponse[5] & 0x80) == 0x80; - if(pageResponse.Length < 26) return decoded; + if(pageResponse.Length < 26) + return decoded; decoded.ReadDVDRAM |= (pageResponse[2] & 0x20) == 0x20; decoded.ReadDVDR |= (pageResponse[2] & 0x10) == 0x10; @@ -280,7 +233,8 @@ namespace DiscImageChef.Decoders.SCSI decoded.CMRSupported = (ushort)((pageResponse[22] << 8) + pageResponse[23]); - if(pageResponse.Length < 32) return decoded; + if(pageResponse.Length < 32) + return decoded; decoded.BUF |= (pageResponse[4] & 0x80) == 0x80; decoded.RotationControlSelected = (byte)(pageResponse[27] & 0x03); @@ -307,96 +261,191 @@ namespace DiscImageChef.Decoders.SCSI pageResponse[0] = 0x2A; - if(decoded.PS) pageResponse[0] += 0x80; + if(decoded.PS) + pageResponse[0] += 0x80; - if(decoded.AudioPlay) pageResponse[4] += 0x01; - if(decoded.Mode2Form1) pageResponse[4] += 0x10; - if(decoded.Mode2Form2) pageResponse[4] += 0x20; - if(decoded.MultiSession) pageResponse[4] += 0x40; + if(decoded.AudioPlay) + pageResponse[4] += 0x01; - if(decoded.CDDACommand) pageResponse[5] += 0x01; - if(decoded.AccurateCDDA) pageResponse[5] += 0x02; - if(decoded.Subchannel) pageResponse[5] += 0x04; - if(decoded.DeinterlaveSubchannel) pageResponse[5] += 0x08; - if(decoded.C2Pointer) pageResponse[5] += 0x10; - if(decoded.UPC) pageResponse[5] += 0x20; - if(decoded.ISRC) pageResponse[5] += 0x40; + if(decoded.Mode2Form1) + pageResponse[4] += 0x10; + + if(decoded.Mode2Form2) + pageResponse[4] += 0x20; + + if(decoded.MultiSession) + pageResponse[4] += 0x40; + + if(decoded.CDDACommand) + pageResponse[5] += 0x01; + + if(decoded.AccurateCDDA) + pageResponse[5] += 0x02; + + if(decoded.Subchannel) + pageResponse[5] += 0x04; + + if(decoded.DeinterlaveSubchannel) + pageResponse[5] += 0x08; + + if(decoded.C2Pointer) + pageResponse[5] += 0x10; + + if(decoded.UPC) + pageResponse[5] += 0x20; + + if(decoded.ISRC) + pageResponse[5] += 0x40; decoded.LoadingMechanism = (byte)((pageResponse[6] & 0xE0) >> 5); - if(decoded.Lock) pageResponse[6] += 0x01; - if(decoded.LockState) pageResponse[6] += 0x02; - if(decoded.PreventJumper) pageResponse[6] += 0x04; - if(decoded.Eject) pageResponse[6] += 0x08; - if(decoded.SeparateChannelVolume) pageResponse[7] += 0x01; - if(decoded.SeparateChannelMute) pageResponse[7] += 0x02; + if(decoded.Lock) + pageResponse[6] += 0x01; + + if(decoded.LockState) + pageResponse[6] += 0x02; + + if(decoded.PreventJumper) + pageResponse[6] += 0x04; + + if(decoded.Eject) + pageResponse[6] += 0x08; + + if(decoded.SeparateChannelVolume) + pageResponse[7] += 0x01; + + if(decoded.SeparateChannelMute) + pageResponse[7] += 0x02; decoded.MaximumSpeed = (ushort)((pageResponse[8] << 8) + pageResponse[9]); decoded.SupportedVolumeLevels = (ushort)((pageResponse[10] << 8) + pageResponse[11]); decoded.BufferSize = (ushort)((pageResponse[12] << 8) + pageResponse[13]); decoded.CurrentSpeed = (ushort)((pageResponse[14] << 8) + pageResponse[15]); - if(decoded.Method2 || decoded.ReadCDRW || decoded.ReadCDR || decoded.WriteCDRW || - decoded.WriteCDR || - decoded.Composite || decoded.DigitalPort1 || decoded.DigitalPort2 || decoded.SDP || - decoded.SSS || - decoded.Length > 0 || decoded.LSBF || decoded.RCK || decoded.BCK) + if(decoded.Method2 || + decoded.ReadCDRW || + decoded.ReadCDR || + decoded.WriteCDRW || + decoded.WriteCDR || + decoded.Composite || + decoded.DigitalPort1 || + decoded.DigitalPort2 || + decoded.SDP || + decoded.SSS || + decoded.Length > 0 || + decoded.LSBF || + decoded.RCK || + decoded.BCK) { length = 20; - if(decoded.Method2) pageResponse[2] += 0x04; - if(decoded.ReadCDRW) pageResponse[2] += 0x02; - if(decoded.ReadCDR) pageResponse[2] += 0x01; - if(decoded.WriteCDRW) pageResponse[3] += 0x02; - if(decoded.WriteCDR) pageResponse[3] += 0x01; + if(decoded.Method2) + pageResponse[2] += 0x04; - if(decoded.Composite) pageResponse[4] += 0x02; - if(decoded.DigitalPort1) pageResponse[4] += 0x04; - if(decoded.DigitalPort2) pageResponse[4] += 0x08; + if(decoded.ReadCDRW) + pageResponse[2] += 0x02; - if(decoded.SDP) pageResponse[7] += 0x04; - if(decoded.SSS) pageResponse[7] += 0x08; + if(decoded.ReadCDR) + pageResponse[2] += 0x01; + + if(decoded.WriteCDRW) + pageResponse[3] += 0x02; + + if(decoded.WriteCDR) + pageResponse[3] += 0x01; + + if(decoded.Composite) + pageResponse[4] += 0x02; + + if(decoded.DigitalPort1) + pageResponse[4] += 0x04; + + if(decoded.DigitalPort2) + pageResponse[4] += 0x08; + + if(decoded.SDP) + pageResponse[7] += 0x04; + + if(decoded.SSS) + pageResponse[7] += 0x08; pageResponse[17] = (byte)(decoded.Length << 4); - if(decoded.LSBF) pageResponse[17] += 0x08; - if(decoded.RCK) pageResponse[17] += 0x04; - if(decoded.BCK) pageResponse[17] += 0x02; + + if(decoded.LSBF) + pageResponse[17] += 0x08; + + if(decoded.RCK) + pageResponse[17] += 0x04; + + if(decoded.BCK) + pageResponse[17] += 0x02; } - if(decoded.TestWrite || decoded.MaxWriteSpeed > 0 || decoded.CurrentWriteSpeed > 0 || decoded.ReadBarcode) + if(decoded.TestWrite || + decoded.MaxWriteSpeed > 0 || + decoded.CurrentWriteSpeed > 0 || + decoded.ReadBarcode) { length = 22; - if(decoded.TestWrite) pageResponse[3] += 0x04; + + if(decoded.TestWrite) + pageResponse[3] += 0x04; + pageResponse[18] = (byte)((decoded.MaxWriteSpeed & 0xFF00) >> 8); pageResponse[19] = (byte)(decoded.MaxWriteSpeed & 0xFF); pageResponse[20] = (byte)((decoded.CurrentWriteSpeed & 0xFF00) >> 8); pageResponse[21] = (byte)(decoded.CurrentWriteSpeed & 0xFF); - if(decoded.ReadBarcode) pageResponse[5] += 0x80; + + if(decoded.ReadBarcode) + pageResponse[5] += 0x80; } - if(decoded.ReadDVDRAM || decoded.ReadDVDR || decoded.ReadDVDROM || decoded.WriteDVDRAM || - decoded.WriteDVDR || decoded.LeadInPW || decoded.SCC || decoded.CMRSupported > 0) + if(decoded.ReadDVDRAM || + decoded.ReadDVDR || + decoded.ReadDVDROM || + decoded.WriteDVDRAM || + decoded.WriteDVDR || + decoded.LeadInPW || + decoded.SCC || + decoded.CMRSupported > 0) { length = 26; - if(decoded.ReadDVDRAM) pageResponse[2] += 0x20; - if(decoded.ReadDVDR) pageResponse[2] += 0x10; - if(decoded.ReadDVDROM) pageResponse[2] += 0x08; - if(decoded.WriteDVDRAM) pageResponse[3] += 0x20; - if(decoded.WriteDVDR) pageResponse[3] += 0x10; + if(decoded.ReadDVDRAM) + pageResponse[2] += 0x20; - if(decoded.LeadInPW) pageResponse[3] += 0x20; - if(decoded.SCC) pageResponse[3] += 0x10; + if(decoded.ReadDVDR) + pageResponse[2] += 0x10; + + if(decoded.ReadDVDROM) + pageResponse[2] += 0x08; + + if(decoded.WriteDVDRAM) + pageResponse[3] += 0x20; + + if(decoded.WriteDVDR) + pageResponse[3] += 0x10; + + if(decoded.LeadInPW) + pageResponse[3] += 0x20; + + if(decoded.SCC) + pageResponse[3] += 0x10; pageResponse[22] = (byte)((decoded.CMRSupported & 0xFF00) >> 8); pageResponse[23] = (byte)(decoded.CMRSupported & 0xFF); } - if(decoded.BUF || decoded.RotationControlSelected > 0 || decoded.CurrentWriteSpeedSelected > 0) + if(decoded.BUF || + decoded.RotationControlSelected > 0 || + decoded.CurrentWriteSpeedSelected > 0) { length = 32; - if(decoded.BUF) pageResponse[4] += 0x80; + + if(decoded.BUF) + pageResponse[4] += 0x80; + pageResponse[27] += decoded.RotationControlSelected; pageResponse[28] = (byte)((decoded.CurrentWriteSpeedSelected & 0xFF00) >> 8); pageResponse[29] = (byte)(decoded.CurrentWriteSpeedSelected & 0xFF); @@ -405,12 +454,15 @@ namespace DiscImageChef.Decoders.SCSI if(decoded.WriteSpeedPerformanceDescriptors != null) { length = 32; + for(int i = 0; i < decoded.WriteSpeedPerformanceDescriptors.Length; i++) { length += 4; pageResponse[1 + 32 + i * 4] = decoded.WriteSpeedPerformanceDescriptors[i].RotationControl; + pageResponse[2 + 32 + i * 4] = (byte)((decoded.WriteSpeedPerformanceDescriptors[i].WriteSpeed & 0xFF00) >> 8); + pageResponse[3 + 32 + i * 4] = (byte)(decoded.WriteSpeedPerformanceDescriptors[i].WriteSpeed & 0xFF); } @@ -419,6 +471,7 @@ namespace DiscImageChef.Decoders.SCSI pageResponse[1] = (byte)(length - 2); byte[] buf = new byte[length]; Array.Copy(pageResponse, 0, buf, 0, length); + return buf; } @@ -427,57 +480,87 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyModePage_2A(ModePage_2A modePage) { - if(modePage is null) return null; + if(modePage is null) + return null; - ModePage_2A page = modePage; - StringBuilder sb = new StringBuilder(); + ModePage_2A page = modePage; + var sb = new StringBuilder(); sb.AppendLine("SCSI CD-ROM capabilities page:"); - if(page.PS) sb.AppendLine("\tParameters can be saved"); + if(page.PS) + sb.AppendLine("\tParameters can be saved"); - if(page.AudioPlay) sb.AppendLine("\tDrive can play audio"); - if(page.Mode2Form1) sb.AppendLine("\tDrive can read sectors in Mode 2 Form 1 format"); - if(page.Mode2Form2) sb.AppendLine("\tDrive can read sectors in Mode 2 Form 2 format"); - if(page.MultiSession) sb.AppendLine("\tDrive supports multi-session discs and/or Photo-CD"); + if(page.AudioPlay) + sb.AppendLine("\tDrive can play audio"); - if(page.CDDACommand) sb.AppendLine("\tDrive can read digital audio"); - if(page.AccurateCDDA) sb.AppendLine("\tDrive can continue from streaming loss"); - if(page.Subchannel) sb.AppendLine("\tDrive can read uncorrected and interleaved R-W subchannels"); - if(page.DeinterlaveSubchannel) sb.AppendLine("\tDrive can read, deinterleave and correct R-W subchannels"); - if(page.C2Pointer) sb.AppendLine("\tDrive supports C2 pointers"); - if(page.UPC) sb.AppendLine("\tDrive can read Media Catalogue Number"); - if(page.ISRC) sb.AppendLine("\tDrive can read ISRC"); + if(page.Mode2Form1) + sb.AppendLine("\tDrive can read sectors in Mode 2 Form 1 format"); + + if(page.Mode2Form2) + sb.AppendLine("\tDrive can read sectors in Mode 2 Form 2 format"); + + if(page.MultiSession) + sb.AppendLine("\tDrive supports multi-session discs and/or Photo-CD"); + + if(page.CDDACommand) + sb.AppendLine("\tDrive can read digital audio"); + + if(page.AccurateCDDA) + sb.AppendLine("\tDrive can continue from streaming loss"); + + if(page.Subchannel) + sb.AppendLine("\tDrive can read uncorrected and interleaved R-W subchannels"); + + if(page.DeinterlaveSubchannel) + sb.AppendLine("\tDrive can read, deinterleave and correct R-W subchannels"); + + if(page.C2Pointer) + sb.AppendLine("\tDrive supports C2 pointers"); + + if(page.UPC) + sb.AppendLine("\tDrive can read Media Catalogue Number"); + + if(page.ISRC) + sb.AppendLine("\tDrive can read ISRC"); switch(page.LoadingMechanism) { case 0: sb.AppendLine("\tDrive uses media caddy"); + break; case 1: sb.AppendLine("\tDrive uses a tray"); + break; case 2: sb.AppendLine("\tDrive is pop-up"); + break; case 4: sb.AppendLine("\tDrive is a changer with individually changeable discs"); + break; case 5: sb.AppendLine("\tDrive is a changer using cartridges"); + break; default: - sb.AppendFormat("\tDrive uses unknown loading mechanism type {0}", page.LoadingMechanism) - .AppendLine(); + sb.AppendFormat("\tDrive uses unknown loading mechanism type {0}", page.LoadingMechanism). + AppendLine(); + break; } - if(page.Lock) sb.AppendLine("\tDrive can lock media"); + if(page.Lock) + sb.AppendLine("\tDrive can lock media"); + if(page.PreventJumper) { sb.AppendLine("\tDrive power ups locked"); - sb.AppendLine(page.LockState - ? "\tDrive is locked, media cannot be ejected or inserted" + + sb.AppendLine(page.LockState ? "\tDrive is locked, media cannot be ejected or inserted" : "\tDrive is not locked, media can be ejected and inserted"); } else @@ -485,16 +568,24 @@ namespace DiscImageChef.Decoders.SCSI ? "\tDrive is locked, media cannot be ejected, but if empty, can be inserted" : "\tDrive is not locked, media can be ejected and inserted"); - if(page.Eject) sb.AppendLine("\tDrive can eject media"); + if(page.Eject) + sb.AppendLine("\tDrive can eject media"); - if(page.SeparateChannelMute) sb.AppendLine("\tEach channel can be muted independently"); - if(page.SeparateChannelVolume) sb.AppendLine("\tEach channel's volume can be controlled independently"); + if(page.SeparateChannelMute) + sb.AppendLine("\tEach channel can be muted independently"); + + if(page.SeparateChannelVolume) + sb.AppendLine("\tEach channel's volume can be controlled independently"); if(page.SupportedVolumeLevels > 0) sb.AppendFormat("\tDrive supports {0} volume levels", page.SupportedVolumeLevels).AppendLine(); - if(page.BufferSize > 0) sb.AppendFormat("\tDrive has {0} Kbyte of buffer", page.BufferSize).AppendLine(); + + if(page.BufferSize > 0) + sb.AppendFormat("\tDrive has {0} Kbyte of buffer", page.BufferSize).AppendLine(); + if(page.MaximumSpeed > 0) sb.AppendFormat("\tDrive's maximum reading speed is {0} Kbyte/sec.", page.MaximumSpeed).AppendLine(); + if(page.CurrentSpeed > 0) sb.AppendFormat("\tDrive's current reading speed is {0} Kbyte/sec.", page.CurrentSpeed).AppendLine(); @@ -502,23 +593,34 @@ namespace DiscImageChef.Decoders.SCSI { sb.AppendLine(page.WriteCDR ? "\tDrive can read and write CD-R" : "\tDrive can read CD-R"); - if(page.Method2) sb.AppendLine("\tDrive supports reading CD-R packet media"); + if(page.Method2) + sb.AppendLine("\tDrive supports reading CD-R packet media"); } if(page.ReadCDRW) sb.AppendLine(page.WriteCDRW ? "\tDrive can read and write CD-RW" : "\tDrive can read CD-RW"); - if(page.ReadDVDROM) sb.AppendLine("\tDrive can read DVD-ROM"); + if(page.ReadDVDROM) + sb.AppendLine("\tDrive can read DVD-ROM"); + if(page.ReadDVDR) sb.AppendLine(page.WriteDVDR ? "\tDrive can read and write DVD-R" : "\tDrive can read DVD-R"); + if(page.ReadDVDRAM) sb.AppendLine(page.WriteDVDRAM ? "\tDrive can read and write DVD-RAM" : "\tDrive can read DVD-RAM"); - if(page.Composite) sb.AppendLine("\tDrive can deliver a composite audio and video data stream"); - if(page.DigitalPort1) sb.AppendLine("\tDrive supports IEC-958 digital output on port 1"); - if(page.DigitalPort2) sb.AppendLine("\tDrive supports IEC-958 digital output on port 2"); + if(page.Composite) + sb.AppendLine("\tDrive can deliver a composite audio and video data stream"); + + if(page.DigitalPort1) + sb.AppendLine("\tDrive supports IEC-958 digital output on port 1"); + + if(page.DigitalPort2) + sb.AppendLine("\tDrive supports IEC-958 digital output on port 2"); + + if(page.SDP) + sb.AppendLine("\tDrive contains a changer that can report the exact contents of the slots"); - if(page.SDP) sb.AppendLine("\tDrive contains a changer that can report the exact contents of the slots"); if(page.CurrentWriteSpeedSelected > 0) { if(page.RotationControlSelected == 0) @@ -531,33 +633,41 @@ namespace DiscImageChef.Decoders.SCSI else { if(page.MaxWriteSpeed > 0) - sb.AppendFormat("\tDrive's maximum writing speed is {0} Kbyte/sec.", page.MaxWriteSpeed) - .AppendLine(); + sb.AppendFormat("\tDrive's maximum writing speed is {0} Kbyte/sec.", page.MaxWriteSpeed). + AppendLine(); + if(page.CurrentWriteSpeed > 0) - sb.AppendFormat("\tDrive's current writing speed is {0} Kbyte/sec.", page.CurrentWriteSpeed) - .AppendLine(); + sb.AppendFormat("\tDrive's current writing speed is {0} Kbyte/sec.", page.CurrentWriteSpeed). + AppendLine(); } if(page.WriteSpeedPerformanceDescriptors != null) foreach(ModePage_2A_WriteDescriptor descriptor in page.WriteSpeedPerformanceDescriptors.Where(descriptor => descriptor.WriteSpeed > 0)) if(descriptor.RotationControl == 0) - sb.AppendFormat("\tDrive supports writing at {0} Kbyte/sec. in CLV mode", descriptor.WriteSpeed) - .AppendLine(); + sb.AppendFormat("\tDrive supports writing at {0} Kbyte/sec. in CLV mode", + descriptor.WriteSpeed).AppendLine(); else if(descriptor.RotationControl == 1) sb.AppendFormat("\tDrive supports writing at is {0} Kbyte/sec. in pure CAV mode", descriptor.WriteSpeed).AppendLine(); - if(page.TestWrite) sb.AppendLine("\tDrive supports test writing"); + if(page.TestWrite) + sb.AppendLine("\tDrive supports test writing"); - if(page.ReadBarcode) sb.AppendLine("\tDrive can read barcode"); + if(page.ReadBarcode) + sb.AppendLine("\tDrive can read barcode"); - if(page.SCC) sb.AppendLine("\tDrive can read both sides of a disc"); - if(page.LeadInPW) sb.AppendLine("\tDrive an read raw R-W subchannel from the Lead-In"); + if(page.SCC) + sb.AppendLine("\tDrive can read both sides of a disc"); - if(page.CMRSupported == 1) sb.AppendLine("\tDrive supports DVD CSS and/or DVD CPPM"); + if(page.LeadInPW) + sb.AppendLine("\tDrive an read raw R-W subchannel from the Lead-In"); - if(page.BUF) sb.AppendLine("\tDrive supports buffer under-run free recording"); + if(page.CMRSupported == 1) + sb.AppendLine("\tDrive supports DVD CSS and/or DVD CPPM"); + + if(page.BUF) + sb.AppendLine("\tDrive supports buffer under-run free recording"); return sb.ToString(); } diff --git a/SCSI/Modes/2F_IBM.cs b/SCSI/Modes/2F_IBM.cs index 58de6bd..6633d6a 100644 --- a/SCSI/Modes/2F_IBM.cs +++ b/SCSI/Modes/2F_IBM.cs @@ -35,18 +35,14 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "UnassignedField.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "UnassignedField.Global")] public static partial class Modes { #region IBM Mode Page 0x2F: Behaviour Configuration Mode page public struct IBM_ModePage_2F { - /// - /// Parameters can be saved - /// + /// Parameters can be saved public bool PS; public byte FenceBehaviour; public byte CleanBehaviour; @@ -63,27 +59,28 @@ namespace DiscImageChef.Decoders.SCSI public static IBM_ModePage_2F? DecodeIBMModePage_2F(byte[] pageResponse) { - if((pageResponse?[0] & 0x40) == 0x40) return null; + if((pageResponse?[0] & 0x40) == 0x40) + return null; - if((pageResponse?[0] & 0x3F) != 0x2F) return null; + if((pageResponse?[0] & 0x3F) != 0x2F) + return null; - if(pageResponse[1] + 2 != pageResponse.Length) return null; + if(pageResponse[1] + 2 != pageResponse.Length) + return null; - if(pageResponse.Length < 8) return null; + if(pageResponse.Length < 8) + return null; return new IBM_ModePage_2F { - PS = (pageResponse[0] & 0x80) == 0x80, - FenceBehaviour = pageResponse[2], - CleanBehaviour = pageResponse[3], - WORMEmulation = pageResponse[4], - SenseDataBehaviour = pageResponse[5], - CCDM = (pageResponse[6] & 0x04) == 0x04, - DDEOR = (pageResponse[6] & 0x02) == 0x02, - CLNCHK = (pageResponse[6] & 0x01) == 0x01, - FirmwareUpdateBehaviour = pageResponse[7], - UOE_C = (byte)((pageResponse[8] & 0x30) >> 4), - UOE_F = (byte)((pageResponse[8] & 0x0C) >> 2) + PS = (pageResponse[0] & 0x80) == 0x80, FenceBehaviour = pageResponse[2], + CleanBehaviour = pageResponse[3], WORMEmulation = pageResponse[4], + SenseDataBehaviour = pageResponse[5], + CCDM = (pageResponse[6] & 0x04) == 0x04, + DDEOR = (pageResponse[6] & 0x02) == 0x02, + CLNCHK = (pageResponse[6] & 0x01) == 0x01, FirmwareUpdateBehaviour = pageResponse[7], + UOE_C = (byte)((pageResponse[8] & 0x30) >> 4), + UOE_F = (byte)((pageResponse[8] & 0x0C) >> 2) }; } @@ -92,25 +89,30 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyIBMModePage_2F(IBM_ModePage_2F? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; IBM_ModePage_2F page = modePage.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendLine("IBM Behaviour Configuration Mode Page:"); - if(page.PS) sb.AppendLine("\tParameters can be saved"); + if(page.PS) + sb.AppendLine("\tParameters can be saved"); switch(page.FenceBehaviour) { case 0: sb.AppendLine("\tFence behaviour is normal"); + break; case 1: sb.AppendLine("\tPanic fence behaviour is enabled"); + break; default: sb.AppendFormat("\tUnknown fence behaviour code {0}", page.FenceBehaviour).AppendLine(); + break; } @@ -118,12 +120,15 @@ namespace DiscImageChef.Decoders.SCSI { case 0: sb.AppendLine("\tCleaning behaviour is normal"); + break; case 1: sb.AppendLine("\tDrive will periodically request cleaning"); + break; default: sb.AppendFormat("\tUnknown cleaning behaviour code {0}", page.CleanBehaviour).AppendLine(); + break; } @@ -131,12 +136,15 @@ namespace DiscImageChef.Decoders.SCSI { case 0: sb.AppendLine("\tWORM emulation is disabled"); + break; case 1: sb.AppendLine("\tWORM emulation is enabled"); + break; default: sb.AppendFormat("\tUnknown WORM emulation code {0}", page.WORMEmulation).AppendLine(); + break; } @@ -144,24 +152,38 @@ namespace DiscImageChef.Decoders.SCSI { case 0: sb.AppendLine("\tUses 35-bytes sense data"); + break; case 1: sb.AppendLine("\tUses 96-bytes sense data"); + break; default: sb.AppendFormat("\tUnknown sense data behaviour code {0}", page.WORMEmulation).AppendLine(); + break; } - if(page.CLNCHK) sb.AppendLine("\tDrive will set Check Condition when cleaning is needed"); - if(page.DDEOR) sb.AppendLine("\tNo deferred error will be reported to a rewind command"); - if(page.CCDM) sb.AppendLine("\tDrive will set Check Condition when the criteria for Dead Media is met"); + if(page.CLNCHK) + sb.AppendLine("\tDrive will set Check Condition when cleaning is needed"); + + if(page.DDEOR) + sb.AppendLine("\tNo deferred error will be reported to a rewind command"); + + if(page.CCDM) + sb.AppendLine("\tDrive will set Check Condition when the criteria for Dead Media is met"); + if(page.FirmwareUpdateBehaviour > 0) sb.AppendLine("\tDrive will not accept downlevel firmware via an FMR tape"); - if(page.UOE_C == 1) sb.AppendLine("\tDrive will eject cleaning cartridges on error"); - if(page.UOE_F == 1) sb.AppendLine("\tDrive will eject firmware cartridges on error"); - if(page.UOE_D == 1) sb.AppendLine("\tDrive will eject data cartridges on error"); + if(page.UOE_C == 1) + sb.AppendLine("\tDrive will eject cleaning cartridges on error"); + + if(page.UOE_F == 1) + sb.AppendLine("\tDrive will eject firmware cartridges on error"); + + if(page.UOE_D == 1) + sb.AppendLine("\tDrive will eject data cartridges on error"); return sb.ToString(); } diff --git a/SCSI/Modes/30_Apple.cs b/SCSI/Modes/30_Apple.cs index b1876fd..e34da1e 100644 --- a/SCSI/Modes/30_Apple.cs +++ b/SCSI/Modes/30_Apple.cs @@ -36,27 +36,30 @@ using System.Linq; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Modes { #region Apple Mode Page 0x30: Apple OEM String static readonly byte[] AppleOEMString = { - 0x41, 0x50, 0x50, 0x4C, 0x45, 0x20, 0x43, 0x4F, 0x4D, 0x50, 0x55, 0x54, 0x45, 0x52, 0x2C, 0x20, 0x49, - 0x4E, 0x43, 0x2E + 0x41, 0x50, 0x50, 0x4C, 0x45, 0x20, 0x43, 0x4F, 0x4D, 0x50, 0x55, 0x54, 0x45, 0x52, 0x2C, 0x20, 0x49, 0x4E, + 0x43, 0x2E }; public static bool IsAppleModePage_30(byte[] pageResponse) { - if((pageResponse?[0] & 0x40) == 0x40) return false; + if((pageResponse?[0] & 0x40) == 0x40) + return false; - if((pageResponse?[0] & 0x3F) != 0x30) return false; + if((pageResponse?[0] & 0x3F) != 0x30) + return false; - if(pageResponse[1] + 2 != pageResponse.Length) return false; + if(pageResponse[1] + 2 != pageResponse.Length) + return false; - if(pageResponse.Length != 30) return false; + if(pageResponse.Length != 30) + return false; byte[] str = new byte[20]; Array.Copy(pageResponse, 10, str, 0, 20); diff --git a/SCSI/Modes/3B_HP.cs b/SCSI/Modes/3B_HP.cs index a959d78..bda66c3 100644 --- a/SCSI/Modes/3B_HP.cs +++ b/SCSI/Modes/3B_HP.cs @@ -36,17 +36,14 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Modes { #region HP Mode Page 0x3B: Serial Number Override Mode page public struct HP_ModePage_3B { - /// - /// Parameters can be saved - /// + /// Parameters can be saved public bool PS; public byte MSN; public byte[] SerialNumber; @@ -54,15 +51,19 @@ namespace DiscImageChef.Decoders.SCSI public static HP_ModePage_3B? DecodeHPModePage_3B(byte[] pageResponse) { - if((pageResponse?[0] & 0x40) == 0x40) return null; + if((pageResponse?[0] & 0x40) == 0x40) + return null; - if((pageResponse?[0] & 0x3F) != 0x3B) return null; + if((pageResponse?[0] & 0x3F) != 0x3B) + return null; - if(pageResponse[1] + 2 != pageResponse.Length) return null; + if(pageResponse[1] + 2 != pageResponse.Length) + return null; - if(pageResponse.Length != 16) return null; + if(pageResponse.Length != 16) + return null; - HP_ModePage_3B decoded = new HP_ModePage_3B(); + var decoded = new HP_ModePage_3B(); decoded.PS |= (pageResponse[0] & 0x80) == 0x80; decoded.MSN = (byte)(pageResponse[2] & 0x03); @@ -77,22 +78,26 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyHPModePage_3B(HP_ModePage_3B? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; HP_ModePage_3B page = modePage.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendLine("HP Serial Number Override Mode Page:"); - if(page.PS) sb.AppendLine("\tParameters can be saved"); + if(page.PS) + sb.AppendLine("\tParameters can be saved"); switch(page.MSN) { case 1: sb.AppendLine("\tSerial number is the manufacturer's default value"); + break; case 3: sb.AppendLine("\tSerial number is not the manufacturer's default value"); + break; } diff --git a/SCSI/Modes/3C_HP.cs b/SCSI/Modes/3C_HP.cs index 24ea30a..e71880d 100644 --- a/SCSI/Modes/3C_HP.cs +++ b/SCSI/Modes/3C_HP.cs @@ -36,17 +36,14 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Modes { #region HP Mode Page 0x3C: Device Time Mode page public struct HP_ModePage_3C { - /// - /// Parameters can be saved - /// + /// Parameters can be saved public bool PS; public bool LT; public bool WT; @@ -64,30 +61,39 @@ namespace DiscImageChef.Decoders.SCSI public static HP_ModePage_3C? DecodeHPModePage_3C(byte[] pageResponse) { - if((pageResponse?[0] & 0x40) == 0x40) return null; + if((pageResponse?[0] & 0x40) == 0x40) + return null; - if((pageResponse?[0] & 0x3F) != 0x3C) return null; + if((pageResponse?[0] & 0x3F) != 0x3C) + return null; - if(pageResponse[1] + 2 != pageResponse.Length) return null; + if(pageResponse[1] + 2 != pageResponse.Length) + return null; - if(pageResponse.Length != 36) return null; + if(pageResponse.Length != 36) + return null; - HP_ModePage_3C decoded = new HP_ModePage_3C(); + var decoded = new HP_ModePage_3C(); decoded.PS |= (pageResponse[0] & 0x80) == 0x80; decoded.LT |= (pageResponse[2] & 0x04) == 0x04; decoded.WT |= (pageResponse[2] & 0x02) == 0x02; decoded.PT |= (pageResponse[2] & 0x01) == 0x01; decoded.CurrentPowerOn = (ushort)((pageResponse[6] << 8) + pageResponse[7]); + decoded.PowerOnTime = (uint)((pageResponse[8] << 24) + (pageResponse[9] << 16) + (pageResponse[10] << 8) + pageResponse[11]); + decoded.UTC |= (pageResponse[14] & 0x02) == 0x02; decoded.NTP |= (pageResponse[14] & 0x01) == 0x01; + decoded.WorldTime = (uint)((pageResponse[16] << 24) + (pageResponse[17] << 16) + (pageResponse[18] << 8) + pageResponse[19]); + decoded.LibraryHours = pageResponse[23]; decoded.LibraryMinutes = pageResponse[24]; decoded.LibrarySeconds = pageResponse[25]; + decoded.CumulativePowerOn = (uint)((pageResponse[32] << 24) + (pageResponse[33] << 16) + (pageResponse[34] << 8) + pageResponse[35]); @@ -99,30 +105,38 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyHPModePage_3C(HP_ModePage_3C? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; HP_ModePage_3C page = modePage.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendLine("HP Device Time Mode Page:"); - if(page.PS) sb.AppendLine("\tParameters can be saved"); + if(page.PS) + sb.AppendLine("\tParameters can be saved"); if(page.PT) { sb.AppendFormat("\tDrive has been powered up {0} times", page.CurrentPowerOn); + sb.AppendFormat("\tDrive has been powered up since {0} this time", TimeSpan.FromSeconds(page.PowerOnTime)).AppendLine(); + sb.AppendFormat("\tDrive has been powered up a total of {0}", TimeSpan.FromSeconds(page.CumulativePowerOn)).AppendLine(); } if(page.WT) { - sb.AppendFormat("\tDrive's date/time is: {0}", DateHandlers.UnixUnsignedToDateTime(page.WorldTime)) - .AppendLine(); - if(page.UTC) sb.AppendLine("\tDrive's time is UTC"); - if(page.NTP) sb.AppendLine("\tDrive's time is synchronized with a NTP source"); + sb.AppendFormat("\tDrive's date/time is: {0}", DateHandlers.UnixUnsignedToDateTime(page.WorldTime)). + AppendLine(); + + if(page.UTC) + sb.AppendLine("\tDrive's time is UTC"); + + if(page.NTP) + sb.AppendLine("\tDrive's time is synchronized with a NTP source"); } if(page.LT) diff --git a/SCSI/Modes/3D_HP.cs b/SCSI/Modes/3D_HP.cs index 2cdc9a9..288c1ea 100644 --- a/SCSI/Modes/3D_HP.cs +++ b/SCSI/Modes/3D_HP.cs @@ -35,32 +35,33 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Modes { #region HP Mode Page 0x3D: Extended Reset Mode page public struct HP_ModePage_3D { - /// - /// Parameters can be saved - /// + /// Parameters can be saved public bool PS; public byte ResetBehaviour; } public static HP_ModePage_3D? DecodeHPModePage_3D(byte[] pageResponse) { - if((pageResponse?[0] & 0x40) == 0x40) return null; + if((pageResponse?[0] & 0x40) == 0x40) + return null; - if((pageResponse?[0] & 0x3F) != 0x3D) return null; + if((pageResponse?[0] & 0x3F) != 0x3D) + return null; - if(pageResponse[1] + 2 != pageResponse.Length) return null; + if(pageResponse[1] + 2 != pageResponse.Length) + return null; - if(pageResponse.Length != 4) return null; + if(pageResponse.Length != 4) + return null; - HP_ModePage_3D decoded = new HP_ModePage_3D(); + var decoded = new HP_ModePage_3D(); decoded.PS |= (pageResponse[0] & 0x80) == 0x80; decoded.ResetBehaviour = (byte)(pageResponse[2] & 0x03); @@ -73,25 +74,30 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyHPModePage_3D(HP_ModePage_3D? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; HP_ModePage_3D page = modePage.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendLine("HP Extended Reset Mode Page:"); - if(page.PS) sb.AppendLine("\tParameters can be saved"); + if(page.PS) + sb.AppendLine("\tParameters can be saved"); switch(page.ResetBehaviour) { case 0: sb.AppendLine("\tNormal reset behaviour"); + break; case 1: sb.AppendLine("\tDrive will flush and position itself on a LUN or target reset"); + break; case 2: sb.AppendLine("\tDrive will maintain position on a LUN or target reset"); + break; } diff --git a/SCSI/Modes/3D_IBM.cs b/SCSI/Modes/3D_IBM.cs index 6a63ca0..6bb8915 100644 --- a/SCSI/Modes/3D_IBM.cs +++ b/SCSI/Modes/3D_IBM.cs @@ -35,32 +35,33 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Modes { #region IBM Mode Page 0x3D: Behaviour Configuration Mode page public struct IBM_ModePage_3D { - /// - /// Parameters can be saved - /// + /// Parameters can be saved public bool PS; public ushort NumberOfWraps; } public static IBM_ModePage_3D? DecodeIBMModePage_3D(byte[] pageResponse) { - if((pageResponse?[0] & 0x40) == 0x40) return null; + if((pageResponse?[0] & 0x40) == 0x40) + return null; - if((pageResponse?[0] & 0x3F) != 0x3D) return null; + if((pageResponse?[0] & 0x3F) != 0x3D) + return null; - if(pageResponse[1] + 2 != pageResponse.Length) return null; + if(pageResponse[1] + 2 != pageResponse.Length) + return null; - if(pageResponse.Length != 5) return null; + if(pageResponse.Length != 5) + return null; - IBM_ModePage_3D decoded = new IBM_ModePage_3D(); + var decoded = new IBM_ModePage_3D(); decoded.PS |= (pageResponse[0] & 0x80) == 0x80; decoded.NumberOfWraps = (ushort)((pageResponse[3] << 8) + pageResponse[4]); @@ -73,14 +74,16 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyIBMModePage_3D(IBM_ModePage_3D? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; IBM_ModePage_3D page = modePage.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendLine("IBM LEOT Mode Page:"); - if(page.PS) sb.AppendLine("\tParameters can be saved"); + if(page.PS) + sb.AppendLine("\tParameters can be saved"); sb.AppendFormat("\t{0} wraps", page.NumberOfWraps).AppendLine(); diff --git a/SCSI/Modes/3E_Fujitsu.cs b/SCSI/Modes/3E_Fujitsu.cs index f19d2cd..0eff379 100644 --- a/SCSI/Modes/3E_Fujitsu.cs +++ b/SCSI/Modes/3E_Fujitsu.cs @@ -36,68 +36,51 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] public static partial class Modes { #region Fujitsu Mode Page 0x3E: Verify Control page public enum Fujitsu_VerifyModes : byte { - /// - /// Always verify after writing - /// - Always = 0, - /// - /// Never verify after writing - /// - Never = 1, - /// - /// Verify after writing depending on condition - /// - Depends = 2, - Reserved = 4 + /// Always verify after writing + Always = 0, /// Never verify after writing + Never = 1, /// Verify after writing depending on condition + Depends = 2, Reserved = 4 } public struct Fujitsu_ModePage_3E { - /// - /// Parameters can be saved - /// + /// Parameters can be saved public bool PS; - /// - /// If set, AV data support mode is applied - /// + /// If set, AV data support mode is applied public bool audioVisualMode; - /// - /// If set the test write operation is restricted - /// + /// If set the test write operation is restricted public bool streamingMode; public byte Reserved1; - /// - /// Verify mode for WRITE commands - /// + /// Verify mode for WRITE commands public Fujitsu_VerifyModes verifyMode; public byte Reserved2; - /// - /// Device type provided in response to INQUIRY - /// + /// Device type provided in response to INQUIRY public PeripheralDeviceTypes devType; public byte[] Reserved3; } public static Fujitsu_ModePage_3E? DecodeFujitsuModePage_3E(byte[] pageResponse) { - if((pageResponse?[0] & 0x40) == 0x40) return null; + if((pageResponse?[0] & 0x40) == 0x40) + return null; - if((pageResponse?[0] & 0x3F) != 0x3E) return null; + if((pageResponse?[0] & 0x3F) != 0x3E) + return null; - if(pageResponse[1] + 2 != pageResponse.Length) return null; + if(pageResponse[1] + 2 != pageResponse.Length) + return null; - if(pageResponse.Length != 8) return null; + if(pageResponse.Length != 8) + return null; - Fujitsu_ModePage_3E decoded = new Fujitsu_ModePage_3E(); + var decoded = new Fujitsu_ModePage_3E(); decoded.PS |= (pageResponse[0] & 0x80) == 0x80; @@ -120,16 +103,20 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyFujitsuModePage_3E(Fujitsu_ModePage_3E? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; Fujitsu_ModePage_3E page = modePage.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendLine("Fujitsu Verify Control Page:"); - if(page.PS) sb.AppendLine("\tParameters can be saved"); + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + if(page.audioVisualMode) + sb.AppendLine("\tAudio/Visual data support mode is applied"); - if(page.audioVisualMode) sb.AppendLine("\tAudio/Visual data support mode is applied"); if(page.streamingMode) sb.AppendLine("\tTest write operation is restricted during read or write operations."); @@ -137,17 +124,20 @@ namespace DiscImageChef.Decoders.SCSI { case Fujitsu_VerifyModes.Always: sb.AppendLine("\tAlways apply the verify operation"); + break; case Fujitsu_VerifyModes.Never: sb.AppendLine("\tNever apply the verify operation"); + break; case Fujitsu_VerifyModes.Depends: sb.AppendLine("\tApply the verify operation depending on the condition"); + break; } - sb.AppendFormat("\tThe device type that would be provided in the INQUIRY response is {0}", page.devType) - .AppendLine(); + sb.AppendFormat("\tThe device type that would be provided in the INQUIRY response is {0}", page.devType). + AppendLine(); return sb.ToString(); } diff --git a/SCSI/Modes/3E_HP.cs b/SCSI/Modes/3E_HP.cs index a938bbf..3ea5241 100644 --- a/SCSI/Modes/3E_HP.cs +++ b/SCSI/Modes/3E_HP.cs @@ -35,17 +35,14 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Modes { #region HP Mode Page 0x3E: CD-ROM Emulation/Disaster Recovery Mode page public struct HP_ModePage_3E { - /// - /// Parameters can be saved - /// + /// Parameters can be saved public bool PS; public bool NonAuto; public bool CDmode; @@ -53,15 +50,19 @@ namespace DiscImageChef.Decoders.SCSI public static HP_ModePage_3E? DecodeHPModePage_3E(byte[] pageResponse) { - if((pageResponse?[0] & 0x40) == 0x40) return null; + if((pageResponse?[0] & 0x40) == 0x40) + return null; - if((pageResponse?[0] & 0x3F) != 0x3E) return null; + if((pageResponse?[0] & 0x3F) != 0x3E) + return null; - if(pageResponse[1] + 2 != pageResponse.Length) return null; + if(pageResponse[1] + 2 != pageResponse.Length) + return null; - if(pageResponse.Length != 4) return null; + if(pageResponse.Length != 4) + return null; - HP_ModePage_3E decoded = new HP_ModePage_3E(); + var decoded = new HP_ModePage_3E(); decoded.PS |= (pageResponse[0] & 0x80) == 0x80; decoded.NonAuto |= (pageResponse[2] & 0x02) == 0x02; @@ -75,19 +76,22 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifyHPModePage_3E(HP_ModePage_3E? modePage) { - if(!modePage.HasValue) return null; + if(!modePage.HasValue) + return null; HP_ModePage_3E page = modePage.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendLine("HP CD-ROM Emulation/Disaster Recovery Mode Page:"); - if(page.PS) sb.AppendLine("\tParameters can be saved"); + if(page.PS) + sb.AppendLine("\tParameters can be saved"); - sb.AppendLine(page.CDmode - ? "\tDrive is emulating a CD-ROM drive" + sb.AppendLine(page.CDmode ? "\tDrive is emulating a CD-ROM drive" : "\tDrive is not emulating a CD-ROM drive"); - if(page.NonAuto) sb.AppendLine("\tDrive will not exit emulation automatically"); + + if(page.NonAuto) + sb.AppendLine("\tDrive will not exit emulation automatically"); return sb.ToString(); } diff --git a/SCSI/Modes/Headers.cs b/SCSI/Modes/Headers.cs index 6b03eeb..9121b21 100644 --- a/SCSI/Modes/Headers.cs +++ b/SCSI/Modes/Headers.cs @@ -35,9 +35,8 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Modes { public static string GetMediumTypeDescription(MediumTypes type) @@ -51,7 +50,7 @@ namespace DiscImageChef.Decoders.SCSI return "ECMA-59 & ANSI X3.121-1984: 200 mm Flexible Disk Cartridge using Two-Frequency Recording at 13262 ftprad on Both Sides"; case MediumTypes.ECMA69: - return "ECMA-69: 200 mm Flexible Disk Cartridge using MFM Recording at 13262 ftprad on Both Sides"; + return"ECMA-69: 200 mm Flexible Disk Cartridge using MFM Recording at 13262 ftprad on Both Sides"; case MediumTypes.ECMA66: return "ECMA-66: 130 mm Flexible Disk Cartridge using Two-Frequency Recording at 7958 ftprad on One Side"; @@ -67,6 +66,7 @@ namespace DiscImageChef.Decoders.SCSI case MediumTypes.ECMA100: return "ECMA-100 & ANSI X3.137: 90 mm Flexible Disk Cartridge using MFM Recording at 7859 ftprad on Both Sides; 5,3 Tracks per mm"; + // Most probably they will never appear, but magneto-opticals use these codes /* case MediumTypes.Unspecified_SS: @@ -74,16 +74,17 @@ namespace DiscImageChef.Decoders.SCSI case MediumTypes.Unspecified_DS: return "Unspecified double sided flexible disk"; */ - case MediumTypes.X3_73: return "ANSI X3.73-1980: 200 mm, 6631 ftprad, 1,9 Tracks per mm, 1 side"; - case MediumTypes.X3_73_DS: return "ANSI X3.73-1980: 200 mm, 6631 ftprad, 1,9 Tracks per mm, 2 sides"; - case MediumTypes.X3_82: return "ANSI X3.80-1980: 130 mm, 3979 ftprad, 1,9 Tracks per mm, 1 side"; + case MediumTypes.X3_73: return"ANSI X3.73-1980: 200 mm, 6631 ftprad, 1,9 Tracks per mm, 1 side"; + case MediumTypes.X3_73_DS: return"ANSI X3.73-1980: 200 mm, 6631 ftprad, 1,9 Tracks per mm, 2 sides"; + case MediumTypes.X3_82: return"ANSI X3.80-1980: 130 mm, 3979 ftprad, 1,9 Tracks per mm, 1 side"; case MediumTypes.Type3Floppy: - return "3.5-inch, 135 tpi, 12362 bits/radian, double-sided MFM (aka 1.25Mb)"; - case MediumTypes.HDFloppy: return "3.5-inch, 135 tpi, 15916 bits/radian, double-sided MFM (aka 1.44Mb)"; - case MediumTypes.ReadOnly: return "a Read-only optical"; - case MediumTypes.WORM: return "a Write-once Read-many optical"; - case MediumTypes.Erasable: return "a Erasable optical"; - case MediumTypes.RO_WORM: return "a combination of read-only and write-once optical"; + return"3.5-inch, 135 tpi, 12362 bits/radian, double-sided MFM (aka 1.25Mb)"; + case MediumTypes.HDFloppy: return"3.5-inch, 135 tpi, 15916 bits/radian, double-sided MFM (aka 1.44Mb)"; + case MediumTypes.ReadOnly: return"a Read-only optical"; + case MediumTypes.WORM: return"a Write-once Read-many optical"; + case MediumTypes.Erasable: return"a Erasable optical"; + case MediumTypes.RO_WORM: return"a combination of read-only and write-once optical"; + // These magneto-opticals were never manufactured /* case MediumTypes.RO_RW: @@ -92,16 +93,17 @@ namespace DiscImageChef.Decoders.SCSI case MediumTypes.WORM_RW: return "a combination of write-once and erasable optical"; */ - case MediumTypes.DOW: return "a direct-overwrite optical"; - default: return $"Unknown medium type 0x{(byte)type:X2}"; + case MediumTypes.DOW: return"a direct-overwrite optical"; + default: return$"Unknown medium type 0x{(byte)type:X2}"; } } public static string PrettifyModeHeader(ModeHeader? header, PeripheralDeviceTypes deviceType) { - if(!header.HasValue) return null; + if(!header.HasValue) + return null; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendLine("SCSI Mode Sense Header:"); @@ -111,31 +113,38 @@ namespace DiscImageChef.Decoders.SCSI case PeripheralDeviceTypes.DirectAccess: { if(header.Value.MediumType != MediumTypes.Default) - sb.AppendFormat("\tMedium is {0}", GetMediumTypeDescription(header.Value.MediumType)) - .AppendLine(); + sb.AppendFormat("\tMedium is {0}", GetMediumTypeDescription(header.Value.MediumType)). + AppendLine(); - if(header.Value.WriteProtected) sb.AppendLine("\tMedium is write protected"); + if(header.Value.WriteProtected) + sb.AppendLine("\tMedium is write protected"); - if(header.Value.DPOFUA) sb.AppendLine("\tDrive supports DPO and FUA bits"); + if(header.Value.DPOFUA) + sb.AppendLine("\tDrive supports DPO and FUA bits"); if(header.Value.BlockDescriptors != null) foreach(BlockDescriptor descriptor in header.Value.BlockDescriptors) { string density = ""; + switch(descriptor.Density) { case DensityType.Default: break; case DensityType.Flux7958: density = "7958 flux transitions per radian"; + break; case DensityType.Flux13262: density = "13262 flux transitions per radian"; + break; case DensityType.Flux15916: density = "15916 flux transitions per radian"; + break; default: density = $"with unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } @@ -147,8 +156,8 @@ namespace DiscImageChef.Decoders.SCSI sb.AppendFormat("\t{0} blocks have {1} and are {2} bytes each", descriptor.Blocks, density, descriptor.BlockLength).AppendLine(); else if(descriptor.Blocks == 0) - sb.AppendFormat("\tAll remaining blocks are {0} bytes each", descriptor.BlockLength) - .AppendLine(); + sb.AppendFormat("\tAll remaining blocks are {0} bytes each", descriptor.BlockLength). + AppendLine(); else sb.AppendFormat("\t{0} blocks are {1} bytes each", descriptor.Blocks, descriptor.BlockLength).AppendLine(); @@ -165,23 +174,30 @@ namespace DiscImageChef.Decoders.SCSI { case 0: sb.AppendLine("\tDevice writes directly to media"); + break; case 1: sb.AppendLine("\tDevice uses a write cache"); + break; case 2: sb.AppendLine("\tDevice uses a write cache but doesn't return until cache is flushed"); + break; default: - sb.AppendFormat("\tUnknown buffered mode code 0x{0:X2}", header.Value.BufferedMode) - .AppendLine(); + sb.AppendFormat("\tUnknown buffered mode code 0x{0:X2}", header.Value.BufferedMode). + AppendLine(); + break; } - if(header.Value.Speed == 0) sb.AppendLine("\tDevice uses default speed"); - else sb.AppendFormat("\tDevice uses speed {0}", header.Value.Speed).AppendLine(); + if(header.Value.Speed == 0) + sb.AppendLine("\tDevice uses default speed"); + else + sb.AppendFormat("\tDevice uses speed {0}", header.Value.Speed).AppendLine(); - if(header.Value.WriteProtected) sb.AppendLine("\tMedium is write protected"); + if(header.Value.WriteProtected) + sb.AppendLine("\tMedium is write protected"); string medium; @@ -189,180 +205,239 @@ namespace DiscImageChef.Decoders.SCSI { case MediumTypes.Default: medium = "undefined"; + break; case MediumTypes.Tape12: medium = "6,3 mm tape with 12 tracks at 394 ftpmm or DC-9250"; + break; case MediumTypes.Tape24: medium = "6,3 mm tape with 24 tracks at 394 ftpmm or MLR1-26GBSL"; + break; case MediumTypes.LTOWORM: medium = "LTO Ultrium WORM or cleaning cartridge"; + break; case MediumTypes.LTO: medium = "LTO Ultrium"; + break; case MediumTypes.LTO2: medium = "LTO Ultrium-2"; + break; case MediumTypes.DC2900SL: medium = "DC-2900SL"; + break; case MediumTypes.MLR1: medium = "MLR1-26GB or DDS-3"; + break; case MediumTypes.DC9200: medium = "DC-9200 or DDS-4"; + break; case MediumTypes.DAT72: medium = "DAT-72"; + break; case MediumTypes.LTO3: medium = "LTO Ultrium-3"; + break; case MediumTypes.LTO3WORM: medium = "LTO Ultrium-3 WORM"; + break; case MediumTypes.DDSCleaning: medium = "DDS cleaning cartridge"; + break; case MediumTypes.SLR32: medium = "SLR-32"; + break; case MediumTypes.SLRtape50: medium = "SLRtape-50"; + break; case MediumTypes.LTO4: medium = "LTO Ultrium-4"; + break; case MediumTypes.LTO4WORM: medium = "LTO Ultrium-4 WORM"; + break; case MediumTypes.SLRtape50SL: medium = "SLRtape-50 SL"; + break; case MediumTypes.SLR32SL: medium = "SLR-32SL"; + break; case MediumTypes.SLR5: medium = "SLR-5"; + break; case MediumTypes.SLR5SL: medium = "SLR-5SL"; + break; case MediumTypes.LTO5: medium = "LTO Ultrium-5"; + break; case MediumTypes.LTO5WORM: medium = "LTO Ultrium-5 WORM"; + break; case MediumTypes.SLRtape7: medium = "SLRtape-7"; + break; case MediumTypes.SLRtape7SL: medium = "SLRtape-7 SL"; + break; case MediumTypes.SLRtape24: medium = "SLRtape-24"; + break; case MediumTypes.SLRtape24SL: medium = "SLRtape-24 SL"; + break; case MediumTypes.LTO6: medium = "LTO Ultrium-6"; + break; case MediumTypes.LTO6WORM: medium = "LTO Ultrium-6 WORM"; + break; case MediumTypes.SLRtape140: medium = "SLRtape-140"; + break; case MediumTypes.SLRtape40: medium = "SLRtape-40"; + break; case MediumTypes.SLRtape60: medium = "SLRtape-60 or SLRtape-75"; + break; case MediumTypes.SLRtape100: medium = "SLRtape-100"; + break; case MediumTypes.SLR40_60_100: medium = "SLR-40, SLR-60 or SLR-100"; + break; case MediumTypes.LTO7: medium = "LTO Ultrium-7"; + break; case MediumTypes.LTO7WORM: medium = "LTO Ultrium-7 WORM"; + break; case MediumTypes.LTOCD: medium = "LTO Ultrium"; + break; case MediumTypes.Exatape15m: medium = "Exatape 15m, IBM MagStar or VXA"; + break; case MediumTypes.CT1: medium = "CompactTape I, Exatape 28m, CompactTape II, VXA-2 or VXA-3"; + break; case MediumTypes.Exatape54m: medium = "Exatape 54m or DLTtape III"; + break; case MediumTypes.Exatape80m: medium = "Exatape 80m or DLTtape IIIxt"; + break; case MediumTypes.Exatape106m: medium = "Exatape 106m, DLTtape IV or Travan 5"; + break; case MediumTypes.Exatape106mXL: medium = "Exatape 160m XL or Super DLTtape I"; + break; case MediumTypes.SDLT2: medium = "Super DLTtape II"; + break; case MediumTypes.VStapeI: medium = "VStape I"; + break; case MediumTypes.DLTtapeS4: medium = "DLTtape S4"; + break; case MediumTypes.Travan7: medium = "Travan 7"; + break; case MediumTypes.Exatape22m: medium = "Exatape 22m"; + break; case MediumTypes.Exatape40m: medium = "Exatape 40m"; + break; case MediumTypes.Exatape76m: medium = "Exatape 76m"; + break; case MediumTypes.Exatape112m: medium = "Exatape 112m"; + break; case MediumTypes.Exatape22mAME: medium = "Exatape 22m AME"; + break; case MediumTypes.Exatape170m: medium = "Exatape 170m"; + break; case MediumTypes.Exatape125m: medium = "Exatape 125m"; + break; case MediumTypes.Exatape45m: medium = "Exatape 45m"; + break; case MediumTypes.Exatape225m: medium = "Exatape 225m"; + break; case MediumTypes.Exatape150m: medium = "Exatape 150m"; + break; case MediumTypes.Exatape75m: medium = "Exatape 75m"; + break; default: medium = $"unknown medium type 0x{(byte)header.Value.MediumType:X2}"; + break; } @@ -372,6 +447,7 @@ namespace DiscImageChef.Decoders.SCSI foreach(BlockDescriptor descriptor in header.Value.BlockDescriptors) { string density = ""; + switch(header.Value.MediumType) { case MediumTypes.Default: @@ -382,146 +458,188 @@ namespace DiscImageChef.Decoders.SCSI case DensityType.ECMA62: density = "ECMA-62 & ANSI X3.22-1983: 12,7 mm 9-Track Magnetic Tape, 32 ftpmm, NRZI, 32 cpmm"; + break; case DensityType.ECMA62_Phase: density = "ECMA-62 & ANSI X3.39-1986: 12,7 mm 9-Track Magnetic Tape, 126 ftpmm, Phase Encoding, 63 cpmm"; + break; case DensityType.ECMA62_GCR: density = "ECMA-62 & ANSI X3.54-1986: 12,7 mm 9-Track Magnetic Tape, 356 ftpmm, NRZI, 245 cpmm GCR"; + break; case DensityType.ECMA79: density = "ECMA-79 & ANSI X3.116-1986: 6,30 mm Magnetic Tape Cartridge, 252 ftpmm, MFM"; + break; case DensityType.IBM3480: density = "Draft ECMA & ANSI X3B5/87-099: 12,7 mm 18-Track Magnetic Tape Cartridge, 1944 ftpmm, IFM, GCR (IBM 3480, 3490, 3490E)"; + break; case DensityType.ECMA46: density = "ECMA-46 & ANSI X3.56-1986: 6,30 mm Magnetic Tape Cartridge, Phase Encoding, 63 bpmm"; + break; case DensityType.ECMA98: density = "ECMA-98: 6,30 mm Magnetic Tape Cartridge, NRZI, 394 ftpmm"; + break; case DensityType.X3_136: density = "ANXI X3.136-1986: 6,3 mm 4 or 9-Track Magnetic Tape Cartridge, 315 bpmm, GCR (QIC-24)"; + break; case DensityType.X3_157: density = "ANXI X3.157-1987: 12,7 mm 9-Track Magnetic Tape, 126 bpmm, Phase Encoding"; + break; case DensityType.X3_158: density = "ANXI X3.158-1987: 3,81 mm 4-Track Magnetic Tape Cassette, 315 bpmm, GCR"; + break; case DensityType.X3B5_86: density = "ANXI X3B5/86-199: 12,7 mm 22-Track Magnetic Tape Cartridge, 262 bpmm, MFM"; + break; case DensityType.HiTC1: density = "HI-TC1: 12,7 mm 24-Track Magnetic Tape Cartridge, 500 bpmm, GCR"; + break; case DensityType.HiTC2: density = "HI-TC2: 12,7 mm 24-Track Magnetic Tape Cartridge, 999 bpmm, GCR"; + break; case DensityType.QIC120: density = "QIC-120: 6,3 mm 15-Track Magnetic Tape Cartridge, 394 bpmm, GCR"; + break; case DensityType.QIC150: density = "QIC-150: 6,3 mm 18-Track Magnetic Tape Cartridge, 394 bpmm, GCR"; + break; case DensityType.QIC320: density = "QIC-320: 6,3 mm 26-Track Magnetic Tape Cartridge, 630 bpmm, GCR"; + break; case DensityType.QIC1350: density = "QIC-1350: 6,3 mm 30-Track Magnetic Tape Cartridge, 2034 bpmm, RLL"; + break; case DensityType.X3B5_88: density = "ANXI X3B5/88-185A: 3,81 mm Magnetic Tape Cassette, 2400 bpmm, DDS"; + break; case DensityType.X3_202: density = "ANXI X3.202-1991: 8 mm Magnetic Tape Cassette, 1703 bpmm, RLL"; + break; case DensityType.ECMA_TC17: density = "ECMA TC17: 8 mm Magnetic Tape Cassette, 1789 bpmm, RLL"; + break; case DensityType.X3_193: density = "ANXI X3.193-1990: 12,7 mm 48-Track Magnetic Tape Cartridge, 394 bpmm, MFM"; + break; case DensityType.X3B5_91: density = "ANXI X3B5/97-174: 12,7 mm 48-Track Magnetic Tape Cartridge, 1673 bpmm, MFM"; + break; case DensityType.QIC11: density = "QIC-11"; + break; case DensityType.IBM3490E: density = "IBM 3490E"; + break; case DensityType.LTO1: //case DensityType.SAIT1: density = "LTO Ultrium or Super AIT-1"; + break; case DensityType.LTO2Old: density = "LTO Ultrium-2"; + break; case DensityType.LTO2: //case DensityType.T9840: density = "LTO Ultrium-2 or T9840"; + break; case DensityType.T9940: density = "T9940"; + break; case DensityType.LTO3: //case DensityType.T9940: density = "LTO Ultrium-3 or T9940"; + break; case DensityType.T9840C: density = "T9840C"; + break; case DensityType.LTO4: //case DensityType.T9840D: density = "LTO Ultrium-4 or T9840D"; + break; case DensityType.T10000A: density = "T10000A"; + break; case DensityType.T10000B: density = "T10000B"; + break; case DensityType.T10000C: density = "T10000C"; + break; case DensityType.T10000D: density = "T10000D"; + break; case DensityType.AIT1: density = "AIT-1"; + break; case DensityType.AIT2: density = "AIT-2"; + break; case DensityType.AIT3: density = "AIT-3"; + break; case DensityType.DDS2: density = "DDS-2"; + break; case DensityType.DDS3: density = "DDS-3"; + break; case DensityType.DDS4: density = "DDS-4"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -533,18 +651,23 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.Default: density = "LTO Ultrium cleaning cartridge"; + break; case DensityType.LTO3: density = "LTO Ultrium-3 WORM"; + break; case DensityType.LTO4: density = "LTO Ultrium-4 WORM"; + break; case DensityType.LTO5: density = "LTO Ultrium-5 WORM"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -556,9 +679,11 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.LTO1: density = "LTO Ultrium"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -570,9 +695,11 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.LTO2: density = "LTO Ultrium-2"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -584,12 +711,15 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.Default: density = "MLR1-26GB"; + break; case DensityType.DDS3: density = "DDS-3"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -601,12 +731,15 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.Default: density = "DC-9200"; + break; case DensityType.DDS4: density = "DDS-4"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -618,9 +751,11 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.DAT72: density = "DAT-72"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -633,9 +768,11 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.LTO3: density = "LTO Ultrium-3"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -647,9 +784,11 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.Default: density = "DDS cleaning cartridge"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -662,9 +801,11 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.LTO4: density = "LTO Ultrium-4"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -677,9 +818,11 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.LTO5: density = "LTO Ultrium-5"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -692,9 +835,11 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.LTO6: density = "LTO Ultrium-6"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -707,9 +852,11 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.LTO7: density = "LTO Ultrium-7"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -721,18 +868,23 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.LTO2: density = "LTO Ultrium-2 in CD emulation mode"; + break; case DensityType.LTO3: density = "LTO Ultrium-3 in CD emulation mode"; + break; case DensityType.LTO4: density = "LTO Ultrium-4 in CD emulation mode"; + break; case DensityType.LTO5: density = "LTO Ultrium-5 in CD emulation mode"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -744,30 +896,39 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.Ex8200: density = "EXB-8200"; + break; case DensityType.Ex8200c: density = "EXB-8200 compressed"; + break; case DensityType.Ex8500: density = "EXB-8500"; + break; case DensityType.Ex8500c: density = "EXB-8500 compressed"; + break; case DensityType.Mammoth: density = "Mammoth"; + break; case DensityType.IBM3590: density = "IBM 3590"; + break; case DensityType.IBM3590E: density = "IBM 3590E"; + break; case DensityType.VXA1: density = "VXA-1"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -779,39 +940,51 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.Ex8200: density = "EXB-8200"; + break; case DensityType.Ex8200c: density = "EXB-8200 compressed"; + break; case DensityType.Ex8500: density = "EXB-8500"; + break; case DensityType.Ex8500c: density = "EXB-8500 compressed"; + break; case DensityType.Mammoth: density = "Mammoth"; + break; case DensityType.CT1: density = "CompactTape I"; + break; case DensityType.CT2: density = "CompactTape II"; + break; case DensityType.IBM3590: density = "IBM 3590 extended"; + break; case DensityType.IBM3590E: density = "IBM 3590E extended"; + break; case DensityType.VXA2: density = "VXA-2"; + break; case DensityType.VXA3: density = "VXA-3"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -823,34 +996,44 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.Ex8200: density = "EXB-8200"; + break; case DensityType.Ex8200c: density = "EXB-8200 compressed"; + break; case DensityType.Ex8500: density = "EXB-8500"; + break; case DensityType.Ex8500c: density = "EXB-8500 compressed"; + break; case DensityType.Mammoth: density = "Mammoth"; + break; case DensityType.DLT3_42k: density = "DLTtape III at 42500 bpi"; + break; case DensityType.DLT3_56t: density = "DLTtape III with 56 tracks"; + break; case DensityType.DLT3_62k: case DensityType.DLT3_62kAlt: density = "DLTtape III at 62500 bpi"; + break; case DensityType.DLT3c: density = "DLTtape III compressed"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -862,28 +1045,36 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.Ex8200: density = "EXB-8200"; + break; case DensityType.Ex8200c: density = "EXB-8200 compressed"; + break; case DensityType.Ex8500: density = "EXB-8500"; + break; case DensityType.Ex8500c: density = "EXB-8500 compressed"; + break; case DensityType.Mammoth: density = "Mammoth"; + break; case DensityType.DLT3_62k: case DensityType.DLT3_62kAlt: density = "DLTtape IIIxt"; + break; case DensityType.DLT3c: density = "DLTtape IIIxt compressed"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -895,50 +1086,65 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.Ex8200: density = "EXB-8200"; + break; case DensityType.Ex8200c: density = "EXB-8200 compressed"; + break; case DensityType.Ex8500: density = "EXB-8500"; + break; case DensityType.Ex8500c: density = "EXB-8500 compressed"; + break; case DensityType.Mammoth: density = "Mammoth"; + break; case DensityType.DLT4: case DensityType.DLT4Alt: density = "DLTtape IV"; + break; case DensityType.DLT4_123k: case DensityType.DLT4_123kAlt: density = "DLTtape IV at 123090 bpi"; + break; case DensityType.DLT4_98k: density = "DLTtape IV at 98250 bpi"; + break; case DensityType.Travan5: density = "Travan 5"; + break; case DensityType.DLT4c: density = "DLTtape IV compressed"; + break; case DensityType.DLT4_85k: density = "DLTtape IV at 85937 bpi"; + break; case DensityType.DLT4c_85k: density = "DLTtape IV at 85937 bpi compressed"; + break; case DensityType.DLT4c_123k: density = "DLTtape IV at 123090 bpi compressed"; + break; case DensityType.DLT4c_98k: density = "DLTtape IV at 98250 bpi compressed"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -950,35 +1156,44 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.Ex8200: density = "EXB-8200"; + break; case DensityType.Ex8200c: density = "EXB-8200 compressed"; + break; case DensityType.Ex8500: density = "EXB-8500"; + break; case DensityType.Ex8500c: density = "EXB-8500 compressed"; + break; case DensityType.Mammoth: density = "Mammoth"; + break; case DensityType.SDLT1_133k: case DensityType.SDLT1_133kAlt: density = "Super DLTtape I at 133000 bpi"; + break; case DensityType.SDLT1: //case DensityType.SDLT1Alt: density = "Super DLTtape I"; + break; case DensityType.SDLT1c: density = "Super DLTtape I compressed"; + break; /*case DensityType.SDLT1_133kAlt: density = "Super DLTtape I at 133000 bpi compressed"; break;*/ default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -990,9 +1205,11 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.SDLT2: density = "Super DLTtape II"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -1005,12 +1222,15 @@ namespace DiscImageChef.Decoders.SCSI case DensityType.VStape1: case DensityType.VStape1Alt: density = "VStape I"; + break; case DensityType.VStape1c: density = "VStape I compressed"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -1022,9 +1242,11 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.DLTS4: density = "DLTtape S4"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -1036,18 +1258,23 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.Ex8200: density = "EXB-8200"; + break; case DensityType.Ex8200c: density = "EXB-8200 compressed"; + break; case DensityType.Ex8500: density = "EXB-8500"; + break; case DensityType.Ex8500c: density = "EXB-8500 compressed"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -1059,21 +1286,27 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.Ex8200: density = "EXB-8200"; + break; case DensityType.Ex8200c: density = "EXB-8200 compressed"; + break; case DensityType.Ex8500: density = "EXB-8500"; + break; case DensityType.Ex8500c: density = "EXB-8500 compressed"; + break; case DensityType.Mammoth: density = "Mammoth"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -1085,21 +1318,27 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.Ex8200: density = "EXB-8200"; + break; case DensityType.Ex8200c: density = "EXB-8200 compressed"; + break; case DensityType.Ex8500: density = "EXB-8500"; + break; case DensityType.Ex8500c: density = "EXB-8500 compressed"; + break; case DensityType.Mammoth: density = "Mammoth"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -1111,21 +1350,27 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.Ex8200: density = "EXB-8200"; + break; case DensityType.Ex8200c: density = "EXB-8200 compressed"; + break; case DensityType.Ex8500: density = "EXB-8500"; + break; case DensityType.Ex8500c: density = "EXB-8500 compressed"; + break; case DensityType.Mammoth: density = "Mammoth"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -1143,12 +1388,15 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.Mammoth: density = "Mammoth"; + break; case DensityType.Mammoth2: density = "Mammoth-2"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -1160,9 +1408,11 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.Default: density = "DC-2900SL"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -1174,9 +1424,11 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.Default: density = "DC-9250"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -1188,9 +1440,11 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.Default: density = "SLR-32"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -1202,9 +1456,11 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.Default: density = "MRL1-26GBSL"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -1216,9 +1472,11 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.Default: density = "SLRtape-50"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -1230,9 +1488,11 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.Default: density = "SLRtape-50 SL"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -1244,9 +1504,11 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.Default: density = "SLR-32 SL"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -1258,9 +1520,11 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.Default: density = "SLR-5"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -1272,9 +1536,11 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.Default: density = "SLR-5 SL"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -1286,9 +1552,11 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.Default: density = "SLRtape-7"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -1300,9 +1568,11 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.Default: density = "SLRtape-7 SL"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -1314,9 +1584,11 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.Default: density = "SLRtape-24"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -1328,9 +1600,11 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.Default: density = "SLRtape-24 SL"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -1342,9 +1616,11 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.Default: density = "SLRtape-140"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -1356,9 +1632,11 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.Default: density = "SLRtape-40"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -1370,9 +1648,11 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.Default: density = "SLRtape-60 or SLRtape-75"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -1384,9 +1664,11 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.Default: density = "SLRtape-100"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -1398,9 +1680,11 @@ namespace DiscImageChef.Decoders.SCSI { case DensityType.Default: density = "SLR40, SLR60 or SLR100"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } } @@ -1408,14 +1692,15 @@ namespace DiscImageChef.Decoders.SCSI break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } if(density != "") if(descriptor.Blocks == 0) if(descriptor.BlockLength == 0) - sb - .AppendFormat("\tAll remaining blocks conform to {0} and have a variable length", + sb. + AppendFormat("\tAll remaining blocks conform to {0} and have a variable length", density).AppendLine(); else sb.AppendFormat("\tAll remaining blocks conform to {0} and are {1} bytes each", @@ -1430,8 +1715,8 @@ namespace DiscImageChef.Decoders.SCSI if(descriptor.BlockLength == 0) sb.AppendFormat("\tAll remaining blocks have a variable length").AppendLine(); else - sb.AppendFormat("\tAll remaining blocks are {0} bytes each", descriptor.BlockLength) - .AppendLine(); + sb.AppendFormat("\tAll remaining blocks are {0} bytes each", + descriptor.BlockLength).AppendLine(); else if(descriptor.BlockLength == 0) sb.AppendFormat("\t{0} blocks have a variable length", descriptor.Blocks).AppendLine(); else @@ -1450,13 +1735,16 @@ namespace DiscImageChef.Decoders.SCSI { case 0: sb.AppendLine("\tDevice prints directly"); + break; case 1: sb.AppendLine("\tDevice uses a print cache"); + break; default: - sb.AppendFormat("\tUnknown buffered mode code 0x{0:X2}", header.Value.BufferedMode) - .AppendLine(); + sb.AppendFormat("\tUnknown buffered mode code 0x{0:X2}", header.Value.BufferedMode). + AppendLine(); + break; } @@ -1475,77 +1763,101 @@ namespace DiscImageChef.Decoders.SCSI { case MediumTypes.ReadOnly: sb.AppendLine("a Read-only optical"); + break; case MediumTypes.WORM: sb.AppendLine("a Write-once Read-many optical"); + break; case MediumTypes.Erasable: sb.AppendLine("a Erasable optical"); + break; case MediumTypes.RO_WORM: sb.AppendLine("a combination of read-only and write-once optical"); + break; case MediumTypes.RO_RW: sb.AppendLine("a combination of read-only and erasable optical"); + break; case MediumTypes.WORM_RW: sb.AppendLine("a combination of write-once and erasable optical"); + break; case MediumTypes.DOW: sb.AppendLine("a direct-overwrite optical"); + break; default: - sb.AppendFormat("an unknown medium type 0x{0:X2}", (byte)header.Value.MediumType) - .AppendLine(); + sb.AppendFormat("an unknown medium type 0x{0:X2}", (byte)header.Value.MediumType). + AppendLine(); + break; } } - if(header.Value.WriteProtected) sb.AppendLine("\tMedium is write protected"); - if(header.Value.EBC) sb.AppendLine("\tBlank checking during write is enabled"); - if(header.Value.DPOFUA) sb.AppendLine("\tDrive supports DPO and FUA bits"); + if(header.Value.WriteProtected) + sb.AppendLine("\tMedium is write protected"); + + if(header.Value.EBC) + sb.AppendLine("\tBlank checking during write is enabled"); + + if(header.Value.DPOFUA) + sb.AppendLine("\tDrive supports DPO and FUA bits"); if(header.Value.BlockDescriptors != null) foreach(BlockDescriptor descriptor in header.Value.BlockDescriptors) { string density = ""; + switch(descriptor.Density) { case DensityType.Default: break; case DensityType.ISO10090: density = "ISO/IEC 10090: 86 mm Read/Write single-sided optical disc with 12500 tracks"; + break; case DensityType.D581: density = "89 mm Read/Write double-sided optical disc with 12500 tracks"; + break; case DensityType.X3_212: density = "ANSI X3.212: 130 mm Read/Write double-sided optical disc with 18750 tracks"; + break; case DensityType.X3_191: density = "ANSI X3.191: 130 mm Write-Once double-sided optical disc with 30000 tracks"; + break; case DensityType.X3_214: density = "ANSI X3.214: 130 mm Write-Once double-sided optical disc with 20000 tracks"; + break; case DensityType.X3_211: density = "ANSI X3.211: 130 mm Write-Once double-sided optical disc with 18750 tracks"; + break; case DensityType.D407: density = "200 mm optical disc"; + break; case DensityType.ISO13614: density = "ISO/IEC 13614: 300 mm double-sided optical disc"; + break; case DensityType.X3_200: density = "ANSI X3.200: 356 mm double-sided optical disc with 56350 tracks"; + break; default: density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } @@ -1567,8 +1879,8 @@ namespace DiscImageChef.Decoders.SCSI if(descriptor.BlockLength == 0) sb.AppendFormat("\tAll remaining blocks have a variable length").AppendLine(); else - sb.AppendFormat("\tAll remaining blocks are {0} bytes each", descriptor.BlockLength) - .AppendLine(); + sb.AppendFormat("\tAll remaining blocks are {0} bytes each", + descriptor.BlockLength).AppendLine(); else if(descriptor.BlockLength == 0) sb.AppendFormat("\t{0} blocks have a variable length", descriptor.Blocks).AppendLine(); else @@ -1589,154 +1901,203 @@ namespace DiscImageChef.Decoders.SCSI { case MediumTypes.CDROM: sb.AppendLine("120 mm CD-ROM"); + break; case MediumTypes.CDDA: sb.AppendLine("120 mm Compact Disc Digital Audio"); + break; case MediumTypes.MixedCD: sb.AppendLine("120 mm Compact Disc with data and audio"); + break; case MediumTypes.CDROM_80: sb.AppendLine("80 mm CD-ROM"); + break; case MediumTypes.CDDA_80: sb.AppendLine("80 mm Compact Disc Digital Audio"); + break; case MediumTypes.MixedCD_80: sb.AppendLine("80 mm Compact Disc with data and audio"); + break; case MediumTypes.Unknown_CD: sb.AppendLine("Unknown medium type"); + break; case MediumTypes.HybridCD: sb.AppendLine("120 mm Hybrid disc (Photo CD)"); + break; case MediumTypes.Unknown_CDR: sb.AppendLine("Unknown size CD-R"); + break; case MediumTypes.CDR: sb.AppendLine("120 mm CD-R with data only"); + break; case MediumTypes.CDR_DA: sb.AppendLine("120 mm CD-R with audio only"); + break; case MediumTypes.CDR_Mixed: sb.AppendLine("120 mm CD-R with data and audio"); + break; case MediumTypes.HybridCDR: sb.AppendLine("120 mm Hybrid CD-R (Photo CD)"); + break; case MediumTypes.CDR_80: sb.AppendLine("80 mm CD-R with data only"); + break; case MediumTypes.CDR_DA_80: sb.AppendLine("80 mm CD-R with audio only"); + break; case MediumTypes.CDR_Mixed_80: sb.AppendLine("80 mm CD-R with data and audio"); + break; case MediumTypes.HybridCDR_80: sb.AppendLine("80 mm Hybrid CD-R (Photo CD)"); + break; case MediumTypes.Unknown_CDRW: sb.AppendLine("Unknown size CD-RW"); + break; case MediumTypes.CDRW: sb.AppendLine("120 mm CD-RW with data only"); + break; case MediumTypes.CDRW_DA: sb.AppendLine("120 mm CD-RW with audio only"); + break; case MediumTypes.CDRW_Mixed: sb.AppendLine("120 mm CD-RW with data and audio"); + break; case MediumTypes.HybridCDRW: sb.AppendLine("120 mm Hybrid CD-RW (Photo CD)"); + break; case MediumTypes.CDRW_80: sb.AppendLine("80 mm CD-RW with data only"); + break; case MediumTypes.CDRW_DA_80: sb.AppendLine("80 mm CD-RW with audio only"); + break; case MediumTypes.CDRW_Mixed_80: sb.AppendLine("80 mm CD-RW with data and audio"); + break; case MediumTypes.HybridCDRW_80: sb.AppendLine("80 mm Hybrid CD-RW (Photo CD)"); + break; case MediumTypes.Unknown_HD: sb.AppendLine("Unknown size HD disc"); + break; case MediumTypes.HD: sb.AppendLine("120 mm HD disc"); + break; case MediumTypes.HD_80: sb.AppendLine("80 mm HD disc"); + break; case MediumTypes.NoDisc: sb.AppendLine("No disc inserted, tray closed or caddy inserted"); + break; case MediumTypes.TrayOpen: sb.AppendLine("Tray open or no caddy inserted"); + break; case MediumTypes.MediumError: sb.AppendLine("Tray closed or caddy inserted but medium error"); + break; case MediumTypes.UnknownBlockDevice: sb.AppendLine("Unknown block device"); + break; case MediumTypes.ReadOnlyBlockDevice: sb.AppendLine("Read-only block device"); + break; case MediumTypes.ReadWriteBlockDevice: sb.AppendLine("Read/Write block device"); + break; case MediumTypes.LTOCD: sb.AppendLine("LTO in CD-ROM emulation mode"); + break; default: sb.AppendFormat("Unknown medium type 0x{0:X2}", (byte)header.Value.MediumType).AppendLine(); + break; } - if(header.Value.WriteProtected) sb.AppendLine("\tMedium is write protected"); + if(header.Value.WriteProtected) + sb.AppendLine("\tMedium is write protected"); - if(header.Value.DPOFUA) sb.AppendLine("\tDrive supports DPO and FUA bits"); + if(header.Value.DPOFUA) + sb.AppendLine("\tDrive supports DPO and FUA bits"); if(header.Value.BlockDescriptors != null) foreach(BlockDescriptor descriptor in header.Value.BlockDescriptors) { string density = ""; + switch(descriptor.Density) { case DensityType.Default: break; case DensityType.User: density = "user data only"; + break; case DensityType.UserAuxiliary: density = "user data plus auxiliary data"; + break; case DensityType.UserAuxiliaryTag: density = "4-byte tag, user data plus auxiliary data"; + break; case DensityType.Audio: density = "audio information only"; + break; case DensityType.LTO2: density = "LTO Ultrium-2"; + break; case DensityType.LTO3: density = "LTO Ultrium-3"; + break; case DensityType.LTO4: density = "LTO Ultrium-4"; + break; case DensityType.LTO5: density = "LTO Ultrium-5"; + break; default: density = $"with unknown density code 0x{(byte)descriptor.Density:X2}"; + break; } @@ -1748,8 +2109,8 @@ namespace DiscImageChef.Decoders.SCSI sb.AppendFormat("\t{0} blocks have {1} and are {2} bytes each", descriptor.Blocks, density, descriptor.BlockLength).AppendLine(); else if(descriptor.Blocks == 0) - sb.AppendFormat("\tAll remaining blocks are {0} bytes each", descriptor.BlockLength) - .AppendLine(); + sb.AppendFormat("\tAll remaining blocks are {0} bytes each", descriptor.BlockLength). + AppendLine(); else sb.AppendFormat("\t{0} blocks are {1} bytes each", descriptor.Blocks, descriptor.BlockLength).AppendLine(); diff --git a/SCSI/Modes/Mode10.cs b/SCSI/Modes/Mode10.cs index 29a0b18..33becfb 100644 --- a/SCSI/Modes/Mode10.cs +++ b/SCSI/Modes/Mode10.cs @@ -37,21 +37,26 @@ using System.Linq; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Modes { public static ModeHeader? DecodeModeHeader10(byte[] modeResponse, PeripheralDeviceTypes deviceType) { - if(modeResponse == null || modeResponse.Length < 8) return null; + if(modeResponse == null || + modeResponse.Length < 8) + return null; ushort modeLength = (ushort)((modeResponse[0] << 8) + modeResponse[1]); ushort blockDescLength = (ushort)((modeResponse[6] << 8) + modeResponse[7]); - if(modeResponse.Length < modeLength) return null; + if(modeResponse.Length < modeLength) + return null; - ModeHeader header = new ModeHeader {MediumType = (MediumTypes)modeResponse[2]}; + var header = new ModeHeader + { + MediumType = (MediumTypes)modeResponse[2] + }; bool longLBA = (modeResponse[4] & 0x01) == 0x01; @@ -59,11 +64,17 @@ namespace DiscImageChef.Decoders.SCSI if(longLBA) { header.BlockDescriptors = new BlockDescriptor[blockDescLength / 16]; + for(int i = 0; i < header.BlockDescriptors.Length; i++) { - if(12 + i * 16 + 8 >= modeResponse.Length) break; + if(12 + i * 16 + 8 >= modeResponse.Length) + break; + + header.BlockDescriptors[i] = new BlockDescriptor + { + Density = DensityType.Default + }; - header.BlockDescriptors[i] = new BlockDescriptor {Density = DensityType.Default}; byte[] temp = new byte[8]; temp[0] = modeResponse[7 + i * 16 + 8]; temp[1] = modeResponse[6 + i * 16 + 8]; @@ -83,11 +94,14 @@ namespace DiscImageChef.Decoders.SCSI else { header.BlockDescriptors = new BlockDescriptor[blockDescLength / 8]; + for(int i = 0; i < header.BlockDescriptors.Length; i++) { - if(7 + i * 8 + 8 >= modeResponse.Length) break; + if(7 + i * 8 + 8 >= modeResponse.Length) + break; header.BlockDescriptors[i] = new BlockDescriptor(); + if(deviceType != PeripheralDeviceTypes.DirectAccess) header.BlockDescriptors[i].Density = (DensityType)modeResponse[0 + i * 8 + 8]; else @@ -111,19 +125,23 @@ namespace DiscImageChef.Decoders.SCSI case PeripheralDeviceTypes.MultiMediaDevice: header.WriteProtected = (modeResponse[3] & 0x80) == 0x80; header.DPOFUA = (modeResponse[3] & 0x10) == 0x10; + break; case PeripheralDeviceTypes.SequentialAccess: header.WriteProtected = (modeResponse[3] & 0x80) == 0x80; header.Speed = (byte)(modeResponse[3] & 0x0F); header.BufferedMode = (byte)((modeResponse[3] & 0x70) >> 4); + break; case PeripheralDeviceTypes.PrinterDevice: header.BufferedMode = (byte)((modeResponse[3] & 0x70) >> 4); + break; case PeripheralDeviceTypes.OpticalDevice: header.WriteProtected = (modeResponse[3] & 0x80) == 0x80; header.EBC = (modeResponse[3] & 0x01) == 0x01; header.DPOFUA = (modeResponse[3] & 0x10) == 0x10; + break; } @@ -136,29 +154,41 @@ namespace DiscImageChef.Decoders.SCSI public static DecodedMode? DecodeMode10(byte[] modeResponse, PeripheralDeviceTypes deviceType) { ModeHeader? hdr = DecodeModeHeader10(modeResponse, deviceType); - if(!hdr.HasValue) return null; - DecodedMode decoded = new DecodedMode {Header = hdr.Value}; - bool longlba = (modeResponse[4] & 0x01) == 0x01; - int offset; - int blkDrLength = 0; - if(decoded.Header.BlockDescriptors != null) blkDrLength = decoded.Header.BlockDescriptors.Length; + if(!hdr.HasValue) + return null; + + var decoded = new DecodedMode + { + Header = hdr.Value + }; + + bool longlba = (modeResponse[4] & 0x01) == 0x01; + int offset; + int blkDrLength = 0; + + if(decoded.Header.BlockDescriptors != null) + blkDrLength = decoded.Header.BlockDescriptors.Length; + + if(longlba) + offset = 8 + blkDrLength * 16; + else + offset = 8 + blkDrLength * 8; - if(longlba) offset = 8 + blkDrLength * 16; - else offset = 8 + blkDrLength * 8; int length = modeResponse[0] << 8; length += modeResponse[1]; length += 2; - if(length != modeResponse.Length) return decoded; + if(length != modeResponse.Length) + return decoded; List listpages = new List(); while(offset < modeResponse.Length) { - bool isSubpage = (modeResponse[offset] & 0x40) == 0x40; - ModePage pg = new ModePage(); - byte pageNo = (byte)(modeResponse[offset] & 0x3F); + bool isSubpage = (modeResponse[offset] & 0x40) == 0x40; + var pg = new ModePage(); + byte pageNo = (byte)(modeResponse[offset] & 0x3F); if(pageNo == 0) { @@ -174,7 +204,8 @@ namespace DiscImageChef.Decoders.SCSI { pg.PageResponse = new byte[(modeResponse[offset + 2] << 8) + modeResponse[offset + 3] + 4]; - if(pg.PageResponse.Length + offset > modeResponse.Length) return decoded; + if(pg.PageResponse.Length + offset > modeResponse.Length) + return decoded; Array.Copy(modeResponse, offset, pg.PageResponse, 0, pg.PageResponse.Length); pg.Page = (byte)(modeResponse[offset] & 0x3F); @@ -185,7 +216,8 @@ namespace DiscImageChef.Decoders.SCSI { pg.PageResponse = new byte[modeResponse[offset + 1] + 2]; - if(pg.PageResponse.Length + offset > modeResponse.Length) return decoded; + if(pg.PageResponse.Length + offset > modeResponse.Length) + return decoded; Array.Copy(modeResponse, offset, pg.PageResponse, 0, pg.PageResponse.Length); pg.Page = (byte)(modeResponse[offset] & 0x3F); @@ -203,15 +235,15 @@ namespace DiscImageChef.Decoders.SCSI } public static byte[] EncodeModeHeader10(ModeHeader header, PeripheralDeviceTypes deviceType, - bool longLBA = false) + bool longLBA = false) { byte[] hdr; if(header.BlockDescriptors != null) - hdr = longLBA - ? new byte[8 + header.BlockDescriptors.Length * 16] - : new byte[8 + header.BlockDescriptors.Length * 8]; - else hdr = new byte[8]; + hdr = longLBA ? new byte[8 + header.BlockDescriptors.Length * 16] + : new byte[8 + header.BlockDescriptors.Length * 8]; + else + hdr = new byte[8]; hdr[2] = (byte)header.MediumType; @@ -219,27 +251,43 @@ namespace DiscImageChef.Decoders.SCSI { case PeripheralDeviceTypes.DirectAccess: case PeripheralDeviceTypes.MultiMediaDevice: - if(header.WriteProtected) hdr[3] += 0x80; - if(header.DPOFUA) hdr[3] += 0x10; + if(header.WriteProtected) + hdr[3] += 0x80; + + if(header.DPOFUA) + hdr[3] += 0x10; + break; case PeripheralDeviceTypes.SequentialAccess: - if(header.WriteProtected) hdr[3] += 0x80; + if(header.WriteProtected) + hdr[3] += 0x80; + hdr[3] += (byte)(header.Speed & 0x0F); hdr[3] += (byte)((header.BufferedMode << 4) & 0x70); + break; case PeripheralDeviceTypes.PrinterDevice: hdr[3] += (byte)((header.BufferedMode << 4) & 0x70); + break; case PeripheralDeviceTypes.OpticalDevice: - if(header.WriteProtected) hdr[3] += 0x80; - if(header.EBC) hdr[3] += 0x01; - if(header.DPOFUA) hdr[3] += 0x10; + if(header.WriteProtected) + hdr[3] += 0x80; + + if(header.EBC) + hdr[3] += 0x01; + + if(header.DPOFUA) + hdr[3] += 0x10; + break; } - if(longLBA) hdr[4] += 0x01; + if(longLBA) + hdr[4] += 0x01; - if(header.BlockDescriptors == null) return hdr; + if(header.BlockDescriptors == null) + return hdr; if(longLBA) for(int i = 0; i < header.BlockDescriptors.Length; i++) @@ -262,8 +310,10 @@ namespace DiscImageChef.Decoders.SCSI for(int i = 0; i < header.BlockDescriptors.Length; i++) { if(deviceType != PeripheralDeviceTypes.DirectAccess) - hdr[0 + i * 8 + 8] = (byte)header.BlockDescriptors[i].Density; - else hdr[0 + i * 8 + 8] = (byte)((header.BlockDescriptors[i].Blocks & 0xFF000000) >> 24); + hdr[0 + i * 8 + 8] = (byte)header.BlockDescriptors[i].Density; + else + hdr[0 + i * 8 + 8] = (byte)((header.BlockDescriptors[i].Blocks & 0xFF000000) >> 24); + hdr[1 + i * 8 + 8] = (byte)((header.BlockDescriptors[i].Blocks & 0xFF0000) >> 16); hdr[2 + i * 8 + 8] = (byte)((header.BlockDescriptors[i].Blocks & 0xFF00) >> 8); hdr[3 + i * 8 + 8] = (byte)(header.BlockDescriptors[i].Blocks & 0xFF); @@ -277,8 +327,10 @@ namespace DiscImageChef.Decoders.SCSI public static byte[] EncodeMode10(DecodedMode mode, PeripheralDeviceTypes deviceType) { - int modeSize = 0; - if(mode.Pages != null) modeSize += mode.Pages.Sum(page => page.PageResponse.Length); + int modeSize = 0; + + if(mode.Pages != null) + modeSize += mode.Pages.Sum(page => page.PageResponse.Length); byte[] hdr = EncodeModeHeader10(mode.Header, deviceType); modeSize += hdr.Length; @@ -286,10 +338,12 @@ namespace DiscImageChef.Decoders.SCSI Array.Copy(hdr, 0, md, 0, hdr.Length); - if(mode.Pages == null) return md; + if(mode.Pages == null) + return md; { int offset = hdr.Length; + foreach(ModePage page in mode.Pages) { Array.Copy(page.PageResponse, 0, md, offset, page.PageResponse.Length); diff --git a/SCSI/Modes/Mode6.cs b/SCSI/Modes/Mode6.cs index 89531b5..e044024 100644 --- a/SCSI/Modes/Mode6.cs +++ b/SCSI/Modes/Mode6.cs @@ -37,21 +37,26 @@ using System.Linq; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Modes { public static ModeHeader? DecodeModeHeader6(byte[] modeResponse, PeripheralDeviceTypes deviceType) { - if(modeResponse == null || modeResponse.Length < 4 || modeResponse.Length < modeResponse[0] + 1) + if(modeResponse == null || + modeResponse.Length < 4 || + modeResponse.Length < modeResponse[0] + 1) return null; - ModeHeader header = new ModeHeader {MediumType = (MediumTypes)modeResponse[1]}; + var header = new ModeHeader + { + MediumType = (MediumTypes)modeResponse[1] + }; if(modeResponse[3] > 0) { header.BlockDescriptors = new BlockDescriptor[modeResponse[3] / 8]; + for(int i = 0; i < header.BlockDescriptors.Length; i++) { header.BlockDescriptors[i].Density = (DensityType)modeResponse[0 + i * 8 + 4]; @@ -70,19 +75,23 @@ namespace DiscImageChef.Decoders.SCSI case PeripheralDeviceTypes.MultiMediaDevice: header.WriteProtected = (modeResponse[2] & 0x80) == 0x80; header.DPOFUA = (modeResponse[2] & 0x10) == 0x10; + break; case PeripheralDeviceTypes.SequentialAccess: header.WriteProtected = (modeResponse[2] & 0x80) == 0x80; header.Speed = (byte)(modeResponse[2] & 0x0F); header.BufferedMode = (byte)((modeResponse[2] & 0x70) >> 4); + break; case PeripheralDeviceTypes.PrinterDevice: header.BufferedMode = (byte)((modeResponse[2] & 0x70) >> 4); + break; case PeripheralDeviceTypes.OpticalDevice: header.WriteProtected = (modeResponse[2] & 0x80) == 0x80; header.EBC = (modeResponse[2] & 0x01) == 0x01; header.DPOFUA = (modeResponse[2] & 0x10) == 0x10; + break; } @@ -95,24 +104,33 @@ namespace DiscImageChef.Decoders.SCSI public static DecodedMode? DecodeMode6(byte[] modeResponse, PeripheralDeviceTypes deviceType) { ModeHeader? hdr = DecodeModeHeader6(modeResponse, deviceType); - if(!hdr.HasValue) return null; - DecodedMode decoded = new DecodedMode {Header = hdr.Value}; - int blkDrLength = 0; - if(decoded.Header.BlockDescriptors != null) blkDrLength = decoded.Header.BlockDescriptors.Length; + if(!hdr.HasValue) + return null; + + var decoded = new DecodedMode + { + Header = hdr.Value + }; + + int blkDrLength = 0; + + if(decoded.Header.BlockDescriptors != null) + blkDrLength = decoded.Header.BlockDescriptors.Length; int offset = 4 + blkDrLength * 8; int length = modeResponse[0] + 1; - if(length != modeResponse.Length) return decoded; + if(length != modeResponse.Length) + return decoded; List listpages = new List(); while(offset < modeResponse.Length) { - bool isSubpage = (modeResponse[offset] & 0x40) == 0x40; - ModePage pg = new ModePage(); - byte pageNo = (byte)(modeResponse[offset] & 0x3F); + bool isSubpage = (modeResponse[offset] & 0x40) == 0x40; + var pg = new ModePage(); + byte pageNo = (byte)(modeResponse[offset] & 0x3F); if(pageNo == 0) { @@ -126,10 +144,13 @@ namespace DiscImageChef.Decoders.SCSI { if(isSubpage) { - if(offset + 3 >= modeResponse.Length) break; + if(offset + 3 >= modeResponse.Length) + break; pg.PageResponse = new byte[(modeResponse[offset + 2] << 8) + modeResponse[offset + 3] + 4]; - if(pg.PageResponse.Length + offset > modeResponse.Length) return decoded; + + if(pg.PageResponse.Length + offset > modeResponse.Length) + return decoded; Array.Copy(modeResponse, offset, pg.PageResponse, 0, pg.PageResponse.Length); pg.Page = (byte)(modeResponse[offset] & 0x3F); @@ -138,10 +159,13 @@ namespace DiscImageChef.Decoders.SCSI } else { - if(offset + 1 >= modeResponse.Length) break; + if(offset + 1 >= modeResponse.Length) + break; pg.PageResponse = new byte[modeResponse[offset + 1] + 2]; - if(pg.PageResponse.Length + offset > modeResponse.Length) return decoded; + + if(pg.PageResponse.Length + offset > modeResponse.Length) + return decoded; Array.Copy(modeResponse, offset, pg.PageResponse, 0, pg.PageResponse.Length); pg.Page = (byte)(modeResponse[offset] & 0x3F); @@ -160,8 +184,7 @@ namespace DiscImageChef.Decoders.SCSI public static byte[] EncodeModeHeader6(ModeHeader header, PeripheralDeviceTypes deviceType) { - byte[] hdr = header.BlockDescriptors != null - ? new byte[4 + header.BlockDescriptors.Length * 8] + byte[] hdr = header.BlockDescriptors != null ? new byte[4 + header.BlockDescriptors.Length * 8] : new byte[4]; hdr[1] = (byte)header.MediumType; @@ -170,25 +193,40 @@ namespace DiscImageChef.Decoders.SCSI { case PeripheralDeviceTypes.DirectAccess: case PeripheralDeviceTypes.MultiMediaDevice: - if(header.WriteProtected) hdr[2] += 0x80; - if(header.DPOFUA) hdr[2] += 0x10; + if(header.WriteProtected) + hdr[2] += 0x80; + + if(header.DPOFUA) + hdr[2] += 0x10; + break; case PeripheralDeviceTypes.SequentialAccess: - if(header.WriteProtected) hdr[2] += 0x80; + if(header.WriteProtected) + hdr[2] += 0x80; + hdr[2] += (byte)(header.Speed & 0x0F); hdr[2] += (byte)((header.BufferedMode << 4) & 0x70); + break; case PeripheralDeviceTypes.PrinterDevice: hdr[2] += (byte)((header.BufferedMode << 4) & 0x70); + break; case PeripheralDeviceTypes.OpticalDevice: - if(header.WriteProtected) hdr[2] += 0x80; - if(header.EBC) hdr[2] += 0x01; - if(header.DPOFUA) hdr[2] += 0x10; + if(header.WriteProtected) + hdr[2] += 0x80; + + if(header.EBC) + hdr[2] += 0x01; + + if(header.DPOFUA) + hdr[2] += 0x10; + break; } - if(header.BlockDescriptors == null) return hdr; + if(header.BlockDescriptors == null) + return hdr; hdr[3] = (byte)(header.BlockDescriptors.Length * 8); @@ -208,8 +246,10 @@ namespace DiscImageChef.Decoders.SCSI public static byte[] EncodeMode6(DecodedMode mode, PeripheralDeviceTypes deviceType) { - int modeSize = 0; - if(mode.Pages != null) modeSize += mode.Pages.Sum(page => page.PageResponse.Length); + int modeSize = 0; + + if(mode.Pages != null) + modeSize += mode.Pages.Sum(page => page.PageResponse.Length); byte[] hdr = EncodeModeHeader6(mode.Header, deviceType); modeSize += hdr.Length; @@ -217,10 +257,12 @@ namespace DiscImageChef.Decoders.SCSI Array.Copy(hdr, 0, md, 0, hdr.Length); - if(mode.Pages == null) return md; + if(mode.Pages == null) + return md; { int offset = hdr.Length; + foreach(ModePage page in mode.Pages) { Array.Copy(page.PageResponse, 0, md, offset, page.PageResponse.Length); diff --git a/SCSI/Modes/Structs.cs b/SCSI/Modes/Structs.cs index 124075c..00109d6 100644 --- a/SCSI/Modes/Structs.cs +++ b/SCSI/Modes/Structs.cs @@ -34,9 +34,8 @@ using System.Diagnostics.CodeAnalysis; namespace DiscImageChef.Decoders.SCSI { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Modes { public struct BlockDescriptor diff --git a/SCSI/SSC/BlockLimits.cs b/SCSI/SSC/BlockLimits.cs index 18456ff..625aff1 100644 --- a/SCSI/SSC/BlockLimits.cs +++ b/SCSI/SSC/BlockLimits.cs @@ -36,30 +36,14 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI.SSC { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static class BlockLimits { - public struct BlockLimitsData - { - /// - /// All blocks size must be multiple of 2^ - /// - public byte granularity; - /// - /// Maximum block length in bytes - /// - public uint maxBlockLen; - /// - /// Minimum block length in bytes - /// - public ushort minBlockLen; - } - public static BlockLimitsData? Decode(byte[] response) { - if(response?.Length != 6) return null; + if(response?.Length != 6) + return null; return new BlockLimitsData { @@ -71,9 +55,10 @@ namespace DiscImageChef.Decoders.SCSI.SSC public static string Prettify(BlockLimitsData? decoded) { - if(decoded == null) return null; + if(decoded == null) + return null; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); if(decoded.Value.maxBlockLen == decoded.Value.minBlockLen) sb.AppendFormat("Device's block size is fixed at {0} bytes", decoded.Value.minBlockLen).AppendLine(); @@ -81,7 +66,9 @@ namespace DiscImageChef.Decoders.SCSI.SSC { if(decoded.Value.maxBlockLen > 0) sb.AppendFormat("Device's maximum block size is {0} bytes", decoded.Value.maxBlockLen).AppendLine(); - else sb.AppendLine("Device does not specify a maximum block size"); + else + sb.AppendLine("Device does not specify a maximum block size"); + sb.AppendFormat("Device's minimum block size is {0} bytes", decoded.Value.minBlockLen).AppendLine(); if(decoded.Value.granularity > 0) @@ -93,5 +80,15 @@ namespace DiscImageChef.Decoders.SCSI.SSC } public static string Prettify(byte[] response) => Prettify(Decode(response)); + + public struct BlockLimitsData + { + /// All blocks size must be multiple of 2^ + public byte granularity; + /// Maximum block length in bytes + public uint maxBlockLen; + /// Minimum block length in bytes + public ushort minBlockLen; + } } } \ No newline at end of file diff --git a/SCSI/SSC/DensitySupport.cs b/SCSI/SSC/DensitySupport.cs index 8e88567..e2ddaf5 100644 --- a/SCSI/SSC/DensitySupport.cs +++ b/SCSI/SSC/DensitySupport.cs @@ -37,12 +37,212 @@ using System.Text; namespace DiscImageChef.Decoders.SCSI.SSC { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] public static class DensitySupport { + public static DensitySupportHeader? DecodeDensity(byte[] response) + { + if(response == null) + return null; + + if(response.Length <= 56) + return null; + + ushort responseLen = (ushort)((response[0] << 8) + response[1] + 2); + + if(response.Length != responseLen) + return null; + + List descriptors = new List(); + int offset = 4; + + while(offset < response.Length) + { + var descriptor = new DensitySupportDescriptor + { + primaryCode = response[offset + 0], secondaryCode = response[offset + 1], + writable = (response[offset + 2] & 0x80) == 0x80, + duplicate = (response[offset + 2] & 0x40) == 0x40, + defaultDensity = (response[offset + 2] & 0x20) == 0x20, + reserved = (byte)((response[offset + 2] & 0x1E) >> 1), + lenvalid = + (response[offset + 2] & + 0x01) == 0x01, + len = + (ushort)((response[offset + 3] << 8) + response[offset + 4]), + bpmm = (uint)((response[offset + 5] << 16) + (response[offset + 6] << 8) + + response[offset + 7]), + width = + (ushort)((response[offset + 8] << 8) + response[offset + 9]), + tracks = (ushort)((response[offset + 10] << 8) + + response[offset + 11]), + capacity = (uint)((response[offset + 12] << 24) + (response[offset + 13] << 16) + + (response[offset + 14] << 8) + response[offset + 15]) + }; + + byte[] tmp = new byte[8]; + Array.Copy(response, offset + 16, tmp, 0, 8); + descriptor.organization = StringHandlers.CToString(tmp).Trim(); + tmp = new byte[8]; + Array.Copy(response, offset + 24, tmp, 0, 8); + descriptor.name = StringHandlers.CToString(tmp).Trim(); + tmp = new byte[20]; + Array.Copy(response, offset + 32, tmp, 0, 20); + descriptor.description = StringHandlers.CToString(tmp).Trim(); + + if(descriptor.lenvalid) + offset += descriptor.len + 5; + else + offset += 52; + + descriptors.Add(descriptor); + } + + var decoded = new DensitySupportHeader + { + length = responseLen, reserved = (ushort)((response[2] << 8) + response[3] + 2), + descriptors = descriptors.ToArray() + }; + + return decoded; + } + + public static string PrettifyDensity(DensitySupportHeader? density) + { + if(density == null) + return null; + + DensitySupportHeader decoded = density.Value; + var sb = new StringBuilder(); + + foreach(DensitySupportDescriptor descriptor in decoded.descriptors) + { + sb.AppendFormat("Density \"{0}\" defined by \"{1}\".", descriptor.name, descriptor.organization). + AppendLine(); + + sb.AppendFormat("\tPrimary code: {0:X2}h", descriptor.primaryCode).AppendLine(); + + if(descriptor.primaryCode != descriptor.secondaryCode) + sb.AppendFormat("\tSecondary code: {0:X2}h", descriptor.secondaryCode).AppendLine(); + + if(descriptor.writable) + sb.AppendLine("\tDrive can write this density"); + + if(descriptor.duplicate) + sb.AppendLine("\tThis descriptor is duplicated"); + + if(descriptor.defaultDensity) + sb.AppendLine("\tThis is the default density on the drive"); + + sb.AppendFormat("\tDensity has {0} bits per mm, with {1} tracks in a {2} mm width tape", + descriptor.bpmm, descriptor.tracks, descriptor.width / (double)10).AppendLine(); + + sb.AppendFormat("\tDensity maximum capacity is {0} megabytes", descriptor.capacity).AppendLine(); + sb.AppendFormat("\tDensity description: {0}", descriptor.description).AppendLine(); + sb.AppendLine(); + } + + return sb.ToString(); + } + + public static string PrettifyDensity(byte[] response) => PrettifyDensity(DecodeDensity(response)); + + public static MediaTypeSupportHeader? DecodeMediumType(byte[] response) + { + if(response == null) + return null; + + if(response.Length <= 60) + return null; + + ushort responseLen = (ushort)((response[0] << 8) + response[1] + 2); + + if(response.Length != responseLen) + return null; + + List descriptors = new List(); + int offset = 4; + + while(offset < response.Length) + { + var descriptor = new MediaTypeSupportDescriptor + { + mediumType = response[offset + 0], reserved1 = response[offset + 1], + len = (ushort)((response[offset + 2] << 8) + response[offset + 3]) + }; + + if(descriptor.len != 52) + return null; + + descriptor.numberOfCodes = response[offset + 4]; + descriptor.densityCodes = new byte[9]; + Array.Copy(response, offset + 5, descriptor.densityCodes, 0, 9); + descriptor.width = (ushort)((response[offset + 14] << 8) + response[offset + 15]); + descriptor.length = (ushort)((response[offset + 16] << 8) + response[offset + 17]); + descriptor.reserved1 = response[offset + 18]; + descriptor.reserved1 = response[offset + 19]; + byte[] tmp = new byte[8]; + Array.Copy(response, offset + 20, tmp, 0, 8); + descriptor.organization = StringHandlers.CToString(tmp).Trim(); + tmp = new byte[8]; + Array.Copy(response, offset + 28, tmp, 0, 8); + descriptor.name = StringHandlers.CToString(tmp).Trim(); + tmp = new byte[20]; + Array.Copy(response, offset + 36, tmp, 0, 20); + descriptor.description = StringHandlers.CToString(tmp).Trim(); + + offset += 56; + + descriptors.Add(descriptor); + } + + var decoded = new MediaTypeSupportHeader + { + length = responseLen, reserved = (ushort)((response[2] << 8) + response[3] + 2), + descriptors = descriptors.ToArray() + }; + + return decoded; + } + + public static string PrettifyMediumType(MediaTypeSupportHeader? mediumType) + { + if(mediumType == null) + return null; + + MediaTypeSupportHeader decoded = mediumType.Value; + var sb = new StringBuilder(); + + foreach(MediaTypeSupportDescriptor descriptor in decoded.descriptors) + { + sb.AppendFormat("Medium type \"{0}\" defined by \"{1}\".", descriptor.name, descriptor.organization). + AppendLine(); + + sb.AppendFormat("\tMedium type code: {0:X2}h", descriptor.mediumType).AppendLine(); + + if(descriptor.numberOfCodes > 0) + { + sb.AppendFormat("\tMedium supports following density codes:"); + + for(int i = 0; i < descriptor.numberOfCodes; i++) + sb.AppendFormat(" {0:X2}h", descriptor.densityCodes[i]); + + sb.AppendLine(); + } + + sb.AppendFormat("\tMedium has a nominal length of {0} m in a {1} mm width tape", descriptor.length, + descriptor.width / (double)10).AppendLine(); + + sb.AppendFormat("\tMedium description: {0}", descriptor.description).AppendLine(); + sb.AppendLine(); + } + + return sb.ToString(); + } + + public static string PrettifyMediumType(byte[] response) => PrettifyMediumType(DecodeMediumType(response)); + public struct DensitySupportHeader { public ushort length; @@ -91,179 +291,5 @@ namespace DiscImageChef.Decoders.SCSI.SSC public string name; public string description; } - - public static DensitySupportHeader? DecodeDensity(byte[] response) - { - if(response == null) return null; - - if(response.Length <= 56) return null; - - ushort responseLen = (ushort)((response[0] << 8) + response[1] + 2); - - if(response.Length != responseLen) return null; - - List descriptors = new List(); - int offset = 4; - - while(offset < response.Length) - { - DensitySupportDescriptor descriptor = new DensitySupportDescriptor - { - primaryCode = response[offset + 0], - secondaryCode = response[offset + 1], - writable = (response[offset + 2] & 0x80) == 0x80, - duplicate = (response[offset + 2] & 0x40) == 0x40, - defaultDensity = (response[offset + 2] & 0x20) == 0x20, - reserved = (byte)((response[offset + 2] & 0x1E) >> 1), - lenvalid = (response[offset + 2] & 0x01) == 0x01, - len = (ushort)((response[offset + 3] << 8) + response[offset + 4]), - bpmm = - (uint)((response[offset + 5] << 16) + (response[offset + 6] << 8) + response[offset + 7]), - width = (ushort)((response[offset + 8] << 8) + response[offset + 9]), - tracks = (ushort)((response[offset + 10] << 8) + response[offset + 11]), - capacity = (uint)((response[offset + 12] << 24) + (response[offset + 13] << 16) + - (response[offset + 14] << 8) + response[offset + 15]) - }; - byte[] tmp = new byte[8]; - Array.Copy(response, offset + 16, tmp, 0, 8); - descriptor.organization = StringHandlers.CToString(tmp).Trim(); - tmp = new byte[8]; - Array.Copy(response, offset + 24, tmp, 0, 8); - descriptor.name = StringHandlers.CToString(tmp).Trim(); - tmp = new byte[20]; - Array.Copy(response, offset + 32, tmp, 0, 20); - descriptor.description = StringHandlers.CToString(tmp).Trim(); - - if(descriptor.lenvalid) offset += descriptor.len + 5; - else offset += 52; - - descriptors.Add(descriptor); - } - - DensitySupportHeader decoded = new DensitySupportHeader - { - length = responseLen, - reserved = (ushort)((response[2] << 8) + response[3] + 2), - descriptors = descriptors.ToArray() - }; - - return decoded; - } - - public static string PrettifyDensity(DensitySupportHeader? density) - { - if(density == null) return null; - - DensitySupportHeader decoded = density.Value; - StringBuilder sb = new StringBuilder(); - - foreach(DensitySupportDescriptor descriptor in decoded.descriptors) - { - sb.AppendFormat("Density \"{0}\" defined by \"{1}\".", descriptor.name, descriptor.organization) - .AppendLine(); - sb.AppendFormat("\tPrimary code: {0:X2}h", descriptor.primaryCode).AppendLine(); - if(descriptor.primaryCode != descriptor.secondaryCode) - sb.AppendFormat("\tSecondary code: {0:X2}h", descriptor.secondaryCode).AppendLine(); - if(descriptor.writable) sb.AppendLine("\tDrive can write this density"); - if(descriptor.duplicate) sb.AppendLine("\tThis descriptor is duplicated"); - if(descriptor.defaultDensity) sb.AppendLine("\tThis is the default density on the drive"); - sb.AppendFormat("\tDensity has {0} bits per mm, with {1} tracks in a {2} mm width tape", - descriptor.bpmm, descriptor.tracks, descriptor.width / (double)10).AppendLine(); - sb.AppendFormat("\tDensity maximum capacity is {0} megabytes", descriptor.capacity).AppendLine(); - sb.AppendFormat("\tDensity description: {0}", descriptor.description).AppendLine(); - sb.AppendLine(); - } - - return sb.ToString(); - } - - public static string PrettifyDensity(byte[] response) => PrettifyDensity(DecodeDensity(response)); - - public static MediaTypeSupportHeader? DecodeMediumType(byte[] response) - { - if(response == null) return null; - - if(response.Length <= 60) return null; - - ushort responseLen = (ushort)((response[0] << 8) + response[1] + 2); - - if(response.Length != responseLen) return null; - - List descriptors = new List(); - int offset = 4; - - while(offset < response.Length) - { - MediaTypeSupportDescriptor descriptor = new MediaTypeSupportDescriptor - { - mediumType = response[offset + 0], - reserved1 = response[offset + 1], - len = (ushort)((response[offset + 2] << 8) + response[offset + 3]) - }; - if(descriptor.len != 52) return null; - - descriptor.numberOfCodes = response[offset + 4]; - descriptor.densityCodes = new byte[9]; - Array.Copy(response, offset + 5, descriptor.densityCodes, 0, 9); - descriptor.width = (ushort)((response[offset + 14] << 8) + response[offset + 15]); - descriptor.length = (ushort)((response[offset + 16] << 8) + response[offset + 17]); - descriptor.reserved1 = response[offset + 18]; - descriptor.reserved1 = response[offset + 19]; - byte[] tmp = new byte[8]; - Array.Copy(response, offset + 20, tmp, 0, 8); - descriptor.organization = StringHandlers.CToString(tmp).Trim(); - tmp = new byte[8]; - Array.Copy(response, offset + 28, tmp, 0, 8); - descriptor.name = StringHandlers.CToString(tmp).Trim(); - tmp = new byte[20]; - Array.Copy(response, offset + 36, tmp, 0, 20); - descriptor.description = StringHandlers.CToString(tmp).Trim(); - - offset += 56; - - descriptors.Add(descriptor); - } - - MediaTypeSupportHeader decoded = new MediaTypeSupportHeader - { - length = responseLen, - reserved = (ushort)((response[2] << 8) + response[3] + 2), - descriptors = descriptors.ToArray() - }; - - return decoded; - } - - public static string PrettifyMediumType(MediaTypeSupportHeader? mediumType) - { - if(mediumType == null) return null; - - MediaTypeSupportHeader decoded = mediumType.Value; - StringBuilder sb = new StringBuilder(); - - foreach(MediaTypeSupportDescriptor descriptor in decoded.descriptors) - { - sb.AppendFormat("Medium type \"{0}\" defined by \"{1}\".", descriptor.name, descriptor.organization) - .AppendLine(); - sb.AppendFormat("\tMedium type code: {0:X2}h", descriptor.mediumType).AppendLine(); - if(descriptor.numberOfCodes > 0) - { - sb.AppendFormat("\tMedium supports following density codes:"); - for(int i = 0; i < descriptor.numberOfCodes; i++) - sb.AppendFormat(" {0:X2}h", descriptor.densityCodes[i]); - - sb.AppendLine(); - } - - sb.AppendFormat("\tMedium has a nominal length of {0} m in a {1} mm width tape", descriptor.length, - descriptor.width / (double)10).AppendLine(); - sb.AppendFormat("\tMedium description: {0}", descriptor.description).AppendLine(); - sb.AppendLine(); - } - - return sb.ToString(); - } - - public static string PrettifyMediumType(byte[] response) => PrettifyMediumType(DecodeMediumType(response)); } } \ No newline at end of file diff --git a/SCSI/Sense.cs b/SCSI/Sense.cs index 47b32b9..b208c77 100644 --- a/SCSI/Sense.cs +++ b/SCSI/Sense.cs @@ -40,197 +40,99 @@ namespace DiscImageChef.Decoders.SCSI { public enum SenseType { - StandardSense, - ExtendedSenseFixedCurrent, - ExtendedSenseFixedPast, - ExtendedSenseDescriptorCurrent, - ExtendedSenseDescriptorPast, - Invalid, + StandardSense, ExtendedSenseFixedCurrent, ExtendedSenseFixedPast, + ExtendedSenseDescriptorCurrent, ExtendedSenseDescriptorPast, Invalid, Unknown } - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] - [SuppressMessage("ReSharper", "InconsistentNaming")] + [SuppressMessage("ReSharper", "MemberCanBeInternal"), SuppressMessage("ReSharper", "NotAccessedField.Global"), + SuppressMessage("ReSharper", "InconsistentNaming")] public struct StandardSense { - /// - /// If set, is valid - /// + /// If set, is valid public bool AddressValid; - /// - /// Error class, 0 to 6 - /// + /// Error class, 0 to 6 public byte ErrorClass; - /// - /// Error type - /// + /// Error type public byte ErrorType; - /// - /// Private usage - /// + /// Private usage public byte Private; - /// - /// LBA where error happened - /// + /// LBA where error happened public uint LBA; } public enum SenseKeys : byte { - /// - /// No information to be reported, but bits should be checked - /// - NoSense = 0, - /// - /// Target performed some recovery to successfully complete last command - /// - RecoveredError = 1, - /// - /// Target is not ready - /// - NotReady = 2, - /// - /// Non-recoverable medium error occurred - /// - MediumError = 3, - /// - /// Non-recoverable hardware error occurred - /// - HardwareError = 4, - /// - /// Target has received an illegal request - /// - IllegalRequest = 5, - /// - /// Target requires initiator attention - /// - UnitAttention = 6, - /// - /// A protected command has been denied - /// - DataProtect = 7, - /// - /// A blank block has been tried to read or a non-rewritable one to write - /// - BlankCheck = 8, - /// - /// For private/vendor usage - /// - PrivateUse = 9, - /// - /// COPY command aborted - /// - CopyAborted = 0xA, - /// - /// Command aborted - /// - AbortedCommand = 0xB, - /// - /// SEARCH command has been satisfied - /// - Equal = 0xC, - /// - /// End-of-medium reached with data remaining in buffer - /// - VolumeOverflow = 0xD, - /// - /// COMPARE failed - /// - Miscompare = 0xE, - /// - /// Complated - /// + /// No information to be reported, but bits should be checked + NoSense = 0, /// Target performed some recovery to successfully complete last command + RecoveredError = 1, /// Target is not ready + NotReady = 2, /// Non-recoverable medium error occurred + MediumError = 3, /// Non-recoverable hardware error occurred + HardwareError = 4, /// Target has received an illegal request + IllegalRequest = 5, /// Target requires initiator attention + UnitAttention = 6, /// A protected command has been denied + DataProtect = 7, /// A blank block has been tried to read or a non-rewritable one to write + BlankCheck = 8, /// For private/vendor usage + PrivateUse = 9, /// COPY command aborted + CopyAborted = 0xA, /// Command aborted + AbortedCommand = 0xB, /// SEARCH command has been satisfied + Equal = 0xC, /// End-of-medium reached with data remaining in buffer + VolumeOverflow = 0xD, /// COMPARE failed + Miscompare = 0xE, /// Complated Completed = 0xF } - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "UnassignedField.Global")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "UnassignedField.Global"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct FixedSense { - /// - /// If set, is valid - /// + /// If set, is valid public bool InformationValid; - /// - /// Contains number of current segment descriptor - /// + /// Contains number of current segment descriptor public byte SegmentNumber; - /// - /// If set indicates current command has read a filemark or a setmark - /// + /// If set indicates current command has read a filemark or a setmark public bool Filemark; - /// - /// If set indicates device has arrived end-of-medium - /// + /// If set indicates device has arrived end-of-medium public bool EOM; - /// - /// Means the requested logical block length did not match the logical block length on the medium - /// + /// Means the requested logical block length did not match the logical block length on the medium public bool ILI; - /// - /// Contains the sense key - /// + /// Contains the sense key public SenseKeys SenseKey; - /// - /// Additional information - /// + /// Additional information public uint Information; - /// - /// Additional sense length - /// + /// Additional sense length public byte AdditionalLength; - /// - /// Command specific information field - /// + /// Command specific information field public uint CommandSpecific; - /// - /// Additional sense code - /// + /// Additional sense code public byte ASC; - /// - /// Additional sense code qualifier - /// + /// Additional sense code qualifier public byte ASCQ; public byte FieldReplaceable; - /// - /// If set, is valid - /// + /// If set, is valid public bool SKSV; public uint SenseKeySpecific; public byte[] AdditionalSense; } - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + [SuppressMessage("ReSharper", "MemberCanBeInternal"), SuppressMessage("ReSharper", "InconsistentNaming"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct DescriptorSense { - /// - /// Contains the sense key - /// + /// Contains the sense key public SenseKeys SenseKey; - /// - /// Additional sense code - /// + /// Additional sense code public byte ASC; - /// - /// Additional sense code qualifier - /// + /// Additional sense code qualifier public byte ASCQ; public bool Overflow; - /// - /// The descriptors, indexed by type - /// + /// The descriptors, indexed by type public Dictionary Descriptors; } - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + [SuppressMessage("ReSharper", "MemberCanBeInternal"), SuppressMessage("ReSharper", "InconsistentNaming"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public struct AnotherProgressIndicationSenseDescriptor { public SenseKeys SenseKey; @@ -242,18 +144,19 @@ namespace DiscImageChef.Decoders.SCSI [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static class Sense { - /// - /// Gets the SCSI SENSE type to help chosing the correct decoding function - /// + /// Gets the SCSI SENSE type to help chosing the correct decoding function /// The type. /// Sense bytes. public static SenseType GetType(byte[] sense) { - if(sense == null) return SenseType.Invalid; + if(sense == null) + return SenseType.Invalid; - if(sense.Length < 4) return SenseType.Invalid; + if(sense.Length < 4) + return SenseType.Invalid; - if((sense[0] & 0x70) != 0x70) return sense.Length != 4 ? SenseType.Invalid : SenseType.StandardSense; + if((sense[0] & 0x70) != 0x70) + return sense.Length != 4 ? SenseType.Invalid : SenseType.StandardSense; switch(sense[0] & 0x0F) { @@ -267,9 +170,10 @@ namespace DiscImageChef.Decoders.SCSI public static StandardSense? DecodeStandard(byte[] sense) { - if(GetType(sense) != SenseType.StandardSense) return null; + if(GetType(sense) != SenseType.StandardSense) + return null; - StandardSense decoded = new StandardSense(); + var decoded = new StandardSense(); decoded.AddressValid |= (sense[0] & 0x80) == 0x80; decoded.ErrorClass = (byte)((sense[0] & 0x70) >> 4); decoded.ErrorType = (byte)(sense[0] & 0x0F); @@ -284,16 +188,18 @@ namespace DiscImageChef.Decoders.SCSI public static FixedSense? DecodeFixed(byte[] sense, out string senseDescription) { senseDescription = null; - if((sense[0] & 0x7F) != 0x70 && (sense[0] & 0x7F) != 0x71) return null; - if(sense.Length < 8) return null; + if((sense[0] & 0x7F) != 0x70 && + (sense[0] & 0x7F) != 0x71) + return null; - FixedSense decoded = new FixedSense + if(sense.Length < 8) + return null; + + var decoded = new FixedSense { - InformationValid = (sense[0] & 0x80) == 0x80, - SegmentNumber = sense[1], - Filemark = (sense[2] & 0x80) == 0x80, - EOM = (sense[2] & 0x40) == 0x40, + InformationValid = (sense[0] & 0x80) == 0x80, SegmentNumber = sense[1], + Filemark = (sense[2] & 0x80) == 0x80, EOM = (sense[2] & 0x40) == 0x40, ILI = (sense[2] & 0x20) == 0x20, SenseKey = (SenseKeys)(sense[2] & 0x0F), Information = (uint)((sense[3] << 24) + (sense[4] << 16) + (sense[5] << 8) + sense[6]), @@ -310,11 +216,14 @@ namespace DiscImageChef.Decoders.SCSI senseDescription = GetSenseDescription(decoded.ASC, decoded.ASCQ); } - if(sense.Length >= 15) decoded.FieldReplaceable = sense[14]; + if(sense.Length >= 15) + decoded.FieldReplaceable = sense[14]; - if(sense.Length >= 18) decoded.SenseKeySpecific = (uint)((sense[15] << 16) + (sense[16] << 8) + sense[17]); + if(sense.Length >= 18) + decoded.SenseKeySpecific = (uint)((sense[15] << 16) + (sense[16] << 8) + sense[17]); - if(sense.Length <= 18) return decoded; + if(sense.Length <= 18) + return decoded; decoded.AdditionalSense = new byte[sense.Length - 18]; Array.Copy(sense, 18, decoded.AdditionalSense, 0, decoded.AdditionalSense.Length); @@ -328,22 +237,22 @@ namespace DiscImageChef.Decoders.SCSI { senseDescription = null; - if(sense == null) return null; + if(sense == null) + return null; - if(sense.Length < 8) return null; + if(sense.Length < 8) + return null; - DescriptorSense decoded = new DescriptorSense + var decoded = new DescriptorSense { - SenseKey = (SenseKeys)(sense[1] & 0x0F), - ASC = sense[2], - ASCQ = sense[3], - Overflow = (sense[4] & 0x80) == 0x80, - Descriptors = new Dictionary() + SenseKey = (SenseKeys)(sense[1] & 0x0F), ASC = sense[2], ASCQ = sense[3], + Overflow = (sense[4] & 0x80) == 0x80, Descriptors = new Dictionary() }; senseDescription = GetSenseDescription(decoded.ASC, decoded.ASCQ); int offset = 8; + while(offset < sense.Length) if(offset + 2 < sense.Length) { @@ -353,7 +262,8 @@ namespace DiscImageChef.Decoders.SCSI byte[] desc = new byte[descLen]; Array.Copy(sense, offset, desc, 0, descLen); - if(!decoded.Descriptors.ContainsKey(descType)) decoded.Descriptors.Add(descType, desc); + if(!decoded.Descriptors.ContainsKey(descType)) + decoded.Descriptors.Add(descType, desc); offset += descLen; } @@ -380,7 +290,8 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifySense(StandardSense? sense) { - if(!sense.HasValue) return null; + if(!sense.HasValue) + return null; return sense.Value.AddressValid ? $"Error class {sense.Value.ErrorClass} type {sense.Value.ErrorType} happened on block {sense.Value.LBA}\n" @@ -389,52 +300,68 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifySense(FixedSense? sense) { - if(!sense.HasValue) return null; + if(!sense.HasValue) + return null; FixedSense decoded = sense.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendFormat("SCSI SENSE: {0}", GetSenseKey(decoded.SenseKey)).AppendLine(); - if(decoded.SegmentNumber > 0) sb.AppendFormat("On segment {0}", decoded.SegmentNumber).AppendLine(); - if(decoded.Filemark) sb.AppendLine("Filemark or setmark found"); - if(decoded.EOM) sb.AppendLine("End-of-medium/partition found"); - if(decoded.ILI) sb.AppendLine("Incorrect length indicator"); - if(decoded.InformationValid) sb.AppendFormat("On logical block {0}", decoded.Information).AppendLine(); - if(decoded.AdditionalLength < 6) return sb.ToString(); + if(decoded.SegmentNumber > 0) + sb.AppendFormat("On segment {0}", decoded.SegmentNumber).AppendLine(); + + if(decoded.Filemark) + sb.AppendLine("Filemark or setmark found"); + + if(decoded.EOM) + sb.AppendLine("End-of-medium/partition found"); + + if(decoded.ILI) + sb.AppendLine("Incorrect length indicator"); + + if(decoded.InformationValid) + sb.AppendFormat("On logical block {0}", decoded.Information).AppendLine(); + + if(decoded.AdditionalLength < 6) + return sb.ToString(); sb.AppendLine(GetSenseDescription(decoded.ASC, decoded.ASCQ)); - if(decoded.AdditionalLength < 10) return sb.ToString(); + if(decoded.AdditionalLength < 10) + return sb.ToString(); - if(!decoded.SKSV) return sb.ToString(); + if(!decoded.SKSV) + return sb.ToString(); switch(decoded.SenseKey) { case SenseKeys.IllegalRequest: { - sb.AppendLine((decoded.SenseKeySpecific & 0x400000) == 0x400000 - ? "Illegal field in CDB" + sb.AppendLine((decoded.SenseKeySpecific & 0x400000) == 0x400000 ? "Illegal field in CDB" : "Illegal field in data parameters"); if((decoded.SenseKeySpecific & 0x200000) == 0x200000) sb.AppendFormat("Invalid value in bit {0} in field {1} of CDB", - (decoded.SenseKeySpecific & 0x70000) >> 16, decoded.SenseKeySpecific & 0xFFFF) - .AppendLine(); + (decoded.SenseKeySpecific & 0x70000) >> 16, decoded.SenseKeySpecific & 0xFFFF). + AppendLine(); else - sb.AppendFormat("Invalid value in field {0} of CDB", decoded.SenseKeySpecific & 0xFFFF) - .AppendLine(); + sb.AppendFormat("Invalid value in field {0} of CDB", decoded.SenseKeySpecific & 0xFFFF). + AppendLine(); } + break; case SenseKeys.NotReady: - sb.AppendFormat("Format progress {0:P}", (double)(decoded.SenseKeySpecific & 0xFFFF) / 65536) - .AppendLine(); + sb.AppendFormat("Format progress {0:P}", (double)(decoded.SenseKeySpecific & 0xFFFF) / 65536). + AppendLine(); + break; case SenseKeys.RecoveredError: case SenseKeys.HardwareError: case SenseKeys.MediumError: sb.AppendFormat("Actual retry count is {0}", decoded.SenseKeySpecific & 0xFFFF).AppendLine(); + break; } @@ -443,36 +370,40 @@ namespace DiscImageChef.Decoders.SCSI public static string PrettifySense(DescriptorSense? sense) { - if(!sense.HasValue) return null; + if(!sense.HasValue) + return null; DescriptorSense decoded = sense.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendFormat("SCSI SENSE: {0}", GetSenseKey(decoded.SenseKey)).AppendLine(); sb.AppendLine(GetSenseDescription(decoded.ASC, decoded.ASCQ)); - if(decoded.Descriptors == null || decoded.Descriptors.Count == 0) return sb.ToString(); + if(decoded.Descriptors == null || + decoded.Descriptors.Count == 0) + return sb.ToString(); foreach(KeyValuePair kvp in decoded.Descriptors) switch(kvp.Key) { case 0x00: sb.AppendLine(PrettifyDescriptor00(kvp.Value)); + break; } return sb.ToString(); } - /// - /// Decodes the information sense data descriptor - /// + /// Decodes the information sense data descriptor /// The information value /// Descriptor. public static ulong DecodeDescriptor00(byte[] descriptor) { - if(descriptor.Length != 12 || descriptor[0] != 0x00) return 0; + if(descriptor.Length != 12 || + descriptor[0] != 0x00) + return 0; byte[] temp = new byte[8]; @@ -488,14 +419,14 @@ namespace DiscImageChef.Decoders.SCSI return BitConverter.ToUInt64(temp, 0); } - /// - /// Decodes the command-specific information sense data descriptor - /// + /// Decodes the command-specific information sense data descriptor /// The command-specific information sense data descriptor. /// Descriptor. public static ulong DecodeDescriptor01(byte[] descriptor) { - if(descriptor.Length != 12 || descriptor[0] != 0x01) return 0; + if(descriptor.Length != 12 || + descriptor[0] != 0x01) + return 0; byte[] temp = new byte[8]; @@ -511,96 +442,72 @@ namespace DiscImageChef.Decoders.SCSI return BitConverter.ToUInt64(temp, 0); } - /// - /// Decodes the sense key specific sense data descriptor - /// + /// Decodes the sense key specific sense data descriptor /// The sense key specific sense data descriptor. /// Descriptor. public static byte[] DecodeDescriptor02(byte[] descriptor) { - if(descriptor.Length != 8 || descriptor[0] != 0x02) return null; + if(descriptor.Length != 8 || + descriptor[0] != 0x02) + return null; byte[] temp = new byte[3]; Array.Copy(descriptor, 4, temp, 0, 3); + return temp; } - /// - /// Decodes the field replaceable unit sense data descriptor - /// + /// Decodes the field replaceable unit sense data descriptor /// The field replaceable unit sense data descriptor. /// Descriptor. public static byte DecodeDescriptor03(byte[] descriptor) { - if(descriptor.Length != 4 || descriptor[0] != 0x03) return 0; + if(descriptor.Length != 4 || + descriptor[0] != 0x03) + return 0; return descriptor[3]; } - /// - /// Decodes the another progress indication sense data descriptor - /// + /// Decodes the another progress indication sense data descriptor /// The another progress indication sense data descriptor. /// Descriptor. public static AnotherProgressIndicationSenseDescriptor? DecodeDescriptor0A(byte[] descriptor) { - if(descriptor.Length != 8 || descriptor[0] != 0x0A) return null; + if(descriptor.Length != 8 || + descriptor[0] != 0x0A) + return null; return new AnotherProgressIndicationSenseDescriptor { - SenseKey = (SenseKeys)descriptor[2], - ASC = descriptor[3], - ASCQ = descriptor[4], + SenseKey = (SenseKeys)descriptor[2], ASC = descriptor[3], ASCQ = descriptor[4], Progress = (ushort)((descriptor[6] << 8) + descriptor[7]) }; } - public static void DecodeDescriptor04(byte[] descriptor) - { - throw new NotImplementedException("Check SSC-4"); - } + public static void DecodeDescriptor04(byte[] descriptor) => throw new NotImplementedException("Check SSC-4"); - public static void DecodeDescriptor05(byte[] descriptor) - { - throw new NotImplementedException("Check SBC-3"); - } + public static void DecodeDescriptor05(byte[] descriptor) => throw new NotImplementedException("Check SBC-3"); - public static void DecodeDescriptor06(byte[] descriptor) - { - throw new NotImplementedException("Check OSD"); - } + public static void DecodeDescriptor06(byte[] descriptor) => throw new NotImplementedException("Check OSD"); - public static void DecodeDescriptor07(byte[] descriptor) - { - throw new NotImplementedException("Check OSD"); - } + public static void DecodeDescriptor07(byte[] descriptor) => throw new NotImplementedException("Check OSD"); - public static void DecodeDescriptor08(byte[] descriptor) - { - throw new NotImplementedException("Check OSD"); - } + public static void DecodeDescriptor08(byte[] descriptor) => throw new NotImplementedException("Check OSD"); - public static AtaErrorRegistersLba48 DecodeDescriptor09(byte[] descriptor) => - new AtaErrorRegistersLba48 - { - Error = descriptor[3], - SectorCount = (ushort)((descriptor[4] << 8) + descriptor[5]), - LbaLow = (ushort)((descriptor[6] << 8) + descriptor[7]), - LbaMid = (ushort)((descriptor[8] << 8) + descriptor[9]), - LbaHigh = (ushort)((descriptor[10] << 8) + descriptor[11]), - DeviceHead = descriptor[12], - Status = descriptor[13] - }; - - public static void DecodeDescriptor0B(byte[] descriptor) + public static AtaErrorRegistersLba48 DecodeDescriptor09(byte[] descriptor) => new AtaErrorRegistersLba48 { - throw new NotImplementedException("Check SBC-3"); - } + Error = descriptor[3], SectorCount = (ushort)((descriptor[4] << 8) + descriptor[5]), + LbaLow = (ushort)((descriptor[6] << 8) + descriptor[7]), + LbaMid = (ushort)((descriptor[8] << 8) + descriptor[9]), + LbaHigh = (ushort)((descriptor[10] << 8) + descriptor[11]), + DeviceHead = descriptor[12], + Status = descriptor[13] + }; - public static void DecodeDescriptor0D(byte[] descriptor) - { - throw new NotImplementedException("Check SBC-3"); - } + public static void DecodeDescriptor0B(byte[] descriptor) => throw new NotImplementedException("Check SBC-3"); + + public static void DecodeDescriptor0D(byte[] descriptor) => throw new NotImplementedException("Check SBC-3"); public static string PrettifyDescriptor00(ulong information) => $"On logical block {information}\n"; @@ -611,22 +518,22 @@ namespace DiscImageChef.Decoders.SCSI { switch(key) { - case SenseKeys.AbortedCommand: return "ABORTED COMMAND"; - case SenseKeys.BlankCheck: return "BLANK CHECK"; - case SenseKeys.CopyAborted: return "COPY ABORTED"; - case SenseKeys.DataProtect: return "DATA PROTECT"; - case SenseKeys.Equal: return "EQUAL"; - case SenseKeys.HardwareError: return "HARDWARE ERROR"; - case SenseKeys.IllegalRequest: return "ILLEGAL REQUEST"; - case SenseKeys.MediumError: return "MEDIUM ERROR"; - case SenseKeys.Miscompare: return "MISCOMPARE"; - case SenseKeys.NoSense: return "NO SENSE"; - case SenseKeys.PrivateUse: return "PRIVATE USE"; - case SenseKeys.RecoveredError: return "RECOVERED ERROR"; - case SenseKeys.Completed: return "COMPLETED"; - case SenseKeys.UnitAttention: return "UNIT ATTENTION"; - case SenseKeys.VolumeOverflow: return "VOLUME OVERFLOW"; - default: return "UNKNOWN"; + case SenseKeys.AbortedCommand: return"ABORTED COMMAND"; + case SenseKeys.BlankCheck: return"BLANK CHECK"; + case SenseKeys.CopyAborted: return"COPY ABORTED"; + case SenseKeys.DataProtect: return"DATA PROTECT"; + case SenseKeys.Equal: return"EQUAL"; + case SenseKeys.HardwareError: return"HARDWARE ERROR"; + case SenseKeys.IllegalRequest: return"ILLEGAL REQUEST"; + case SenseKeys.MediumError: return"MEDIUM ERROR"; + case SenseKeys.Miscompare: return"MISCOMPARE"; + case SenseKeys.NoSense: return"NO SENSE"; + case SenseKeys.PrivateUse: return"PRIVATE USE"; + case SenseKeys.RecoveredError: return"RECOVERED ERROR"; + case SenseKeys.Completed: return"COMPLETED"; + case SenseKeys.UnitAttention: return"UNIT ATTENTION"; + case SenseKeys.VolumeOverflow: return"VOLUME OVERFLOW"; + default: return"UNKNOWN"; } } @@ -638,1370 +545,1370 @@ namespace DiscImageChef.Decoders.SCSI case 0x00: switch(ASCQ) { - case 0x00: return "NO ADDITIONAL SENSE INFORMATION"; - case 0x01: return "FILEMARK DETECTED"; - case 0x02: return "END-OF-PARTITION/MEDIUM DETECTED"; - case 0x03: return "SETMARK DETECTED"; - case 0x04: return "BEGINNING-OF-PARTITION/MEDIUM DETECTED"; - case 0x05: return "END-OF-DATA DETECTED"; - case 0x06: return "I/O PROCESS TERMINATED"; - case 0x07: return "PROGRAMMABLE EARLY WARNING DETECTED"; - case 0x11: return "AUDIO PLAY OPERATION IN PROGRESS"; - case 0x12: return "AUDIO PLAY OPERATION PAUSED"; - case 0x13: return "AUDIO PLAY OPERATION SUCCESSFULLY COMPLETED"; - case 0x14: return "AUDIO PLAY OPERATION STOPPED DUE TO ERROR"; - case 0x15: return "NO CURRENT AUDIO STATUS TO RETURN"; - case 0x16: return "OPERATION IN PROGRESS"; - case 0x17: return "CLEANING REQUESTED"; - case 0x18: return "ERASE OPERATION IN PROGRESS"; - case 0x19: return "LOCATE OPERATION IN PROGRESS"; - case 0x1A: return "REWIND OPERATION IN PROGRESS"; - case 0x1B: return "SET CAPACITY OPERATION IN PROGRESS"; - case 0x1C: return "VERIFY OPERATION IN PROGRESS"; - case 0x1D: return "ATA PASS THROUGH INFORMATION AVAILABLE"; - case 0x1E: return "CONFLICTING SA CREATION REQUEST"; - case 0x1F: return "LOGICAL UNIT TRANSITIONING TO ANOTHER POWER CONDITION"; - case 0x20: return "EXTENDED COPY INFORMATION AVAILABLE"; - case 0x21: return "ATOMIC COMMAND ABORTED DUE TO ACA"; + case 0x00: return"NO ADDITIONAL SENSE INFORMATION"; + case 0x01: return"FILEMARK DETECTED"; + case 0x02: return"END-OF-PARTITION/MEDIUM DETECTED"; + case 0x03: return"SETMARK DETECTED"; + case 0x04: return"BEGINNING-OF-PARTITION/MEDIUM DETECTED"; + case 0x05: return"END-OF-DATA DETECTED"; + case 0x06: return"I/O PROCESS TERMINATED"; + case 0x07: return"PROGRAMMABLE EARLY WARNING DETECTED"; + case 0x11: return"AUDIO PLAY OPERATION IN PROGRESS"; + case 0x12: return"AUDIO PLAY OPERATION PAUSED"; + case 0x13: return"AUDIO PLAY OPERATION SUCCESSFULLY COMPLETED"; + case 0x14: return"AUDIO PLAY OPERATION STOPPED DUE TO ERROR"; + case 0x15: return"NO CURRENT AUDIO STATUS TO RETURN"; + case 0x16: return"OPERATION IN PROGRESS"; + case 0x17: return"CLEANING REQUESTED"; + case 0x18: return"ERASE OPERATION IN PROGRESS"; + case 0x19: return"LOCATE OPERATION IN PROGRESS"; + case 0x1A: return"REWIND OPERATION IN PROGRESS"; + case 0x1B: return"SET CAPACITY OPERATION IN PROGRESS"; + case 0x1C: return"VERIFY OPERATION IN PROGRESS"; + case 0x1D: return"ATA PASS THROUGH INFORMATION AVAILABLE"; + case 0x1E: return"CONFLICTING SA CREATION REQUEST"; + case 0x1F: return"LOGICAL UNIT TRANSITIONING TO ANOTHER POWER CONDITION"; + case 0x20: return"EXTENDED COPY INFORMATION AVAILABLE"; + case 0x21: return"ATOMIC COMMAND ABORTED DUE TO ACA"; } break; case 0x01: switch(ASCQ) { - case 0x00: return "NO INDEX/SECTOR SIGNAL"; + case 0x00: return"NO INDEX/SECTOR SIGNAL"; } break; case 0x02: switch(ASCQ) { - case 0x00: return "NO SEEK COMPLETE"; + case 0x00: return"NO SEEK COMPLETE"; } break; case 0x03: switch(ASCQ) { - case 0x00: return "PERIPHERAL DEVICE WRITE FAULT"; - case 0x01: return "NO WRITE CURRENT"; - case 0x02: return "EXCESSIVE WRITE ERRORS"; + case 0x00: return"PERIPHERAL DEVICE WRITE FAULT"; + case 0x01: return"NO WRITE CURRENT"; + case 0x02: return"EXCESSIVE WRITE ERRORS"; } break; case 0x04: switch(ASCQ) { - case 0x00: return "LOGICAL UNIT NOT READY, CAUSE NOT REPORTABLE"; - case 0x01: return "LOGICAL UNIT IS IN PROCESS OF BECOMING READY"; - case 0x02: return "LOGICAL UNIT NOT READY, INITIALIZING COMMAND REQUIRED"; - case 0x03: return "LOGICAL UNIT NOT READY, MANUAL INTERVENTION REQUIRED"; - case 0x04: return "LOGICAL UNIT NOT READY, FORMAT IN PROGRESS"; - case 0x05: return "LOGICAL UNIT NOT READY, REBUILD IN PROGRESS"; - case 0x06: return "LOGICAL UNIT NOT READY, RECALCULATION IN PROGRESS"; - case 0x07: return "LOGICAL UNIT NOT READY, OPERATION IN PROGRESS"; - case 0x08: return "LOGICAL UNIT NOT READY, LONG WRITE IN PROGRESS"; - case 0x09: return "LOGICAL UNIT NOT READY, SELF-TEST IN PROGRESS"; - case 0x0A: return "LOGICAL UNIT NOT ACCESSIBLE, ASYMMETRIC ACCESS STATE TRANSITION"; - case 0x0B: return "LOGICAL UNIT NOT ACCESSIBLE, TARGET IN STANDBY STATE"; - case 0x0C: return "LOGICAL UNIT NOT ACCESSIBLE, TARGET PORT IN UNAVAILABLE STATE"; - case 0x0D: return "LOGICAL UNIT NOT READY, STRUCTURE CHECK REQUIRED"; - case 0x0E: return "LOGICAL UNIT NOT READY, SECURITY SESSION IN PROGRESS"; - case 0x10: return "LOGICAL UNIT NOT READY, AUXILIARY MEMORY NOT ACCESSIBLE"; - case 0x11: return "LOGICAL UNIT NOT READY, NOTIFY (ENABLE SPINUP) REQUIRED"; - case 0x12: return "LOGICAL UNIT NOT READY, OFFLINE"; - case 0x13: return "LOGICAL UNIT NOT READY, SA CREATION IN PROGRESS"; - case 0x14: return "LOGICAL UNIT NOT READY, SPACE ALLOCATION IN PROGRESS"; - case 0x15: return "LOGICAL UNIT NOT READY, ROBOTICS DISABLED"; - case 0x16: return "LOGICAL UNIT NOT READY, CONFIGURATION REQUIRED"; - case 0x17: return "LOGICAL UNIT NOT READY, CALIBRATION REQUIRED"; - case 0x18: return "LOGICAL UNIT NOT READY, A DOOR IS OPEN"; - case 0x19: return "LOGICAL UNIT NOT READY, OPERATING IN SEQUENTIAL MODE"; - case 0x1A: return "LOGICAL UNIT NOT READY, START STOP UNIT IN PROGRESS"; - case 0x1B: return "LOGICAL UNIT NOT READY, SANITIZE IN PROGRESS"; - case 0x1C: return "LOGICAL UNIT NOT READY, ADDITIONAL POWER USE NOT YET GRANTED"; - case 0x1D: return "LOGICAL UNIT NOT READY, CONFIGURATION IN PROGRESS"; - case 0x1E: return "LOGICAL UNIT NOT READY, MICROCODE ACTIVATION REQUIRED"; - case 0x1F: return "LOGICAL UNIT NOT READY, MICROCODE DOWNLOAD REQUIRED"; - case 0x20: return "LOGICAL UNIT NOT READY, LOGICAL UNIT RESET REQUIRED"; - case 0x21: return "LOGICAL UNIT NOT READY, HARD RESET REQUIRED"; - case 0x22: return "LOGICAL UNIT NOT READY, POWER CYCLE REQUIRED"; + case 0x00: return"LOGICAL UNIT NOT READY, CAUSE NOT REPORTABLE"; + case 0x01: return"LOGICAL UNIT IS IN PROCESS OF BECOMING READY"; + case 0x02: return"LOGICAL UNIT NOT READY, INITIALIZING COMMAND REQUIRED"; + case 0x03: return"LOGICAL UNIT NOT READY, MANUAL INTERVENTION REQUIRED"; + case 0x04: return"LOGICAL UNIT NOT READY, FORMAT IN PROGRESS"; + case 0x05: return"LOGICAL UNIT NOT READY, REBUILD IN PROGRESS"; + case 0x06: return"LOGICAL UNIT NOT READY, RECALCULATION IN PROGRESS"; + case 0x07: return"LOGICAL UNIT NOT READY, OPERATION IN PROGRESS"; + case 0x08: return"LOGICAL UNIT NOT READY, LONG WRITE IN PROGRESS"; + case 0x09: return"LOGICAL UNIT NOT READY, SELF-TEST IN PROGRESS"; + case 0x0A: return"LOGICAL UNIT NOT ACCESSIBLE, ASYMMETRIC ACCESS STATE TRANSITION"; + case 0x0B: return"LOGICAL UNIT NOT ACCESSIBLE, TARGET IN STANDBY STATE"; + case 0x0C: return"LOGICAL UNIT NOT ACCESSIBLE, TARGET PORT IN UNAVAILABLE STATE"; + case 0x0D: return"LOGICAL UNIT NOT READY, STRUCTURE CHECK REQUIRED"; + case 0x0E: return"LOGICAL UNIT NOT READY, SECURITY SESSION IN PROGRESS"; + case 0x10: return"LOGICAL UNIT NOT READY, AUXILIARY MEMORY NOT ACCESSIBLE"; + case 0x11: return"LOGICAL UNIT NOT READY, NOTIFY (ENABLE SPINUP) REQUIRED"; + case 0x12: return"LOGICAL UNIT NOT READY, OFFLINE"; + case 0x13: return"LOGICAL UNIT NOT READY, SA CREATION IN PROGRESS"; + case 0x14: return"LOGICAL UNIT NOT READY, SPACE ALLOCATION IN PROGRESS"; + case 0x15: return"LOGICAL UNIT NOT READY, ROBOTICS DISABLED"; + case 0x16: return"LOGICAL UNIT NOT READY, CONFIGURATION REQUIRED"; + case 0x17: return"LOGICAL UNIT NOT READY, CALIBRATION REQUIRED"; + case 0x18: return"LOGICAL UNIT NOT READY, A DOOR IS OPEN"; + case 0x19: return"LOGICAL UNIT NOT READY, OPERATING IN SEQUENTIAL MODE"; + case 0x1A: return"LOGICAL UNIT NOT READY, START STOP UNIT IN PROGRESS"; + case 0x1B: return"LOGICAL UNIT NOT READY, SANITIZE IN PROGRESS"; + case 0x1C: return"LOGICAL UNIT NOT READY, ADDITIONAL POWER USE NOT YET GRANTED"; + case 0x1D: return"LOGICAL UNIT NOT READY, CONFIGURATION IN PROGRESS"; + case 0x1E: return"LOGICAL UNIT NOT READY, MICROCODE ACTIVATION REQUIRED"; + case 0x1F: return"LOGICAL UNIT NOT READY, MICROCODE DOWNLOAD REQUIRED"; + case 0x20: return"LOGICAL UNIT NOT READY, LOGICAL UNIT RESET REQUIRED"; + case 0x21: return"LOGICAL UNIT NOT READY, HARD RESET REQUIRED"; + case 0x22: return"LOGICAL UNIT NOT READY, POWER CYCLE REQUIRED"; } break; case 0x05: switch(ASCQ) { - case 0x00: return "LOGICAL UNIT DOES NOT RESPOND TO SELECTION"; + case 0x00: return"LOGICAL UNIT DOES NOT RESPOND TO SELECTION"; } break; case 0x06: switch(ASCQ) { - case 0x00: return "NO REFERENCE POSITION FOUND"; + case 0x00: return"NO REFERENCE POSITION FOUND"; } break; case 0x07: switch(ASCQ) { - case 0x00: return "MULTIPLE PERIPHERAL DEVICES SELECTED"; + case 0x00: return"MULTIPLE PERIPHERAL DEVICES SELECTED"; } break; case 0x08: switch(ASCQ) { - case 0x00: return "LOGICAL UNIT COMMUNICATION FAILURE"; - case 0x01: return "LOGICAL UNIT COMMUNICATION TIME-OUT"; - case 0x02: return "LOGICAL UNIT COMMUNICATION PARITY ERROR"; - case 0x03: return "LOGICAL UNIT COMMUNICATION CRC ERROR"; - case 0x04: return "UNREACHABLE COPY TARGET"; + case 0x00: return"LOGICAL UNIT COMMUNICATION FAILURE"; + case 0x01: return"LOGICAL UNIT COMMUNICATION TIME-OUT"; + case 0x02: return"LOGICAL UNIT COMMUNICATION PARITY ERROR"; + case 0x03: return"LOGICAL UNIT COMMUNICATION CRC ERROR"; + case 0x04: return"UNREACHABLE COPY TARGET"; } break; case 0x09: switch(ASCQ) { - case 0x00: return "TRACK FLOLLOWING ERROR"; - case 0x01: return "TRACKING SERVO FAILURE"; - case 0x02: return "FOCUS SERVO FAILURE"; - case 0x03: return "SPINDLE SERVO FAILURE"; - case 0x04: return "HEAD SELECT FAULT"; - case 0x05: return "VIBRATION INDUCED TRACKING ERROR"; + case 0x00: return"TRACK FLOLLOWING ERROR"; + case 0x01: return"TRACKING SERVO FAILURE"; + case 0x02: return"FOCUS SERVO FAILURE"; + case 0x03: return"SPINDLE SERVO FAILURE"; + case 0x04: return"HEAD SELECT FAULT"; + case 0x05: return"VIBRATION INDUCED TRACKING ERROR"; } break; case 0x0A: switch(ASCQ) { - case 0x00: return "ERROR LOG OVERFLOW"; + case 0x00: return"ERROR LOG OVERFLOW"; } break; case 0x0B: switch(ASCQ) { - case 0x00: return "WARNING"; - case 0x01: return "WARNING - SPECIFIED TEMPERATURE EXCEEDED"; - case 0x02: return "WARNING - ENCLOSURE DEGRADED"; - case 0x03: return "WARNING - BACKGROUND SELF-TEST FAILED"; - case 0x04: return "WARNING - BACKGROUND PRE-SCAN DETECTED MEDIUM ERROR"; - case 0x05: return "WARNING - BACKGROUND MEDIUM SCAN DETECTED MEDIUM ERROR"; - case 0x06: return "WARNING - NON-VOLATILE CACHE NOW VOLATILE"; - case 0x07: return "WARNING - DEGRADED POWER TO NON-VOLATILE CACHE"; - case 0x08: return "WARNING - POWER LOSS EXPECTED"; - case 0x09: return "WARNING - DEVICE STATISTICS NOTIFICATION ACTIVE"; - case 0x0A: return "WARNING - HIGH CRITICAL TEMPERATURE LIMIT EXCEEDED"; - case 0x0B: return "WARNING - LOW CRITICAL TEMPERATURE LIMIT EXCEEDED"; - case 0x0C: return "WARNING - HIGH OPERATING TEMPERATURE LIMIT EXCEEDED"; - case 0x0D: return "WARNING - LOW OPERATING TEMPERATURE LIMIT EXCEEDED"; - case 0x0E: return "WARNING - HIGH CRITICAL HUMIDITY LIMIT EXCEEDED"; - case 0x0F: return "WARNING - LOW CRITICAL HUMIDITY LIMIT EXCEEDED"; - case 0x10: return "WARNING - HIGH OPERATING HUMIDITY LIMIT EXCEEDED"; - case 0x11: return "WARNING - LOW OPERATING HUMIDITY LIMIT EXCEEDED"; + case 0x00: return"WARNING"; + case 0x01: return"WARNING - SPECIFIED TEMPERATURE EXCEEDED"; + case 0x02: return"WARNING - ENCLOSURE DEGRADED"; + case 0x03: return"WARNING - BACKGROUND SELF-TEST FAILED"; + case 0x04: return"WARNING - BACKGROUND PRE-SCAN DETECTED MEDIUM ERROR"; + case 0x05: return"WARNING - BACKGROUND MEDIUM SCAN DETECTED MEDIUM ERROR"; + case 0x06: return"WARNING - NON-VOLATILE CACHE NOW VOLATILE"; + case 0x07: return"WARNING - DEGRADED POWER TO NON-VOLATILE CACHE"; + case 0x08: return"WARNING - POWER LOSS EXPECTED"; + case 0x09: return"WARNING - DEVICE STATISTICS NOTIFICATION ACTIVE"; + case 0x0A: return"WARNING - HIGH CRITICAL TEMPERATURE LIMIT EXCEEDED"; + case 0x0B: return"WARNING - LOW CRITICAL TEMPERATURE LIMIT EXCEEDED"; + case 0x0C: return"WARNING - HIGH OPERATING TEMPERATURE LIMIT EXCEEDED"; + case 0x0D: return"WARNING - LOW OPERATING TEMPERATURE LIMIT EXCEEDED"; + case 0x0E: return"WARNING - HIGH CRITICAL HUMIDITY LIMIT EXCEEDED"; + case 0x0F: return"WARNING - LOW CRITICAL HUMIDITY LIMIT EXCEEDED"; + case 0x10: return"WARNING - HIGH OPERATING HUMIDITY LIMIT EXCEEDED"; + case 0x11: return"WARNING - LOW OPERATING HUMIDITY LIMIT EXCEEDED"; } break; case 0x0C: switch(ASCQ) { - case 0x00: return "WRITE ERROR"; - case 0x01: return "WRITE ERROR - RECOVERED WITH AUTO REALLOCATION"; - case 0x02: return "WRITE ERROR - AUTO REALLOCATION FAILED"; - case 0x03: return "WRITE ERROR - RECOMMENDED REASSIGNMENT"; - case 0x04: return "COMPRESSION CHECK MISCOMPARE ERROR"; - case 0x05: return "DATA EXPANSION OCCURRED DURING COMPRESSION"; - case 0x06: return "BLOCK NOT COMPRESSIBLE"; - case 0x07: return "WRITE ERROR - RECOVERY NEEDED"; - case 0x08: return "WRITE ERROR - RECOVERY FAILED"; - case 0x09: return "WRITE ERROR - LOSS OF STREAMING"; - case 0x0A: return "WRITE ERROR - PADDING BLOCKS ADDED"; - case 0x0B: return "AUXILIARY MEMORY WRITE ERROR"; - case 0x0C: return "WRITE ERROR - UNEXPECTED UNSOLICITED DATA"; - case 0x0D: return "WRITE ERROR - NOT ENOUGH UNSOLICITED DATA"; - case 0x0E: return "MULTIPLE WRITE ERRORS"; - case 0x0F: return "DEFECTS IN ERROR WINDOW"; - case 0x10: return "INCOMPLETE MULTIPLE ATOMIC WRITE OPERATIONS"; - case 0x11: return "WRITE ERROR - RECOVERY SCAN NEEDED"; - case 0x12: return "WRITE ERROR - INSUFFICIENT ZONE RESOURCES"; + case 0x00: return"WRITE ERROR"; + case 0x01: return"WRITE ERROR - RECOVERED WITH AUTO REALLOCATION"; + case 0x02: return"WRITE ERROR - AUTO REALLOCATION FAILED"; + case 0x03: return"WRITE ERROR - RECOMMENDED REASSIGNMENT"; + case 0x04: return"COMPRESSION CHECK MISCOMPARE ERROR"; + case 0x05: return"DATA EXPANSION OCCURRED DURING COMPRESSION"; + case 0x06: return"BLOCK NOT COMPRESSIBLE"; + case 0x07: return"WRITE ERROR - RECOVERY NEEDED"; + case 0x08: return"WRITE ERROR - RECOVERY FAILED"; + case 0x09: return"WRITE ERROR - LOSS OF STREAMING"; + case 0x0A: return"WRITE ERROR - PADDING BLOCKS ADDED"; + case 0x0B: return"AUXILIARY MEMORY WRITE ERROR"; + case 0x0C: return"WRITE ERROR - UNEXPECTED UNSOLICITED DATA"; + case 0x0D: return"WRITE ERROR - NOT ENOUGH UNSOLICITED DATA"; + case 0x0E: return"MULTIPLE WRITE ERRORS"; + case 0x0F: return"DEFECTS IN ERROR WINDOW"; + case 0x10: return"INCOMPLETE MULTIPLE ATOMIC WRITE OPERATIONS"; + case 0x11: return"WRITE ERROR - RECOVERY SCAN NEEDED"; + case 0x12: return"WRITE ERROR - INSUFFICIENT ZONE RESOURCES"; } break; case 0x0D: switch(ASCQ) { - case 0x00: return "ERROR DETECTED BY THIRD PARTY TEMPORARY INITIATOR"; - case 0x01: return "THIRD PARTY DEVICE FAILURE"; - case 0x02: return "COPY TARGET DEVICE NOT REACHABLE"; - case 0x03: return "INCORRECT COPY TARGET DEVICE TYPE"; - case 0x04: return "COPY TARGET DEVICE DATA UNDERRUN"; - case 0x05: return "COPY TARGET DEVICE DATA OVERRUN"; + case 0x00: return"ERROR DETECTED BY THIRD PARTY TEMPORARY INITIATOR"; + case 0x01: return"THIRD PARTY DEVICE FAILURE"; + case 0x02: return"COPY TARGET DEVICE NOT REACHABLE"; + case 0x03: return"INCORRECT COPY TARGET DEVICE TYPE"; + case 0x04: return"COPY TARGET DEVICE DATA UNDERRUN"; + case 0x05: return"COPY TARGET DEVICE DATA OVERRUN"; } break; case 0x0E: switch(ASCQ) { - case 0x00: return "INVALID INFORMATION UNIT"; - case 0x01: return "INFORMATION UNIT TOO SHORT"; - case 0x02: return "INFORMATION UNIT TOO LONG"; - case 0x03: return "INVALID FIELD IN COMMAND INFORMATION UNIT"; + case 0x00: return"INVALID INFORMATION UNIT"; + case 0x01: return"INFORMATION UNIT TOO SHORT"; + case 0x02: return"INFORMATION UNIT TOO LONG"; + case 0x03: return"INVALID FIELD IN COMMAND INFORMATION UNIT"; } break; case 0x10: switch(ASCQ) { - case 0x00: return "ID CRC OR ECC ERROR"; - case 0x01: return "LOGICAL BLOCK GUARD CHECK FAILED"; - case 0x02: return "LOGICAL BLOCK APPLICATION TAG CHECK FAILED"; - case 0x03: return "LOGICAL BLOCK REFERENCE TAG CHECK FAILED"; - case 0x04: return "LOGICAL BLOCK PROTECTION ERROR ON RECOVER BUFFERED DATA"; - case 0x05: return "LOGICAL BLOCK PROTECTION METHOD ERROR"; + case 0x00: return"ID CRC OR ECC ERROR"; + case 0x01: return"LOGICAL BLOCK GUARD CHECK FAILED"; + case 0x02: return"LOGICAL BLOCK APPLICATION TAG CHECK FAILED"; + case 0x03: return"LOGICAL BLOCK REFERENCE TAG CHECK FAILED"; + case 0x04: return"LOGICAL BLOCK PROTECTION ERROR ON RECOVER BUFFERED DATA"; + case 0x05: return"LOGICAL BLOCK PROTECTION METHOD ERROR"; } break; case 0x11: switch(ASCQ) { - case 0x00: return "UNRECOVERED READ ERROR"; - case 0x01: return "READ RETRIES EXHAUSTED"; - case 0x02: return "ERROR TOO LONG TO CORRECT"; - case 0x03: return "MULTIPLE READ ERRORS"; - case 0x04: return "UNRECOVERED READ ERROR - AUTO REALLOCATE FAILED"; - case 0x05: return "L-EC UNCORRECTABLE ERROR"; - case 0x06: return "CIRC UNRECOVERED ERROR"; - case 0x07: return "DATA RESYNCHRONIZATION ERROR"; - case 0x08: return "INCOMPLETE BLOCK READ"; - case 0x09: return "NO GAP FOUND"; - case 0x0A: return "MISCORRECTED ERROR"; - case 0x0B: return "UNRECOVERED READ ERROR - RECOMMENDED REASSIGNMENT"; - case 0x0C: return "UNRECOVERED READ ERROR - RECOMMENDED REWRITE THE DATA"; - case 0x0D: return "DE-COMPRESSION CRC ERROR"; - case 0x0E: return "CANNOT DECOMPRESS USING DECLARED ALGORITHM"; - case 0x0F: return "ERROR READING UPC/EAN NUMBER"; - case 0x10: return "ERROR READING ISRC NUMBER"; - case 0x11: return "READ ERROR - LOSS OF STREAMING"; - case 0x12: return "AUXILIARY MEMORY READ ERROR"; - case 0x13: return "READ ERROR - FAILED RETRANSMISSITION REQUEST"; - case 0x14: return "READ ERROR - LBA MARKED BAD BY APPLICATION CLIENT"; - case 0x15: return "WRITE AFTER SANITIZE REQUIRED"; + case 0x00: return"UNRECOVERED READ ERROR"; + case 0x01: return"READ RETRIES EXHAUSTED"; + case 0x02: return"ERROR TOO LONG TO CORRECT"; + case 0x03: return"MULTIPLE READ ERRORS"; + case 0x04: return"UNRECOVERED READ ERROR - AUTO REALLOCATE FAILED"; + case 0x05: return"L-EC UNCORRECTABLE ERROR"; + case 0x06: return"CIRC UNRECOVERED ERROR"; + case 0x07: return"DATA RESYNCHRONIZATION ERROR"; + case 0x08: return"INCOMPLETE BLOCK READ"; + case 0x09: return"NO GAP FOUND"; + case 0x0A: return"MISCORRECTED ERROR"; + case 0x0B: return"UNRECOVERED READ ERROR - RECOMMENDED REASSIGNMENT"; + case 0x0C: return"UNRECOVERED READ ERROR - RECOMMENDED REWRITE THE DATA"; + case 0x0D: return"DE-COMPRESSION CRC ERROR"; + case 0x0E: return"CANNOT DECOMPRESS USING DECLARED ALGORITHM"; + case 0x0F: return"ERROR READING UPC/EAN NUMBER"; + case 0x10: return"ERROR READING ISRC NUMBER"; + case 0x11: return"READ ERROR - LOSS OF STREAMING"; + case 0x12: return"AUXILIARY MEMORY READ ERROR"; + case 0x13: return"READ ERROR - FAILED RETRANSMISSITION REQUEST"; + case 0x14: return"READ ERROR - LBA MARKED BAD BY APPLICATION CLIENT"; + case 0x15: return"WRITE AFTER SANITIZE REQUIRED"; } break; case 0x12: switch(ASCQ) { - case 0x00: return "ADDRESS MARK NOT FOUND FOR ID FIELD"; + case 0x00: return"ADDRESS MARK NOT FOUND FOR ID FIELD"; } break; case 0x13: switch(ASCQ) { - case 0x00: return "ADDRESS MARK NOT FOUND FOR DATA FIELD"; + case 0x00: return"ADDRESS MARK NOT FOUND FOR DATA FIELD"; } break; case 0x14: switch(ASCQ) { - case 0x00: return "RECORDED ENTITY NOT FOUND"; - case 0x01: return "RECORD NOT FOUND"; - case 0x02: return "FILEMARK OR SETMARK NOT FOUND"; - case 0x03: return "END-OF-DATA NOT FOUND"; - case 0x04: return "BLOCK SEQUENCE ERROR"; - case 0x05: return "RECORD NOT FOUND - RECOMMENDAD REASSIGNMENT"; - case 0x06: return "RECORD NOT FOUND - DATA AUTO-REALLOCATED"; - case 0x07: return "LOCATE OPERATION FAILURE"; + case 0x00: return"RECORDED ENTITY NOT FOUND"; + case 0x01: return"RECORD NOT FOUND"; + case 0x02: return"FILEMARK OR SETMARK NOT FOUND"; + case 0x03: return"END-OF-DATA NOT FOUND"; + case 0x04: return"BLOCK SEQUENCE ERROR"; + case 0x05: return"RECORD NOT FOUND - RECOMMENDAD REASSIGNMENT"; + case 0x06: return"RECORD NOT FOUND - DATA AUTO-REALLOCATED"; + case 0x07: return"LOCATE OPERATION FAILURE"; } break; case 0x15: switch(ASCQ) { - case 0x00: return "RANDOM POSITIONING ERROR"; - case 0x01: return "MECHANICAL POSITIONING ERROR"; - case 0x02: return "POSITIONING ERROR DETECTED BY READ OF MEDIUM"; + case 0x00: return"RANDOM POSITIONING ERROR"; + case 0x01: return"MECHANICAL POSITIONING ERROR"; + case 0x02: return"POSITIONING ERROR DETECTED BY READ OF MEDIUM"; } break; case 0x16: switch(ASCQ) { - case 0x00: return "DATA SYNCHRONIZATION MARK ERROR"; - case 0x01: return "DATA SYNC ERROR - DATA REWRITTEN"; - case 0x02: return "DATA SYNC ERROR - RECOMMENDED REWRITE"; - case 0x03: return "DATA SYNC ERROR - DATA AUTO-REALLOCATED"; - case 0x04: return "DATA SYNC ERROR - RECOMMENDED REASSIGNMENT"; + case 0x00: return"DATA SYNCHRONIZATION MARK ERROR"; + case 0x01: return"DATA SYNC ERROR - DATA REWRITTEN"; + case 0x02: return"DATA SYNC ERROR - RECOMMENDED REWRITE"; + case 0x03: return"DATA SYNC ERROR - DATA AUTO-REALLOCATED"; + case 0x04: return"DATA SYNC ERROR - RECOMMENDED REASSIGNMENT"; } break; case 0x17: switch(ASCQ) { - case 0x00: return "RECOVERED DATA WITH NO ERROR CORRECTION APPLIED"; - case 0x01: return "RECOVERED DATA WITH RETRIES"; - case 0x02: return "RECOVERED DATA WITH POSITIVE HEAD OFFSET"; - case 0x03: return "RECOVERED DATA WITH NEGATIVE HEAD OFFSET"; - case 0x04: return "RECOVERED DATA WITH RETRIES AND/OR CIRC APPLIED"; - case 0x05: return "RECOVERED DATA USING PREVIOUS SECTOR ID"; - case 0x06: return "RECOVERED DATA WITHOUT ECC - DATA AUTO-REALLOCATED"; - case 0x07: return "RECOVERED DATA WITHOUT ECC - RECOMMENDED REASSIGNMENT"; - case 0x08: return "RECOVERED DATA WITHOUT ECC - RECOMMENDED REWRITE"; - case 0x09: return "RECOVERED DATA WITHOUT ECC - DATA REWRITTEN"; + case 0x00: return"RECOVERED DATA WITH NO ERROR CORRECTION APPLIED"; + case 0x01: return"RECOVERED DATA WITH RETRIES"; + case 0x02: return"RECOVERED DATA WITH POSITIVE HEAD OFFSET"; + case 0x03: return"RECOVERED DATA WITH NEGATIVE HEAD OFFSET"; + case 0x04: return"RECOVERED DATA WITH RETRIES AND/OR CIRC APPLIED"; + case 0x05: return"RECOVERED DATA USING PREVIOUS SECTOR ID"; + case 0x06: return"RECOVERED DATA WITHOUT ECC - DATA AUTO-REALLOCATED"; + case 0x07: return"RECOVERED DATA WITHOUT ECC - RECOMMENDED REASSIGNMENT"; + case 0x08: return"RECOVERED DATA WITHOUT ECC - RECOMMENDED REWRITE"; + case 0x09: return"RECOVERED DATA WITHOUT ECC - DATA REWRITTEN"; } break; case 0x18: switch(ASCQ) { - case 0x00: return "RECOVERED DATA WITH ERROR CORRECTION APPLIED"; - case 0x01: return "RECOVERED DATA WITH ERROR CORRECTION & RETRIES APPLIED"; - case 0x02: return "RECOVERED DATA - DATA AUTO-REALLOCATED"; - case 0x03: return "RECOVERED DATA WITH CIRC"; - case 0x04: return "RECOVERED DATA WITH L-EC"; - case 0x05: return "RECOVERED DATA - RECOMMENDED REASSIGNMENT"; - case 0x06: return "RECOVERED DATA - RECOMMENDED REWRITE"; - case 0x07: return "RECOVERED DATA WITH ECC - DATA REWRITTEN"; - case 0x08: return "RECOVERED DATA WITH LINKING"; + case 0x00: return"RECOVERED DATA WITH ERROR CORRECTION APPLIED"; + case 0x01: return"RECOVERED DATA WITH ERROR CORRECTION & RETRIES APPLIED"; + case 0x02: return"RECOVERED DATA - DATA AUTO-REALLOCATED"; + case 0x03: return"RECOVERED DATA WITH CIRC"; + case 0x04: return"RECOVERED DATA WITH L-EC"; + case 0x05: return"RECOVERED DATA - RECOMMENDED REASSIGNMENT"; + case 0x06: return"RECOVERED DATA - RECOMMENDED REWRITE"; + case 0x07: return"RECOVERED DATA WITH ECC - DATA REWRITTEN"; + case 0x08: return"RECOVERED DATA WITH LINKING"; } break; case 0x19: switch(ASCQ) { - case 0x00: return "DEFECT LIST ERROR"; - case 0x01: return "DEFECT LIST NOT AVAILABLE"; - case 0x02: return "DEFECT LIST ERROR IN PRIMARY LIST"; - case 0x03: return "DEFECT LIST ERROR IN GROWN LIST"; + case 0x00: return"DEFECT LIST ERROR"; + case 0x01: return"DEFECT LIST NOT AVAILABLE"; + case 0x02: return"DEFECT LIST ERROR IN PRIMARY LIST"; + case 0x03: return"DEFECT LIST ERROR IN GROWN LIST"; } break; case 0x1A: switch(ASCQ) { - case 0x00: return "PARAMETER LIST LENGTH ERROR"; + case 0x00: return"PARAMETER LIST LENGTH ERROR"; } break; case 0x1B: switch(ASCQ) { - case 0x00: return "SYNCHRONOUS DATA TRANSFER ERROR"; + case 0x00: return"SYNCHRONOUS DATA TRANSFER ERROR"; } break; case 0x1C: switch(ASCQ) { - case 0x00: return "DEFECT LIST NOT FOUND"; - case 0x01: return "PRIMARY DEFECT LIST NOT FOUND"; - case 0x02: return "GROWN DEFECT LIST NOT FOUND"; + case 0x00: return"DEFECT LIST NOT FOUND"; + case 0x01: return"PRIMARY DEFECT LIST NOT FOUND"; + case 0x02: return"GROWN DEFECT LIST NOT FOUND"; } break; case 0x1D: switch(ASCQ) { - case 0x00: return "MISCOMPARE DURING VERIFY OPERATION"; - case 0x01: return "MISCOMPARE VERIFY OF UNMAPPED LBA"; + case 0x00: return"MISCOMPARE DURING VERIFY OPERATION"; + case 0x01: return"MISCOMPARE VERIFY OF UNMAPPED LBA"; } break; case 0x1E: switch(ASCQ) { - case 0x00: return "RECOVERED ID WITH ECC CORRECTION"; + case 0x00: return"RECOVERED ID WITH ECC CORRECTION"; } break; case 0x1F: switch(ASCQ) { - case 0x00: return "PARTIAL DEFECT LIST TRANSFER"; + case 0x00: return"PARTIAL DEFECT LIST TRANSFER"; } break; case 0x20: switch(ASCQ) { - case 0x00: return "INVALID COMMAND OPERATION CODE"; - case 0x01: return "ACCESS DENIED - INITIATOR PENDING-ENROLLED"; - case 0x02: return "ACCESS DENIED - NO ACCESS RIGHTS"; - case 0x03: return "ACCESS DENIED - INVALID MGMT ID KEY"; - case 0x04: return "ILLEGAL COMMAND WHILE IN WRITE CAPABLE STATE"; - case 0x05: return "ILLEGAL COMMAND WHILE IN READ CAPABLE STATE"; - case 0x06: return "ILLEGAL COMMAND WHILE IN EXPLICIT ADDRESS MODE"; - case 0x07: return "ILLEGAL COMMAND WHILE IN IMPLICIT ADDRESS MODE"; - case 0x08: return "ACCESS DENIED - ENROLLMENT CONFLICT"; - case 0x09: return "ACCESS DENIED - INVALID LUN IDENTIFIER"; - case 0x0A: return "ACCESS DENIED - INVALID PROXY TOKEN"; - case 0x0B: return "ACCESS DENIED - ACL LUN CONFLICT"; - case 0x0C: return "ILLEGAL COMMAND WHEN NOT IN APPEND-ONLY MODE"; + case 0x00: return"INVALID COMMAND OPERATION CODE"; + case 0x01: return"ACCESS DENIED - INITIATOR PENDING-ENROLLED"; + case 0x02: return"ACCESS DENIED - NO ACCESS RIGHTS"; + case 0x03: return"ACCESS DENIED - INVALID MGMT ID KEY"; + case 0x04: return"ILLEGAL COMMAND WHILE IN WRITE CAPABLE STATE"; + case 0x05: return"ILLEGAL COMMAND WHILE IN READ CAPABLE STATE"; + case 0x06: return"ILLEGAL COMMAND WHILE IN EXPLICIT ADDRESS MODE"; + case 0x07: return"ILLEGAL COMMAND WHILE IN IMPLICIT ADDRESS MODE"; + case 0x08: return"ACCESS DENIED - ENROLLMENT CONFLICT"; + case 0x09: return"ACCESS DENIED - INVALID LUN IDENTIFIER"; + case 0x0A: return"ACCESS DENIED - INVALID PROXY TOKEN"; + case 0x0B: return"ACCESS DENIED - ACL LUN CONFLICT"; + case 0x0C: return"ILLEGAL COMMAND WHEN NOT IN APPEND-ONLY MODE"; } break; case 0x21: switch(ASCQ) { - case 0x00: return "LOGICAL BLOCK ADDRESS OUT OF RANGE"; - case 0x01: return "INVALID ELEMENT ADDRESS"; - case 0x02: return "INVALID ADDRESS FOR WRITE"; - case 0x03: return "INVALID WRITE CROSSING LAYER JUMP"; - case 0x04: return "UNALIGNED WRITE COMMAND"; - case 0x05: return "WRITE BOUNDARY VIOLATION"; - case 0x06: return "ATTEMPT TO READ INVALID DATA"; - case 0x07: return "READ BOUNDARY VIOLATION"; + case 0x00: return"LOGICAL BLOCK ADDRESS OUT OF RANGE"; + case 0x01: return"INVALID ELEMENT ADDRESS"; + case 0x02: return"INVALID ADDRESS FOR WRITE"; + case 0x03: return"INVALID WRITE CROSSING LAYER JUMP"; + case 0x04: return"UNALIGNED WRITE COMMAND"; + case 0x05: return"WRITE BOUNDARY VIOLATION"; + case 0x06: return"ATTEMPT TO READ INVALID DATA"; + case 0x07: return"READ BOUNDARY VIOLATION"; } break; case 0x22: switch(ASCQ) { - case 0x00: return "ILLEGAL FUNCTION"; + case 0x00: return"ILLEGAL FUNCTION"; } break; case 0x23: switch(ASCQ) { - case 0x00: return "INVALID TOKEN OPERATION, CAUSE NOT REPORTABLE"; - case 0x01: return "INVALID TOKEN OPERATION, UNSUPPORTED TOKEN TYPE"; - case 0x02: return "INVALID TOKEN OPERATION, REMOTE TOKEN USAGE NOT SUPPORTED"; - case 0x03: return "INVALID TOKEN OPERATION, REMOTE ROD TOKEN CREATION NOT SUPPORTED"; - case 0x04: return "INVALID TOKEN OPERATION, TOKEN UNKNOWN"; - case 0x05: return "INVALID TOKEN OPERATION, TOKEN CORRUPT"; - case 0x06: return "INVALID TOKEN OPERATION, TOKEN REVOKED"; - case 0x07: return "INVALID TOKEN OPERATION, TOKEN EXPIRED"; - case 0x08: return "INVALID TOKEN OPERATION, TOKEN CANCELLED"; - case 0x09: return "INVALID TOKEN OPERATION, TOKEN DELETED"; - case 0x0A: return "INVALID TOKEN OPERATION, INVALID TOKEN LENGTH"; + case 0x00: return"INVALID TOKEN OPERATION, CAUSE NOT REPORTABLE"; + case 0x01: return"INVALID TOKEN OPERATION, UNSUPPORTED TOKEN TYPE"; + case 0x02: return"INVALID TOKEN OPERATION, REMOTE TOKEN USAGE NOT SUPPORTED"; + case 0x03: return"INVALID TOKEN OPERATION, REMOTE ROD TOKEN CREATION NOT SUPPORTED"; + case 0x04: return"INVALID TOKEN OPERATION, TOKEN UNKNOWN"; + case 0x05: return"INVALID TOKEN OPERATION, TOKEN CORRUPT"; + case 0x06: return"INVALID TOKEN OPERATION, TOKEN REVOKED"; + case 0x07: return"INVALID TOKEN OPERATION, TOKEN EXPIRED"; + case 0x08: return"INVALID TOKEN OPERATION, TOKEN CANCELLED"; + case 0x09: return"INVALID TOKEN OPERATION, TOKEN DELETED"; + case 0x0A: return"INVALID TOKEN OPERATION, INVALID TOKEN LENGTH"; } break; case 0x24: switch(ASCQ) { - case 0x00: return "ILLEGAL FIELD IN CDB"; - case 0x01: return "CDB DECRYPTION ERROR"; - case 0x02: return "INVALID CDB FIELD WHILE IN EXPLICIT BLOCK ADDRESS MODEL"; - case 0x03: return "INVALID CDB FIELD WHILE IN IMPLICIT BLOCK ADDRESS MODEL"; - case 0x04: return "SECURITY AUDIT VALUE FROZEN"; - case 0x05: return "SECURITY WORKING KEY FROZEN"; - case 0x06: return "NONCE NOT UNIQUE"; - case 0x07: return "NONCE TIMESTAMP OUT OF RANGE"; - case 0x08: return "INVALID XCDB"; + case 0x00: return"ILLEGAL FIELD IN CDB"; + case 0x01: return"CDB DECRYPTION ERROR"; + case 0x02: return"INVALID CDB FIELD WHILE IN EXPLICIT BLOCK ADDRESS MODEL"; + case 0x03: return"INVALID CDB FIELD WHILE IN IMPLICIT BLOCK ADDRESS MODEL"; + case 0x04: return"SECURITY AUDIT VALUE FROZEN"; + case 0x05: return"SECURITY WORKING KEY FROZEN"; + case 0x06: return"NONCE NOT UNIQUE"; + case 0x07: return"NONCE TIMESTAMP OUT OF RANGE"; + case 0x08: return"INVALID XCDB"; } break; case 0x25: switch(ASCQ) { - case 0x00: return "LOGICAL UNIT NOT SUPPORTED"; + case 0x00: return"LOGICAL UNIT NOT SUPPORTED"; } break; case 0x26: switch(ASCQ) { - case 0x00: return "INVALID FIELD IN PARAMETER LIST"; - case 0x01: return "PARAMETER NOT SUPPORTED"; - case 0x02: return "PARAMETER VALUE INVALID"; - case 0x03: return "THRESHOLD PARAMETERS NOT SUPPORTED"; - case 0x04: return "INVALID RELEASE OF PERSISTENT RESERVATION"; - case 0x05: return "DATA DECRYPTION ERROR"; - case 0x06: return "TOO MANY TARGET DESCRIPTORS"; - case 0x07: return "UNSUPPORTED TARGET DESCRIPTOR TYPE CODE"; - case 0x08: return "TOO MANY SEGMENT DESCRIPTORS"; - case 0x09: return "UNSUPPORTED SEGMENT DESCRIPTOR TYPE CODE"; - case 0x0A: return "UNEXPECTED INEXACT SEGMENT"; - case 0x0B: return "INLINE DATA LENGTH EXCEEDED"; - case 0x0C: return "INVALID OPERATION FOR COPY SOURCE OR DESTINATION"; - case 0x0D: return "COPY SEGMENT GRANULARITY VIOLATION"; - case 0x0E: return "INVALID PARAMETER WHILE PORT IS ENABLED"; - case 0x0F: return "INVALID DATA-OUT BUFFER INTEGRITY CHECK VALUE"; - case 0x10: return "DATA DECRYPTION KEY FAIL LIMIT REACHED"; - case 0x11: return "INCOMPLETE KEY-ASSOCIATED DATA SET"; - case 0x12: return "VENDOR SPECIFIC KEY REFERENCE NOT FOUND"; - case 0x13: return "APPLICATION TAG MODE PAGE IS INVALID"; + case 0x00: return"INVALID FIELD IN PARAMETER LIST"; + case 0x01: return"PARAMETER NOT SUPPORTED"; + case 0x02: return"PARAMETER VALUE INVALID"; + case 0x03: return"THRESHOLD PARAMETERS NOT SUPPORTED"; + case 0x04: return"INVALID RELEASE OF PERSISTENT RESERVATION"; + case 0x05: return"DATA DECRYPTION ERROR"; + case 0x06: return"TOO MANY TARGET DESCRIPTORS"; + case 0x07: return"UNSUPPORTED TARGET DESCRIPTOR TYPE CODE"; + case 0x08: return"TOO MANY SEGMENT DESCRIPTORS"; + case 0x09: return"UNSUPPORTED SEGMENT DESCRIPTOR TYPE CODE"; + case 0x0A: return"UNEXPECTED INEXACT SEGMENT"; + case 0x0B: return"INLINE DATA LENGTH EXCEEDED"; + case 0x0C: return"INVALID OPERATION FOR COPY SOURCE OR DESTINATION"; + case 0x0D: return"COPY SEGMENT GRANULARITY VIOLATION"; + case 0x0E: return"INVALID PARAMETER WHILE PORT IS ENABLED"; + case 0x0F: return"INVALID DATA-OUT BUFFER INTEGRITY CHECK VALUE"; + case 0x10: return"DATA DECRYPTION KEY FAIL LIMIT REACHED"; + case 0x11: return"INCOMPLETE KEY-ASSOCIATED DATA SET"; + case 0x12: return"VENDOR SPECIFIC KEY REFERENCE NOT FOUND"; + case 0x13: return"APPLICATION TAG MODE PAGE IS INVALID"; } break; case 0x27: switch(ASCQ) { - case 0x00: return "WRITE PROTECTED"; - case 0x01: return "HARDWARE WRITE PROTECTED"; - case 0x02: return "LOGICAL UNIT SOFTWARE WRITE PROTECTED"; - case 0x03: return "ASSOCIATED WRITE PROTECT"; - case 0x04: return "PERSISTENT WRITE PROTECT"; - case 0x05: return "PERMANENT WRITE PROTECT"; - case 0x06: return "CONDITIONAL WRITE PROTECT"; - case 0x07: return "SPACE ALLOCATION FAILED WRITE PROTECT"; - case 0x08: return "ZONE IS READ ONLY"; + case 0x00: return"WRITE PROTECTED"; + case 0x01: return"HARDWARE WRITE PROTECTED"; + case 0x02: return"LOGICAL UNIT SOFTWARE WRITE PROTECTED"; + case 0x03: return"ASSOCIATED WRITE PROTECT"; + case 0x04: return"PERSISTENT WRITE PROTECT"; + case 0x05: return"PERMANENT WRITE PROTECT"; + case 0x06: return"CONDITIONAL WRITE PROTECT"; + case 0x07: return"SPACE ALLOCATION FAILED WRITE PROTECT"; + case 0x08: return"ZONE IS READ ONLY"; } break; case 0x28: switch(ASCQ) { - case 0x00: return "NOT READY TO READY CHANGE (MEDIUM MAY HAVE CHANGED)"; - case 0x01: return "IMPORT OR EXPORT ELEMENT ACCESSED"; - case 0x02: return "FORMAT-LAYER MAY HAVE CHANGED"; - case 0x03: return "IMPORT/EXPORT ELEMENT ACCESSED, MEDIUM CHANGED"; + case 0x00: return"NOT READY TO READY CHANGE (MEDIUM MAY HAVE CHANGED)"; + case 0x01: return"IMPORT OR EXPORT ELEMENT ACCESSED"; + case 0x02: return"FORMAT-LAYER MAY HAVE CHANGED"; + case 0x03: return"IMPORT/EXPORT ELEMENT ACCESSED, MEDIUM CHANGED"; } break; case 0x29: switch(ASCQ) { - case 0x00: return "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED"; - case 0x01: return "POWER ON OCCURRED"; - case 0x02: return "SCSI BUS RESET OCCURRED"; - case 0x03: return "BUS DEVICE RESET FUNCTION OCCURRED"; - case 0x04: return "DEVICE INTERNAL RESET"; - case 0x05: return "TRANSCEIVER MODE CHANGED TO SINGLE-ENDED"; - case 0x06: return "TRANSCEIVER MODE CHANGED TO LVD"; - case 0x07: return "I_T NEXUS LOSS OCCURRED"; + case 0x00: return"POWER ON, RESET, OR BUS DEVICE RESET OCCURRED"; + case 0x01: return"POWER ON OCCURRED"; + case 0x02: return"SCSI BUS RESET OCCURRED"; + case 0x03: return"BUS DEVICE RESET FUNCTION OCCURRED"; + case 0x04: return"DEVICE INTERNAL RESET"; + case 0x05: return"TRANSCEIVER MODE CHANGED TO SINGLE-ENDED"; + case 0x06: return"TRANSCEIVER MODE CHANGED TO LVD"; + case 0x07: return"I_T NEXUS LOSS OCCURRED"; } break; case 0x2A: switch(ASCQ) { - case 0x00: return "PARAMETERS CHANGED"; - case 0x01: return "MODE PARAMETERS CHANGED"; - case 0x02: return "LOG PARAMETERS CHANGED"; - case 0x03: return "RESERVATIONS PREEMPTED"; - case 0x04: return "RESERVATIONS RELEASED"; - case 0x05: return "REGISTRATIONS PREEMPTED"; - case 0x06: return "ASYMMETRIC ACCESS STATE CHANGED"; - case 0x07: return "IMPLICIT ASYMMETRIC ACCESS STATE TRANSITION FAILED"; - case 0x08: return "PRIORITY CHANGED"; - case 0x09: return "CAPACITY DATA HAS CHANGED"; - case 0x0A: return "ERROR HISTORY I_T NEXUS CLEARED"; - case 0x0B: return "ERROR HISTORY SNAPSHOT RELEASED"; - case 0x0C: return "ERROR RECOVERY ATTRIBUTES HAVE CHANGED"; - case 0x0D: return "DATA ENCRYPTION CAPABILITIES CHANGED"; - case 0x10: return "TIMESTAMP CHANGED"; - case 0x11: return "DATA ENCRYPTION PARAMETERS CHANGED BY ANOTHER I_T NEXUS"; - case 0x12: return "DATA ENCRYPTION PARAMETERS CHANGED BY VENDOR SPECIFIC EVENT"; - case 0x13: return "DATA ENCRYPTION KEY INSTANCE COUNTER HAS CHANGED"; - case 0x14: return "SA CREATION CAPABILITIES DATA HAS CHANGED"; - case 0x15: return "MEDIUM REMOVAL PREVENTION PREEMPTED"; + case 0x00: return"PARAMETERS CHANGED"; + case 0x01: return"MODE PARAMETERS CHANGED"; + case 0x02: return"LOG PARAMETERS CHANGED"; + case 0x03: return"RESERVATIONS PREEMPTED"; + case 0x04: return"RESERVATIONS RELEASED"; + case 0x05: return"REGISTRATIONS PREEMPTED"; + case 0x06: return"ASYMMETRIC ACCESS STATE CHANGED"; + case 0x07: return"IMPLICIT ASYMMETRIC ACCESS STATE TRANSITION FAILED"; + case 0x08: return"PRIORITY CHANGED"; + case 0x09: return"CAPACITY DATA HAS CHANGED"; + case 0x0A: return"ERROR HISTORY I_T NEXUS CLEARED"; + case 0x0B: return"ERROR HISTORY SNAPSHOT RELEASED"; + case 0x0C: return"ERROR RECOVERY ATTRIBUTES HAVE CHANGED"; + case 0x0D: return"DATA ENCRYPTION CAPABILITIES CHANGED"; + case 0x10: return"TIMESTAMP CHANGED"; + case 0x11: return"DATA ENCRYPTION PARAMETERS CHANGED BY ANOTHER I_T NEXUS"; + case 0x12: return"DATA ENCRYPTION PARAMETERS CHANGED BY VENDOR SPECIFIC EVENT"; + case 0x13: return"DATA ENCRYPTION KEY INSTANCE COUNTER HAS CHANGED"; + case 0x14: return"SA CREATION CAPABILITIES DATA HAS CHANGED"; + case 0x15: return"MEDIUM REMOVAL PREVENTION PREEMPTED"; } break; case 0x2B: switch(ASCQ) { - case 0x00: return "COPY CANNOT EXECUTE SINCE HOST CANNOT DISCONNECT"; + case 0x00: return"COPY CANNOT EXECUTE SINCE HOST CANNOT DISCONNECT"; } break; case 0x2C: switch(ASCQ) { - case 0x00: return "COMMAND SEQUENCE ERROR"; - case 0x01: return "TOO MANY WINDOWS SPECIFIED"; - case 0x02: return "INVALID COMBINATION OF WINDOWS SPECIFIED"; - case 0x03: return "CURRENT PROGRAM AREA IS NOT EMPTY"; - case 0x04: return "CURRENT PROGRAM AREA IS EMPTY"; - case 0x05: return "ILLEGAL POWER CONDITION REQUEST"; - case 0x06: return "PERSISTENT PREVENT CONFLICT"; - case 0x07: return "PREVIOUS BUSY STATUS"; - case 0x08: return "PREVIOUS TASK SET FULL STATUS"; - case 0x09: return "PREVIOUS RESERVATION CONFLICT STATUS"; - case 0x0A: return "PARTITION OR COLLECTION CONTAINS USER OBJECTS"; - case 0x0B: return "NOT RESERVED"; - case 0x0C: return "ORWRITE GENERATION DOES NOT MATCH"; - case 0x0D: return "RESET WRITE POINTER NOT ALLOWED"; - case 0x0E: return "ZONE IS OFFLINE"; - case 0x0F: return "STREAM NOT OPEN"; - case 0x10: return "UNWRITTEN DATA IN ZONE"; + case 0x00: return"COMMAND SEQUENCE ERROR"; + case 0x01: return"TOO MANY WINDOWS SPECIFIED"; + case 0x02: return"INVALID COMBINATION OF WINDOWS SPECIFIED"; + case 0x03: return"CURRENT PROGRAM AREA IS NOT EMPTY"; + case 0x04: return"CURRENT PROGRAM AREA IS EMPTY"; + case 0x05: return"ILLEGAL POWER CONDITION REQUEST"; + case 0x06: return"PERSISTENT PREVENT CONFLICT"; + case 0x07: return"PREVIOUS BUSY STATUS"; + case 0x08: return"PREVIOUS TASK SET FULL STATUS"; + case 0x09: return"PREVIOUS RESERVATION CONFLICT STATUS"; + case 0x0A: return"PARTITION OR COLLECTION CONTAINS USER OBJECTS"; + case 0x0B: return"NOT RESERVED"; + case 0x0C: return"ORWRITE GENERATION DOES NOT MATCH"; + case 0x0D: return"RESET WRITE POINTER NOT ALLOWED"; + case 0x0E: return"ZONE IS OFFLINE"; + case 0x0F: return"STREAM NOT OPEN"; + case 0x10: return"UNWRITTEN DATA IN ZONE"; } break; case 0x2D: switch(ASCQ) { - case 0x00: return "OVERWRITE ERROR ON UPDATE IN PLACE"; + case 0x00: return"OVERWRITE ERROR ON UPDATE IN PLACE"; } break; case 0x2E: switch(ASCQ) { - case 0x00: return "INSUFFICIENT TIME FOR OPERATION"; - case 0x01: return "COMMAND TIMEOUT BEFORE PROCESSING"; - case 0x02: return "COMMAND TIMEOUT DURING PROCESSING"; - case 0x03: return "COMMAND TIMEOUT DURING PROCESSING DUE TO ERROR RECOVERY"; + case 0x00: return"INSUFFICIENT TIME FOR OPERATION"; + case 0x01: return"COMMAND TIMEOUT BEFORE PROCESSING"; + case 0x02: return"COMMAND TIMEOUT DURING PROCESSING"; + case 0x03: return"COMMAND TIMEOUT DURING PROCESSING DUE TO ERROR RECOVERY"; } break; case 0x2F: switch(ASCQ) { - case 0x00: return "COMMANDS CLEARED BY ANOTHER INITIATOR"; - case 0x01: return "COMMANDS CLEARED BY POWER LOSS NOTIFICATION"; - case 0x02: return "COMMANDS CLEARED BY DEVICE SERVER"; - case 0x03: return "SOME COMMANDS CLEARED BY QUEUING LAYER EVENT"; + case 0x00: return"COMMANDS CLEARED BY ANOTHER INITIATOR"; + case 0x01: return"COMMANDS CLEARED BY POWER LOSS NOTIFICATION"; + case 0x02: return"COMMANDS CLEARED BY DEVICE SERVER"; + case 0x03: return"SOME COMMANDS CLEARED BY QUEUING LAYER EVENT"; } break; case 0x30: switch(ASCQ) { - case 0x00: return "INCOMPATIBLE MEDIUM INSTALLED"; - case 0x01: return "CANNOT READ MEDIUM - UNKNOWN FORMAT"; - case 0x02: return "CANNOT READ MEDIUM - INCOMPATIBLE FORMAT"; - case 0x03: return "CLEANING CARTRIDGE INSTALLED"; - case 0x04: return "CANNOT WRITE MEDIUM - UNKNOWN FORMAT"; - case 0x05: return "CANNOT WRITE MEDIUM - INCOMPATIBLE FORMAT"; - case 0x06: return "CANNOT FORMAT MEDIUM - INCOMPATIBLE MEDIUM"; - case 0x07: return "CLEANING FAILURE"; - case 0x08: return "CANNOT WRITE - APPLICATION CODE MISMATCH"; - case 0x09: return "CURRENT SESSION NOT FIXATED FOR APPEND"; - case 0x0A: return "CLEANING REQUEST REJECTED"; - case 0x0C: return "WORM MEDIUM - OVERWRITE ATTEMPTED"; - case 0x0D: return "WORM MEDIUM - INTEGRITY CHECK"; - case 0x10: return "MEDIUM NOT FORMATTED"; - case 0x11: return "INCOMPATIBLE VOLUME TYPE"; - case 0x12: return "INCOMPATIBLE VOLUME QUALIFIER"; - case 0x13: return "CLEANING VOLUME EXPIRED"; + case 0x00: return"INCOMPATIBLE MEDIUM INSTALLED"; + case 0x01: return"CANNOT READ MEDIUM - UNKNOWN FORMAT"; + case 0x02: return"CANNOT READ MEDIUM - INCOMPATIBLE FORMAT"; + case 0x03: return"CLEANING CARTRIDGE INSTALLED"; + case 0x04: return"CANNOT WRITE MEDIUM - UNKNOWN FORMAT"; + case 0x05: return"CANNOT WRITE MEDIUM - INCOMPATIBLE FORMAT"; + case 0x06: return"CANNOT FORMAT MEDIUM - INCOMPATIBLE MEDIUM"; + case 0x07: return"CLEANING FAILURE"; + case 0x08: return"CANNOT WRITE - APPLICATION CODE MISMATCH"; + case 0x09: return"CURRENT SESSION NOT FIXATED FOR APPEND"; + case 0x0A: return"CLEANING REQUEST REJECTED"; + case 0x0C: return"WORM MEDIUM - OVERWRITE ATTEMPTED"; + case 0x0D: return"WORM MEDIUM - INTEGRITY CHECK"; + case 0x10: return"MEDIUM NOT FORMATTED"; + case 0x11: return"INCOMPATIBLE VOLUME TYPE"; + case 0x12: return"INCOMPATIBLE VOLUME QUALIFIER"; + case 0x13: return"CLEANING VOLUME EXPIRED"; } break; case 0x31: switch(ASCQ) { - case 0x00: return "MEDIUM FORMAT CORRUPTED"; - case 0x01: return "FORMAT COMMAND FAILED"; - case 0x02: return "ZONED FORMATTING FAILED DUE TO SPARE LINKING"; - case 0x03: return "SANITIZE COMMAND FAILED"; + case 0x00: return"MEDIUM FORMAT CORRUPTED"; + case 0x01: return"FORMAT COMMAND FAILED"; + case 0x02: return"ZONED FORMATTING FAILED DUE TO SPARE LINKING"; + case 0x03: return"SANITIZE COMMAND FAILED"; } break; case 0x32: switch(ASCQ) { - case 0x00: return "NO DEFECT SPARE LOCATION AVAILABLE"; - case 0x01: return "DEFECT LIST UPDATE FAILURE"; + case 0x00: return"NO DEFECT SPARE LOCATION AVAILABLE"; + case 0x01: return"DEFECT LIST UPDATE FAILURE"; } break; case 0x33: switch(ASCQ) { - case 0x00: return "TAPE LENGTH ERROR"; + case 0x00: return"TAPE LENGTH ERROR"; } break; case 0x34: switch(ASCQ) { - case 0x00: return "ENCLOSURE FAILURE"; + case 0x00: return"ENCLOSURE FAILURE"; } break; case 0x35: switch(ASCQ) { - case 0x00: return "ENCLOSURE SERVICES FAILURE"; - case 0x01: return "UNSUPPORTED ENCLOSURE FUNCTION"; - case 0x02: return "ENCLOSURE SERVICES UNAVAILABLE"; - case 0x03: return "ENCLOSURE SERVICES TRANSFER FAILURE"; - case 0x04: return "ENCLOSURE SERVICES TRANSFER REFUSED"; - case 0x05: return "ENCLOSURE SERVICES CHECKSUM ERROR"; + case 0x00: return"ENCLOSURE SERVICES FAILURE"; + case 0x01: return"UNSUPPORTED ENCLOSURE FUNCTION"; + case 0x02: return"ENCLOSURE SERVICES UNAVAILABLE"; + case 0x03: return"ENCLOSURE SERVICES TRANSFER FAILURE"; + case 0x04: return"ENCLOSURE SERVICES TRANSFER REFUSED"; + case 0x05: return"ENCLOSURE SERVICES CHECKSUM ERROR"; } break; case 0x36: switch(ASCQ) { - case 0x00: return "RIBBON, INK, OR TONER FAILURE"; + case 0x00: return"RIBBON, INK, OR TONER FAILURE"; } break; case 0x37: switch(ASCQ) { - case 0x00: return "ROUNDED PARAMETER"; + case 0x00: return"ROUNDED PARAMETER"; } break; case 0x38: switch(ASCQ) { - case 0x00: return "EVENT STATUS NOTIFICATION"; - case 0x02: return "ESN - POWER MANAGEMENT CLASS EVENT"; - case 0x04: return "ESN - MEDIA CLASS EVENT"; - case 0x06: return "ESN - DEVICE BUSY CLASS EVENT"; - case 0x07: return "THIN PROVISIONING SOFT THRESHOLD REACHED"; + case 0x00: return"EVENT STATUS NOTIFICATION"; + case 0x02: return"ESN - POWER MANAGEMENT CLASS EVENT"; + case 0x04: return"ESN - MEDIA CLASS EVENT"; + case 0x06: return"ESN - DEVICE BUSY CLASS EVENT"; + case 0x07: return"THIN PROVISIONING SOFT THRESHOLD REACHED"; } break; case 0x39: switch(ASCQ) { - case 0x00: return "SAVING PARAMETERS NOT SUPPORTED"; + case 0x00: return"SAVING PARAMETERS NOT SUPPORTED"; } break; case 0x3A: switch(ASCQ) { - case 0x00: return "MEDIUM NOT PRESENT"; - case 0x01: return "MEDIUM NOT PRESENT - TRAY CLOSED"; - case 0x02: return "MEDIUM NOT PRESENT - TRAY OPEN"; - case 0x03: return "MEDIUM NOT PRESENT - LOADABLE"; - case 0x04: return "MEDIUM NOT PRESENT - MEDIUM AUXILIARY MEMORY ACCESSIBLE"; + case 0x00: return"MEDIUM NOT PRESENT"; + case 0x01: return"MEDIUM NOT PRESENT - TRAY CLOSED"; + case 0x02: return"MEDIUM NOT PRESENT - TRAY OPEN"; + case 0x03: return"MEDIUM NOT PRESENT - LOADABLE"; + case 0x04: return"MEDIUM NOT PRESENT - MEDIUM AUXILIARY MEMORY ACCESSIBLE"; } break; case 0x3B: switch(ASCQ) { - case 0x00: return "SEQUENTIAL POSITIONING ERROR"; - case 0x01: return "TAPE POSITION ERROR AT BEGINNING-OF-MEDIUM"; - case 0x02: return "TAPE POSITION ERROR AT END-OF-MEDIUM"; - case 0x03: return "TAPE OR ELECTRONIC VERTICAL FORMS UNIT NOT READY"; - case 0x04: return "SLEW FAILURE"; - case 0x05: return "PAPER JAM"; - case 0x06: return "FAILED TO SENSE TOP-OF-FORM"; - case 0x07: return "FAILED TO SENSE BOTTOM-OF-FORM"; - case 0x08: return "REPOSITION ERROR"; - case 0x09: return "READ PAST END OF MEDIUM"; - case 0x0A: return "READ PAST BEGINNING OF MEDIUM"; - case 0x0B: return "POSITION PAST END OF MEDIUM"; - case 0x0C: return "POSITION PAST BEGINNING OF MEDIUM"; - case 0x0D: return "MEDIUM DESTINATION ELEMENT FULL"; - case 0x0E: return "MEDIUM SOURCE ELEMENT EMPTY"; - case 0x0F: return "END OF MEDIUM REACHED"; - case 0x11: return "MEDIUM MAGAZINE NOT ACCESSIBLE"; - case 0x12: return "MEDIUM MAGAZINE REMOVED"; - case 0x13: return "MEDIUM MAGAZINE INSERTED"; - case 0x14: return "MEDIUM MAGAZINE LOCKED"; - case 0x15: return "MEDIUM MAGAZINE UNLOCKED"; - case 0x16: return "MECHANICAL POSITIONING OR CHANGER ERROR"; - case 0x17: return "READ PAST END OF USER OBJECT"; - case 0x18: return "ELEMENT DISABLED"; - case 0x19: return "ELEMENT ENABLED"; - case 0x1A: return "DATA TRANSFER DEVICE REMOVED"; - case 0x1B: return "DATA TRANSFER DEVICE INSERTED"; - case 0x1C: return "TOO MANY LOGICAL OBJECTS ON PARTITION TO SUPPORT OPERATION"; + case 0x00: return"SEQUENTIAL POSITIONING ERROR"; + case 0x01: return"TAPE POSITION ERROR AT BEGINNING-OF-MEDIUM"; + case 0x02: return"TAPE POSITION ERROR AT END-OF-MEDIUM"; + case 0x03: return"TAPE OR ELECTRONIC VERTICAL FORMS UNIT NOT READY"; + case 0x04: return"SLEW FAILURE"; + case 0x05: return"PAPER JAM"; + case 0x06: return"FAILED TO SENSE TOP-OF-FORM"; + case 0x07: return"FAILED TO SENSE BOTTOM-OF-FORM"; + case 0x08: return"REPOSITION ERROR"; + case 0x09: return"READ PAST END OF MEDIUM"; + case 0x0A: return"READ PAST BEGINNING OF MEDIUM"; + case 0x0B: return"POSITION PAST END OF MEDIUM"; + case 0x0C: return"POSITION PAST BEGINNING OF MEDIUM"; + case 0x0D: return"MEDIUM DESTINATION ELEMENT FULL"; + case 0x0E: return"MEDIUM SOURCE ELEMENT EMPTY"; + case 0x0F: return"END OF MEDIUM REACHED"; + case 0x11: return"MEDIUM MAGAZINE NOT ACCESSIBLE"; + case 0x12: return"MEDIUM MAGAZINE REMOVED"; + case 0x13: return"MEDIUM MAGAZINE INSERTED"; + case 0x14: return"MEDIUM MAGAZINE LOCKED"; + case 0x15: return"MEDIUM MAGAZINE UNLOCKED"; + case 0x16: return"MECHANICAL POSITIONING OR CHANGER ERROR"; + case 0x17: return"READ PAST END OF USER OBJECT"; + case 0x18: return"ELEMENT DISABLED"; + case 0x19: return"ELEMENT ENABLED"; + case 0x1A: return"DATA TRANSFER DEVICE REMOVED"; + case 0x1B: return"DATA TRANSFER DEVICE INSERTED"; + case 0x1C: return"TOO MANY LOGICAL OBJECTS ON PARTITION TO SUPPORT OPERATION"; } break; case 0x3D: switch(ASCQ) { - case 0x00: return "INVALID BITS IN IDENTIFY MESSAGE"; + case 0x00: return"INVALID BITS IN IDENTIFY MESSAGE"; } break; case 0x3E: switch(ASCQ) { - case 0x00: return "LOGICAL UNIT HAS NOT SELF-CONFIGURED YET"; - case 0x01: return "LOGICAL UNIT FAILURE"; - case 0x02: return "TIMEOUT ON LOGICAL UNIT"; - case 0x03: return "LOGICAL UNIT FAILED SELF-TEST"; - case 0x04: return "LOGICAL UNIT UNABLE TO UPDATE SELF-TEST LOG"; + case 0x00: return"LOGICAL UNIT HAS NOT SELF-CONFIGURED YET"; + case 0x01: return"LOGICAL UNIT FAILURE"; + case 0x02: return"TIMEOUT ON LOGICAL UNIT"; + case 0x03: return"LOGICAL UNIT FAILED SELF-TEST"; + case 0x04: return"LOGICAL UNIT UNABLE TO UPDATE SELF-TEST LOG"; } break; case 0x3F: switch(ASCQ) { - case 0x00: return "TARGET OPERATING CONDITIONS HAVE CHANGED"; - case 0x01: return "MICROCODE HAS BEEN CHANGED"; - case 0x02: return "CHANGED OPERATING DEFINITION"; - case 0x03: return "INQUIRY DATA HAS CHANGED"; - case 0x04: return "COMPONENT DEVICE ATTACHED"; - case 0x05: return "DEVICE IDENTIFIED CHANGED"; - case 0x06: return "REDUNDANCY GROUP CREATED OR MODIFIED"; - case 0x07: return "REDUNDANCY GROUP DELETED"; - case 0x08: return "SPARE CREATED OR MODIFIED"; - case 0x09: return "SPARE DELETED"; - case 0x0A: return "VOLUME SET CREATED OR MODIFIED"; - case 0x0B: return "VOLUME SET DELETED"; - case 0x0C: return "VOLUME SET DEASSIGNED"; - case 0x0D: return "VOLUME SET REASSIGNED"; - case 0x0E: return "REPORTED LUNS DATA HAS CHANGED"; - case 0x0F: return "ECHO BUFFER OVERWRITTEN"; - case 0x10: return "MEDIUM LOADABLE"; - case 0x11: return "MEDIUM AUXILIARY MEMORY ACCESSIBLE"; - case 0x12: return "iSCSI IP ADDRESS ADDED"; - case 0x13: return "iSCSI IP ADDRESS REMOVED"; - case 0x14: return "iSCSI IP ADDRESS CHANGED"; - case 0x15: return "INSPECT REFERRALS SENSE DESCRIPTORS"; - case 0x16: return "MICROCODE HAS BEEN CHANGED WITHOUT RESET"; - case 0x17: return "ZONE TRANSITION TO FULL"; + case 0x00: return"TARGET OPERATING CONDITIONS HAVE CHANGED"; + case 0x01: return"MICROCODE HAS BEEN CHANGED"; + case 0x02: return"CHANGED OPERATING DEFINITION"; + case 0x03: return"INQUIRY DATA HAS CHANGED"; + case 0x04: return"COMPONENT DEVICE ATTACHED"; + case 0x05: return"DEVICE IDENTIFIED CHANGED"; + case 0x06: return"REDUNDANCY GROUP CREATED OR MODIFIED"; + case 0x07: return"REDUNDANCY GROUP DELETED"; + case 0x08: return"SPARE CREATED OR MODIFIED"; + case 0x09: return"SPARE DELETED"; + case 0x0A: return"VOLUME SET CREATED OR MODIFIED"; + case 0x0B: return"VOLUME SET DELETED"; + case 0x0C: return"VOLUME SET DEASSIGNED"; + case 0x0D: return"VOLUME SET REASSIGNED"; + case 0x0E: return"REPORTED LUNS DATA HAS CHANGED"; + case 0x0F: return"ECHO BUFFER OVERWRITTEN"; + case 0x10: return"MEDIUM LOADABLE"; + case 0x11: return"MEDIUM AUXILIARY MEMORY ACCESSIBLE"; + case 0x12: return"iSCSI IP ADDRESS ADDED"; + case 0x13: return"iSCSI IP ADDRESS REMOVED"; + case 0x14: return"iSCSI IP ADDRESS CHANGED"; + case 0x15: return"INSPECT REFERRALS SENSE DESCRIPTORS"; + case 0x16: return"MICROCODE HAS BEEN CHANGED WITHOUT RESET"; + case 0x17: return"ZONE TRANSITION TO FULL"; } break; case 0x40: switch(ASCQ) { - case 0x00: return "RAM FAILURE"; - default: return $"DIAGNOSTIC FAILURE ON COMPONENT {ASCQ:X2}h"; + case 0x00: return"RAM FAILURE"; + default: return$"DIAGNOSTIC FAILURE ON COMPONENT {ASCQ:X2}h"; } case 0x41: switch(ASCQ) { - case 0x00: return "DATA PATH FAILURE"; + case 0x00: return"DATA PATH FAILURE"; } break; case 0x42: switch(ASCQ) { - case 0x00: return "POWER-ON OR SELF-TEST FAILURE"; + case 0x00: return"POWER-ON OR SELF-TEST FAILURE"; } break; case 0x43: switch(ASCQ) { - case 0x00: return "MESSAGE ERROR"; + case 0x00: return"MESSAGE ERROR"; } break; case 0x44: switch(ASCQ) { - case 0x00: return "INTERNAL TARGET FAILURE"; - case 0x01: return "PERSISTENT RESERVATION INFORMATION LOST"; - case 0x71: return "ATA DEVICE FAILED SET FEATURES"; + case 0x00: return"INTERNAL TARGET FAILURE"; + case 0x01: return"PERSISTENT RESERVATION INFORMATION LOST"; + case 0x71: return"ATA DEVICE FAILED SET FEATURES"; } break; case 0x45: switch(ASCQ) { - case 0x00: return "SELECT OR RESELECT FAILURE"; + case 0x00: return"SELECT OR RESELECT FAILURE"; } break; case 0x46: switch(ASCQ) { - case 0x00: return "UNSUCCESSFUL SOFT RESET"; + case 0x00: return"UNSUCCESSFUL SOFT RESET"; } break; case 0x47: switch(ASCQ) { - case 0x00: return "SCSI PARITY ERROR"; - case 0x01: return "DATA PHASE CRC ERROR DETECTED"; - case 0x02: return "SCSI PARITY ERROR DETECTED DURING ST DATA PHASE"; - case 0x03: return "INFORMATION UNIT iuCRC ERROR DETECTED"; - case 0x04: return "ASYNCHRONOUS INFORMATION PROTECTION ERROR DETECTED"; - case 0x05: return "PROTOCOL SERVICE CRC ERROR"; - case 0x06: return "PHY TEST FUNCTION IN PROGRESS"; - case 0x7F: return "SOME COMMANDS CLEARED BY iSCSI PROTOCOL EVENT"; + case 0x00: return"SCSI PARITY ERROR"; + case 0x01: return"DATA PHASE CRC ERROR DETECTED"; + case 0x02: return"SCSI PARITY ERROR DETECTED DURING ST DATA PHASE"; + case 0x03: return"INFORMATION UNIT iuCRC ERROR DETECTED"; + case 0x04: return"ASYNCHRONOUS INFORMATION PROTECTION ERROR DETECTED"; + case 0x05: return"PROTOCOL SERVICE CRC ERROR"; + case 0x06: return"PHY TEST FUNCTION IN PROGRESS"; + case 0x7F: return"SOME COMMANDS CLEARED BY iSCSI PROTOCOL EVENT"; } break; case 0x48: switch(ASCQ) { - case 0x00: return "INITIATOR DETECTED ERROR MESSAGE RECEIVED"; + case 0x00: return"INITIATOR DETECTED ERROR MESSAGE RECEIVED"; } break; case 0x49: switch(ASCQ) { - case 0x00: return "INVALID MESSAGE ERROR"; + case 0x00: return"INVALID MESSAGE ERROR"; } break; case 0x4A: switch(ASCQ) { - case 0x00: return "COMMAND PHASE ERROR"; + case 0x00: return"COMMAND PHASE ERROR"; } break; case 0x4B: switch(ASCQ) { - case 0x00: return "DATA PHASE ERROR"; - case 0x01: return "INVALID TARGET PORT TRANSFER TAG RECEIVED"; - case 0x02: return "TOO MUCH WRITE DATA"; - case 0x03: return "ACK/NAK TIMEOUT"; - case 0x04: return "NAK RECEIVED"; - case 0x05: return "DATA OFFSET ERROR"; - case 0x06: return "INITIATOR RESPONSE TIMEOUT"; - case 0x07: return "CONNECTION LOST"; - case 0x08: return "DATA-IN BUFFER OVERFLOW - DATA BUFFER SIZE"; - case 0x09: return "DATA-IN BUFFER OVERFLOW - DATA BUFFER DESCRIPTOR AREA"; - case 0x0A: return "DATA-IN BUFFER ERROR"; - case 0x0B: return "DATA-OUT BUFFER OVERFLOW - DATA BUFFER SIZE"; - case 0x0C: return "DATA-OUT BUFFER OVERFLOW - DATA BUFFER DESCRIPTOR AREA"; - case 0x0D: return "DATA-OUT BUFFER ERROR"; - case 0x0E: return "PCIe FABRIC ERROR"; - case 0x0F: return "PCIe COMPLETION TIMEOUT"; - case 0x10: return "PCIe COMPLETION ABORT"; - case 0x11: return "PCIe POISONED TLP RECEIVED"; - case 0x12: return "PCIe ECRC CHECK FAILED"; - case 0x13: return "PCIe UNSUPPORTED REQUEST"; - case 0x14: return "PCIe ACS VIOLATION"; - case 0x15: return "PCIe TLP PREFIX BLOCKED"; + case 0x00: return"DATA PHASE ERROR"; + case 0x01: return"INVALID TARGET PORT TRANSFER TAG RECEIVED"; + case 0x02: return"TOO MUCH WRITE DATA"; + case 0x03: return"ACK/NAK TIMEOUT"; + case 0x04: return"NAK RECEIVED"; + case 0x05: return"DATA OFFSET ERROR"; + case 0x06: return"INITIATOR RESPONSE TIMEOUT"; + case 0x07: return"CONNECTION LOST"; + case 0x08: return"DATA-IN BUFFER OVERFLOW - DATA BUFFER SIZE"; + case 0x09: return"DATA-IN BUFFER OVERFLOW - DATA BUFFER DESCRIPTOR AREA"; + case 0x0A: return"DATA-IN BUFFER ERROR"; + case 0x0B: return"DATA-OUT BUFFER OVERFLOW - DATA BUFFER SIZE"; + case 0x0C: return"DATA-OUT BUFFER OVERFLOW - DATA BUFFER DESCRIPTOR AREA"; + case 0x0D: return"DATA-OUT BUFFER ERROR"; + case 0x0E: return"PCIe FABRIC ERROR"; + case 0x0F: return"PCIe COMPLETION TIMEOUT"; + case 0x10: return"PCIe COMPLETION ABORT"; + case 0x11: return"PCIe POISONED TLP RECEIVED"; + case 0x12: return"PCIe ECRC CHECK FAILED"; + case 0x13: return"PCIe UNSUPPORTED REQUEST"; + case 0x14: return"PCIe ACS VIOLATION"; + case 0x15: return"PCIe TLP PREFIX BLOCKED"; } break; case 0x4C: switch(ASCQ) { - case 0x00: return "LOGICAL UNIT FAILED SELF-CONFIGURATION"; + case 0x00: return"LOGICAL UNIT FAILED SELF-CONFIGURATION"; } break; - case 0x4E: return $"OVERLAPPED COMMANDS ATTEMPTED FOR TASK TAG {ASCQ:X2}h"; + case 0x4E: return$"OVERLAPPED COMMANDS ATTEMPTED FOR TASK TAG {ASCQ:X2}h"; case 0x50: switch(ASCQ) { - case 0x00: return "WRITE APPEND ERROR"; - case 0x01: return "WRITE APPEND POSITION ERROR"; - case 0x02: return "POSITION ERROR RELATED TO TIMING"; + case 0x00: return"WRITE APPEND ERROR"; + case 0x01: return"WRITE APPEND POSITION ERROR"; + case 0x02: return"POSITION ERROR RELATED TO TIMING"; } break; case 0x51: switch(ASCQ) { - case 0x00: return "ERASE FAILURE"; - case 0x01: return "ERASE FAILURE - INCOMPLETE ERASE OPERATION DETECTED"; + case 0x00: return"ERASE FAILURE"; + case 0x01: return"ERASE FAILURE - INCOMPLETE ERASE OPERATION DETECTED"; } break; case 0x52: switch(ASCQ) { - case 0x00: return "CARTRIDGE FAULT"; + case 0x00: return"CARTRIDGE FAULT"; } break; case 0x53: switch(ASCQ) { - case 0x00: return "MEDIA LOAD OR EJECT FAILED"; - case 0x01: return "UNLOAD TAPE FAILURE"; - case 0x02: return "MEDIUM REMOVAL PREVENTED"; - case 0x03: return "MEDIUM REMOVAL PREVENTED BY DATA TRANSFER ELEMENT"; - case 0x04: return "MEDIUM THREAD OR UNTHREAD FAILURE"; - case 0x05: return "VOLUME IDENTIFIER INVALID"; - case 0x06: return "VOLUME IDENTIFIED MISSING"; - case 0x07: return "DUPLICATE VOLUME IDENTIFIER"; - case 0x08: return "ELEMENT STATUS UNKNOWN"; - case 0x09: return "DATA TRANSFER DEVICE ERROR - LOAD FAILED"; - case 0x0A: return "DATA TRANSFER DEVICE ERROR - UNLOAD FAILED"; - case 0x0B: return "DATA TRANSFER DEVICE ERROR - UNLOAD MISSING"; - case 0x0C: return "DATA TRANSFER DEVICE ERROR - EJECT FAILED"; - case 0x0D: return "DATA TRANSFER DEVICE ERROR - LIBRARY COMMUNICATION FAILED"; + case 0x00: return"MEDIA LOAD OR EJECT FAILED"; + case 0x01: return"UNLOAD TAPE FAILURE"; + case 0x02: return"MEDIUM REMOVAL PREVENTED"; + case 0x03: return"MEDIUM REMOVAL PREVENTED BY DATA TRANSFER ELEMENT"; + case 0x04: return"MEDIUM THREAD OR UNTHREAD FAILURE"; + case 0x05: return"VOLUME IDENTIFIER INVALID"; + case 0x06: return"VOLUME IDENTIFIED MISSING"; + case 0x07: return"DUPLICATE VOLUME IDENTIFIER"; + case 0x08: return"ELEMENT STATUS UNKNOWN"; + case 0x09: return"DATA TRANSFER DEVICE ERROR - LOAD FAILED"; + case 0x0A: return"DATA TRANSFER DEVICE ERROR - UNLOAD FAILED"; + case 0x0B: return"DATA TRANSFER DEVICE ERROR - UNLOAD MISSING"; + case 0x0C: return"DATA TRANSFER DEVICE ERROR - EJECT FAILED"; + case 0x0D: return"DATA TRANSFER DEVICE ERROR - LIBRARY COMMUNICATION FAILED"; } break; case 0x54: switch(ASCQ) { - case 0x00: return "SCSI TO HOST SYSTEM INTERFACE FAILURE"; + case 0x00: return"SCSI TO HOST SYSTEM INTERFACE FAILURE"; } break; case 0x55: switch(ASCQ) { - case 0x00: return "SYSTEM RESOURCE FAILURE"; - case 0x01: return "SYSTEM BUFFER FULL"; - case 0x02: return "INSUFFICIENT RESERVATION RESOURCES"; - case 0x03: return "INSUFFICIENT RESOURCES"; - case 0x04: return "INSUFFICIENT REGISTRATION RESOURCES"; - case 0x05: return "INSUFFICIENT ACCESS CONTROL RESOURCES"; - case 0x06: return "AUXILIARY MEMORY OUT OF SPACE"; - case 0x07: return "QUOTA ERROR"; - case 0x08: return "MAXIMUM NUMBER OF SUPPLEMENTAL DECRYPTION KEYS EXCEEDED"; - case 0x09: return "MEDIUM AUXILIARY MEMORY NOT ACCESSIBLE"; - case 0x0A: return "DATA CURRENTLY UNAVAILABLE"; - case 0x0B: return "INSUFFICIENT POWER FOR OPERATION"; - case 0x0C: return "INSUFFICIENT RESOURCES TO CREATE ROD"; - case 0x0D: return "INSUFFICIENT RESOURCES TO CREATE ROD TOKEN"; - case 0x0E: return "INSUFFICIENT ZONE RESOURCES"; - case 0x0F: return "INSUFFICIENT ZONE RESOURCES TO COMPLETE WRITE"; - case 0x10: return "MAXIMUM NUMBER OF STREAMS OPEN"; + case 0x00: return"SYSTEM RESOURCE FAILURE"; + case 0x01: return"SYSTEM BUFFER FULL"; + case 0x02: return"INSUFFICIENT RESERVATION RESOURCES"; + case 0x03: return"INSUFFICIENT RESOURCES"; + case 0x04: return"INSUFFICIENT REGISTRATION RESOURCES"; + case 0x05: return"INSUFFICIENT ACCESS CONTROL RESOURCES"; + case 0x06: return"AUXILIARY MEMORY OUT OF SPACE"; + case 0x07: return"QUOTA ERROR"; + case 0x08: return"MAXIMUM NUMBER OF SUPPLEMENTAL DECRYPTION KEYS EXCEEDED"; + case 0x09: return"MEDIUM AUXILIARY MEMORY NOT ACCESSIBLE"; + case 0x0A: return"DATA CURRENTLY UNAVAILABLE"; + case 0x0B: return"INSUFFICIENT POWER FOR OPERATION"; + case 0x0C: return"INSUFFICIENT RESOURCES TO CREATE ROD"; + case 0x0D: return"INSUFFICIENT RESOURCES TO CREATE ROD TOKEN"; + case 0x0E: return"INSUFFICIENT ZONE RESOURCES"; + case 0x0F: return"INSUFFICIENT ZONE RESOURCES TO COMPLETE WRITE"; + case 0x10: return"MAXIMUM NUMBER OF STREAMS OPEN"; } break; case 0x57: switch(ASCQ) { - case 0x00: return "UNABLE TO RECOVER TABLE-OF-CONTENTS"; + case 0x00: return"UNABLE TO RECOVER TABLE-OF-CONTENTS"; } break; case 0x58: switch(ASCQ) { - case 0x00: return "GENERATION DOES NOT EXIST"; + case 0x00: return"GENERATION DOES NOT EXIST"; } break; case 0x59: switch(ASCQ) { - case 0x00: return "UPDATED BLOCK READ"; + case 0x00: return"UPDATED BLOCK READ"; } break; case 0x5A: switch(ASCQ) { - case 0x00: return "OPERATOR REQUEST OR STATE CHANGE INPUT"; - case 0x01: return "OPERATOR MEDIUM REMOVAL REQUEST"; - case 0x02: return "OPERATOR SELECTED WRITE PROTECT"; - case 0x03: return "OPERATOR SELECTED WRITE PERMIT"; + case 0x00: return"OPERATOR REQUEST OR STATE CHANGE INPUT"; + case 0x01: return"OPERATOR MEDIUM REMOVAL REQUEST"; + case 0x02: return"OPERATOR SELECTED WRITE PROTECT"; + case 0x03: return"OPERATOR SELECTED WRITE PERMIT"; } break; case 0x5B: switch(ASCQ) { - case 0x00: return "LOG EXCEPTION"; - case 0x01: return "THRESHOLD CONDITION MET"; - case 0x02: return "LOG COUNTER AT MAXIMUM"; - case 0x03: return "LOG LIST CODES EXHAUSTED"; + case 0x00: return"LOG EXCEPTION"; + case 0x01: return"THRESHOLD CONDITION MET"; + case 0x02: return"LOG COUNTER AT MAXIMUM"; + case 0x03: return"LOG LIST CODES EXHAUSTED"; } break; case 0x5C: switch(ASCQ) { - case 0x00: return "RPL STATUS CHANGE"; - case 0x01: return "SPINDLES SYNCHRONIZED"; - case 0x02: return "SPINDLES NOT SYNCHRONIZED"; - case 0x03: return "SPARE AREA EXHAUSTION PREDICTION THRESHOLD EXCEEDED"; - case 0x10: return "HARDWARE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE"; - case 0x11: return "HARDWARE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH"; - case 0x12: return "HARDWARE IMPENDING FAILURE DATA ERROR RATE TOO HIGH"; - case 0x13: return "HARDWARE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH"; - case 0x14: return "HARDWARE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS"; - case 0x15: return "HARDWARE IMPENDING FAILURE ACCESS TIME TOO HIGH"; - case 0x16: return "HARDWARE IMPENDING FAILURE START UNIT TIMES TOO HIGH"; - case 0x17: return "HARDWARE IMPENDING FAILURE CHANNEL PARAMETRICS"; - case 0x18: return "HARDWARE IMPENDING FAILURE CONTROLLER DETECTED"; - case 0x19: return "HARDWARE IMPENDING FAILURE THROUGHPUT PERFORMANCE"; - case 0x1A: return "HARDWARE IMPENDING FAILURE SEEK TIME PERFORMANCE"; - case 0x1B: return "HARDWARE IMPENDING FAILURE SPIN-UP RETRY COUNT"; - case 0x1C: return "HARDWARE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT"; - case 0x20: return "CONTROLLER IMPENDING FAILURE GENERAL HARD DRIVE FAILURE"; - case 0x21: return "CONTROLLER IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH"; - case 0x22: return "CONTROLLER IMPENDING FAILURE DATA ERROR RATE TOO HIGH"; - case 0x23: return "CONTROLLER IMPENDING FAILURE SEEK ERROR RATE TOO HIGH"; - case 0x24: return "CONTROLLER IMPENDING FAILURE TOO MANY BLOCK REASSIGNS"; - case 0x25: return "CONTROLLER IMPENDING FAILURE ACCESS TIME TOO HIGH"; - case 0x26: return "CONTROLLER IMPENDING FAILURE START UNIT TIMES TOO HIGH"; - case 0x27: return "CONTROLLER IMPENDING FAILURE CHANNEL PARAMETRICS"; - case 0x28: return "CONTROLLER IMPENDING FAILURE CONTROLLER DETECTED"; - case 0x29: return "CONTROLLER IMPENDING FAILURE THROUGHPUT PERFORMANCE"; - case 0x2A: return "CONTROLLER IMPENDING FAILURE SEEK TIME PERFORMANCE"; - case 0x2B: return "CONTROLLER IMPENDING FAILURE SPIN-UP RETRY COUNT"; - case 0x2C: return "CONTROLLER IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT"; - case 0x30: return "DATA CHANNEL IMPENDING FAILURE GENERAL HARD DRIVE FAILURE"; - case 0x31: return "DATA CHANNEL IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH"; - case 0x32: return "DATA CHANNEL IMPENDING FAILURE DATA ERROR RATE TOO HIGH"; - case 0x33: return "DATA CHANNEL IMPENDING FAILURE SEEK ERROR RATE TOO HIGH"; - case 0x34: return "DATA CHANNEL IMPENDING FAILURE TOO MANY BLOCK REASSIGNS"; - case 0x35: return "DATA CHANNEL IMPENDING FAILURE ACCESS TIME TOO HIGH"; - case 0x36: return "DATA CHANNEL IMPENDING FAILURE START UNIT TIMES TOO HIGH"; - case 0x37: return "DATA CHANNEL IMPENDING FAILURE CHANNEL PARAMETRICS"; - case 0x38: return "DATA CHANNEL IMPENDING FAILURE DATA CHANNEL DETECTED"; - case 0x39: return "DATA CHANNEL IMPENDING FAILURE THROUGHPUT PERFORMANCE"; - case 0x3A: return "DATA CHANNEL IMPENDING FAILURE SEEK TIME PERFORMANCE"; - case 0x3B: return "DATA CHANNEL IMPENDING FAILURE SPIN-UP RETRY COUNT"; - case 0x3C: return "DATA CHANNEL IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT"; - case 0x40: return "SERVO IMPENDING FAILURE GENERAL HARD DRIVE FAILURE"; - case 0x41: return "SERVO IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH"; - case 0x42: return "SERVO IMPENDING FAILURE DATA ERROR RATE TOO HIGH"; - case 0x43: return "SERVO IMPENDING FAILURE SEEK ERROR RATE TOO HIGH"; - case 0x44: return "SERVO IMPENDING FAILURE TOO MANY BLOCK REASSIGNS"; - case 0x45: return "SERVO IMPENDING FAILURE ACCESS TIME TOO HIGH"; - case 0x46: return "SERVO IMPENDING FAILURE START UNIT TIMES TOO HIGH"; - case 0x47: return "SERVO IMPENDING FAILURE CHANNEL PARAMETRICS"; - case 0x48: return "SERVO IMPENDING FAILURE SERVO DETECTED"; - case 0x49: return "SERVO IMPENDING FAILURE THROUGHPUT PERFORMANCE"; - case 0x4A: return "SERVO IMPENDING FAILURE SEEK TIME PERFORMANCE"; - case 0x4B: return "SERVO IMPENDING FAILURE SPIN-UP RETRY COUNT"; - case 0x4C: return "SERVO IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT"; - case 0x50: return "SPINDLE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE"; - case 0x51: return "SPINDLE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH"; - case 0x52: return "SPINDLE IMPENDING FAILURE DATA ERROR RATE TOO HIGH"; - case 0x53: return "SPINDLE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH"; - case 0x54: return "SPINDLE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS"; - case 0x55: return "SPINDLE IMPENDING FAILURE ACCESS TIME TOO HIGH"; - case 0x56: return "SPINDLE IMPENDING FAILURE START UNIT TIMES TOO HIGH"; - case 0x57: return "SPINDLE IMPENDING FAILURE CHANNEL PARAMETRICS"; - case 0x58: return "SPINDLE IMPENDING FAILURE SPINDLE DETECTED"; - case 0x59: return "SPINDLE IMPENDING FAILURE THROUGHPUT PERFORMANCE"; - case 0x5A: return "SPINDLE IMPENDING FAILURE SEEK TIME PERFORMANCE"; - case 0x5B: return "SPINDLE IMPENDING FAILURE SPIN-UP RETRY COUNT"; - case 0x5C: return "SPINDLE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT"; - case 0x60: return "FIRMWARE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE"; - case 0x61: return "FIRMWARE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH"; - case 0x62: return "FIRMWARE IMPENDING FAILURE DATA ERROR RATE TOO HIGH"; - case 0x63: return "FIRMWARE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH"; - case 0x64: return "FIRMWARE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS"; - case 0x65: return "FIRMWARE IMPENDING FAILURE ACCESS TIME TOO HIGH"; - case 0x66: return "FIRMWARE IMPENDING FAILURE START UNIT TIMES TOO HIGH"; - case 0x67: return "FIRMWARE IMPENDING FAILURE CHANNEL PARAMETRICS"; - case 0x68: return "FIRMWARE IMPENDING FAILURE FIRMWARE DETECTED"; - case 0x69: return "FIRMWARE IMPENDING FAILURE THROUGHPUT PERFORMANCE"; - case 0x6A: return "FIRMWARE IMPENDING FAILURE SEEK TIME PERFORMANCE"; - case 0x6B: return "FIRMWARE IMPENDING FAILURE SPIN-UP RETRY COUNT"; - case 0x6C: return "FIRMWARE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT"; - case 0xFF: return "FAILURE PREDICTION THRESHOLD EXCEEDED (FALSE)"; + case 0x00: return"RPL STATUS CHANGE"; + case 0x01: return"SPINDLES SYNCHRONIZED"; + case 0x02: return"SPINDLES NOT SYNCHRONIZED"; + case 0x03: return"SPARE AREA EXHAUSTION PREDICTION THRESHOLD EXCEEDED"; + case 0x10: return"HARDWARE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE"; + case 0x11: return"HARDWARE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH"; + case 0x12: return"HARDWARE IMPENDING FAILURE DATA ERROR RATE TOO HIGH"; + case 0x13: return"HARDWARE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH"; + case 0x14: return"HARDWARE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS"; + case 0x15: return"HARDWARE IMPENDING FAILURE ACCESS TIME TOO HIGH"; + case 0x16: return"HARDWARE IMPENDING FAILURE START UNIT TIMES TOO HIGH"; + case 0x17: return"HARDWARE IMPENDING FAILURE CHANNEL PARAMETRICS"; + case 0x18: return"HARDWARE IMPENDING FAILURE CONTROLLER DETECTED"; + case 0x19: return"HARDWARE IMPENDING FAILURE THROUGHPUT PERFORMANCE"; + case 0x1A: return"HARDWARE IMPENDING FAILURE SEEK TIME PERFORMANCE"; + case 0x1B: return"HARDWARE IMPENDING FAILURE SPIN-UP RETRY COUNT"; + case 0x1C: return"HARDWARE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT"; + case 0x20: return"CONTROLLER IMPENDING FAILURE GENERAL HARD DRIVE FAILURE"; + case 0x21: return"CONTROLLER IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH"; + case 0x22: return"CONTROLLER IMPENDING FAILURE DATA ERROR RATE TOO HIGH"; + case 0x23: return"CONTROLLER IMPENDING FAILURE SEEK ERROR RATE TOO HIGH"; + case 0x24: return"CONTROLLER IMPENDING FAILURE TOO MANY BLOCK REASSIGNS"; + case 0x25: return"CONTROLLER IMPENDING FAILURE ACCESS TIME TOO HIGH"; + case 0x26: return"CONTROLLER IMPENDING FAILURE START UNIT TIMES TOO HIGH"; + case 0x27: return"CONTROLLER IMPENDING FAILURE CHANNEL PARAMETRICS"; + case 0x28: return"CONTROLLER IMPENDING FAILURE CONTROLLER DETECTED"; + case 0x29: return"CONTROLLER IMPENDING FAILURE THROUGHPUT PERFORMANCE"; + case 0x2A: return"CONTROLLER IMPENDING FAILURE SEEK TIME PERFORMANCE"; + case 0x2B: return"CONTROLLER IMPENDING FAILURE SPIN-UP RETRY COUNT"; + case 0x2C: return"CONTROLLER IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT"; + case 0x30: return"DATA CHANNEL IMPENDING FAILURE GENERAL HARD DRIVE FAILURE"; + case 0x31: return"DATA CHANNEL IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH"; + case 0x32: return"DATA CHANNEL IMPENDING FAILURE DATA ERROR RATE TOO HIGH"; + case 0x33: return"DATA CHANNEL IMPENDING FAILURE SEEK ERROR RATE TOO HIGH"; + case 0x34: return"DATA CHANNEL IMPENDING FAILURE TOO MANY BLOCK REASSIGNS"; + case 0x35: return"DATA CHANNEL IMPENDING FAILURE ACCESS TIME TOO HIGH"; + case 0x36: return"DATA CHANNEL IMPENDING FAILURE START UNIT TIMES TOO HIGH"; + case 0x37: return"DATA CHANNEL IMPENDING FAILURE CHANNEL PARAMETRICS"; + case 0x38: return"DATA CHANNEL IMPENDING FAILURE DATA CHANNEL DETECTED"; + case 0x39: return"DATA CHANNEL IMPENDING FAILURE THROUGHPUT PERFORMANCE"; + case 0x3A: return"DATA CHANNEL IMPENDING FAILURE SEEK TIME PERFORMANCE"; + case 0x3B: return"DATA CHANNEL IMPENDING FAILURE SPIN-UP RETRY COUNT"; + case 0x3C: return"DATA CHANNEL IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT"; + case 0x40: return"SERVO IMPENDING FAILURE GENERAL HARD DRIVE FAILURE"; + case 0x41: return"SERVO IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH"; + case 0x42: return"SERVO IMPENDING FAILURE DATA ERROR RATE TOO HIGH"; + case 0x43: return"SERVO IMPENDING FAILURE SEEK ERROR RATE TOO HIGH"; + case 0x44: return"SERVO IMPENDING FAILURE TOO MANY BLOCK REASSIGNS"; + case 0x45: return"SERVO IMPENDING FAILURE ACCESS TIME TOO HIGH"; + case 0x46: return"SERVO IMPENDING FAILURE START UNIT TIMES TOO HIGH"; + case 0x47: return"SERVO IMPENDING FAILURE CHANNEL PARAMETRICS"; + case 0x48: return"SERVO IMPENDING FAILURE SERVO DETECTED"; + case 0x49: return"SERVO IMPENDING FAILURE THROUGHPUT PERFORMANCE"; + case 0x4A: return"SERVO IMPENDING FAILURE SEEK TIME PERFORMANCE"; + case 0x4B: return"SERVO IMPENDING FAILURE SPIN-UP RETRY COUNT"; + case 0x4C: return"SERVO IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT"; + case 0x50: return"SPINDLE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE"; + case 0x51: return"SPINDLE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH"; + case 0x52: return"SPINDLE IMPENDING FAILURE DATA ERROR RATE TOO HIGH"; + case 0x53: return"SPINDLE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH"; + case 0x54: return"SPINDLE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS"; + case 0x55: return"SPINDLE IMPENDING FAILURE ACCESS TIME TOO HIGH"; + case 0x56: return"SPINDLE IMPENDING FAILURE START UNIT TIMES TOO HIGH"; + case 0x57: return"SPINDLE IMPENDING FAILURE CHANNEL PARAMETRICS"; + case 0x58: return"SPINDLE IMPENDING FAILURE SPINDLE DETECTED"; + case 0x59: return"SPINDLE IMPENDING FAILURE THROUGHPUT PERFORMANCE"; + case 0x5A: return"SPINDLE IMPENDING FAILURE SEEK TIME PERFORMANCE"; + case 0x5B: return"SPINDLE IMPENDING FAILURE SPIN-UP RETRY COUNT"; + case 0x5C: return"SPINDLE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT"; + case 0x60: return"FIRMWARE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE"; + case 0x61: return"FIRMWARE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH"; + case 0x62: return"FIRMWARE IMPENDING FAILURE DATA ERROR RATE TOO HIGH"; + case 0x63: return"FIRMWARE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH"; + case 0x64: return"FIRMWARE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS"; + case 0x65: return"FIRMWARE IMPENDING FAILURE ACCESS TIME TOO HIGH"; + case 0x66: return"FIRMWARE IMPENDING FAILURE START UNIT TIMES TOO HIGH"; + case 0x67: return"FIRMWARE IMPENDING FAILURE CHANNEL PARAMETRICS"; + case 0x68: return"FIRMWARE IMPENDING FAILURE FIRMWARE DETECTED"; + case 0x69: return"FIRMWARE IMPENDING FAILURE THROUGHPUT PERFORMANCE"; + case 0x6A: return"FIRMWARE IMPENDING FAILURE SEEK TIME PERFORMANCE"; + case 0x6B: return"FIRMWARE IMPENDING FAILURE SPIN-UP RETRY COUNT"; + case 0x6C: return"FIRMWARE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT"; + case 0xFF: return"FAILURE PREDICTION THRESHOLD EXCEEDED (FALSE)"; } break; case 0x5E: switch(ASCQ) { - case 0x00: return "LOW POWER CONDITION ON"; - case 0x01: return "IDLE CONDITION ACTIVATED BY TIMER"; - case 0x02: return "STANDBY CONDITION ACTIVATED BY TIMER"; - case 0x03: return "IDLE CONDITION ACTIVATED BY COMMAND"; - case 0x04: return "STANDBY CONDITION ACTIVATED BY COMMAND"; - case 0x05: return "IDLE_B CONDITION ACTIVATED BY TIMER"; - case 0x06: return "IDLE_B CONDITION ACTIVATED BY COMMAND"; - case 0x07: return "IDLE_C CONDITION ACTIVATED BY TIMER"; - case 0x08: return "IDLE_C CONDITION ACTIVATED BY COMMAND"; - case 0x09: return "STANDBY_Y CONDITION ACTIVATED BY TIMER"; - case 0x0A: return "STANDBY_Y CONDITION ACTIVATED BY COMMAND"; - case 0x41: return "POWER STATE CHANGED TO ACTIVE"; - case 0x42: return "POWER STATE CHANGED TO IDLE"; - case 0x43: return "POWER STATE CHANGED TO STANDBY"; - case 0x45: return "POWER STATE CHANGED TO SLEEP"; - case 0x47: return "POWER STATE CHANGED TO DEVICE CONTROL"; + case 0x00: return"LOW POWER CONDITION ON"; + case 0x01: return"IDLE CONDITION ACTIVATED BY TIMER"; + case 0x02: return"STANDBY CONDITION ACTIVATED BY TIMER"; + case 0x03: return"IDLE CONDITION ACTIVATED BY COMMAND"; + case 0x04: return"STANDBY CONDITION ACTIVATED BY COMMAND"; + case 0x05: return"IDLE_B CONDITION ACTIVATED BY TIMER"; + case 0x06: return"IDLE_B CONDITION ACTIVATED BY COMMAND"; + case 0x07: return"IDLE_C CONDITION ACTIVATED BY TIMER"; + case 0x08: return"IDLE_C CONDITION ACTIVATED BY COMMAND"; + case 0x09: return"STANDBY_Y CONDITION ACTIVATED BY TIMER"; + case 0x0A: return"STANDBY_Y CONDITION ACTIVATED BY COMMAND"; + case 0x41: return"POWER STATE CHANGED TO ACTIVE"; + case 0x42: return"POWER STATE CHANGED TO IDLE"; + case 0x43: return"POWER STATE CHANGED TO STANDBY"; + case 0x45: return"POWER STATE CHANGED TO SLEEP"; + case 0x47: return"POWER STATE CHANGED TO DEVICE CONTROL"; } break; case 0x60: switch(ASCQ) { - case 0x00: return "LAMP FAILURE"; + case 0x00: return"LAMP FAILURE"; } break; case 0x61: switch(ASCQ) { - case 0x00: return "VIDEO ACQUISTION ERROR"; - case 0x01: return "UNABLE TO ACQUIRE VIDEO"; - case 0x02: return "OUT OF FOCUS"; + case 0x00: return"VIDEO ACQUISTION ERROR"; + case 0x01: return"UNABLE TO ACQUIRE VIDEO"; + case 0x02: return"OUT OF FOCUS"; } break; case 0x62: switch(ASCQ) { - case 0x00: return "SCAN HEAD POSITIONING ERROR"; + case 0x00: return"SCAN HEAD POSITIONING ERROR"; } break; case 0x63: switch(ASCQ) { - case 0x00: return "END OF USER AREA ENCOUNTERED ON THIS TRACK"; - case 0x01: return "PACKET DOES NOT FIT IN AVAILABLE SPACE"; + case 0x00: return"END OF USER AREA ENCOUNTERED ON THIS TRACK"; + case 0x01: return"PACKET DOES NOT FIT IN AVAILABLE SPACE"; } break; case 0x64: switch(ASCQ) { - case 0x00: return "ILLEGAL MODE FOR THIS TRACK"; - case 0x01: return "INVALID PACKET SIZE"; + case 0x00: return"ILLEGAL MODE FOR THIS TRACK"; + case 0x01: return"INVALID PACKET SIZE"; } break; case 0x65: switch(ASCQ) { - case 0x00: return "VOLTAGE FAULT"; + case 0x00: return"VOLTAGE FAULT"; } break; case 0x66: switch(ASCQ) { - case 0x00: return "AUTOMATIC DOCUMENT FEEDER COVER UP"; - case 0x01: return "AUTOMATIC DOCUMENT FEEDER LIFT UP"; - case 0x02: return "DOCUMENT JAM IN AUTOMATIC DOCUMENT FEEDER"; - case 0x03: return "DOCUMENT MISS FEED AUTOMATIC IN DOCUMENT FEEDER"; + case 0x00: return"AUTOMATIC DOCUMENT FEEDER COVER UP"; + case 0x01: return"AUTOMATIC DOCUMENT FEEDER LIFT UP"; + case 0x02: return"DOCUMENT JAM IN AUTOMATIC DOCUMENT FEEDER"; + case 0x03: return"DOCUMENT MISS FEED AUTOMATIC IN DOCUMENT FEEDER"; } break; case 0x67: switch(ASCQ) { - case 0x00: return "CONFIGURATION FAILURE"; - case 0x01: return "CONFIGURATION OF INCAPABLE LOGICAL UNITS FAILED"; - case 0x02: return "ADD LOGICAL UNIT FAILED"; - case 0x03: return "MODIFICATION OF LOGICAL UNIT FAILED"; - case 0x04: return "EXCHANGE OF LOGICAL UNIT FAILED"; - case 0x05: return "REMOVE OF LOGICAL UNIT FAILED"; - case 0x06: return "ATTACHMENT OF LOGICAL UNIT FAILED"; - case 0x07: return "CREATION OF LOGICAL UNIT FAILED"; - case 0x08: return "ASSIGN FAILURE OCCURRED"; - case 0x09: return "MULTIPLY ASSIGNED LOGICAL UNIT"; - case 0x0A: return "SET TARGET PORT GROUPS COMMAND FAILED"; - case 0x0B: return "ATA DEVICE FEATURE NOT ENABLED"; + case 0x00: return"CONFIGURATION FAILURE"; + case 0x01: return"CONFIGURATION OF INCAPABLE LOGICAL UNITS FAILED"; + case 0x02: return"ADD LOGICAL UNIT FAILED"; + case 0x03: return"MODIFICATION OF LOGICAL UNIT FAILED"; + case 0x04: return"EXCHANGE OF LOGICAL UNIT FAILED"; + case 0x05: return"REMOVE OF LOGICAL UNIT FAILED"; + case 0x06: return"ATTACHMENT OF LOGICAL UNIT FAILED"; + case 0x07: return"CREATION OF LOGICAL UNIT FAILED"; + case 0x08: return"ASSIGN FAILURE OCCURRED"; + case 0x09: return"MULTIPLY ASSIGNED LOGICAL UNIT"; + case 0x0A: return"SET TARGET PORT GROUPS COMMAND FAILED"; + case 0x0B: return"ATA DEVICE FEATURE NOT ENABLED"; } break; case 0x68: switch(ASCQ) { - case 0x00: return "LOGICAL UNIT NOT CONFIGURED"; - case 0x01: return "SUBSIDIARY LOGICAL UNIT NOT CONFIGURED"; + case 0x00: return"LOGICAL UNIT NOT CONFIGURED"; + case 0x01: return"SUBSIDIARY LOGICAL UNIT NOT CONFIGURED"; } break; case 0x69: switch(ASCQ) { - case 0x00: return "DATA LOSS ON LOGICAL UNIT"; - case 0x01: return "MULTIPLE LOGICAL UNIT FAILURES"; - case 0x02: return "PARITY/DATA MISMATCH"; + case 0x00: return"DATA LOSS ON LOGICAL UNIT"; + case 0x01: return"MULTIPLE LOGICAL UNIT FAILURES"; + case 0x02: return"PARITY/DATA MISMATCH"; } break; case 0x6A: switch(ASCQ) { - case 0x00: return "INFORMATIONAL, REFER TO LOG"; + case 0x00: return"INFORMATIONAL, REFER TO LOG"; } break; case 0x6B: switch(ASCQ) { - case 0x00: return "STATE CHANGE HAS OCCURRED"; - case 0x01: return "REDUNDANCY LEVEL GOT BETTER"; - case 0x02: return "REDUNDANCY LEVEL GOT WORSE"; + case 0x00: return"STATE CHANGE HAS OCCURRED"; + case 0x01: return"REDUNDANCY LEVEL GOT BETTER"; + case 0x02: return"REDUNDANCY LEVEL GOT WORSE"; } break; case 0x6C: switch(ASCQ) { - case 0x00: return "REBUILD FAILURE OCCURRED"; + case 0x00: return"REBUILD FAILURE OCCURRED"; } break; case 0x6D: switch(ASCQ) { - case 0x00: return "RECALCULATE FAILURE OCCURRED"; + case 0x00: return"RECALCULATE FAILURE OCCURRED"; } break; case 0x6E: switch(ASCQ) { - case 0x00: return "COMMAND TO LOGICAL UNIT FAILED"; + case 0x00: return"COMMAND TO LOGICAL UNIT FAILED"; } break; case 0x6F: switch(ASCQ) { - case 0x00: return "COPY PROTECTION KEY EXCHANGE FAILURE - AUTHENTICATION FAILURE"; - case 0x01: return "COPY PROTECTION KEY EXCHANGE FAILURE - KEY NOT PRESENT"; - case 0x02: return "COPY PROTECTION KEY EXCHANGE FAILURE - KEY NOT ESTABLISHED"; - case 0x03: return "READ OF SCRAMBLED SECTOR WITHOUT AUTHENTICATION"; - case 0x04: return "MEDIA REGION CODE IS MISMATCHED TO LOGICAL UNIT REGION"; - case 0x05: return "DRIVE REGION MUST BE PERMANENT/REGION RESET COUNT ERROR"; - case 0x06: return "INSUFFICIENT BLOCK COUNT FOR BINDING NONCE RECORDING"; - case 0x07: return "CONFLICT IN BINDING NONCE RECORDING"; + case 0x00: return"COPY PROTECTION KEY EXCHANGE FAILURE - AUTHENTICATION FAILURE"; + case 0x01: return"COPY PROTECTION KEY EXCHANGE FAILURE - KEY NOT PRESENT"; + case 0x02: return"COPY PROTECTION KEY EXCHANGE FAILURE - KEY NOT ESTABLISHED"; + case 0x03: return"READ OF SCRAMBLED SECTOR WITHOUT AUTHENTICATION"; + case 0x04: return"MEDIA REGION CODE IS MISMATCHED TO LOGICAL UNIT REGION"; + case 0x05: return"DRIVE REGION MUST BE PERMANENT/REGION RESET COUNT ERROR"; + case 0x06: return"INSUFFICIENT BLOCK COUNT FOR BINDING NONCE RECORDING"; + case 0x07: return"CONFLICT IN BINDING NONCE RECORDING"; } break; - case 0x70: return $"DECOMPRESSION EXCEPTION SHORT ALGORITHM ID OF {ASCQ:X2}h"; + case 0x70: return$"DECOMPRESSION EXCEPTION SHORT ALGORITHM ID OF {ASCQ:X2}h"; case 0x71: switch(ASCQ) { - case 0x00: return "DECOMPRESSIONG EXCEPTION LONG ALGORITHM ID"; + case 0x00: return"DECOMPRESSIONG EXCEPTION LONG ALGORITHM ID"; } break; case 0x72: switch(ASCQ) { - case 0x00: return "SESSION FIXATION ERROR"; - case 0x01: return "SESSION FIXATION ERROR WRITING LEAD-IN"; - case 0x02: return "SESSION FIXATION ERROR WRITING LEAD-OUT"; - case 0x03: return "SESSION FIXATION ERROR - INCOMPLETE TRACK IN SESSION"; - case 0x04: return "EMPTY OR PARTIALLY WRITTEN RESERVED TRACK"; - case 0x05: return "NO MORE TRACK RESERVATIONS ALLOWED"; - case 0x06: return "RMZ EXTENSION IS NOT ALLOWED"; - case 0x07: return "NO MORE TEST ZONE EXTENSIONS ARE ALLOWED"; + case 0x00: return"SESSION FIXATION ERROR"; + case 0x01: return"SESSION FIXATION ERROR WRITING LEAD-IN"; + case 0x02: return"SESSION FIXATION ERROR WRITING LEAD-OUT"; + case 0x03: return"SESSION FIXATION ERROR - INCOMPLETE TRACK IN SESSION"; + case 0x04: return"EMPTY OR PARTIALLY WRITTEN RESERVED TRACK"; + case 0x05: return"NO MORE TRACK RESERVATIONS ALLOWED"; + case 0x06: return"RMZ EXTENSION IS NOT ALLOWED"; + case 0x07: return"NO MORE TEST ZONE EXTENSIONS ARE ALLOWED"; } break; case 0x73: switch(ASCQ) { - case 0x00: return "CD CONTROL ERROR"; - case 0x01: return "POWER CALIBRATION AREA ALMOST FULL"; - case 0x02: return "POWER CALIBRATION AREA IS FULL"; - case 0x03: return "POWER CALIBRATION AREA ERROR"; - case 0x04: return "PROGRAM MEMORY AREA UPDATE FAILURE"; - case 0x05: return "PROGRAM MEMORY AREA IS FULL"; - case 0x06: return "RMA/PMA IS ALMOST FULL"; - case 0x10: return "CURRENT POWER CALIBRATION AREA ALMOST FULL"; - case 0x11: return "CURRENT POWER CALIBRATION AREA IS FULL"; - case 0x17: return "RDZ IS FULL"; + case 0x00: return"CD CONTROL ERROR"; + case 0x01: return"POWER CALIBRATION AREA ALMOST FULL"; + case 0x02: return"POWER CALIBRATION AREA IS FULL"; + case 0x03: return"POWER CALIBRATION AREA ERROR"; + case 0x04: return"PROGRAM MEMORY AREA UPDATE FAILURE"; + case 0x05: return"PROGRAM MEMORY AREA IS FULL"; + case 0x06: return"RMA/PMA IS ALMOST FULL"; + case 0x10: return"CURRENT POWER CALIBRATION AREA ALMOST FULL"; + case 0x11: return"CURRENT POWER CALIBRATION AREA IS FULL"; + case 0x17: return"RDZ IS FULL"; } break; case 0x74: switch(ASCQ) { - case 0x00: return "SECURITY ERROR"; - case 0x01: return "UNABLE TO DECRYPT DATA"; - case 0x02: return "UNENCRYPTED DATA ENCOUNTERED WHILE DECRYPTING"; - case 0x03: return "INCORRECT DATA ENCRYPTION KEY"; - case 0x04: return "CRYPTOGRAPHIC INTEGRITY VALIDATION FAILED"; - case 0x05: return "ERROR DECRYPTING DATA"; - case 0x06: return "UNKNOWN SIGNATURE VERIFICATION KEY"; - case 0x07: return "ENCRYPTION PARAMETERS NOT USEABLE"; - case 0x08: return "DIGITAL SIGNATURE VALIDATION FAILURE"; - case 0x09: return "ENCRYPTION MODE MISMATCH ON READ"; - case 0x0A: return "ENCRYPTED BLOCK NOT RAW READ ENABLED"; - case 0x0B: return "INCORRECT ENCRYPTION PARAMETERS"; - case 0x0C: return "UNABLE TO DECRYPT PARAMETER LIST"; - case 0x0D: return "ENCRYPTION ALGORITHM DISABLED"; - case 0x10: return "SA CREATION PARAMETER VALUE INVALID"; - case 0x11: return "SA CREATION PARAMETER VALUE REJECTED"; - case 0x12: return "INVALID SA USAGE"; - case 0x21: return "DATA ENCRYPTION CONFIGURATION PREVENTED"; - case 0x30: return "SA CREATION PARAMETER NOT SUPPORTED"; - case 0x40: return "AUTHENTICATION FAILED"; - case 0x61: return "EXTERNAL DATA ENCRYPTION KEY MANAGER ACCESS ERROR"; - case 0x62: return "EXTERNAL DATA ENCRYPTION KEY MANAGER ERROR"; - case 0x63: return "EXTERNAL DATA ENCRYPTION KEY NOT FOUND"; - case 0x64: return "EXTERNAL DATA ENCRYPTION REQUEST NOT AUTHORIZED"; - case 0x6E: return "EXTERNAL DATA ENCRYPTION CONTROL TIMEOUT"; - case 0x6F: return "EXTERNAL DATA ENCRYPTION CONTROL ERROR"; - case 0x71: return "LOGICAL UNIT ACCESS NOT AUTHORIZED"; - case 0x79: return "SECURITY CONFLICT IN TRANSLATED DEVICE"; + case 0x00: return"SECURITY ERROR"; + case 0x01: return"UNABLE TO DECRYPT DATA"; + case 0x02: return"UNENCRYPTED DATA ENCOUNTERED WHILE DECRYPTING"; + case 0x03: return"INCORRECT DATA ENCRYPTION KEY"; + case 0x04: return"CRYPTOGRAPHIC INTEGRITY VALIDATION FAILED"; + case 0x05: return"ERROR DECRYPTING DATA"; + case 0x06: return"UNKNOWN SIGNATURE VERIFICATION KEY"; + case 0x07: return"ENCRYPTION PARAMETERS NOT USEABLE"; + case 0x08: return"DIGITAL SIGNATURE VALIDATION FAILURE"; + case 0x09: return"ENCRYPTION MODE MISMATCH ON READ"; + case 0x0A: return"ENCRYPTED BLOCK NOT RAW READ ENABLED"; + case 0x0B: return"INCORRECT ENCRYPTION PARAMETERS"; + case 0x0C: return"UNABLE TO DECRYPT PARAMETER LIST"; + case 0x0D: return"ENCRYPTION ALGORITHM DISABLED"; + case 0x10: return"SA CREATION PARAMETER VALUE INVALID"; + case 0x11: return"SA CREATION PARAMETER VALUE REJECTED"; + case 0x12: return"INVALID SA USAGE"; + case 0x21: return"DATA ENCRYPTION CONFIGURATION PREVENTED"; + case 0x30: return"SA CREATION PARAMETER NOT SUPPORTED"; + case 0x40: return"AUTHENTICATION FAILED"; + case 0x61: return"EXTERNAL DATA ENCRYPTION KEY MANAGER ACCESS ERROR"; + case 0x62: return"EXTERNAL DATA ENCRYPTION KEY MANAGER ERROR"; + case 0x63: return"EXTERNAL DATA ENCRYPTION KEY NOT FOUND"; + case 0x64: return"EXTERNAL DATA ENCRYPTION REQUEST NOT AUTHORIZED"; + case 0x6E: return"EXTERNAL DATA ENCRYPTION CONTROL TIMEOUT"; + case 0x6F: return"EXTERNAL DATA ENCRYPTION CONTROL ERROR"; + case 0x71: return"LOGICAL UNIT ACCESS NOT AUTHORIZED"; + case 0x79: return"SECURITY CONFLICT IN TRANSLATED DEVICE"; } break; diff --git a/SCSI/Types.cs b/SCSI/Types.cs index ab06e3a..bcf0017 100644 --- a/SCSI/Types.cs +++ b/SCSI/Types.cs @@ -40,555 +40,180 @@ namespace DiscImageChef.Decoders.SCSI Default = 0x00, #region Medium Types defined in ECMA-111 for Direct-Access devices - /// - /// ECMA-54: 200 mm Flexible Disk Cartridge using Two-Frequency Recording at 13262 ftprad on One Side + /// ECMA-54: 200 mm Flexible Disk Cartridge using Two-Frequency Recording at 13262 ftprad on One Side + ECMA54 = 0x09, /// + /// ECMA-59 & ANSI X3.121-1984: 200 mm Flexible Disk Cartridge using Two-Frequency Recording at 13262 ftprad + /// on Both Sides /// - ECMA54 = 0x09, - /// - /// ECMA-59 & ANSI X3.121-1984: 200 mm Flexible Disk Cartridge using Two-Frequency Recording at 13262 ftprad on - /// Both Sides + ECMA59 = 0x0A, /// ECMA-69: 200 mm Flexible Disk Cartridge using MFM Recording at 13262 ftprad on Both Sides + ECMA69 = 0x0B, /// ECMA-66: 130 mm Flexible Disk Cartridge using Two-Frequency Recording at 7958 ftprad on One Side + ECMA66 = 0x0E, /// + /// ECMA-70 & ANSI X3.125-1985: 130 mm Flexible Disk Cartridge using MFM Recording at 7958 ftprad on Both + /// Sides; 1,9 Tracks per mm /// - ECMA59 = 0x0A, - /// - /// ECMA-69: 200 mm Flexible Disk Cartridge using MFM Recording at 13262 ftprad on Both Sides + ECMA70 = 0x12, /// + /// ECMA-78 & ANSI X3.126-1986: 130 mm Flexible Disk Cartridge using MFM Recording at 7958 ftprad on Both + /// Sides; 3,8 Tracks per mm /// - ECMA69 = 0x0B, - /// - /// ECMA-66: 130 mm Flexible Disk Cartridge using Two-Frequency Recording at 7958 ftprad on One Side - /// - ECMA66 = 0x0E, - /// - /// ECMA-70 & ANSI X3.125-1985: 130 mm Flexible Disk Cartridge using MFM Recording at 7958 ftprad on Both Sides; - /// 1,9 Tracks per mm - /// - ECMA70 = 0x12, - /// - /// ECMA-78 & ANSI X3.126-1986: 130 mm Flexible Disk Cartridge using MFM Recording at 7958 ftprad on Both Sides; + ECMA78 = 0x16, /// + /// ECMA-99 & ISO 8630-1985: 130 mm Flexible Disk Cartridge using MFM Recording at 13262 ftprad on Both Sides; /// 3,8 Tracks per mm /// - ECMA78 = 0x16, - /// - /// ECMA-99 & ISO 8630-1985: 130 mm Flexible Disk Cartridge using MFM Recording at 13262 ftprad on Both Sides; 3,8 - /// Tracks per mm - /// - ECMA99 = 0x1A, - /// - /// ECMA-100 & ANSI X3.137: 90 mm Flexible Disk Cartridge using MFM Recording at 7859 ftprad on Both Sides; 5,3 - /// Tracks per mm + ECMA99 = 0x1A, /// + /// ECMA-100 & ANSI X3.137: 90 mm Flexible Disk Cartridge using MFM Recording at 7859 ftprad on Both Sides; + /// 5,3 Tracks per mm /// ECMA100 = 0x1E, #endregion Medium Types defined in ECMA-111 for Direct-Access devices #region Medium Types defined in SCSI-2 for Direct-Access devices - /// - /// Unspecified single sided flexible disk - /// - Unspecified_SS = 0x01, - /// - /// Unspecified double sided flexible disk - /// - Unspecified_DS = 0x02, - /// - /// ANSI X3.73-1980: 200 mm, 6631 ftprad, 1,9 Tracks per mm, 1 side - /// - X3_73 = 0x05, - /// - /// ANSI X3.73-1980: 200 mm, 6631 ftprad, 1,9 Tracks per mm, 2 sides - /// - X3_73_DS = 0x06, - /// - /// ANSI X3.80-1980: 130 mm, 3979 ftprad, 1,9 Tracks per mm, 1 side - /// - X3_82 = 0x0D, - /// - /// 6,3 mm tape with 12 tracks at 394 ftpmm - /// - Tape12 = 0x40, - /// - /// 6,3 mm tape with 24 tracks at 394 ftpmm - /// + /// Unspecified single sided flexible disk + Unspecified_SS = 0x01, /// Unspecified double sided flexible disk + Unspecified_DS = 0x02, /// ANSI X3.73-1980: 200 mm, 6631 ftprad, 1,9 Tracks per mm, 1 side + X3_73 = 0x05, /// ANSI X3.73-1980: 200 mm, 6631 ftprad, 1,9 Tracks per mm, 2 sides + X3_73_DS = 0x06, /// ANSI X3.80-1980: 130 mm, 3979 ftprad, 1,9 Tracks per mm, 1 side + X3_82 = 0x0D, /// 6,3 mm tape with 12 tracks at 394 ftpmm + Tape12 = 0x40, /// 6,3 mm tape with 24 tracks at 394 ftpmm Tape24 = 0x44, #endregion Medium Types defined in SCSI-2 for Direct-Access devices #region Medium Types defined in SCSI-3 SBC-1 for Optical devices - /// - /// Read-only medium - /// - ReadOnly = 0x01, - /// - /// Write-once Read-many medium - /// - WORM = 0x02, - /// - /// Erasable medium - /// - Erasable = 0x03, - /// - /// Combination of read-only and write-once medium - /// - RO_WORM = 0x04, - /// - /// Combination of read-only and erasable medium - /// - RO_RW = 0x05, - /// - /// Combination of write-once and erasable medium - /// + /// Read-only medium + ReadOnly = 0x01, /// Write-once Read-many medium + WORM = 0x02, /// Erasable medium + Erasable = 0x03, /// Combination of read-only and write-once medium + RO_WORM = 0x04, /// Combination of read-only and erasable medium + RO_RW = 0x05, /// Combination of write-once and erasable medium WORM_RW = 0x06, #endregion Medium Types defined in SCSI-3 SBC-1 for Optical devices #region Medium Types defined in SCSI-2 for MultiMedia devices - /// - /// 120 mm CD-ROM - /// - CDROM = 0x01, - /// - /// 120 mm Compact Disc Digital Audio - /// - CDDA = 0x02, - /// - /// 120 mm Compact Disc with data and audio - /// - MixedCD = 0x03, - /// - /// 80 mm CD-ROM - /// - CDROM_80 = 0x05, - /// - /// 80 mm Compact Disc Digital Audio - /// - CDDA_80 = 0x06, - /// - /// 80 mm Compact Disc with data and audio - /// + /// 120 mm CD-ROM + CDROM = 0x01, /// 120 mm Compact Disc Digital Audio + CDDA = 0x02, /// 120 mm Compact Disc with data and audio + MixedCD = 0x03, /// 80 mm CD-ROM + CDROM_80 = 0x05, /// 80 mm Compact Disc Digital Audio + CDDA_80 = 0x06, /// 80 mm Compact Disc with data and audio MixedCD_80 = 0x07, #endregion Medium Types defined in SCSI-2 for MultiMedia devices #region Medium Types defined in SFF-8020i - /// - /// Unknown medium type - /// - Unknown_CD = 0x00, - /// - /// 120 mm Hybrid disc (Photo CD) - /// - HybridCD = 0x04, - /// - /// Unknown size CD-R - /// - Unknown_CDR = 0x10, - /// - /// 120 mm CD-R with data only - /// - CDR = 0x11, - /// - /// 120 mm CD-R with audio only - /// - CDR_DA = 0x12, - /// - /// 120 mm CD-R with data and audio - /// - CDR_Mixed = 0x13, - /// - /// 120 mm Hybrid CD-R (Photo CD) - /// - HybridCDR = 0x14, - /// - /// 80 mm CD-R with data only - /// - CDR_80 = 0x15, - /// - /// 80 mm CD-R with audio only - /// - CDR_DA_80 = 0x16, - /// - /// 80 mm CD-R with data and audio - /// - CDR_Mixed_80 = 0x17, - /// - /// 80 mm Hybrid CD-R (Photo CD) - /// - HybridCDR_80 = 0x18, - /// - /// Unknown size CD-RW - /// - Unknown_CDRW = 0x20, - /// - /// 120 mm CD-RW with data only - /// - CDRW = 0x21, - /// - /// 120 mm CD-RW with audio only - /// - CDRW_DA = 0x22, - /// - /// 120 mm CD-RW with data and audio - /// - CDRW_Mixed = 0x23, - /// - /// 120 mm Hybrid CD-RW (Photo CD) - /// - HybridCDRW = 0x24, - /// - /// 80 mm CD-RW with data only - /// - CDRW_80 = 0x25, - /// - /// 80 mm CD-RW with audio only - /// - CDRW_DA_80 = 0x26, - /// - /// 80 mm CD-RW with data and audio - /// - CDRW_Mixed_80 = 0x27, - /// - /// 80 mm Hybrid CD-RW (Photo CD) - /// - HybridCDRW_80 = 0x28, - /// - /// Unknown size HD disc - /// - Unknown_HD = 0x30, - /// - /// 120 mm HD disc - /// - HD = 0x31, - /// - /// 80 mm HD disc - /// - HD_80 = 0x35, - /// - /// No disc inserted, tray closed or caddy inserted - /// - NoDisc = 0x70, - /// - /// Tray open or no caddy inserted - /// - TrayOpen = 0x71, - /// - /// Tray closed or caddy inserted but medium error - /// + /// Unknown medium type + Unknown_CD = 0x00, /// 120 mm Hybrid disc (Photo CD) + HybridCD = 0x04, /// Unknown size CD-R + Unknown_CDR = 0x10, /// 120 mm CD-R with data only + CDR = 0x11, /// 120 mm CD-R with audio only + CDR_DA = 0x12, /// 120 mm CD-R with data and audio + CDR_Mixed = 0x13, /// 120 mm Hybrid CD-R (Photo CD) + HybridCDR = 0x14, /// 80 mm CD-R with data only + CDR_80 = 0x15, /// 80 mm CD-R with audio only + CDR_DA_80 = 0x16, /// 80 mm CD-R with data and audio + CDR_Mixed_80 = 0x17, /// 80 mm Hybrid CD-R (Photo CD) + HybridCDR_80 = 0x18, /// Unknown size CD-RW + Unknown_CDRW = 0x20, /// 120 mm CD-RW with data only + CDRW = 0x21, /// 120 mm CD-RW with audio only + CDRW_DA = 0x22, /// 120 mm CD-RW with data and audio + CDRW_Mixed = 0x23, /// 120 mm Hybrid CD-RW (Photo CD) + HybridCDRW = 0x24, /// 80 mm CD-RW with data only + CDRW_80 = 0x25, /// 80 mm CD-RW with audio only + CDRW_DA_80 = 0x26, /// 80 mm CD-RW with data and audio + CDRW_Mixed_80 = 0x27, /// 80 mm Hybrid CD-RW (Photo CD) + HybridCDRW_80 = 0x28, /// Unknown size HD disc + Unknown_HD = 0x30, /// 120 mm HD disc + HD = 0x31, /// 80 mm HD disc + HD_80 = 0x35, /// No disc inserted, tray closed or caddy inserted + NoDisc = 0x70, /// Tray open or no caddy inserted + TrayOpen = 0x71, /// Tray closed or caddy inserted but medium error MediumError = 0x72, #endregion Medium Types defined in SFF-8020i #region Medium Types defined in USB Mass Storage Class - UFI Command Specification - /// - /// 3.5-inch, 135 tpi, 12362 bits/radian, double-sided MFM (aka 1.25Mb) - /// - Type3Floppy = 0x93, - /// - /// 3.5-inch, 135 tpi, 15916 bits/radian, double-sided MFM (aka 1.44Mb) - /// + /// 3.5-inch, 135 tpi, 12362 bits/radian, double-sided MFM (aka 1.25Mb) + Type3Floppy = 0x93, /// 3.5-inch, 135 tpi, 15916 bits/radian, double-sided MFM (aka 1.44Mb) HDFloppy = 0x94, #endregion Medium Types defined in USB Mass Storage Class - UFI Command Specification #region Medium Types defined in INF-8070 - /// - /// Unknown type block device - /// - UnknownBlockDevice = 0x40, - /// - /// Read-only block device - /// - ReadOnlyBlockDevice = 0x41, - /// - /// Read/Write block device - /// + /// Unknown type block device + UnknownBlockDevice = 0x40, /// Read-only block device + ReadOnlyBlockDevice = 0x41, /// Read/Write block device ReadWriteBlockDevice = 0x42, #endregion Medium Types defined in INF-8070 #region Medium Types found in vendor documents - /// - /// LTO WORM as reported by HP drives - /// - LTOWORM = 0x01, - /// - /// LTO cleaning cartridge as reported by Certance/Seagate drives - /// - LTOCleaning = 0x01, - /// - /// Direct-overwrite magneto-optical - /// - DOW = 0x07, - /// - /// LTO Ultrium - /// - LTO = 0x18, - /// - /// LTO Ultrium-2 - /// - LTO2 = 0x28, - /// - /// DC-2900SL - /// - DC2900SL = 0x31, - /// - /// MLR-1 - /// - MLR1 = 0x33, - /// - /// DDS-3 - /// - DDS3 = 0x33, - /// - /// DC-9200 - /// - DC9200 = 0x34, - /// - /// DDS-4 - /// - DDS4 = 0x34, - /// - /// DAT-72 - /// - DAT72 = 0x35, - /// - /// LTO Ultrium-3 - /// - LTO3 = 0x38, - /// - /// LTO Ultrium-3 WORM - /// - LTO3WORM = 0x3C, - /// - /// DDS cleaning cartridge - /// - DDSCleaning = 0x3F, - /// - /// DC-9250 - /// - DC9250 = 0x40, - /// - /// SLR-32 - /// - SLR32 = 0x43, - /// - /// MLR-1SL - /// - MLR1SL = 0x44, - /// - /// SLRtape-50 - /// - SLRtape50 = 0x47, - /// - /// LTO Ultrium-4 - /// - LTO4 = 0x48, - /// - /// LTO Ultrium-4 WORM - /// - LTO4WORM = 0x4C, - /// - /// SLRtape-50SL - /// - SLRtape50SL = 0x50, - /// - /// SLR-32SL - /// - SLR32SL = 0x54, - /// - /// SLR-5 - /// - SLR5 = 0x55, - /// - /// SLR-5SL - /// - SLR5SL = 0x56, - /// - /// LTO Ultrium-5 - /// - LTO5 = 0x58, - /// - /// LTO Ultrium-5 WORM - /// - LTO5WORM = 0x5C, - /// - /// SLRtape-7 - /// - SLRtape7 = 0x63, - /// - /// SLRtape-7SL - /// - SLRtape7SL = 0x64, - /// - /// SLRtape-24 - /// - SLRtape24 = 0x65, - /// - /// SLRtape-24SL - /// - SLRtape24SL = 0x66, - /// - /// LTO Ultrium-6 - /// - LTO6 = 0x68, - /// - /// LTO Ultrium-6 WORM - /// - LTO6WORM = 0x6C, - /// - /// SLRtape-140 - /// - SLRtape140 = 0x70, - /// - /// SLRtape-40 - /// - SLRtape40 = 0x73, - /// - /// SLRtape-60 - /// - SLRtape60 = 0x74, - /// - /// SLRtape-75 - /// - SLRtape75 = 0x74, - /// - /// SLRtape-100 - /// - SLRtape100 = 0x75, - /// - /// SLR-40 or SLR-60 or SLR-100 - /// - SLR40_60_100 = 0x76, - /// - /// LTO Ultrium-7 - /// - LTO7 = 0x78, - /// - /// LTO Ultrium-7 WORM - /// - LTO7WORM = 0x7C, - /// - /// HP LTO emulating a CD - /// - LTOCD = 0x80, - /// - /// Exatape 15m - /// - Exatape15m = 0x81, - /// - /// IBM MagStar - /// - MagStar = 0x81, - /// - /// VXA - /// - VXA = 0x81, - /// - /// CompactTape I - /// - CT1 = 0x82, - /// - /// Exatape 28m - /// - Exatape28m = 0x82, - /// - /// CompactTape II - /// - CT2 = 0x82, - /// - /// VXA-2 - /// - VXA2 = 0x82, - /// - /// VXA-3 - /// - VXA3 = 0x82, - /// - /// Exatape 54m - /// - Exatape54m = 0x83, - /// - /// DLTtape III - /// - DLTtapeIII = 0x83, - /// - /// Exatape 80m - /// - Exatape80m = 0x84, - /// - /// DLTtape IIIxt - /// - DLTtapeIIIxt = 0x84, - /// - /// Exatape 106m - /// - Exatape106m = 0x85, - /// - /// DLTtape IV - /// - DLTtapeIV = 0x85, - /// - /// Travan 5 - /// - Travan5 = 0x85, - /// - /// Exatape 106m XL - /// - Exatape106mXL = 0x86, - /// - /// SuperDLT I - /// - SDLT1 = 0x86, - /// - /// SuperDLT II - /// - SDLT2 = 0x87, - /// - /// VStape I - /// - VStapeI = 0x90, - /// - /// DLTtape S4 - /// - DLTtapeS4 = 0x91, - /// - /// Travan 7 - /// - Travan7 = 0x95, - /// - /// Exatape 22m - /// - Exatape22m = 0xC1, - /// - /// Exatape 40m - /// - Exatape40m = 0xC2, - /// - /// Exatape 76m - /// - Exatape76m = 0xC3, - /// - /// Exatape 112m - /// - Exatape112m = 0xC4, - /// - /// Exatape 22m AME - /// - Exatape22mAME = 0xD1, - /// - /// Exatape 170m - /// - Exatape170m = 0xD2, - /// - /// Exatape 125m - /// - Exatape125m = 0xD3, - /// - /// Exatape 45m - /// - Exatape45m = 0xD4, - /// - /// Exatape 225m - /// - Exatape225m = 0xD5, - /// - /// Exatape 150m - /// - Exatape150m = 0xD6, - /// - /// Exatape 75m - /// + /// LTO WORM as reported by HP drives + LTOWORM = 0x01, /// LTO cleaning cartridge as reported by Certance/Seagate drives + LTOCleaning = 0x01, /// Direct-overwrite magneto-optical + DOW = 0x07, /// LTO Ultrium + LTO = 0x18, /// LTO Ultrium-2 + LTO2 = 0x28, /// DC-2900SL + DC2900SL = 0x31, /// MLR-1 + MLR1 = 0x33, /// DDS-3 + DDS3 = 0x33, /// DC-9200 + DC9200 = 0x34, /// DDS-4 + DDS4 = 0x34, /// DAT-72 + DAT72 = 0x35, /// LTO Ultrium-3 + LTO3 = 0x38, /// LTO Ultrium-3 WORM + LTO3WORM = 0x3C, /// DDS cleaning cartridge + DDSCleaning = 0x3F, /// DC-9250 + DC9250 = 0x40, /// SLR-32 + SLR32 = 0x43, /// MLR-1SL + MLR1SL = 0x44, /// SLRtape-50 + SLRtape50 = 0x47, /// LTO Ultrium-4 + LTO4 = 0x48, /// LTO Ultrium-4 WORM + LTO4WORM = 0x4C, /// SLRtape-50SL + SLRtape50SL = 0x50, /// SLR-32SL + SLR32SL = 0x54, /// SLR-5 + SLR5 = 0x55, /// SLR-5SL + SLR5SL = 0x56, /// LTO Ultrium-5 + LTO5 = 0x58, /// LTO Ultrium-5 WORM + LTO5WORM = 0x5C, /// SLRtape-7 + SLRtape7 = 0x63, /// SLRtape-7SL + SLRtape7SL = 0x64, /// SLRtape-24 + SLRtape24 = 0x65, /// SLRtape-24SL + SLRtape24SL = 0x66, /// LTO Ultrium-6 + LTO6 = 0x68, /// LTO Ultrium-6 WORM + LTO6WORM = 0x6C, /// SLRtape-140 + SLRtape140 = 0x70, /// SLRtape-40 + SLRtape40 = 0x73, /// SLRtape-60 + SLRtape60 = 0x74, /// SLRtape-75 + SLRtape75 = 0x74, /// SLRtape-100 + SLRtape100 = 0x75, /// SLR-40 or SLR-60 or SLR-100 + SLR40_60_100 = 0x76, /// LTO Ultrium-7 + LTO7 = 0x78, /// LTO Ultrium-7 WORM + LTO7WORM = 0x7C, /// HP LTO emulating a CD + LTOCD = 0x80, /// Exatape 15m + Exatape15m = 0x81, /// IBM MagStar + MagStar = 0x81, /// VXA + VXA = 0x81, /// CompactTape I + CT1 = 0x82, /// Exatape 28m + Exatape28m = 0x82, /// CompactTape II + CT2 = 0x82, /// VXA-2 + VXA2 = 0x82, /// VXA-3 + VXA3 = 0x82, /// Exatape 54m + Exatape54m = 0x83, /// DLTtape III + DLTtapeIII = 0x83, /// Exatape 80m + Exatape80m = 0x84, /// DLTtape IIIxt + DLTtapeIIIxt = 0x84, /// Exatape 106m + Exatape106m = 0x85, /// DLTtape IV + DLTtapeIV = 0x85, /// Travan 5 + Travan5 = 0x85, /// Exatape 106m XL + Exatape106mXL = 0x86, /// SuperDLT I + SDLT1 = 0x86, /// SuperDLT II + SDLT2 = 0x87, /// VStape I + VStapeI = 0x90, /// DLTtape S4 + DLTtapeS4 = 0x91, /// Travan 7 + Travan7 = 0x95, /// Exatape 22m + Exatape22m = 0xC1, /// Exatape 40m + Exatape40m = 0xC2, /// Exatape 76m + Exatape76m = 0xC3, /// Exatape 112m + Exatape112m = 0xC4, /// Exatape 22m AME + Exatape22mAME = 0xD1, /// Exatape 170m + Exatape170m = 0xD2, /// Exatape 125m + Exatape125m = 0xD3, /// Exatape 45m + Exatape45m = 0xD4, /// Exatape 225m + Exatape225m = 0xD5, /// Exatape 150m + Exatape150m = 0xD6, /// Exatape 75m Exatape75m = 0xD7, #endregion Medium Types found in vendor documents } @@ -599,445 +224,135 @@ namespace DiscImageChef.Decoders.SCSI Default = 0x00, #region Density Types defined in ECMA-111 for Direct-Access devices - /// - /// 7958 flux transitions per radian - /// - Flux7958 = 0x01, - /// - /// 13262 flux transitions per radian - /// - Flux13262 = 0x02, - /// - /// 15916 flux transitions per radian - /// + /// 7958 flux transitions per radian + Flux7958 = 0x01, /// 13262 flux transitions per radian + Flux13262 = 0x02, /// 15916 flux transitions per radian Flux15916 = 0x03, #endregion Density Types defined in ECMA-111 for Direct-Access devices #region Density Types defined in ECMA-111 for Sequential-Access devices - /// - /// ECMA-62 & ANSI X3.22-1983: 12,7 mm 9-Track Magnetic Tape, 32 ftpmm, NRZI, 32 cpmm - /// - ECMA62 = 0x01, - /// - /// ECMA-62 & ANSI X3.39-1986: 12,7 mm 9-Track Magnetic Tape, 126 ftpmm, Phase Encoding, 63 cpmm - /// - ECMA62_Phase = 0x02, - /// - /// ECMA-62 & ANSI X3.54-1986: 12,7 mm 9-Track Magnetic Tape, 356 ftpmm, NRZI, 245 cpmm GCR - /// - ECMA62_GCR = 0x03, - /// - /// ECMA-79 & ANSI X3.116-1986: 6,30 mm Magnetic Tape Cartridge using MFM Recording at 252 ftpmm - /// - ECMA79 = 0x07, - /// - /// Draft ECMA & ANSI X3B5/87-099: 12,7 mm Magnetic Tape Cartridge using IFM Recording on 18 Tracks at 1944 ftpmm, - /// GCR (IBM 3480, 3490, 3490E) - /// - IBM3480 = 0x09, - /// - /// ECMA-46 & ANSI X3.56-1986: 6,30 mm Magnetic Tape Cartridge, Phase Encoding, 63 bpmm - /// - ECMA46 = 0x0B, - /// - /// ECMA-98: 6,30 mm Magnetic Tape Cartridge, NRZI Recording, 394 ftpmm + /// ECMA-62 & ANSI X3.22-1983: 12,7 mm 9-Track Magnetic Tape, 32 ftpmm, NRZI, 32 cpmm + ECMA62 = 0x01, /// ECMA-62 & ANSI X3.39-1986: 12,7 mm 9-Track Magnetic Tape, 126 ftpmm, Phase Encoding, 63 cpmm + ECMA62_Phase = 0x02, /// ECMA-62 & ANSI X3.54-1986: 12,7 mm 9-Track Magnetic Tape, 356 ftpmm, NRZI, 245 cpmm GCR + ECMA62_GCR = 0x03, /// ECMA-79 & ANSI X3.116-1986: 6,30 mm Magnetic Tape Cartridge using MFM Recording at 252 ftpmm + ECMA79 = 0x07, /// + /// Draft ECMA & ANSI X3B5/87-099: 12,7 mm Magnetic Tape Cartridge using IFM Recording on 18 Tracks at 1944 + /// ftpmm, GCR (IBM 3480, 3490, 3490E) /// + IBM3480 = 0x09, /// ECMA-46 & ANSI X3.56-1986: 6,30 mm Magnetic Tape Cartridge, Phase Encoding, 63 bpmm + ECMA46 = 0x0B, /// ECMA-98: 6,30 mm Magnetic Tape Cartridge, NRZI Recording, 394 ftpmm ECMA98 = 0x0E, #endregion Density Types defined in ECMA-111 for Sequential-Access devices #region Density Types defined in SCSI-2 for Sequential-Access devices - /// - /// ANXI X3.136-1986: 6,35 mm 4 or 9-Track Magnetic Tape Cartridge, 315 bpmm, GCR (QIC-24) - /// - X3_136 = 0x05, - /// - /// ANXI X3.157-1987: 12,7 mm 9-Track Magnetic Tape, 126 bpmm, Phase Encoding - /// - X3_157 = 0x06, - /// - /// ANXI X3.158-1987: 3,81 mm 4-Track Magnetic Tape Cassette, 315 bpmm, GCR - /// - X3_158 = 0x08, - /// - /// ANXI X3B5/86-199: 12,7 mm 22-Track Magnetic Tape Cartridge, 262 bpmm, MFM - /// - X3B5_86 = 0x0A, - /// - /// HI-TC1: 12,7 mm 24-Track Magnetic Tape Cartridge, 500 bpmm, GCR - /// - HiTC1 = 0x0C, - /// - /// HI-TC2: 12,7 mm 24-Track Magnetic Tape Cartridge, 999 bpmm, GCR - /// - HiTC2 = 0x0D, - /// - /// QIC-120: 6,3 mm 15-Track Magnetic Tape Cartridge, 394 bpmm, GCR - /// - QIC120 = 0x0F, - /// - /// QIC-150: 6,3 mm 18-Track Magnetic Tape Cartridge, 394 bpmm, GCR - /// - QIC150 = 0x10, - /// - /// QIC-320: 6,3 mm 26-Track Magnetic Tape Cartridge, 630 bpmm, GCR - /// - QIC320 = 0x11, - /// - /// QIC-1350: 6,3 mm 30-Track Magnetic Tape Cartridge, 2034 bpmm, RLL - /// - QIC1350 = 0x12, - /// - /// ANXI X3B5/88-185A: 3,81 mm Magnetic Tape Cassette, 2400 bpmm, DDS - /// - X3B5_88 = 0x13, - /// - /// ANXI X3.202-1991: 8 mm Magnetic Tape Cassette, 1703 bpmm, RLL - /// - X3_202 = 0x14, - /// - /// ECMA TC17: 8 mm Magnetic Tape Cassette, 1789 bpmm, RLL - /// - ECMA_TC17 = 0x15, - /// - /// ANXI X3.193-1990: 12,7 mm 48-Track Magnetic Tape Cartridge, 394 bpmm, MFM - /// - X3_193 = 0x16, - /// - /// ANXI X3B5/97-174: 12,7 mm 48-Track Magnetic Tape Cartridge, 1673 bpmm, MFM - /// + /// ANXI X3.136-1986: 6,35 mm 4 or 9-Track Magnetic Tape Cartridge, 315 bpmm, GCR (QIC-24) + X3_136 = 0x05, /// ANXI X3.157-1987: 12,7 mm 9-Track Magnetic Tape, 126 bpmm, Phase Encoding + X3_157 = 0x06, /// ANXI X3.158-1987: 3,81 mm 4-Track Magnetic Tape Cassette, 315 bpmm, GCR + X3_158 = 0x08, /// ANXI X3B5/86-199: 12,7 mm 22-Track Magnetic Tape Cartridge, 262 bpmm, MFM + X3B5_86 = 0x0A, /// HI-TC1: 12,7 mm 24-Track Magnetic Tape Cartridge, 500 bpmm, GCR + HiTC1 = 0x0C, /// HI-TC2: 12,7 mm 24-Track Magnetic Tape Cartridge, 999 bpmm, GCR + HiTC2 = 0x0D, /// QIC-120: 6,3 mm 15-Track Magnetic Tape Cartridge, 394 bpmm, GCR + QIC120 = 0x0F, /// QIC-150: 6,3 mm 18-Track Magnetic Tape Cartridge, 394 bpmm, GCR + QIC150 = 0x10, /// QIC-320: 6,3 mm 26-Track Magnetic Tape Cartridge, 630 bpmm, GCR + QIC320 = 0x11, /// QIC-1350: 6,3 mm 30-Track Magnetic Tape Cartridge, 2034 bpmm, RLL + QIC1350 = 0x12, /// ANXI X3B5/88-185A: 3,81 mm Magnetic Tape Cassette, 2400 bpmm, DDS + X3B5_88 = 0x13, /// ANXI X3.202-1991: 8 mm Magnetic Tape Cassette, 1703 bpmm, RLL + X3_202 = 0x14, /// ECMA TC17: 8 mm Magnetic Tape Cassette, 1789 bpmm, RLL + ECMA_TC17 = 0x15, /// ANXI X3.193-1990: 12,7 mm 48-Track Magnetic Tape Cartridge, 394 bpmm, MFM + X3_193 = 0x16, /// ANXI X3B5/97-174: 12,7 mm 48-Track Magnetic Tape Cartridge, 1673 bpmm, MFM X3B5_91 = 0x17, #endregion Density Types defined in SCSI-2 for Sequential-Access devices #region Density Types defined in SCSI-2 for MultiMedia devices - /// - /// User data only - /// - User = 0x01, - /// - /// User data plus auxiliary data field - /// - UserAuxiliary = 0x02, - /// - /// 4-byt tag field, user data plus auxiliary data - /// - UserAuxiliaryTag = 0x03, - /// - /// Audio information only - /// + /// User data only + User = 0x01, /// User data plus auxiliary data field + UserAuxiliary = 0x02, /// 4-byt tag field, user data plus auxiliary data + UserAuxiliaryTag = 0x03, /// Audio information only Audio = 0x04, #endregion Density Types defined in SCSI-2 for MultiMedia devices #region Density Types defined in SCSI-2 for Optical devices - /// - /// ISO/IEC 10090: 86 mm Read/Write single-sided optical disc with 12500 tracks - /// - ISO10090 = 0x01, - /// - /// 89 mm Read/Write double-sided optical disc with 12500 tracks - /// - D581 = 0x02, - /// - /// ANSI X3.212: 130 mm Read/Write double-sided optical disc with 18750 tracks - /// - X3_212 = 0x03, - /// - /// ANSI X3.191: 130 mm Write-Once double-sided optical disc with 30000 tracks - /// - X3_191 = 0x04, - /// - /// ANSI X3.214: 130 mm Write-Once double-sided optical disc with 20000 tracks - /// - X3_214 = 0x05, - /// - /// ANSI X3.211: 130 mm Write-Once double-sided optical disc with 18750 tracks - /// - X3_211 = 0x06, - /// - /// 200 mm optical disc - /// - D407 = 0x07, - /// - /// ISO/IEC 13614: 300 mm double-sided optical disc - /// - ISO13614 = 0x08, - /// - /// ANSI X3.200: 356 mm double-sided optical disc with 56350 tracks - /// + /// ISO/IEC 10090: 86 mm Read/Write single-sided optical disc with 12500 tracks + ISO10090 = 0x01, /// 89 mm Read/Write double-sided optical disc with 12500 tracks + D581 = 0x02, /// ANSI X3.212: 130 mm Read/Write double-sided optical disc with 18750 tracks + X3_212 = 0x03, /// ANSI X3.191: 130 mm Write-Once double-sided optical disc with 30000 tracks + X3_191 = 0x04, /// ANSI X3.214: 130 mm Write-Once double-sided optical disc with 20000 tracks + X3_214 = 0x05, /// ANSI X3.211: 130 mm Write-Once double-sided optical disc with 18750 tracks + X3_211 = 0x06, /// 200 mm optical disc + D407 = 0x07, /// ISO/IEC 13614: 300 mm double-sided optical disc + ISO13614 = 0x08, /// ANSI X3.200: 356 mm double-sided optical disc with 56350 tracks X3_200 = 0x09, #endregion Density Types defined in SCSI-2 for Optical devices #region Density Types found in vendor documents - /// - /// QIC-11 - /// - QIC11 = 0x04, - /// - /// CompactTape I - /// - CT1 = 0x0A, - /// - /// Exabyte 8200 format - /// - Ex8200 = 0x14, - /// - /// Exabyte 8500 format - /// - Ex8500 = 0x15, - /// - /// CompactTape II - /// - CT2 = 0x16, - /// - /// DLTtape III 42500 bpi - /// - DLT3_42k = 0x17, - /// - /// DLTtape III 56 track - /// - DLT3_56t = 0x18, - /// - /// DLTtape III 62500 bpi - /// - DLT3_62k = 0x19, - /// - /// DLTtape IV - /// - DLT4 = 0x1A, - /// - /// DLTtape IV 85937 bpi - /// - DLT4_85k = 0x1B, - /// - /// DDS-2 - /// - DDS2 = 0x24, - /// - /// DDS-3 - /// - DDS3 = 0x25, - /// - /// DDS-4 - /// - DDS4 = 0x26, - /// - /// Exabyte Mammoth - /// - Mammoth = 0x27, - /// - /// IBM 3490 & 3490E - /// - IBM3490E = 0x28, - /// - /// Exabyte Mammoth-2 - /// - Mammoth2 = 0x28, - /// - /// IBM 3590 - /// - IBM3590 = 0x29, - /// - /// IBM 3590E - /// - IBM3590E = 0x2A, - /// - /// AIT-1 - /// - AIT1 = 0x30, - /// - /// AIT-2 - /// - AIT2 = 0x31, - /// - /// AIT-3 - /// - AIT3 = 0x32, - /// - /// DLTtape IV 123090 bpi - /// - DLT4_123k = 0x40, - /// - /// Ultrium-1 - /// - LTO1 = 0x40, - /// - /// Super AIT-1 - /// - SAIT1 = 0x40, - /// - /// DLTtape IV 85937 bpi - /// - DLT4_98k = 0x41, - /// - /// Ultrium-2 as reported by the Certance drive - /// - LTO2Old = 0x41, - /// - /// Ultrium-2 - /// - LTO2 = 0x42, - /// - /// T9840 - /// - T9840 = 0x42, - /// - /// T9940 - /// - T9940 = 0x43, - /// - /// Ultrium- - /// - LTO3 = 0x44, - /// - /// T9840C - /// - T9840C = 0x45, - /// - /// Travan 5 - /// - Travan5 = 0x46, - /// - /// Ultrium-4 - /// - LTO4 = 0x46, - /// - /// T9840D - /// - T9840D = 0x46, - /// - /// DAT-72 - /// - DAT72 = 0x47, - /// - /// Super DLTtape I 133000 bpi - /// - SDLT1_133k = 0x48, - /// - /// Super DLTtape I - /// - SDLT1 = 0x49, - /// - /// T10000A - /// - T10000A = 0x4A, - /// - /// Super DLTtape II - /// - SDLT2 = 0x4A, - /// - /// DLTtape S4 - /// - DLTS4 = 0x4B, - /// - /// T10000B - /// - T10000B = 0x4B, - /// - /// T10000C - /// - T10000C = 0x4C, - /// - /// T10000D - /// - T10000D = 0x4D, - /// - /// VStape I - /// - VStape1 = 0x40, - /// - /// Ultrium-5 - /// - LTO5 = 0x58, - /// - /// Ultrium-6 - /// - LTO6 = 0x5A, - /// - /// Ultrium-7 - /// - LTO7 = 0x5C, - /// - /// DLTtape III 62500 bpi secondary code - /// - DLT3_62kAlt = 0x80, - /// - /// VXA-1 - /// - VXA1 = 0x80, - /// - /// DLTtape III compressed - /// - DLT3c = 0x81, - /// - /// VXA-2 - /// - VXA2 = 0x81, - /// - /// DLTtape IV secondary code - /// - DLT4Alt = 0x82, - /// - /// VXA-3 - /// - VXA3 = 0x82, - /// - /// DLTtape IV compressed - /// - DLT4c = 0x83, - /// - /// DLTtape IV 85937 bpi secondary code - /// - DLT4_85kAlt = 0x84, - /// - /// DLTtape IV 85937 bpi compressed - /// - DLT4c_85k = 0x85, - /// - /// DLTtape IV 123090 bpi secondary code - /// - DLT4_123kAlt = 0x86, - /// - /// DLTtape IV 123090 bpi compressed - /// - DLT4c_123k = 0x87, - /// - /// DLTtape IV 98250 bpi secondary code - /// - DLT4_98kAlt = 0x88, - /// - /// DLTtape IV 98250 bpi compressed - /// - DLT4c_98k = 0x89, - /// - /// Exabyte compressed 8200 format - /// - Ex8500c = 0x8C, - /// - /// Exabyte compressed 8500 format - /// - Ex8200c = 0x90, - /// - /// Super DLTtape I secondary code - /// - SDLT1Alt = 0x90, - /// - /// Super DLTtape I compressed - /// - SDLT1c = 0x91, - /// - /// Super DLTtape I 133000 bpi secondary code - /// - SDLT1_133kAlt = 0x92, - /// - /// Super DLTtape I 133000 bpi compressed - /// - SDLT1c_133k = 0x93, - /// - /// VStape I secondary code - /// - VStape1Alt = 0x98, - /// - /// VStape I compressed - /// + /// QIC-11 + QIC11 = 0x04, /// CompactTape I + CT1 = 0x0A, /// Exabyte 8200 format + Ex8200 = 0x14, /// Exabyte 8500 format + Ex8500 = 0x15, /// CompactTape II + CT2 = 0x16, /// DLTtape III 42500 bpi + DLT3_42k = 0x17, /// DLTtape III 56 track + DLT3_56t = 0x18, /// DLTtape III 62500 bpi + DLT3_62k = 0x19, /// DLTtape IV + DLT4 = 0x1A, /// DLTtape IV 85937 bpi + DLT4_85k = 0x1B, /// DDS-2 + DDS2 = 0x24, /// DDS-3 + DDS3 = 0x25, /// DDS-4 + DDS4 = 0x26, /// Exabyte Mammoth + Mammoth = 0x27, /// IBM 3490 & 3490E + IBM3490E = 0x28, /// Exabyte Mammoth-2 + Mammoth2 = 0x28, /// IBM 3590 + IBM3590 = 0x29, /// IBM 3590E + IBM3590E = 0x2A, /// AIT-1 + AIT1 = 0x30, /// AIT-2 + AIT2 = 0x31, /// AIT-3 + AIT3 = 0x32, /// DLTtape IV 123090 bpi + DLT4_123k = 0x40, /// Ultrium-1 + LTO1 = 0x40, /// Super AIT-1 + SAIT1 = 0x40, /// DLTtape IV 85937 bpi + DLT4_98k = 0x41, /// Ultrium-2 as reported by the Certance drive + LTO2Old = 0x41, /// Ultrium-2 + LTO2 = 0x42, /// T9840 + T9840 = 0x42, /// T9940 + T9940 = 0x43, /// Ultrium- + LTO3 = 0x44, /// T9840C + T9840C = 0x45, /// Travan 5 + Travan5 = 0x46, /// Ultrium-4 + LTO4 = 0x46, /// T9840D + T9840D = 0x46, /// DAT-72 + DAT72 = 0x47, /// Super DLTtape I 133000 bpi + SDLT1_133k = 0x48, /// Super DLTtape I + SDLT1 = 0x49, /// T10000A + T10000A = 0x4A, /// Super DLTtape II + SDLT2 = 0x4A, /// DLTtape S4 + DLTS4 = 0x4B, /// T10000B + T10000B = 0x4B, /// T10000C + T10000C = 0x4C, /// T10000D + T10000D = 0x4D, /// VStape I + VStape1 = 0x40, /// Ultrium-5 + LTO5 = 0x58, /// Ultrium-6 + LTO6 = 0x5A, /// Ultrium-7 + LTO7 = 0x5C, /// DLTtape III 62500 bpi secondary code + DLT3_62kAlt = 0x80, /// VXA-1 + VXA1 = 0x80, /// DLTtape III compressed + DLT3c = 0x81, /// VXA-2 + VXA2 = 0x81, /// DLTtape IV secondary code + DLT4Alt = 0x82, /// VXA-3 + VXA3 = 0x82, /// DLTtape IV compressed + DLT4c = 0x83, /// DLTtape IV 85937 bpi secondary code + DLT4_85kAlt = 0x84, /// DLTtape IV 85937 bpi compressed + DLT4c_85k = 0x85, /// DLTtape IV 123090 bpi secondary code + DLT4_123kAlt = 0x86, /// DLTtape IV 123090 bpi compressed + DLT4c_123k = 0x87, /// DLTtape IV 98250 bpi secondary code + DLT4_98kAlt = 0x88, /// DLTtape IV 98250 bpi compressed + DLT4c_98k = 0x89, /// Exabyte compressed 8200 format + Ex8500c = 0x8C, /// Exabyte compressed 8500 format + Ex8200c = 0x90, /// Super DLTtape I secondary code + SDLT1Alt = 0x90, /// Super DLTtape I compressed + SDLT1c = 0x91, /// Super DLTtape I 133000 bpi secondary code + SDLT1_133kAlt = 0x92, /// Super DLTtape I 133000 bpi compressed + SDLT1c_133k = 0x93, /// VStape I secondary code + VStape1Alt = 0x98, /// VStape I compressed VStape1c = 0x99, #endregion Density Types found in vendor documents } diff --git a/SCSI/VendorString.cs b/SCSI/VendorString.cs index 33d4016..230a9b0 100644 --- a/SCSI/VendorString.cs +++ b/SCSI/VendorString.cs @@ -38,805 +38,805 @@ namespace DiscImageChef.Decoders.SCSI { switch(scsiVendorString) { - case "0B4C": return "MOOSIK Ltd."; - case "13FE": return "PHISON"; - case "2AI": return "2AI (Automatisme et Avenir Informatique)"; - case "3M": return "3M Company"; - case "3nhtech": return "3NH Technologies"; - case "3PARdata": return "3PARdata, Inc."; - case "A-Max": return "A-Max Technology Co., Ltd"; - case "ABSOLUTE": return "Absolute Analysis"; - case "ACARD": return "ACARD Technology Corp."; - case "Accusys": return "Accusys INC."; - case "Acer": return "Acer, Inc."; - case "ACL": return "Automated Cartridge Librarys, Inc."; - case "Actifio": return "Actifio"; - case "Acuid": return "Acuid Corporation Ltd."; - case "AcuLab": return "AcuLab, Inc. (Tulsa, OK)"; - case "ADAPTEC": return "Adaptec"; - case "ADIC": return "Advanced Digital Information Corporation"; - case "ADSI": return "Adaptive Data Systems, Inc. (a Western Digital subsidiary)"; - case "ADTX": return "ADTX Co., Ltd."; - case "ADVA": return "ADVA Optical Networking AG"; - case "AEM": return "AEM Performance Electronics"; - case "AERONICS": return "Aeronics, Inc."; - case "AGFA": return "AGFA"; - case "Agilent": return "Agilent Technologies"; - case "AIC": return "Advanced Industrial Computer, Inc."; - case "AIPTEK": return "AIPTEK International Inc."; - case "Alcohol": return "Alcohol Soft"; - case "ALCOR": return "Alcor Micro, Corp."; - case "AMCC": return "Applied Micro Circuits Corporation"; - case "AMCODYNE": return "Amcodyne"; - case "Amgeon": return "Amgeon LLC"; - case "AMI": return "American Megatrends, Inc."; - case "AMPEX": return "Ampex Data Systems"; - case "Amphenol": return "Amphenol"; - case "Amtl": return "Tenlon Technology Co.,Ltd"; - case "ANAMATIC": return "Anamartic Limited (England)"; - case "Ancor": return "Ancor Communications, Inc."; - case "ANCOT": return "ANCOT Corp."; - case "ANDATACO": return "Andataco"; - case "andiamo": return "Andiamo Systems, Inc."; - case "ANOBIT": return "Anobit"; - case "ANRITSU": return "Anritsu Corporation"; - case "ANTONIO": return "Antonio Precise Products Manufactory Ltd."; - case "AoT": return "Art of Technology AG"; - case "APPLE": return "Apple Computer, Inc."; - case "ARCHIVE": return "Archive"; - case "ARDENCE": return "Ardence Inc"; - case "Areca": return "Areca Technology Corporation"; - case "Arena": return "MaxTronic International Co., Ltd."; - case "Argent": return "Argent Data Systems, Inc."; - case "ARIO": return "Ario Data Networks, Inc."; - case "ARISTOS": return "Aristos Logic Corp."; - case "ARK": return "ARK Research Corporation"; - case "ARL:UT@A": return "Applied Research Laboratories : University of Texas at Austin"; - case "ARTECON": return "Artecon Inc."; - case "Artistic": return "Artistic Licence (UK) Ltd"; - case "ARTON": return "Arton Int."; - case "ASACA": return "ASACA Corp."; - case "ASC": return "Advanced Storage Concepts, Inc."; - case "ASPEN": return "Aspen Peripherals"; - case "AST": return "AST Research"; - case "ASTEK": return "Astek Corporation"; - case "ASTK": return "Alcatel STK A/S"; - case "AStor": return "AccelStor, Inc."; - case "ASTUTE": return "Astute Networks, Inc."; - case "AT&T": return "AT&T"; - case "ATA": return "SCSI / ATA Translator Software (Organization Not Specified)"; - case "ATARI": return "Atari Corporation"; - case "ATech": return "ATech electronics"; - case "ATG CYG": return "ATG Cygnet Inc."; - case "ATL": return "Quantum|ATL Products"; - case "ATTO": return "ATTO Technology Inc."; - case "ATTRATEC": return "Attratech Ltd liab. Co"; - case "ATX": return "Alphatronix"; - case "AURASEN": return "Aurasen Limited"; - case "Avago": return "Avago Technologies"; - case "AVC": return "AVC Technology Ltd"; - case "AVIDVIDR": return "AVID Technologies, Inc."; - case "AVR": return "Advanced Vision Research"; - case "AXSTOR": return "AXSTOR"; - case "Axxana": return "Axxana Ltd."; - case "B*BRIDGE": return "Blockbridge Networks LLC"; - case "BALLARD": return "Ballard Synergy Corp."; - case "Barco": return "Barco"; - case "BAROMTEC": return "Barom Technologies Co., Ltd."; - case "Bassett": return "Bassett Electronic Systems Ltd"; - case "BC Hydro": return "BC Hydro"; - case "BDT": return "BDT AG"; - case "BECEEM": return "Beceem Communications, Inc"; - case "BENQ": return "BENQ Corporation."; - case "BERGSWD": return "Berg Software Design"; - case "BEZIER": return "Bezier Systems, Inc."; - case "BHTi": return "Breece Hill Technologies"; - case "biodata": return "Biodata Devices SL"; - case "BIOS": return "BIOS Corporation"; - case "BIR": return "Bio-Imaging Research, Inc."; - case "BiT": return "BiT Microsystems"; - case "BITMICRO": return "BiT Microsystems, Inc."; - case "Blendlgy": return "Blendology Limited"; - case "BLOOMBAS": return "Bloombase Technologies Limited"; - case "BlueArc": return "BlueArc Corporation"; - case "bluecog": return "bluecog"; - case "BME-HVT": return "Broadband Infocommunicatons and Electromagnetic Theory Department"; - case "BNCHMARK": return "Benchmark Tape Systems Corporation"; - case "Bosch": return "Robert Bosch GmbH"; - case "Botman": return "Botmanfamily Electronics"; - case "BoxHill": return "Box Hill Systems Corporation"; - case "BRDGWRKS": return "Bridgeworks Ltd."; - case "BREA": return "BREA Technologies, Inc."; - case "BREECE": return "Breece Hill LLC"; - case "BreqLabs": return "BreqLabs Inc."; - case "Broadcom": return "Broadcom Corporation"; - case "BROCADE": return "Brocade Communications Systems, Incorporated"; - case "BUFFALO": return "BUFFALO INC."; - case "BULL": return "Bull Peripherals Corp."; - case "BUSLOGIC": return "BusLogic Inc."; - case "BVIRTUAL": return "B-Virtual N.V."; - case "CACHEIO": return "CacheIO LLC"; - case "CalComp": return "CalComp, A Lockheed Company"; - case "CALCULEX": return "CALCULEX, Inc."; - case "CALIPER": return "Caliper (California Peripheral Corp.)"; - case "CAMBEX": return "Cambex Corporation"; - case "CAMEOSYS": return "Cameo Systems Inc."; - case "CANDERA": return "Candera Inc."; - case "CAPTION": return "CAPTION BANK"; - case "CAST": return "Advanced Storage Tech"; - case "CATALYST": return "Catalyst Enterprises"; - case "CCDISK": return "iSCSI Cake"; - case "CDC": return "Control Data or MPI"; - case "CDP": return "Columbia Data Products"; - case "Celsia": return "A M Bromley Limited"; - case "CenData": return "Central Data Corporation"; - case "Cereva": return "Cereva Networks Inc."; - case "CERTANCE": return "Certance"; - case "Chantil": return "Chantil Technology"; - case "CHEROKEE": return "Cherokee Data Systems"; - case "CHINON": return "Chinon"; - case "CHRISTMA": return "Christmann Informationstechnik + Medien GmbH & Co KG"; - case "CIE&YED": return "YE Data, C.Itoh Electric Corp."; - case "CIPHER": return "Cipher Data Products"; - case "Ciprico": return "Ciprico, Inc."; - case "CIRRUSL": return "Cirrus Logic Inc."; - case "CISCO": return "Cisco Systems, Inc."; - case "CLEARSKY": return "ClearSky Data, Inc."; - case "CLOVERLF": return "Cloverleaf Communications, Inc"; - case "CLS": return "Celestica"; - case "CMD": return "CMD Technology Inc."; - case "CMTechno": return "CMTech"; - case "CNGR SFW": return "Congruent Software, Inc."; - case "CNSi": return "Chaparral Network Storage, Inc."; - case "CNT": return "Computer Network Technology"; - case "COBY": return "Coby Electronics Corporation, USA"; - case "COGITO": return "Cogito"; - case "COMAY": return "Corerise Electronics"; - case "COMPAQ": return "Compaq Computer Corporation"; - case "COMPELNT": return "Compellent Technologies, Inc."; - case "COMPORT": return "Comport Corp."; - case "COMPSIG": return "Computer Signal Corporation"; - case "COMPTEX": return "Comptex Pty Limited"; - case "CONNER": return "Conner Peripherals"; - case "COPANSYS": return "COPAN SYSTEMS INC"; - case "CORAID": return "Coraid, Inc"; - case "CORE": return "Core International, Inc."; - case "CORERISE": return "Corerise Electronics"; - case "COVOTE": return "Covote GmbH & Co KG"; - case "COWON": return "COWON SYSTEMS, Inc."; - case "CPL": return "Cross Products Ltd"; - case "CPU TECH": return "CPU Technology, Inc."; - case "CREO": return "Creo Products Inc."; - case "CROSFLD": return "Crosfield Electronics"; - case "CROSSRDS": return "Crossroads Systems, Inc."; - case "crosswlk": return "Crosswalk, Inc."; - case "CSCOVRTS": return "Cisco - Veritas"; - case "CSM, INC": return "Computer SM, Inc."; - case "Cunuqui": return "CUNUQUI SLU"; - case "CYBERNET": return "Cybernetics"; - case "Cygnal": return "Dekimo"; - case "CYPRESS": return "Cypress Semiconductor Corp."; - case "D Bit": return "Digby's Bitpile, Inc. DBA D Bit"; - case "DALSEMI": return "Dallas Semiconductor"; - case "DANEELEC": return "Dane-Elec"; - case "DANGER": return "Danger Inc."; - case "DAT-MG": return "DAT Manufacturers Group"; - case "Data Com": return "Data Com Information Systems Pty. Ltd."; - case "DATABOOK": return "Databook, Inc."; - case "DATACOPY": return "Datacopy Corp."; - case "DataCore": return "DataCore Software Corporation"; - case "DataG": return "DataGravity"; - case "DATAPT": return "Datapoint Corp."; - case "DATARAM": return "Dataram Corporation"; - case "DATC": return "Datum Champion Technology Co., Ltd"; - case "DAVIS": return "Daviscomms (S) Pte Ltd"; - case "DCS": return "ShenZhen DCS Group Co.,Ltd"; - case "DDN": return "DataDirect Networks, Inc."; - case "DDRDRIVE": return "DDRdrive LLC"; - case "DE": return "Dimension Engineering LLC"; - case "DEC": return "Digital Equipment Corporation"; - case "DEI": return "Digital Engineering, Inc."; - case "DELL": return "Dell, Inc."; - case "Dell(tm)": return "Dell, Inc"; - case "DELPHI": return "Delphi Data Div. of Sparks Industries, Inc."; - case "DENON": return "Denon/Nippon Columbia"; - case "DenOptix": return "DenOptix, Inc."; - case "DEST": return "DEST Corp."; - case "DFC": return "DavioFranke.com"; - case "DFT": return "Data Fault Tolerance System CO.,LTD."; - case "DGC": return "Data General Corp."; - case "DIGIDATA": return "Digi-Data Corporation"; - case "DigiIntl": return "Digi International"; - case "Digital": return "Digital Equipment Corporation"; - case "DILOG": return "Distributed Logic Corp."; - case "DISC": return "Document Imaging Systems Corp."; - case "DiscSoft": return "Disc Soft Ltd"; - case "DLNET": return "Driveline"; - case "DNS": return "Data and Network Security"; - case "DNUK": return "Digital Networks Uk Ltd"; - case "DotHill": return "Dot Hill Systems Corp."; - case "DP": return "Dell, Inc."; - case "DPT": return "Distributed Processing Technology"; - case "Drewtech": return "Drew Technologies, Inc."; - case "DROBO": return "Data Robotics, Inc."; - case "DSC": return "DigitalStream Corporation"; - case "DSI": return "Data Spectrum, Inc."; - case "DSM": return "Deterner Steuerungs- und Maschinenbau GmbH & Co."; - case "DSNET": return "Cleversafe, Inc."; - case "DT": return "Double-Take Software, INC."; - case "DTC QUME": return "Data Technology Qume"; - case "DXIMAGIN": return "DX Imaging"; - case "E-Motion": return "E-Motion LLC"; - case "EARTHLAB": return "EarthLabs"; - case "EarthLCD": return "Earth Computer Technologies, Inc."; - case "ECCS": return "ECCS, Inc."; - case "ECMA": return "European Computer Manufacturers Association"; - case "EDS": return "Embedded Data Systems"; - case "EIM": return "InfoCore"; - case "ELE Intl": return "ELE International"; - case "ELEGANT": return "Elegant Invention, LLC"; - case "Elektron": return "Elektron Music Machines MAV AB"; - case "elipsan": return "Elipsan UK Ltd."; - case "Elms": return "Elms Systems Corporation"; - case "ELSE": return "ELSE Ltd."; - case "ELSEC": return "Littlemore Scientific"; - case "EMASS": return "EMASS, Inc."; - case "EMC": return "EMC Corp."; - case "EMiT": return "EMiT Conception Eletronique"; - case "EMTEC": return "EMTEC Magnetics"; - case "EMULEX": return "Emulex"; - case "ENERGY-B": return "Energybeam Corporation"; - case "ENGENIO": return "Engenio Information Technologies, Inc."; - case "ENMOTUS": return "Enmotus Inc"; - case "Entacore": return "Entacore"; - case "EPOS": return "EPOS Technologies Ltd."; - case "EPSON": return "Epson"; - case "EQLOGIC": return "EqualLogic"; - case "Eris/RSI": return "RSI Systems, Inc."; - case "ETERNE": return "EterneData Technology Co.,Ltd.(China PRC.)"; - case "EuroLogc": return "Eurologic Systems Limited"; - case "evolve": return "Evolution Technologies, Inc"; - case "EXABYTE": return "Exabyte Corp."; - case "EXATEL": return "Exatelecom Co., Ltd."; - case "EXAVIO": return "Exavio, Inc."; - case "Exsequi": return "Exsequi Ltd"; - case "Exxotest": return "Annecy Electronique"; - case "FAIRHAVN": return "Fairhaven Health, LLC"; - case "FALCON": return "FalconStor, Inc."; - case "FDS": return "Formation Data Systems"; - case "FFEILTD": return "FujiFilm Electonic Imaging Ltd"; - case "Fibxn": return "Fiberxon, Inc."; - case "FID": return "First International Digital, Inc."; - case "FILENET": return "FileNet Corp."; - case "FirmFact": return "Firmware Factory Ltd"; - case "FLYFISH": return "Flyfish Technologies"; - case "FOXCONN": return "Foxconn Technology Group"; - case "FRAMDRV": return "FRAMEDRIVE Corp."; - case "FREECION": return "Nable Communications, Inc."; - case "FRESHDTK": return "FreshDetect GmbH"; - case "FSC": return "Fujitsu Siemens Computers"; - case "FTPL": return "Frontline Technologies Pte Ltd"; - case "FUJI": return "Fuji Electric Co., Ltd. (Japan)"; - case "FUJIFILM": return "Fuji Photo Film, Co., Ltd."; - case "FUJITSU": return "Fujitsu"; - case "FUNAI": return "Funai Electric Co., Ltd."; - case "FUSIONIO": return "Fusion-io Inc."; - case "FUTURED": return "Future Domain Corp."; - case "G&D": return "Giesecke & Devrient GmbH"; - case "G.TRONIC": return "Globaltronic - Electronica e Telecomunicacoes, S.A."; - case "Gadzoox": return "Gadzoox Networks, Inc."; - case "Gammaflx": return "Gammaflux L.P."; - case "GDI": return "Generic Distribution International"; - case "GEMALTO": return "gemalto"; - case "Gen_Dyn": return "General Dynamics"; - case "Generic": return "Generic Technology Co., Ltd."; - case "GENSIG": return "General Signal Networks"; - case "GEO": return "Green Energy Options Ltd"; - case "GIGATAPE": return "GIGATAPE GmbH"; - case "GIGATRND": return "GigaTrend Incorporated"; - case "Global": return "Global Memory Test Consortium"; - case "Gnutek": return "Gnutek Ltd."; - case "Goidelic": return "Goidelic Precision, Inc."; - case "GoldKey": return "GoldKey Security Corporation"; - case "GoldStar": return "LG Electronics Inc."; - case "GOOGLE": return "Google, Inc."; - case "GORDIUS": return "Gordius"; - case "GOULD": return "Gould"; - case "HAGIWARA": return "Hagiwara Sys-Com Co., Ltd."; - case "HAPP3": return "Inventec Multimedia and Telecom co., ltd"; - case "HDS": return "Horizon Data Systems, Inc."; - case "Helldyne": return "Helldyne, Inc"; - case "Heydays": return "Mazo Technology Co., Ltd."; - case "HGST": return "HGST a Western Digital Company"; - case "HI-TECH": return "HI-TECH Software Pty. Ltd."; - case "HITACHI": return "Hitachi America Ltd or Nissei Sangyo America Ltd"; - case "HL-DT-ST": return "Hitachi-LG Data Storage, Inc."; - case "HONEYWEL": return "Honeywell Inc."; - case "Hoptroff": return "HexWax Ltd"; - case "HORIZONT": return "Horizontigo Software"; - case "HP": return "Hewlett Packard"; - case "HPE": return "Hewlett Packard Enterprise"; - case "HPI": return "HP Inc."; - case "HPQ": return "Hewlett Packard"; - case "HUALU": return "CHINA HUALU GROUP CO., LTD"; - case "HUASY": return "Huawei Symantec Technologies Co., Ltd."; - case "HYLINX": return "Hylinx Ltd."; - case "HYUNWON": return "HYUNWON inc"; - case "i-cubed": return "i-cubed ltd."; - case "IBM": return "International Business Machines"; - case "Icefield": return "Icefield Tools Corporation"; - case "Iceweb": return "Iceweb Storage Corp"; - case "ICL": return "ICL"; - case "ICP": return "ICP vortex Computersysteme GmbH"; - case "IDE": return "International Data Engineering, Inc."; - case "IDG": return "Interface Design Group"; - case "IET": return "ISCSI ENTERPRISE TARGET"; - case "IFT": return "Infortrend Technology, Inc."; - case "IGR": return "Intergraph Corp."; - case "IMAGINE": return "Imagine Communications Corp."; - case "IMAGO": return "IMAGO SOFTWARE SL"; - case "IMATION": return "Imation"; - case "IMPLTD": return "Integrated Micro Products Ltd."; - case "IMPRIMIS": return "Imprimis Technology Inc."; - case "INCIPNT": return "Incipient Technologies Inc."; - case "INCITS": return "InterNational Committee for Information Technology"; - case "INDCOMP": return "Industrial Computing Limited"; - case "Indigita": return "Indigita Corporation"; - case "INFOCORE": return "InfoCore"; - case "INITIO": return "Initio Corporation"; - case "INRANGE": return "INRANGE Technologies Corporation"; - case "Insight": return "L-3 Insight Technology Inc"; - case "INSITE": return "Insite Peripherals"; - case "integrix": return "Integrix, Inc."; - case "INTEL": return "Intel Corporation"; - case "Intransa": return "Intransa, Inc."; - case "IOC": return "I/O Concepts, Inc."; - case "iofy": return "iofy Corporation"; - case "IOMEGA": return "Iomega"; - case "IOT": return "IO Turbine, Inc."; - case "iPaper": return "intelliPaper, LLC"; - case "iqstor": return "iQstor Networks, Inc."; - case "iQue": return "iQue"; - case "ISi": return "Information Storage inc."; - case "Isilon": return "Isilon Systems, Inc."; - case "ISO": return "International Standards Organization"; - case "iStor": return "iStor Networks, Inc."; - case "ITC": return "International Tapetronics Corporation"; - case "iTwin": return "iTwin Pte Ltd"; - case "IVIVITY": return "iVivity, Inc."; - case "IVMMLTD": return "InnoVISION Multimedia Ltd."; - case "JABIL001": return "Jabil Circuit"; - case "JETWAY": return "Jetway Information Co., Ltd"; - case "JMR": return "JMR Electronics Inc."; - case "JOFEMAR": return "Jofemar"; - case "JOLLYLOG": return "Jolly Logic"; - case "JPC Inc.": return "JPC Inc."; - case "JSCSI": return "jSCSI Project"; - case "Juniper": return "Juniper Networks"; - case "JVC": return "JVC Information Products Co."; - case "KASHYA": return "Kashya, Inc."; - case "KENNEDY": return "Kennedy Company"; - case "KENWOOD": return "KENWOOD Corporation"; - case "KEWL": return "Shanghai KEWL Imp&Exp Co., Ltd."; - case "Key Tech": return "Key Technologies, Inc"; - case "KMNRIO": return "Kaminario Technologies Ltd."; - case "KODAK": return "Eastman Kodak"; - case "KONAN": return "Konan"; - case "koncepts": return "koncepts International Ltd."; - case "KONICA": return "Konica Japan"; - case "KOVE": return "KOVE"; - case "KSCOM": return "KSCOM Co. Ltd.,"; - case "KUDELSKI": return "Nagravision SA - Kudelski Group"; - case "Kyocera": return "Kyocera Corporation"; - case "Lapida": return "Gonmalo Electronics"; - case "LAPINE": return "Lapine Technology"; - case "LASERDRV": return "LaserDrive Limited"; - case "LASERGR": return "Lasergraphics, Inc."; - case "LeapFrog": return "LeapFrog Enterprises, Inc."; - case "LEFTHAND": return "LeftHand Networks"; - case "Leica": return "Leica Camera AG"; - case "Lexar": return "Lexar Media, Inc."; - case "LEYIO": return "LEYIO"; - case "LG": return "LG Electronics Inc."; - case "LGE": return "LG Electronics Inc."; - case "LIBNOVA": return "LIBNOVA, SL Digital Preservation Systems"; - case "LION": return "Lion Optics Corporation"; - case "LMS": return "Laser Magnetic Storage International Company"; - case "LoupTech": return "Loup Technologies, Inc."; - case "LSI": return "LSI Corp. (was LSI Logic Corp.)"; - case "LSILOGIC": return "LSI Logic Storage Systems, Inc."; - case "LTO-CVE": return "Linear Tape - Open, Compliance Verification Entity"; - case "LUXPRO": return "Luxpro Corporation"; - case "MacroSAN": return "MacroSAN Technologies Co., Ltd."; - case "Malakite": return "Malachite Technologies (New VID is: Sandial)"; - case "MarcBoon": return "marcboon.com"; - case "Marner": return "Marner Storage Technologies, Inc."; - case "MARVELL": return "Marvell Semiconductor, Inc."; - case "Matrix": return "Matrix Orbital Corp."; - case "MATSHITA": return "Matsushita"; - case "MAXELL": return "Hitachi Maxell, Ltd."; - case "MAXIM-IC": return "Maxim Integrated Products"; - case "MaxOptix": return "Maxoptix Corp."; - case "MAXSTRAT": return "Maximum Strategy, Inc."; - case "MAXTOR": return "Maxtor Corp."; - case "MaXXan": return "MaXXan Systems, Inc."; - case "MAYCOM": return "maycom Co., Ltd."; - case "MBEAT": return "K-WON C&C Co.,Ltd"; - case "MCC": return "Measurement Computing Corporation"; - case "McDATA": return "McDATA Corporation"; - case "MCUBE": return "Mcube Technology Co., Ltd."; - case "MDI": return "Micro Design International, Inc."; - case "MEADE": return "Meade Instruments Corporation"; - case "mediamat": return "mediamatic"; - case "MegaElec": return "Mega Electronics Ltd"; - case "MEII": return "Mountain Engineering II, Inc."; - case "MELA": return "Mitsubishi Electronics America"; - case "MELCO": return "Mitsubishi Electric (Japan)"; - case "mellanox": return "Mellanox Technologies Ltd."; - case "MEMOREX": return "Memorex Telex Japan Ltd."; - case "MEMREL": return "Memrel Corporation"; - case "MEMTECH": return "MemTech Technology"; - case "Mendocin": return "Mendocino Software"; - case "MendoCno": return "Mendocino Software"; - case "MERIDATA": return "Oy Meridata Finland Ltd"; - case "METHODEI": return "Methode Electronics India pvt ltd"; - case "METRUM": return "Metrum, Inc."; - case "MHTL": return "Matsunichi Hi-Tech Limited"; - case "MICROBTX": return "Microbotics Inc."; - case "Microchp": return "Microchip Technology, Inc."; - case "MICROLIT": return "Microlite Corporation"; - case "MICRON": return "Micron Technology, Inc."; - case "MICROP": return "Micropolis"; - case "MICROTEK": return "Microtek Storage Corp"; - case "Minitech": return "Minitech (UK) Limited"; - case "Minolta": return "Minolta Corporation"; - case "MINSCRIB": return "Miniscribe"; - case "MiraLink": return "MiraLink Corporation"; - case "Mirifica": return "Mirifica s.r.l."; - case "MITSUMI": return "Mitsumi Electric Co., Ltd."; - case "MKM": return "Mitsubishi Kagaku Media Co., LTD."; - case "Mobii": return "Mobii Systems (Pty.) Ltd."; - case "MOL": return "Petrosoft Sdn. Bhd."; - case "MOSAID": return "Mosaid Technologies Inc."; - case "MOTOROLA": return "Motorola"; - case "MP-400": return "Daiwa Manufacturing Limited"; - case "MPC": return "MPC Corporation"; - case "MPCCORP": return "MPC Computers"; - case "MPEYE": return "Touchstone Technology Co., Ltd"; - case "MPIO": return "DKT Co.,Ltd"; - case "MPM": return "Mitsubishi Paper Mills, Ltd."; - case "MPMan": return "MPMan.com, Inc."; - case "MSFT": return "Microsoft Corporation"; - case "MSI": return "Micro-Star International Corp."; - case "MST": return "Morning Star Technologies, Inc."; - case "MSystems": return "M-Systems Flash Disk Pioneers"; - case "MTI": return "MTI Technology Corporation"; - case "MTNGATE": return "MountainGate Data Systems"; - case "MXI": return "Memory Experts International"; - case "nac": return "nac Image Technology Inc."; - case "NAGRA": return "Nagravision SA - Kudelski Group"; - case "NAI": return "North Atlantic Industries"; - case "NAKAMICH": return "Nakamichi Corporation"; - case "NatInst": return "National Instruments"; - case "NatSemi": return "National Semiconductor Corp."; - case "NCITS": return "InterNational Committee for Information Technology Standards (INCITS)"; - case "NCL": return "NCL America"; - case "NCR": return "NCR Corporation"; - case "NDBTECH": return "NDB Technologie Inc."; - case "Neartek": return "Neartek, Inc."; - case "NEC": return "NEC"; - case "NETAPP": return "NetApp, Inc. (was Network Appliance)"; - case "NetBSD": return "The NetBSD Foundation"; - case "Netcom": return "Netcom Storage"; - case "NETENGIN": return "NetEngine, Inc."; - case "NEWISYS": return "Newisys Data Storage"; - case "Newtech": return "Newtech Co., Ltd."; - case "NEXSAN": return "Nexsan Technologies, Ltd."; - case "NFINIDAT": return "Infinidat Ltd."; - case "NHR": return "NH Research, Inc."; - case "Nike": return "Nike, Inc."; - case "Nimble": return "Nimble Storage"; - case "NISCA": return "NISCA Inc."; - case "NISHAN": return "Nishan Systems Inc."; - case "Nitz": return "Nitz Associates, Inc."; - case "NKK": return "NKK Corp."; - case "NRC": return "Nakamichi Research Corporation"; - case "NSD": return "Nippon Systems Development Co.,Ltd."; - case "NSM": return "NSM Jukebox GmbH"; - case "nStor": return "nStor Technologies, Inc."; - case "NT": return "Northern Telecom"; - case "NUCONNEX": return "NuConnex"; - case "NUSPEED": return "NuSpeed, Inc."; - case "NVIDIA": return "NVIDIA Corporation"; - case "NVMe": return "NVM Express Working Group"; - case "OAI": return "Optical Access International"; - case "OCE": return "Oce Graphics"; - case "ODS": return "ShenZhen DCS Group Co.,Ltd"; - case "OHDEN": return "Ohden Co., Ltd."; - case "OKI": return "OKI Electric Industry Co.,Ltd (Japan)"; - case "Olidata": return "Olidata S.p.A."; - case "OMI": return "Optical Media International"; - case "OMNIFI": return "Rockford Corporation - Omnifi Media"; - case "OMNIS": return "OMNIS Company (FRANCE)"; - case "Ophidian": return "Ophidian Designs"; - case "opslag": return "Tyrone Systems"; - case "Optelec": return "Optelec BV"; - case "Optiarc": return "Sony Optiarc Inc."; - case "OPTIMEM": return "Cipher/Optimem"; - case "OPTOTECH": return "Optotech"; - case "ORACLE": return "Oracle Corporation"; - case "ORANGE": return "Orange Micro, Inc."; - case "ORCA": return "Orca Technology"; - case "Origin": return "Origin Energy"; - case "OSI": return "Optical Storage International"; - case "OSNEXUS": return "OS NEXUS, Inc."; - case "OTL": return "OTL Engineering"; - case "OVERLAND": return "Overland Storage Inc."; - case "pacdigit": return "Pacific Digital Corp"; - case "Packard": return "Parkard Bell"; - case "Panasas": return "Panasas, Inc."; - case "PARALAN": return "Paralan Corporation"; - case "PASCOsci": return "Pasco Scientific"; - case "PATHLGHT": return "Pathlight Technology, Inc."; - case "PCS": return "Pro Charging Systems, LLC"; - case "PerStor": return "Perstor"; - case "PERTEC": return "Pertec Peripherals Corporation"; - case "PFTI": return "Performance Technology Inc."; - case "PFU": return "PFU Limited"; - case "Phigment": return "Phigment Technologies"; - case "PHILIPS": return "Philips Electronics"; - case "PICO": return "Packard Instrument Company"; - case "PIK": return "TECHNILIENT & MCS"; - case "Pillar": return "Pillar Data Systems"; - case "PIONEER": return "Pioneer Electronic Corp."; - case "Pirus": return "Pirus Networks"; - case "PIVOT3": return "Pivot3, Inc."; - case "PLASMON": return "Plasmon Data"; - case "Pliant": return "Pliant Technology, Inc."; - case "PMCSIERA": return "PMC-Sierra"; - case "PME": return "Precision Measurement Engineering"; - case "PNNMed": return "PNN Medical SA"; - case "POKEN": return "Poken SA"; - case "POLYTRON": return "PT. HARTONO ISTANA TEKNOLOGI"; - case "PRAIRIE": return "PrairieTek"; - case "PREPRESS": return "PrePRESS Solutions"; - case "PRESOFT": return "PreSoft Architects"; - case "PRESTON": return "Preston Scientific"; - case "PRIAM": return "Priam"; - case "PRIMAGFX": return "Primagraphics Ltd"; - case "PRIMOS": return "Primos"; - case "PROCOM": return "Procom Technology"; - case "PROLIFIC": return "Prolific Technology Inc."; - case "PROMISE": return "PROMISE TECHNOLOGY, Inc"; - case "PROSTOR": return "ProStor Systems, Inc."; - case "PROSUM": return "PROSUM"; - case "PROWARE": return "Proware Technology Corp."; - case "PTI": return "Peripheral Technology Inc."; - case "PTICO": return "Pacific Technology International"; - case "PURE": return "PURE Storage"; - case "Qi-Hardw": return "Qi Hardware"; - case "QIC": return "Quarter-Inch Cartridge Drive Standards, Inc."; - case "QLogic": return "QLogic Corporation"; - case "QNAP": return "QNAP Systems"; - case "Qsan": return "QSAN Technology, Inc."; - case "QUALSTAR": return "Qualstar"; - case "QUANTEL": return "Quantel Ltd."; - case "QUANTUM": return "Quantum Corp."; - case "QUIX": return "Quix Computerware AG"; - case "R-BYTE": return "R-Byte, Inc."; - case "RACALREC": return "Racal Recorders"; - case "RADITEC": return "Radikal Technologies Deutschland GmbH"; - case "RADSTONE": return "Radstone Technology"; - case "RAIDINC": return "RAID Inc."; - case "RASSYS": return "Rasilient Systems Inc."; - case "RASVIA": return "Rasvia Systems, Inc."; - case "rave-mp": return "Go Video"; - case "RDKMSTG": return "MMS Dipl. Ing. Rolf-Dieter Klein"; - case "RDStor": return "Rorke China"; - case "Readboy": return "Readboy Ltd Co."; - case "Realm": return "Realm Systems"; - case "realtek": return "Realtek Semiconductor Corp."; - case "REDUXIO": return "Reduxio Systems Ltd."; - case "rehanltd": return "Rehan Electronics Ltd"; - case "REKA": return "REKA HEALTH PTE LTD"; - case "RELDATA": return "RELDATA Inc"; - case "RENAGmbH": return "RENA GmbH"; - case "ReThinkM": return "RETHINK MEDICAL, INC"; - case "Revivio": return "Revivio, Inc."; - case "RGBLaser": return "RGB Lasersysteme GmbH"; - case "RGI": return "Raster Graphics, Inc."; - case "RHAPSODY": return "Rhapsody Networks, Inc."; - case "RHS": return "Racal-Heim Systems GmbH"; - case "RICOH": return "Ricoh"; - case "RODIME": return "Rodime"; - case "Rorke": return "RD DATA Technology (ShenZhen) Limited"; - case "Royaltek": return "RoyalTek company Ltd."; - case "RPS": return "RPS"; - case "RTI": return "Reference Technology"; - case "S-D": return "Sauer-Danfoss"; - case "S-flex": return "Storageflex Inc"; - case "S-SYSTEM": return "S-SYSTEM"; - case "S1": return "storONE"; - case "SAMSUNG": return "Samsung Electronics Co., Ltd."; - case "SAN": return "Storage Area Networks, Ltd."; - case "Sandial": return "Sandial Systems, Inc."; - case "SanDisk": return "SanDisk Corporation"; - case "SANKYO": return "Sankyo Seiki"; - case "SANRAD": return "SANRAD Inc."; - case "SANYO": return "SANYO Electric Co., Ltd."; - case "SC.Net": return "StorageConnections.Net"; - case "SCALE": return "Scale Computing, Inc."; - case "SCIENTEK": return "SCIENTEK CORP"; - case "SCInc.": return "Storage Concepts, Inc."; - case "SCREEN": return "Dainippon Screen Mfg. Co., Ltd."; - case "SDI": return "Storage Dimensions, Inc."; - case "SDS": return "Solid Data Systems"; - case "SEAC": return "SeaChange International, Inc."; - case "SEAGATE": return "Seagate"; - case "SEAGRAND": return "SEAGRAND In Japan"; - case "Seanodes": return "Seanodes"; - case "Sec. Key": return "SecureKey Technologies Inc."; - case "SEQUOIA": return "Sequoia Advanced Technologies, Inc."; - case "SGI": return "Silicon Graphics International"; - case "Shannon": return "Shannon Systems Co., Ltd."; - case "Shinko": return "Shinko Electric Co., Ltd."; - case "SIEMENS": return "Siemens"; - case "SigmaTel": return "SigmaTel, Inc."; - case "SII": return "Seiko Instruments Inc."; - case "SIMPLE": return "SimpleTech, Inc."; - case "SIVMSD": return "IMAGO SOFTWARE SL"; - case "SKhynix": return "SK hynix Inc."; - case "SLCNSTOR": return "SiliconStor, Inc."; - case "SLI": return "Sierra Logic, Inc."; - case "SMCI": return "Super Micro Computer, Inc."; - case "SmrtStor": return "Smart Storage Systems"; - case "SMS": return "Scientific Micro Systems/OMTI"; - case "SMSC": return "SMSC Storage, Inc."; - case "SMX": return "Smartronix, Inc."; - case "SNYSIDE": return "Sunnyside Computing Inc."; - case "SoftLock": return "Softlock Digital Security Provider"; - case "SolidFir": return "SolidFire, Inc."; - case "SONIC": return "Sonic Solutions"; - case "SoniqCas": return "SoniqCast"; - case "SONY": return "Sony Corporation Japan"; - case "SOUL": return "Soul Storage Technology (Wuxi) Co., Ltd"; - case "SPD": return "Storage Products Distribution, Inc."; - case "SPECIAL": return "Special Computing Co."; - case "SPECTRA": return "Spectra Logic, a Division of Western Automation Labs, Inc."; - case "SPERRY": return "Sperry"; - case "Spintso": return "Spintso International AB"; - case "STARBORD": return "Starboard Storage Systems, Inc."; - case "STARWIND": return "StarWind Software, Inc."; - case "STEC": return "STEC, Inc."; - case "Sterling": return "Sterling Diagnostic Imaging, Inc."; - case "STK": return "Storage Technology Corporation"; - case "STNWOOD": return "Stonewood Group"; - case "STONEFLY": return "StoneFly Networks, Inc."; - case "STOR": return "StorageNetworks, Inc."; - case "STORAPP": return "StorageApps, Inc."; - case "STORCIUM": return "Intelligent Systems Services Inc."; - case "STORCOMP": return "Storage Computer Corporation"; - case "STORM": return "Storm Technology, Inc."; - case "StorMagc": return "StorMagic"; - case "Stratus": return "Stratus Technologies"; - case "StrmLgc": return "StreamLogic Corp."; - case "SUMITOMO": return "Sumitomo Electric Industries, Ltd."; - case "SUN": return "Sun Microsystems, Inc."; - case "SUNCORP": return "SunCorporation"; - case "suntx": return "Suntx System Co., Ltd"; - case "SUSE": return "SUSE Linux"; - case "Swinxs": return "Swinxs BV"; - case "SYMANTEC": return "Symantec Corporation"; - case "SYMBIOS": return "Symbios Logic Inc."; - case "SYMWAVE": return "Symwave, Inc."; - case "SYNCSORT": return "Syncsort Incorporated"; - case "SYNERWAY": return "Synerway"; - case "SYNOLOGY": return "Synology, Inc."; - case "SyQuest": return "SyQuest Technology, Inc."; - case "SYSGEN": return "Sysgen"; - case "T-MITTON": return "Transmitton England"; - case "T-MOBILE": return "T-Mobile USA, Inc."; - case "T11": return "INCITS Technical Committee T11"; - case "TALARIS": return "Talaris Systems, Inc."; - case "TALLGRAS": return "Tallgrass Technologies"; - case "TANDBERG": return "Tandberg Data A/S"; - case "TANDEM": return "Tandem"; - case "TANDON": return "Tandon"; - case "TCL": return "TCL Shenzhen ASIC MIcro-electronics Ltd"; - case "TDK": return "TDK Corporation"; - case "TEAC": return "TEAC Japan"; - case "TECOLOTE": return "Tecolote Designs"; - case "TEGRA": return "Tegra Varityper"; - case "Teilch": return "Teilch"; - case "Tek": return "Tektronix"; - case "TELLERT": return "Tellert Elektronik GmbH"; - case "TENTIME": return "Laura Technologies, Inc."; - case "TFDATACO": return "TimeForge"; - case "TGEGROUP": return "TGE Group Co.,LTD."; - case "Thecus": return "Thecus Technology Corp."; - case "TI-DSG": return "Texas Instruments"; - case "TiGi": return "TiGi Corporation"; - case "TILDESGN": return "Tildesign bv"; - case "Tite": return "Tite Technology Limited"; - case "TKS Inc.": return "TimeKeeping Systems, Inc."; - case "TLMKS": return "Telemakus LLC"; - case "TMS": return "Texas Memory Systems, Inc."; - case "TMS100": return "TechnoVas"; - case "TOLISGRP": return "The TOLIS Group"; - case "TOSHIBA": return "Toshiba Japan"; - case "TOYOU": return "TOYOU FEIJI ELECTRONICS CO.,LTD."; - case "Tracker": return "Tracker, LLC"; - case "TRIOFLEX": return "Trioflex Oy"; - case "TRIPACE": return "Tripace"; - case "TRLogger": return "TrueLogger Ltd."; - case "TROIKA": return "Troika Networks, Inc."; - case "TRULY": return "TRULY Electronics MFG. LTD."; - case "TRUSTED": return "Trusted Data Corporation"; - case "TSSTcorp": return "Toshiba Samsung Storage Technology Corporation"; - case "TZM": return "TZ Medical"; - case "UD-DVR": return "Bigstone Project."; - case "UDIGITAL": return "United Digital Limited"; - case "UIT": return "United Infomation Technology"; - case "ULTRA": return "UltraStor Corporation"; - case "UNISTOR": return "Unistor Networks, Inc."; - case "UNISYS": return "Unisys"; - case "USCORE": return "Underscore, Inc."; - case "USDC": return "US Design Corp."; - case "Top VASCO": return "Vasco Data Security"; - case "VDS": return "Victor Data Systems Co., Ltd."; - case "VELDANA": return "VELDANA MEDICAL SA"; - case "VENTANA": return "Ventana Medical Systems"; - case "Verari": return "Verari Systems, Inc."; - case "VERBATIM": return "Verbatim Corporation"; - case "Vercet": return "Vercet LLC"; - case "VERITAS": return "VERITAS Software Corporation"; - case "Vexata": return "Vexata Inc"; - case "VEXCEL": return "VEXCEL IMAGING GmbH"; - case "VICOMSL1": return "Vicom Systems, Inc."; - case "VicomSys": return "Vicom Systems, Inc."; - case "VIDEXINC": return "Videx, Inc."; - case "VIOLIN": return "Violin Memory, Inc."; - case "VIRIDENT": return "Virident Systems, Inc."; - case "VITESSE": return "Vitesse Semiconductor Corporation"; - case "VIXEL": return "Vixel Corporation"; - case "VLS": return "Van Lent Systems BV"; - case "VMAX": return "VMAX Technologies Corp."; - case "VMware": return "VMware Inc."; - case "Vobis": return "Vobis Microcomputer AG"; - case "VOLTAIRE": return "Voltaire Ltd."; - case "VRC": return "Vermont Research Corp."; - case "VRugged": return "Vanguard Rugged Storage"; - case "VTGadget": return "Vermont Gadget Company"; - case "Waitec": return "Waitec NV"; - case "WangDAT": return "WangDAT"; - case "WANGTEK": return "Wangtek"; - case "Wasabi": return "Wasabi Systems"; - case "WAVECOM": return "Wavecom"; - case "WD": return "Western Digital Corporation"; - case "WDC": return "Western Digital Corporation"; - case "WDIGTL": return "Western Digital"; - case "WDTI": return "Western Digital Technologies, Inc."; - case "WEARNES": return "Wearnes Technology Corporation"; - case "WeeraRes": return "Weera Research Pte Ltd"; - case "Wildflwr": return "Wildflower Technologies, Inc."; - case "WSC0001": return "Wisecom, Inc."; - case "X3": return "InterNational Committee for Information Technology Standards (INCITS)"; - case "XEBEC": return "Xebec Corporation"; - case "XENSRC": return "XenSource, Inc."; - case "Xerox": return "Xerox Corporation"; - case "XIOtech": return "XIOtech Corporation"; - case "XIRANET": return "Xiranet Communications GmbH"; - case "XIV": return "XIV"; - case "XtremIO": return "XtremIO"; - case "XYRATEX": return "Xyratex"; - case "YINHE": return "NUDT Computer Co."; - case "YIXUN": return "Yixun Electronic Co.,Ltd."; - case "YOTTA": return "YottaYotta, Inc."; - case "Zarva": return "Zarva Digital Technology Co., Ltd."; - case "ZETTA": return "Zetta Systems, Inc."; - case "ZTE": return "ZTE Corporation"; - case "ZVAULT": return "Zetavault"; - default: return scsiVendorString; + case"0B4C": return"MOOSIK Ltd."; + case"13FE": return"PHISON"; + case"2AI": return"2AI (Automatisme et Avenir Informatique)"; + case"3M": return"3M Company"; + case"3nhtech": return"3NH Technologies"; + case"3PARdata": return"3PARdata, Inc."; + case"A-Max": return"A-Max Technology Co., Ltd"; + case"ABSOLUTE": return"Absolute Analysis"; + case"ACARD": return"ACARD Technology Corp."; + case"Accusys": return"Accusys INC."; + case"Acer": return"Acer, Inc."; + case"ACL": return"Automated Cartridge Librarys, Inc."; + case"Actifio": return"Actifio"; + case"Acuid": return"Acuid Corporation Ltd."; + case"AcuLab": return"AcuLab, Inc. (Tulsa, OK)"; + case"ADAPTEC": return"Adaptec"; + case"ADIC": return"Advanced Digital Information Corporation"; + case"ADSI": return"Adaptive Data Systems, Inc. (a Western Digital subsidiary)"; + case"ADTX": return"ADTX Co., Ltd."; + case"ADVA": return"ADVA Optical Networking AG"; + case"AEM": return"AEM Performance Electronics"; + case"AERONICS": return"Aeronics, Inc."; + case"AGFA": return"AGFA"; + case"Agilent": return"Agilent Technologies"; + case"AIC": return"Advanced Industrial Computer, Inc."; + case"AIPTEK": return"AIPTEK International Inc."; + case"Alcohol": return"Alcohol Soft"; + case"ALCOR": return"Alcor Micro, Corp."; + case"AMCC": return"Applied Micro Circuits Corporation"; + case"AMCODYNE": return"Amcodyne"; + case"Amgeon": return"Amgeon LLC"; + case"AMI": return"American Megatrends, Inc."; + case"AMPEX": return"Ampex Data Systems"; + case"Amphenol": return"Amphenol"; + case"Amtl": return"Tenlon Technology Co.,Ltd"; + case"ANAMATIC": return"Anamartic Limited (England)"; + case"Ancor": return"Ancor Communications, Inc."; + case"ANCOT": return"ANCOT Corp."; + case"ANDATACO": return"Andataco"; + case"andiamo": return"Andiamo Systems, Inc."; + case"ANOBIT": return"Anobit"; + case"ANRITSU": return"Anritsu Corporation"; + case"ANTONIO": return"Antonio Precise Products Manufactory Ltd."; + case"AoT": return"Art of Technology AG"; + case"APPLE": return"Apple Computer, Inc."; + case"ARCHIVE": return"Archive"; + case"ARDENCE": return"Ardence Inc"; + case"Areca": return"Areca Technology Corporation"; + case"Arena": return"MaxTronic International Co., Ltd."; + case"Argent": return"Argent Data Systems, Inc."; + case"ARIO": return"Ario Data Networks, Inc."; + case"ARISTOS": return"Aristos Logic Corp."; + case"ARK": return"ARK Research Corporation"; + case"ARL:UT@A": return"Applied Research Laboratories : University of Texas at Austin"; + case"ARTECON": return"Artecon Inc."; + case"Artistic": return"Artistic Licence (UK) Ltd"; + case"ARTON": return"Arton Int."; + case"ASACA": return"ASACA Corp."; + case"ASC": return"Advanced Storage Concepts, Inc."; + case"ASPEN": return"Aspen Peripherals"; + case"AST": return"AST Research"; + case"ASTEK": return"Astek Corporation"; + case"ASTK": return"Alcatel STK A/S"; + case"AStor": return"AccelStor, Inc."; + case"ASTUTE": return"Astute Networks, Inc."; + case"AT&T": return"AT&T"; + case"ATA": return"SCSI / ATA Translator Software (Organization Not Specified)"; + case"ATARI": return"Atari Corporation"; + case"ATech": return"ATech electronics"; + case"ATG CYG": return"ATG Cygnet Inc."; + case"ATL": return"Quantum|ATL Products"; + case"ATTO": return"ATTO Technology Inc."; + case"ATTRATEC": return"Attratech Ltd liab. Co"; + case"ATX": return"Alphatronix"; + case"AURASEN": return"Aurasen Limited"; + case"Avago": return"Avago Technologies"; + case"AVC": return"AVC Technology Ltd"; + case"AVIDVIDR": return"AVID Technologies, Inc."; + case"AVR": return"Advanced Vision Research"; + case"AXSTOR": return"AXSTOR"; + case"Axxana": return"Axxana Ltd."; + case"B*BRIDGE": return"Blockbridge Networks LLC"; + case"BALLARD": return"Ballard Synergy Corp."; + case"Barco": return"Barco"; + case"BAROMTEC": return"Barom Technologies Co., Ltd."; + case"Bassett": return"Bassett Electronic Systems Ltd"; + case"BC Hydro": return"BC Hydro"; + case"BDT": return"BDT AG"; + case"BECEEM": return"Beceem Communications, Inc"; + case"BENQ": return"BENQ Corporation."; + case"BERGSWD": return"Berg Software Design"; + case"BEZIER": return"Bezier Systems, Inc."; + case"BHTi": return"Breece Hill Technologies"; + case"biodata": return"Biodata Devices SL"; + case"BIOS": return"BIOS Corporation"; + case"BIR": return"Bio-Imaging Research, Inc."; + case"BiT": return"BiT Microsystems"; + case"BITMICRO": return"BiT Microsystems, Inc."; + case"Blendlgy": return"Blendology Limited"; + case"BLOOMBAS": return"Bloombase Technologies Limited"; + case"BlueArc": return"BlueArc Corporation"; + case"bluecog": return"bluecog"; + case"BME-HVT": return"Broadband Infocommunicatons and Electromagnetic Theory Department"; + case"BNCHMARK": return"Benchmark Tape Systems Corporation"; + case"Bosch": return"Robert Bosch GmbH"; + case"Botman": return"Botmanfamily Electronics"; + case"BoxHill": return"Box Hill Systems Corporation"; + case"BRDGWRKS": return"Bridgeworks Ltd."; + case"BREA": return"BREA Technologies, Inc."; + case"BREECE": return"Breece Hill LLC"; + case"BreqLabs": return"BreqLabs Inc."; + case"Broadcom": return"Broadcom Corporation"; + case"BROCADE": return"Brocade Communications Systems, Incorporated"; + case"BUFFALO": return"BUFFALO INC."; + case"BULL": return"Bull Peripherals Corp."; + case"BUSLOGIC": return"BusLogic Inc."; + case"BVIRTUAL": return"B-Virtual N.V."; + case"CACHEIO": return"CacheIO LLC"; + case"CalComp": return"CalComp, A Lockheed Company"; + case"CALCULEX": return"CALCULEX, Inc."; + case"CALIPER": return"Caliper (California Peripheral Corp.)"; + case"CAMBEX": return"Cambex Corporation"; + case"CAMEOSYS": return"Cameo Systems Inc."; + case"CANDERA": return"Candera Inc."; + case"CAPTION": return"CAPTION BANK"; + case"CAST": return"Advanced Storage Tech"; + case"CATALYST": return"Catalyst Enterprises"; + case"CCDISK": return"iSCSI Cake"; + case"CDC": return"Control Data or MPI"; + case"CDP": return"Columbia Data Products"; + case"Celsia": return"A M Bromley Limited"; + case"CenData": return"Central Data Corporation"; + case"Cereva": return"Cereva Networks Inc."; + case"CERTANCE": return"Certance"; + case"Chantil": return"Chantil Technology"; + case"CHEROKEE": return"Cherokee Data Systems"; + case"CHINON": return"Chinon"; + case"CHRISTMA": return"Christmann Informationstechnik + Medien GmbH & Co KG"; + case"CIE&YED": return"YE Data, C.Itoh Electric Corp."; + case"CIPHER": return"Cipher Data Products"; + case"Ciprico": return"Ciprico, Inc."; + case"CIRRUSL": return"Cirrus Logic Inc."; + case"CISCO": return"Cisco Systems, Inc."; + case"CLEARSKY": return"ClearSky Data, Inc."; + case"CLOVERLF": return"Cloverleaf Communications, Inc"; + case"CLS": return"Celestica"; + case"CMD": return"CMD Technology Inc."; + case"CMTechno": return"CMTech"; + case"CNGR SFW": return"Congruent Software, Inc."; + case"CNSi": return"Chaparral Network Storage, Inc."; + case"CNT": return"Computer Network Technology"; + case"COBY": return"Coby Electronics Corporation, USA"; + case"COGITO": return"Cogito"; + case"COMAY": return"Corerise Electronics"; + case"COMPAQ": return"Compaq Computer Corporation"; + case"COMPELNT": return"Compellent Technologies, Inc."; + case"COMPORT": return"Comport Corp."; + case"COMPSIG": return"Computer Signal Corporation"; + case"COMPTEX": return"Comptex Pty Limited"; + case"CONNER": return"Conner Peripherals"; + case"COPANSYS": return"COPAN SYSTEMS INC"; + case"CORAID": return"Coraid, Inc"; + case"CORE": return"Core International, Inc."; + case"CORERISE": return"Corerise Electronics"; + case"COVOTE": return"Covote GmbH & Co KG"; + case"COWON": return"COWON SYSTEMS, Inc."; + case"CPL": return"Cross Products Ltd"; + case"CPU TECH": return"CPU Technology, Inc."; + case"CREO": return"Creo Products Inc."; + case"CROSFLD": return"Crosfield Electronics"; + case"CROSSRDS": return"Crossroads Systems, Inc."; + case"crosswlk": return"Crosswalk, Inc."; + case"CSCOVRTS": return"Cisco - Veritas"; + case"CSM, INC": return"Computer SM, Inc."; + case"Cunuqui": return"CUNUQUI SLU"; + case"CYBERNET": return"Cybernetics"; + case"Cygnal": return"Dekimo"; + case"CYPRESS": return"Cypress Semiconductor Corp."; + case"D Bit": return"Digby's Bitpile, Inc. DBA D Bit"; + case"DALSEMI": return"Dallas Semiconductor"; + case"DANEELEC": return"Dane-Elec"; + case"DANGER": return"Danger Inc."; + case"DAT-MG": return"DAT Manufacturers Group"; + case"Data Com": return"Data Com Information Systems Pty. Ltd."; + case"DATABOOK": return"Databook, Inc."; + case"DATACOPY": return"Datacopy Corp."; + case"DataCore": return"DataCore Software Corporation"; + case"DataG": return"DataGravity"; + case"DATAPT": return"Datapoint Corp."; + case"DATARAM": return"Dataram Corporation"; + case"DATC": return"Datum Champion Technology Co., Ltd"; + case"DAVIS": return"Daviscomms (S) Pte Ltd"; + case"DCS": return"ShenZhen DCS Group Co.,Ltd"; + case"DDN": return"DataDirect Networks, Inc."; + case"DDRDRIVE": return"DDRdrive LLC"; + case"DE": return"Dimension Engineering LLC"; + case"DEC": return"Digital Equipment Corporation"; + case"DEI": return"Digital Engineering, Inc."; + case"DELL": return"Dell, Inc."; + case"Dell(tm)": return"Dell, Inc"; + case"DELPHI": return"Delphi Data Div. of Sparks Industries, Inc."; + case"DENON": return"Denon/Nippon Columbia"; + case"DenOptix": return"DenOptix, Inc."; + case"DEST": return"DEST Corp."; + case"DFC": return"DavioFranke.com"; + case"DFT": return"Data Fault Tolerance System CO.,LTD."; + case"DGC": return"Data General Corp."; + case"DIGIDATA": return"Digi-Data Corporation"; + case"DigiIntl": return"Digi International"; + case"Digital": return"Digital Equipment Corporation"; + case"DILOG": return"Distributed Logic Corp."; + case"DISC": return"Document Imaging Systems Corp."; + case"DiscSoft": return"Disc Soft Ltd"; + case"DLNET": return"Driveline"; + case"DNS": return"Data and Network Security"; + case"DNUK": return"Digital Networks Uk Ltd"; + case"DotHill": return"Dot Hill Systems Corp."; + case"DP": return"Dell, Inc."; + case"DPT": return"Distributed Processing Technology"; + case"Drewtech": return"Drew Technologies, Inc."; + case"DROBO": return"Data Robotics, Inc."; + case"DSC": return"DigitalStream Corporation"; + case"DSI": return"Data Spectrum, Inc."; + case"DSM": return"Deterner Steuerungs- und Maschinenbau GmbH & Co."; + case"DSNET": return"Cleversafe, Inc."; + case"DT": return"Double-Take Software, INC."; + case"DTC QUME": return"Data Technology Qume"; + case"DXIMAGIN": return"DX Imaging"; + case"E-Motion": return"E-Motion LLC"; + case"EARTHLAB": return"EarthLabs"; + case"EarthLCD": return"Earth Computer Technologies, Inc."; + case"ECCS": return"ECCS, Inc."; + case"ECMA": return"European Computer Manufacturers Association"; + case"EDS": return"Embedded Data Systems"; + case"EIM": return"InfoCore"; + case"ELE Intl": return"ELE International"; + case"ELEGANT": return"Elegant Invention, LLC"; + case"Elektron": return"Elektron Music Machines MAV AB"; + case"elipsan": return"Elipsan UK Ltd."; + case"Elms": return"Elms Systems Corporation"; + case"ELSE": return"ELSE Ltd."; + case"ELSEC": return"Littlemore Scientific"; + case"EMASS": return"EMASS, Inc."; + case"EMC": return"EMC Corp."; + case"EMiT": return"EMiT Conception Eletronique"; + case"EMTEC": return"EMTEC Magnetics"; + case"EMULEX": return"Emulex"; + case"ENERGY-B": return"Energybeam Corporation"; + case"ENGENIO": return"Engenio Information Technologies, Inc."; + case"ENMOTUS": return"Enmotus Inc"; + case"Entacore": return"Entacore"; + case"EPOS": return"EPOS Technologies Ltd."; + case"EPSON": return"Epson"; + case"EQLOGIC": return"EqualLogic"; + case"Eris/RSI": return"RSI Systems, Inc."; + case"ETERNE": return"EterneData Technology Co.,Ltd.(China PRC.)"; + case"EuroLogc": return"Eurologic Systems Limited"; + case"evolve": return"Evolution Technologies, Inc"; + case"EXABYTE": return"Exabyte Corp."; + case"EXATEL": return"Exatelecom Co., Ltd."; + case"EXAVIO": return"Exavio, Inc."; + case"Exsequi": return"Exsequi Ltd"; + case"Exxotest": return"Annecy Electronique"; + case"FAIRHAVN": return"Fairhaven Health, LLC"; + case"FALCON": return"FalconStor, Inc."; + case"FDS": return"Formation Data Systems"; + case"FFEILTD": return"FujiFilm Electonic Imaging Ltd"; + case"Fibxn": return"Fiberxon, Inc."; + case"FID": return"First International Digital, Inc."; + case"FILENET": return"FileNet Corp."; + case"FirmFact": return"Firmware Factory Ltd"; + case"FLYFISH": return"Flyfish Technologies"; + case"FOXCONN": return"Foxconn Technology Group"; + case"FRAMDRV": return"FRAMEDRIVE Corp."; + case"FREECION": return"Nable Communications, Inc."; + case"FRESHDTK": return"FreshDetect GmbH"; + case"FSC": return"Fujitsu Siemens Computers"; + case"FTPL": return"Frontline Technologies Pte Ltd"; + case"FUJI": return"Fuji Electric Co., Ltd. (Japan)"; + case"FUJIFILM": return"Fuji Photo Film, Co., Ltd."; + case"FUJITSU": return"Fujitsu"; + case"FUNAI": return"Funai Electric Co., Ltd."; + case"FUSIONIO": return"Fusion-io Inc."; + case"FUTURED": return"Future Domain Corp."; + case"G&D": return"Giesecke & Devrient GmbH"; + case"G.TRONIC": return"Globaltronic - Electronica e Telecomunicacoes, S.A."; + case"Gadzoox": return"Gadzoox Networks, Inc."; + case"Gammaflx": return"Gammaflux L.P."; + case"GDI": return"Generic Distribution International"; + case"GEMALTO": return"gemalto"; + case"Gen_Dyn": return"General Dynamics"; + case"Generic": return"Generic Technology Co., Ltd."; + case"GENSIG": return"General Signal Networks"; + case"GEO": return"Green Energy Options Ltd"; + case"GIGATAPE": return"GIGATAPE GmbH"; + case"GIGATRND": return"GigaTrend Incorporated"; + case"Global": return"Global Memory Test Consortium"; + case"Gnutek": return"Gnutek Ltd."; + case"Goidelic": return"Goidelic Precision, Inc."; + case"GoldKey": return"GoldKey Security Corporation"; + case"GoldStar": return"LG Electronics Inc."; + case"GOOGLE": return"Google, Inc."; + case"GORDIUS": return"Gordius"; + case"GOULD": return"Gould"; + case"HAGIWARA": return"Hagiwara Sys-Com Co., Ltd."; + case"HAPP3": return"Inventec Multimedia and Telecom co., ltd"; + case"HDS": return"Horizon Data Systems, Inc."; + case"Helldyne": return"Helldyne, Inc"; + case"Heydays": return"Mazo Technology Co., Ltd."; + case"HGST": return"HGST a Western Digital Company"; + case"HI-TECH": return"HI-TECH Software Pty. Ltd."; + case"HITACHI": return"Hitachi America Ltd or Nissei Sangyo America Ltd"; + case"HL-DT-ST": return"Hitachi-LG Data Storage, Inc."; + case"HONEYWEL": return"Honeywell Inc."; + case"Hoptroff": return"HexWax Ltd"; + case"HORIZONT": return"Horizontigo Software"; + case"HP": return"Hewlett Packard"; + case"HPE": return"Hewlett Packard Enterprise"; + case"HPI": return"HP Inc."; + case"HPQ": return"Hewlett Packard"; + case"HUALU": return"CHINA HUALU GROUP CO., LTD"; + case"HUASY": return"Huawei Symantec Technologies Co., Ltd."; + case"HYLINX": return"Hylinx Ltd."; + case"HYUNWON": return"HYUNWON inc"; + case"i-cubed": return"i-cubed ltd."; + case"IBM": return"International Business Machines"; + case"Icefield": return"Icefield Tools Corporation"; + case"Iceweb": return"Iceweb Storage Corp"; + case"ICL": return"ICL"; + case"ICP": return"ICP vortex Computersysteme GmbH"; + case"IDE": return"International Data Engineering, Inc."; + case"IDG": return"Interface Design Group"; + case"IET": return"ISCSI ENTERPRISE TARGET"; + case"IFT": return"Infortrend Technology, Inc."; + case"IGR": return"Intergraph Corp."; + case"IMAGINE": return"Imagine Communications Corp."; + case"IMAGO": return"IMAGO SOFTWARE SL"; + case"IMATION": return"Imation"; + case"IMPLTD": return"Integrated Micro Products Ltd."; + case"IMPRIMIS": return"Imprimis Technology Inc."; + case"INCIPNT": return"Incipient Technologies Inc."; + case"INCITS": return"InterNational Committee for Information Technology"; + case"INDCOMP": return"Industrial Computing Limited"; + case"Indigita": return"Indigita Corporation"; + case"INFOCORE": return"InfoCore"; + case"INITIO": return"Initio Corporation"; + case"INRANGE": return"INRANGE Technologies Corporation"; + case"Insight": return"L-3 Insight Technology Inc"; + case"INSITE": return"Insite Peripherals"; + case"integrix": return"Integrix, Inc."; + case"INTEL": return"Intel Corporation"; + case"Intransa": return"Intransa, Inc."; + case"IOC": return"I/O Concepts, Inc."; + case"iofy": return"iofy Corporation"; + case"IOMEGA": return"Iomega"; + case"IOT": return"IO Turbine, Inc."; + case"iPaper": return"intelliPaper, LLC"; + case"iqstor": return"iQstor Networks, Inc."; + case"iQue": return"iQue"; + case"ISi": return"Information Storage inc."; + case"Isilon": return"Isilon Systems, Inc."; + case"ISO": return"International Standards Organization"; + case"iStor": return"iStor Networks, Inc."; + case"ITC": return"International Tapetronics Corporation"; + case"iTwin": return"iTwin Pte Ltd"; + case"IVIVITY": return"iVivity, Inc."; + case"IVMMLTD": return"InnoVISION Multimedia Ltd."; + case"JABIL001": return"Jabil Circuit"; + case"JETWAY": return"Jetway Information Co., Ltd"; + case"JMR": return"JMR Electronics Inc."; + case"JOFEMAR": return"Jofemar"; + case"JOLLYLOG": return"Jolly Logic"; + case"JPC Inc.": return"JPC Inc."; + case"JSCSI": return"jSCSI Project"; + case"Juniper": return"Juniper Networks"; + case"JVC": return"JVC Information Products Co."; + case"KASHYA": return"Kashya, Inc."; + case"KENNEDY": return"Kennedy Company"; + case"KENWOOD": return"KENWOOD Corporation"; + case"KEWL": return"Shanghai KEWL Imp&Exp Co., Ltd."; + case"Key Tech": return"Key Technologies, Inc"; + case"KMNRIO": return"Kaminario Technologies Ltd."; + case"KODAK": return"Eastman Kodak"; + case"KONAN": return"Konan"; + case"koncepts": return"koncepts International Ltd."; + case"KONICA": return"Konica Japan"; + case"KOVE": return"KOVE"; + case"KSCOM": return"KSCOM Co. Ltd.,"; + case"KUDELSKI": return"Nagravision SA - Kudelski Group"; + case"Kyocera": return"Kyocera Corporation"; + case"Lapida": return"Gonmalo Electronics"; + case"LAPINE": return"Lapine Technology"; + case"LASERDRV": return"LaserDrive Limited"; + case"LASERGR": return"Lasergraphics, Inc."; + case"LeapFrog": return"LeapFrog Enterprises, Inc."; + case"LEFTHAND": return"LeftHand Networks"; + case"Leica": return"Leica Camera AG"; + case"Lexar": return"Lexar Media, Inc."; + case"LEYIO": return"LEYIO"; + case"LG": return"LG Electronics Inc."; + case"LGE": return"LG Electronics Inc."; + case"LIBNOVA": return"LIBNOVA, SL Digital Preservation Systems"; + case"LION": return"Lion Optics Corporation"; + case"LMS": return"Laser Magnetic Storage International Company"; + case"LoupTech": return"Loup Technologies, Inc."; + case"LSI": return"LSI Corp. (was LSI Logic Corp.)"; + case"LSILOGIC": return"LSI Logic Storage Systems, Inc."; + case"LTO-CVE": return"Linear Tape - Open, Compliance Verification Entity"; + case"LUXPRO": return"Luxpro Corporation"; + case"MacroSAN": return"MacroSAN Technologies Co., Ltd."; + case"Malakite": return"Malachite Technologies (New VID is: Sandial)"; + case"MarcBoon": return"marcboon.com"; + case"Marner": return"Marner Storage Technologies, Inc."; + case"MARVELL": return"Marvell Semiconductor, Inc."; + case"Matrix": return"Matrix Orbital Corp."; + case"MATSHITA": return"Matsushita"; + case"MAXELL": return"Hitachi Maxell, Ltd."; + case"MAXIM-IC": return"Maxim Integrated Products"; + case"MaxOptix": return"Maxoptix Corp."; + case"MAXSTRAT": return"Maximum Strategy, Inc."; + case"MAXTOR": return"Maxtor Corp."; + case"MaXXan": return"MaXXan Systems, Inc."; + case"MAYCOM": return"maycom Co., Ltd."; + case"MBEAT": return"K-WON C&C Co.,Ltd"; + case"MCC": return"Measurement Computing Corporation"; + case"McDATA": return"McDATA Corporation"; + case"MCUBE": return"Mcube Technology Co., Ltd."; + case"MDI": return"Micro Design International, Inc."; + case"MEADE": return"Meade Instruments Corporation"; + case"mediamat": return"mediamatic"; + case"MegaElec": return"Mega Electronics Ltd"; + case"MEII": return"Mountain Engineering II, Inc."; + case"MELA": return"Mitsubishi Electronics America"; + case"MELCO": return"Mitsubishi Electric (Japan)"; + case"mellanox": return"Mellanox Technologies Ltd."; + case"MEMOREX": return"Memorex Telex Japan Ltd."; + case"MEMREL": return"Memrel Corporation"; + case"MEMTECH": return"MemTech Technology"; + case"Mendocin": return"Mendocino Software"; + case"MendoCno": return"Mendocino Software"; + case"MERIDATA": return"Oy Meridata Finland Ltd"; + case"METHODEI": return"Methode Electronics India pvt ltd"; + case"METRUM": return"Metrum, Inc."; + case"MHTL": return"Matsunichi Hi-Tech Limited"; + case"MICROBTX": return"Microbotics Inc."; + case"Microchp": return"Microchip Technology, Inc."; + case"MICROLIT": return"Microlite Corporation"; + case"MICRON": return"Micron Technology, Inc."; + case"MICROP": return"Micropolis"; + case"MICROTEK": return"Microtek Storage Corp"; + case"Minitech": return"Minitech (UK) Limited"; + case"Minolta": return"Minolta Corporation"; + case"MINSCRIB": return"Miniscribe"; + case"MiraLink": return"MiraLink Corporation"; + case"Mirifica": return"Mirifica s.r.l."; + case"MITSUMI": return"Mitsumi Electric Co., Ltd."; + case"MKM": return"Mitsubishi Kagaku Media Co., LTD."; + case"Mobii": return"Mobii Systems (Pty.) Ltd."; + case"MOL": return"Petrosoft Sdn. Bhd."; + case"MOSAID": return"Mosaid Technologies Inc."; + case"MOTOROLA": return"Motorola"; + case"MP-400": return"Daiwa Manufacturing Limited"; + case"MPC": return"MPC Corporation"; + case"MPCCORP": return"MPC Computers"; + case"MPEYE": return"Touchstone Technology Co., Ltd"; + case"MPIO": return"DKT Co.,Ltd"; + case"MPM": return"Mitsubishi Paper Mills, Ltd."; + case"MPMan": return"MPMan.com, Inc."; + case"MSFT": return"Microsoft Corporation"; + case"MSI": return"Micro-Star International Corp."; + case"MST": return"Morning Star Technologies, Inc."; + case"MSystems": return"M-Systems Flash Disk Pioneers"; + case"MTI": return"MTI Technology Corporation"; + case"MTNGATE": return"MountainGate Data Systems"; + case"MXI": return"Memory Experts International"; + case"nac": return"nac Image Technology Inc."; + case"NAGRA": return"Nagravision SA - Kudelski Group"; + case"NAI": return"North Atlantic Industries"; + case"NAKAMICH": return"Nakamichi Corporation"; + case"NatInst": return"National Instruments"; + case"NatSemi": return"National Semiconductor Corp."; + case"NCITS": return"InterNational Committee for Information Technology Standards (INCITS)"; + case"NCL": return"NCL America"; + case"NCR": return"NCR Corporation"; + case"NDBTECH": return"NDB Technologie Inc."; + case"Neartek": return"Neartek, Inc."; + case"NEC": return"NEC"; + case"NETAPP": return"NetApp, Inc. (was Network Appliance)"; + case"NetBSD": return"The NetBSD Foundation"; + case"Netcom": return"Netcom Storage"; + case"NETENGIN": return"NetEngine, Inc."; + case"NEWISYS": return"Newisys Data Storage"; + case"Newtech": return"Newtech Co., Ltd."; + case"NEXSAN": return"Nexsan Technologies, Ltd."; + case"NFINIDAT": return"Infinidat Ltd."; + case"NHR": return"NH Research, Inc."; + case"Nike": return"Nike, Inc."; + case"Nimble": return"Nimble Storage"; + case"NISCA": return"NISCA Inc."; + case"NISHAN": return"Nishan Systems Inc."; + case"Nitz": return"Nitz Associates, Inc."; + case"NKK": return"NKK Corp."; + case"NRC": return"Nakamichi Research Corporation"; + case"NSD": return"Nippon Systems Development Co.,Ltd."; + case"NSM": return"NSM Jukebox GmbH"; + case"nStor": return"nStor Technologies, Inc."; + case"NT": return"Northern Telecom"; + case"NUCONNEX": return"NuConnex"; + case"NUSPEED": return"NuSpeed, Inc."; + case"NVIDIA": return"NVIDIA Corporation"; + case"NVMe": return"NVM Express Working Group"; + case"OAI": return"Optical Access International"; + case"OCE": return"Oce Graphics"; + case"ODS": return"ShenZhen DCS Group Co.,Ltd"; + case"OHDEN": return"Ohden Co., Ltd."; + case"OKI": return"OKI Electric Industry Co.,Ltd (Japan)"; + case"Olidata": return"Olidata S.p.A."; + case"OMI": return"Optical Media International"; + case"OMNIFI": return"Rockford Corporation - Omnifi Media"; + case"OMNIS": return"OMNIS Company (FRANCE)"; + case"Ophidian": return"Ophidian Designs"; + case"opslag": return"Tyrone Systems"; + case"Optelec": return"Optelec BV"; + case"Optiarc": return"Sony Optiarc Inc."; + case"OPTIMEM": return"Cipher/Optimem"; + case"OPTOTECH": return"Optotech"; + case"ORACLE": return"Oracle Corporation"; + case"ORANGE": return"Orange Micro, Inc."; + case"ORCA": return"Orca Technology"; + case"Origin": return"Origin Energy"; + case"OSI": return"Optical Storage International"; + case"OSNEXUS": return"OS NEXUS, Inc."; + case"OTL": return"OTL Engineering"; + case"OVERLAND": return"Overland Storage Inc."; + case"pacdigit": return"Pacific Digital Corp"; + case"Packard": return"Parkard Bell"; + case"Panasas": return"Panasas, Inc."; + case"PARALAN": return"Paralan Corporation"; + case"PASCOsci": return"Pasco Scientific"; + case"PATHLGHT": return"Pathlight Technology, Inc."; + case"PCS": return"Pro Charging Systems, LLC"; + case"PerStor": return"Perstor"; + case"PERTEC": return"Pertec Peripherals Corporation"; + case"PFTI": return"Performance Technology Inc."; + case"PFU": return"PFU Limited"; + case"Phigment": return"Phigment Technologies"; + case"PHILIPS": return"Philips Electronics"; + case"PICO": return"Packard Instrument Company"; + case"PIK": return"TECHNILIENT & MCS"; + case"Pillar": return"Pillar Data Systems"; + case"PIONEER": return"Pioneer Electronic Corp."; + case"Pirus": return"Pirus Networks"; + case"PIVOT3": return"Pivot3, Inc."; + case"PLASMON": return"Plasmon Data"; + case"Pliant": return"Pliant Technology, Inc."; + case"PMCSIERA": return"PMC-Sierra"; + case"PME": return"Precision Measurement Engineering"; + case"PNNMed": return"PNN Medical SA"; + case"POKEN": return"Poken SA"; + case"POLYTRON": return"PT. HARTONO ISTANA TEKNOLOGI"; + case"PRAIRIE": return"PrairieTek"; + case"PREPRESS": return"PrePRESS Solutions"; + case"PRESOFT": return"PreSoft Architects"; + case"PRESTON": return"Preston Scientific"; + case"PRIAM": return"Priam"; + case"PRIMAGFX": return"Primagraphics Ltd"; + case"PRIMOS": return"Primos"; + case"PROCOM": return"Procom Technology"; + case"PROLIFIC": return"Prolific Technology Inc."; + case"PROMISE": return"PROMISE TECHNOLOGY, Inc"; + case"PROSTOR": return"ProStor Systems, Inc."; + case"PROSUM": return"PROSUM"; + case"PROWARE": return"Proware Technology Corp."; + case"PTI": return"Peripheral Technology Inc."; + case"PTICO": return"Pacific Technology International"; + case"PURE": return"PURE Storage"; + case"Qi-Hardw": return"Qi Hardware"; + case"QIC": return"Quarter-Inch Cartridge Drive Standards, Inc."; + case"QLogic": return"QLogic Corporation"; + case"QNAP": return"QNAP Systems"; + case"Qsan": return"QSAN Technology, Inc."; + case"QUALSTAR": return"Qualstar"; + case"QUANTEL": return"Quantel Ltd."; + case"QUANTUM": return"Quantum Corp."; + case"QUIX": return"Quix Computerware AG"; + case"R-BYTE": return"R-Byte, Inc."; + case"RACALREC": return"Racal Recorders"; + case"RADITEC": return"Radikal Technologies Deutschland GmbH"; + case"RADSTONE": return"Radstone Technology"; + case"RAIDINC": return"RAID Inc."; + case"RASSYS": return"Rasilient Systems Inc."; + case"RASVIA": return"Rasvia Systems, Inc."; + case"rave-mp": return"Go Video"; + case"RDKMSTG": return"MMS Dipl. Ing. Rolf-Dieter Klein"; + case"RDStor": return"Rorke China"; + case"Readboy": return"Readboy Ltd Co."; + case"Realm": return"Realm Systems"; + case"realtek": return"Realtek Semiconductor Corp."; + case"REDUXIO": return"Reduxio Systems Ltd."; + case"rehanltd": return"Rehan Electronics Ltd"; + case"REKA": return"REKA HEALTH PTE LTD"; + case"RELDATA": return"RELDATA Inc"; + case"RENAGmbH": return"RENA GmbH"; + case"ReThinkM": return"RETHINK MEDICAL, INC"; + case"Revivio": return"Revivio, Inc."; + case"RGBLaser": return"RGB Lasersysteme GmbH"; + case"RGI": return"Raster Graphics, Inc."; + case"RHAPSODY": return"Rhapsody Networks, Inc."; + case"RHS": return"Racal-Heim Systems GmbH"; + case"RICOH": return"Ricoh"; + case"RODIME": return"Rodime"; + case"Rorke": return"RD DATA Technology (ShenZhen) Limited"; + case"Royaltek": return"RoyalTek company Ltd."; + case"RPS": return"RPS"; + case"RTI": return"Reference Technology"; + case"S-D": return"Sauer-Danfoss"; + case"S-flex": return"Storageflex Inc"; + case"S-SYSTEM": return"S-SYSTEM"; + case"S1": return"storONE"; + case"SAMSUNG": return"Samsung Electronics Co., Ltd."; + case"SAN": return"Storage Area Networks, Ltd."; + case"Sandial": return"Sandial Systems, Inc."; + case"SanDisk": return"SanDisk Corporation"; + case"SANKYO": return"Sankyo Seiki"; + case"SANRAD": return"SANRAD Inc."; + case"SANYO": return"SANYO Electric Co., Ltd."; + case"SC.Net": return"StorageConnections.Net"; + case"SCALE": return"Scale Computing, Inc."; + case"SCIENTEK": return"SCIENTEK CORP"; + case"SCInc.": return"Storage Concepts, Inc."; + case"SCREEN": return"Dainippon Screen Mfg. Co., Ltd."; + case"SDI": return"Storage Dimensions, Inc."; + case"SDS": return"Solid Data Systems"; + case"SEAC": return"SeaChange International, Inc."; + case"SEAGATE": return"Seagate"; + case"SEAGRAND": return"SEAGRAND In Japan"; + case"Seanodes": return"Seanodes"; + case"Sec. Key": return"SecureKey Technologies Inc."; + case"SEQUOIA": return"Sequoia Advanced Technologies, Inc."; + case"SGI": return"Silicon Graphics International"; + case"Shannon": return"Shannon Systems Co., Ltd."; + case"Shinko": return"Shinko Electric Co., Ltd."; + case"SIEMENS": return"Siemens"; + case"SigmaTel": return"SigmaTel, Inc."; + case"SII": return"Seiko Instruments Inc."; + case"SIMPLE": return"SimpleTech, Inc."; + case"SIVMSD": return"IMAGO SOFTWARE SL"; + case"SKhynix": return"SK hynix Inc."; + case"SLCNSTOR": return"SiliconStor, Inc."; + case"SLI": return"Sierra Logic, Inc."; + case"SMCI": return"Super Micro Computer, Inc."; + case"SmrtStor": return"Smart Storage Systems"; + case"SMS": return"Scientific Micro Systems/OMTI"; + case"SMSC": return"SMSC Storage, Inc."; + case"SMX": return"Smartronix, Inc."; + case"SNYSIDE": return"Sunnyside Computing Inc."; + case"SoftLock": return"Softlock Digital Security Provider"; + case"SolidFir": return"SolidFire, Inc."; + case"SONIC": return"Sonic Solutions"; + case"SoniqCas": return"SoniqCast"; + case"SONY": return"Sony Corporation Japan"; + case"SOUL": return"Soul Storage Technology (Wuxi) Co., Ltd"; + case"SPD": return"Storage Products Distribution, Inc."; + case"SPECIAL": return"Special Computing Co."; + case"SPECTRA": return"Spectra Logic, a Division of Western Automation Labs, Inc."; + case"SPERRY": return"Sperry"; + case"Spintso": return"Spintso International AB"; + case"STARBORD": return"Starboard Storage Systems, Inc."; + case"STARWIND": return"StarWind Software, Inc."; + case"STEC": return"STEC, Inc."; + case"Sterling": return"Sterling Diagnostic Imaging, Inc."; + case"STK": return"Storage Technology Corporation"; + case"STNWOOD": return"Stonewood Group"; + case"STONEFLY": return"StoneFly Networks, Inc."; + case"STOR": return"StorageNetworks, Inc."; + case"STORAPP": return"StorageApps, Inc."; + case"STORCIUM": return"Intelligent Systems Services Inc."; + case"STORCOMP": return"Storage Computer Corporation"; + case"STORM": return"Storm Technology, Inc."; + case"StorMagc": return"StorMagic"; + case"Stratus": return"Stratus Technologies"; + case"StrmLgc": return"StreamLogic Corp."; + case"SUMITOMO": return"Sumitomo Electric Industries, Ltd."; + case"SUN": return"Sun Microsystems, Inc."; + case"SUNCORP": return"SunCorporation"; + case"suntx": return"Suntx System Co., Ltd"; + case"SUSE": return"SUSE Linux"; + case"Swinxs": return"Swinxs BV"; + case"SYMANTEC": return"Symantec Corporation"; + case"SYMBIOS": return"Symbios Logic Inc."; + case"SYMWAVE": return"Symwave, Inc."; + case"SYNCSORT": return"Syncsort Incorporated"; + case"SYNERWAY": return"Synerway"; + case"SYNOLOGY": return"Synology, Inc."; + case"SyQuest": return"SyQuest Technology, Inc."; + case"SYSGEN": return"Sysgen"; + case"T-MITTON": return"Transmitton England"; + case"T-MOBILE": return"T-Mobile USA, Inc."; + case"T11": return"INCITS Technical Committee T11"; + case"TALARIS": return"Talaris Systems, Inc."; + case"TALLGRAS": return"Tallgrass Technologies"; + case"TANDBERG": return"Tandberg Data A/S"; + case"TANDEM": return"Tandem"; + case"TANDON": return"Tandon"; + case"TCL": return"TCL Shenzhen ASIC MIcro-electronics Ltd"; + case"TDK": return"TDK Corporation"; + case"TEAC": return"TEAC Japan"; + case"TECOLOTE": return"Tecolote Designs"; + case"TEGRA": return"Tegra Varityper"; + case"Teilch": return"Teilch"; + case"Tek": return"Tektronix"; + case"TELLERT": return"Tellert Elektronik GmbH"; + case"TENTIME": return"Laura Technologies, Inc."; + case"TFDATACO": return"TimeForge"; + case"TGEGROUP": return"TGE Group Co.,LTD."; + case"Thecus": return"Thecus Technology Corp."; + case"TI-DSG": return"Texas Instruments"; + case"TiGi": return"TiGi Corporation"; + case"TILDESGN": return"Tildesign bv"; + case"Tite": return"Tite Technology Limited"; + case"TKS Inc.": return"TimeKeeping Systems, Inc."; + case"TLMKS": return"Telemakus LLC"; + case"TMS": return"Texas Memory Systems, Inc."; + case"TMS100": return"TechnoVas"; + case"TOLISGRP": return"The TOLIS Group"; + case"TOSHIBA": return"Toshiba Japan"; + case"TOYOU": return"TOYOU FEIJI ELECTRONICS CO.,LTD."; + case"Tracker": return"Tracker, LLC"; + case"TRIOFLEX": return"Trioflex Oy"; + case"TRIPACE": return"Tripace"; + case"TRLogger": return"TrueLogger Ltd."; + case"TROIKA": return"Troika Networks, Inc."; + case"TRULY": return"TRULY Electronics MFG. LTD."; + case"TRUSTED": return"Trusted Data Corporation"; + case"TSSTcorp": return"Toshiba Samsung Storage Technology Corporation"; + case"TZM": return"TZ Medical"; + case"UD-DVR": return"Bigstone Project."; + case"UDIGITAL": return"United Digital Limited"; + case"UIT": return"United Infomation Technology"; + case"ULTRA": return"UltraStor Corporation"; + case"UNISTOR": return"Unistor Networks, Inc."; + case"UNISYS": return"Unisys"; + case"USCORE": return"Underscore, Inc."; + case"USDC": return"US Design Corp."; + case"Top VASCO": return"Vasco Data Security"; + case"VDS": return"Victor Data Systems Co., Ltd."; + case"VELDANA": return"VELDANA MEDICAL SA"; + case"VENTANA": return"Ventana Medical Systems"; + case"Verari": return"Verari Systems, Inc."; + case"VERBATIM": return"Verbatim Corporation"; + case"Vercet": return"Vercet LLC"; + case"VERITAS": return"VERITAS Software Corporation"; + case"Vexata": return"Vexata Inc"; + case"VEXCEL": return"VEXCEL IMAGING GmbH"; + case"VICOMSL1": return"Vicom Systems, Inc."; + case"VicomSys": return"Vicom Systems, Inc."; + case"VIDEXINC": return"Videx, Inc."; + case"VIOLIN": return"Violin Memory, Inc."; + case"VIRIDENT": return"Virident Systems, Inc."; + case"VITESSE": return"Vitesse Semiconductor Corporation"; + case"VIXEL": return"Vixel Corporation"; + case"VLS": return"Van Lent Systems BV"; + case"VMAX": return"VMAX Technologies Corp."; + case"VMware": return"VMware Inc."; + case"Vobis": return"Vobis Microcomputer AG"; + case"VOLTAIRE": return"Voltaire Ltd."; + case"VRC": return"Vermont Research Corp."; + case"VRugged": return"Vanguard Rugged Storage"; + case"VTGadget": return"Vermont Gadget Company"; + case"Waitec": return"Waitec NV"; + case"WangDAT": return"WangDAT"; + case"WANGTEK": return"Wangtek"; + case"Wasabi": return"Wasabi Systems"; + case"WAVECOM": return"Wavecom"; + case"WD": return"Western Digital Corporation"; + case"WDC": return"Western Digital Corporation"; + case"WDIGTL": return"Western Digital"; + case"WDTI": return"Western Digital Technologies, Inc."; + case"WEARNES": return"Wearnes Technology Corporation"; + case"WeeraRes": return"Weera Research Pte Ltd"; + case"Wildflwr": return"Wildflower Technologies, Inc."; + case"WSC0001": return"Wisecom, Inc."; + case"X3": return"InterNational Committee for Information Technology Standards (INCITS)"; + case"XEBEC": return"Xebec Corporation"; + case"XENSRC": return"XenSource, Inc."; + case"Xerox": return"Xerox Corporation"; + case"XIOtech": return"XIOtech Corporation"; + case"XIRANET": return"Xiranet Communications GmbH"; + case"XIV": return"XIV"; + case"XtremIO": return"XtremIO"; + case"XYRATEX": return"Xyratex"; + case"YINHE": return"NUDT Computer Co."; + case"YIXUN": return"Yixun Electronic Co.,Ltd."; + case"YOTTA": return"YottaYotta, Inc."; + case"Zarva": return"Zarva Digital Technology Co., Ltd."; + case"ZETTA": return"Zetta Systems, Inc."; + case"ZTE": return"ZTE Corporation"; + case"ZVAULT": return"Zetavault"; + default: return scsiVendorString; } } } diff --git a/SecureDigital/CID.cs b/SecureDigital/CID.cs index cd821f4..dd3efb8 100644 --- a/SecureDigital/CID.cs +++ b/SecureDigital/CID.cs @@ -36,28 +36,27 @@ using System.Text; namespace DiscImageChef.Decoders.SecureDigital { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public class CID { - public byte Manufacturer; public string ApplicationID; + public byte CRC; + public byte Manufacturer; + public ushort ManufacturingDate; public string ProductName; public byte ProductRevision; public uint ProductSerialNumber; - public ushort ManufacturingDate; - public byte CRC; } - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Decoders { public static CID DecodeCID(uint[] response) { - if(response?.Length != 4) return null; + if(response?.Length != 4) + return null; byte[] data = new byte[16]; @@ -75,16 +74,17 @@ namespace DiscImageChef.Decoders.SecureDigital public static CID DecodeCID(byte[] response) { - if(response?.Length != 16) return null; + if(response?.Length != 16) + return null; - CID cid = new CID + var cid = new CID { - Manufacturer = response[0], - ProductRevision = response[8], + Manufacturer = response[0], ProductRevision = response[8], ProductSerialNumber = BitConverter.ToUInt32(response, 9), ManufacturingDate = (ushort)(((response[13] & 0x0F) << 4) + response[14]), CRC = (byte)((response[15] & 0xFE) >> 1) }; + byte[] tmp = new byte[2]; Array.Copy(response, 1, tmp, 0, 2); cid.ApplicationID = StringHandlers.CToString(tmp); @@ -97,20 +97,25 @@ namespace DiscImageChef.Decoders.SecureDigital public static string PrettifyCID(CID cid) { - if(cid == null) return null; + if(cid == null) + return null; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendLine("SecureDigital Device Identification Register:"); sb.AppendFormat("\tManufacturer: {0}", VendorString.Prettify(cid.Manufacturer)).AppendLine(); sb.AppendFormat("\tApplication ID: {0}", cid.ApplicationID).AppendLine(); sb.AppendFormat("\tProduct name: {0}", cid.ProductName).AppendLine(); + sb.AppendFormat("\tProduct revision: {0:X2}.{1:X2}", (cid.ProductRevision & 0xF0) >> 4, cid.ProductRevision & 0x0F).AppendLine(); + sb.AppendFormat("\tProduct serial number: {0}", cid.ProductSerialNumber).AppendLine(); + sb.AppendFormat("\tDevice manufactured month {0} of {1}", (cid.ManufacturingDate & 0xF00) >> 8, - (cid.ManufacturingDate & 0xFF) + 2000) - .AppendLine(); + (cid.ManufacturingDate & 0xFF) + 2000). + AppendLine(); + sb.AppendFormat("\tCID CRC: 0x{0:X2}", cid.CRC).AppendLine(); return sb.ToString(); diff --git a/SecureDigital/CSD.cs b/SecureDigital/CSD.cs index f4fc8ae..71bd54c 100644 --- a/SecureDigital/CSD.cs +++ b/SecureDigital/CSD.cs @@ -36,49 +36,48 @@ using System.Text; namespace DiscImageChef.Decoders.SecureDigital { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public class CSD { - public byte Structure; - public byte TAAC; - public byte NSAC; - public byte Speed; public ushort Classes; - public byte ReadBlockLength; - public bool ReadsPartialBlocks; - public bool WriteMisalignment; - public bool ReadMisalignment; + public bool Copy; + public byte CRC; public bool DSRImplemented; - public uint Size; - public byte ReadCurrentAtVddMin; - public byte ReadCurrentAtVddMax; - public byte WriteCurrentAtVddMin; - public byte WriteCurrentAtVddMax; - public byte SizeMultiplier; public bool EraseBlockEnable; public byte EraseSectorSize; - public byte WriteProtectGroupSize; - public bool WriteProtectGroupEnable; - public byte WriteSpeedFactor; - public byte WriteBlockLength; - public bool WritesPartialBlocks; - public bool FileFormatGroup; - public bool Copy; - public bool PermanentWriteProtect; - public bool TemporaryWriteProtect; public byte FileFormat; - public byte CRC; + public bool FileFormatGroup; + public byte NSAC; + public bool PermanentWriteProtect; + public byte ReadBlockLength; + public byte ReadCurrentAtVddMax; + public byte ReadCurrentAtVddMin; + public bool ReadMisalignment; + public bool ReadsPartialBlocks; + public uint Size; + public byte SizeMultiplier; + public byte Speed; + public byte Structure; + public byte TAAC; + public bool TemporaryWriteProtect; + public byte WriteBlockLength; + public byte WriteCurrentAtVddMax; + public byte WriteCurrentAtVddMin; + public bool WriteMisalignment; + public bool WriteProtectGroupEnable; + public byte WriteProtectGroupSize; + public bool WritesPartialBlocks; + public byte WriteSpeedFactor; } - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Decoders { public static CSD DecodeCSD(uint[] response) { - if(response?.Length != 4) return null; + if(response?.Length != 4) + return null; byte[] data = new byte[16]; @@ -96,21 +95,20 @@ namespace DiscImageChef.Decoders.SecureDigital public static CSD DecodeCSD(byte[] response) { - if(response?.Length != 16) return null; + if(response?.Length != 16) + return null; - CSD csd = new CSD + var csd = new CSD { - Structure = (byte)((response[0] & 0xC0) >> 6), - TAAC = response[1], + Structure = (byte)((response[0] & 0xC0) >> 6), TAAC = response[1], NSAC = response[2], Speed = response[3], Classes = (ushort)((response[4] << 4) + ((response[5] & 0xF0) >> 4)), - ReadBlockLength = (byte)(response[5] & 0x0F), - ReadsPartialBlocks = (response[6] & 0x80) == 0x80, - WriteMisalignment = (response[6] & 0x40) == 0x40, - ReadMisalignment = (response[6] & 0x20) == 0x20, - DSRImplemented = (response[6] & 0x10) == 0x10, - EraseBlockEnable = (response[10] & 0x40) == 0x40, + ReadBlockLength = (byte)(response[5] & 0x0F), ReadsPartialBlocks = (response[6] & 0x80) == 0x80, + WriteMisalignment = (response[6] & 0x40) == 0x40, + ReadMisalignment = (response[6] & 0x20) == 0x20, + DSRImplemented = (response[6] & 0x10) == 0x10, + EraseBlockEnable = (response[10] & 0x40) == 0x40, EraseSectorSize = (byte)(((response[10] & 0x3F) << 1) + ((response[11] & 0x80) >> 7)), WriteProtectGroupSize = (byte)(response[11] & 0x7F), WriteProtectGroupEnable = (response[12] & 0x80) == 0x80, @@ -122,41 +120,48 @@ namespace DiscImageChef.Decoders.SecureDigital PermanentWriteProtect = (response[14] & 0x20) == 0x20, TemporaryWriteProtect = (response[14] & 0x10) == 0x10, FileFormat = (byte)((response[14] & 0x0C) >> 2), - CRC = (byte)((response[15] & 0xFE) >> 1) + CRC = + (byte)((response[15] & 0xFE) >> 1) }; if(csd.Structure == 0) { csd.Size = (ushort)(((response[6] & 0x03) << 10) + (response[7] << 2) + ((response[8] & 0xC0) >> 6)); + csd.ReadCurrentAtVddMin = (byte)((response[8] & 0x38) >> 3); csd.ReadCurrentAtVddMax = (byte)(response[8] & 0x07); csd.WriteCurrentAtVddMin = (byte)((response[9] & 0xE0) >> 5); csd.WriteCurrentAtVddMax = (byte)((response[9] & 0x1C) >> 2); csd.SizeMultiplier = (byte)(((response[9] & 0x03) << 1) + ((response[10] & 0x80) >> 7)); } - else csd.Size = (uint)(((response[7] & 0x3F) << 16) + (response[8] << 8) + response[9]); + else + csd.Size = (uint)(((response[7] & 0x3F) << 16) + (response[8] << 8) + response[9]); return csd; } public static string PrettifyCSD(CSD csd) { - if(csd == null) return null; + if(csd == null) + return null; double unitFactor = 0; double multiplier = 0; string unit = ""; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendLine("SecureDigital Device Specific Data Register:"); + switch(csd.Structure) { case 0: sb.AppendLine("\tRegister version 1.0"); + break; case 1: sb.AppendLine("\tRegister version 2.0"); + break; } @@ -165,34 +170,42 @@ namespace DiscImageChef.Decoders.SecureDigital case 0: unit = "ns"; unitFactor = 1; + break; case 1: unit = "ns"; unitFactor = 10; + break; case 2: unit = "ns"; unitFactor = 100; + break; case 3: unit = "μs"; unitFactor = 1; + break; case 4: unit = "μs"; unitFactor = 10; + break; case 5: unit = "μs"; unitFactor = 100; + break; case 6: unit = "ms"; unitFactor = 1; + break; case 7: unit = "ms"; unitFactor = 10; + break; } @@ -200,51 +213,67 @@ namespace DiscImageChef.Decoders.SecureDigital { case 0: multiplier = 0; + break; case 1: multiplier = 1; + break; case 2: multiplier = 1.2; + break; case 3: multiplier = 1.3; + break; case 4: multiplier = 1.5; + break; case 5: multiplier = 2; + break; case 6: multiplier = 2.5; + break; case 7: multiplier = 3; + break; case 8: multiplier = 3.5; + break; case 9: multiplier = 4; + break; case 10: multiplier = 4.5; + break; case 11: multiplier = 5; + break; case 12: multiplier = 5.5; + break; case 13: multiplier = 6; + break; case 14: multiplier = 7; + break; case 15: multiplier = 8; + break; } @@ -254,23 +283,29 @@ namespace DiscImageChef.Decoders.SecureDigital sb.AppendFormat("\tClock dependent part of data access is {0} clock cycles", csd.NSAC * 100).AppendLine(); unit = "MBit/s"; + switch(csd.Speed & 0x07) { case 0: unitFactor = 0.1; + break; case 1: unitFactor = 1; + break; case 2: unitFactor = 10; + break; case 3: unitFactor = 100; + break; default: unit = "unknown"; unitFactor = 0; + break; } @@ -278,51 +313,67 @@ namespace DiscImageChef.Decoders.SecureDigital { case 0: multiplier = 0; + break; case 1: multiplier = 1; + break; case 2: multiplier = 1.2; + break; case 3: multiplier = 1.3; + break; case 4: multiplier = 1.5; + break; case 5: multiplier = 2; + break; case 6: multiplier = 2.6; + break; case 7: multiplier = 3; + break; case 8: multiplier = 3.5; + break; case 9: multiplier = 4; + break; case 10: multiplier = 4.5; + break; case 11: multiplier = 5.2; + break; case 12: multiplier = 5.5; + break; case 13: multiplier = 6; + break; case 14: multiplier = 7; + break; case 15: multiplier = 8; + break; } @@ -330,6 +381,7 @@ namespace DiscImageChef.Decoders.SecureDigital sb.AppendFormat("\tDevice's transfer speed: {0}{1}", result, unit).AppendLine(); unit = ""; + for(int cl = 0, mask = 1; cl <= 11; cl++, mask <<= 1) if((csd.Classes & mask) == mask) unit += $" {cl}"; @@ -337,12 +389,17 @@ namespace DiscImageChef.Decoders.SecureDigital sb.AppendFormat("\tDevice support command classes {0}", unit).AppendLine(); sb.AppendFormat("\tRead block length is {0} bytes", Math.Pow(2, csd.ReadBlockLength)).AppendLine(); - if(csd.ReadsPartialBlocks) sb.AppendLine("\tDevice allows reading partial blocks"); + if(csd.ReadsPartialBlocks) + sb.AppendLine("\tDevice allows reading partial blocks"); - if(csd.WriteMisalignment) sb.AppendLine("\tWrite commands can cross physical block boundaries"); - if(csd.ReadMisalignment) sb.AppendLine("\tRead commands can cross physical block boundaries"); + if(csd.WriteMisalignment) + sb.AppendLine("\tWrite commands can cross physical block boundaries"); - if(csd.DSRImplemented) sb.AppendLine("\tDevice implements configurable driver stage"); + if(csd.ReadMisalignment) + sb.AppendLine("\tRead commands can cross physical block boundaries"); + + if(csd.DSRImplemented) + sb.AppendLine("\tDevice implements configurable driver stage"); if(csd.Structure == 0) { @@ -350,23 +407,31 @@ namespace DiscImageChef.Decoders.SecureDigital sb.AppendFormat("\tDevice has {0} blocks", (int)result).AppendLine(); result = (csd.Size + 1) * Math.Pow(2, csd.SizeMultiplier + 2) * Math.Pow(2, csd.ReadBlockLength); + if(result > 1073741824) sb.AppendFormat("\tDevice has {0} GiB", result / 1073741824.0).AppendLine(); - else if(result > 1048576) sb.AppendFormat("\tDevice has {0} MiB", result / 1048576.0).AppendLine(); - else if(result > 1024) sb.AppendFormat("\tDevice has {0} KiB", result / 1024.0).AppendLine(); - else sb.AppendFormat("\tDevice has {0} bytes", result).AppendLine(); + else if(result > 1048576) + sb.AppendFormat("\tDevice has {0} MiB", result / 1048576.0).AppendLine(); + else if(result > 1024) + sb.AppendFormat("\tDevice has {0} KiB", result / 1024.0).AppendLine(); + else + sb.AppendFormat("\tDevice has {0} bytes", result).AppendLine(); } else { sb.AppendFormat("\tDevice has {0} blocks", (csd.Size + 1) * 1024).AppendLine(); result = ((ulong)csd.Size + 1) * 1024 * 512; + if(result > 1099511627776) sb.AppendFormat("\tDevice has {0} TiB", result / 1099511627776.0).AppendLine(); else if(result > 1073741824) sb.AppendFormat("\tDevice has {0} GiB", result / 1073741824.0).AppendLine(); - else if(result > 1048576) sb.AppendFormat("\tDevice has {0} MiB", result / 1048576.0).AppendLine(); - else if(result > 1024) sb.AppendFormat("\tDevice has {0} KiB", result / 1024.0).AppendLine(); - else sb.AppendFormat("\tDevice has {0} bytes", result).AppendLine(); + else if(result > 1048576) + sb.AppendFormat("\tDevice has {0} MiB", result / 1048576.0).AppendLine(); + else if(result > 1024) + sb.AppendFormat("\tDevice has {0} KiB", result / 1024.0).AppendLine(); + else + sb.AppendFormat("\tDevice has {0} bytes", result).AppendLine(); } if(csd.Structure == 0) @@ -375,27 +440,35 @@ namespace DiscImageChef.Decoders.SecureDigital { case 0: sb.AppendLine("\tDevice uses a maximum of 0.5mA for reading at minimum voltage"); + break; case 1: sb.AppendLine("\tDevice uses a maximum of 1mA for reading at minimum voltage"); + break; case 2: sb.AppendLine("\tDevice uses a maximum of 5mA for reading at minimum voltage"); + break; case 3: sb.AppendLine("\tDevice uses a maximum of 10mA for reading at minimum voltage"); + break; case 4: sb.AppendLine("\tDevice uses a maximum of 25mA for reading at minimum voltage"); + break; case 5: sb.AppendLine("\tDevice uses a maximum of 35mA for reading at minimum voltage"); + break; case 6: sb.AppendLine("\tDevice uses a maximum of 60mA for reading at minimum voltage"); + break; case 7: sb.AppendLine("\tDevice uses a maximum of 100mA for reading at minimum voltage"); + break; } @@ -403,27 +476,35 @@ namespace DiscImageChef.Decoders.SecureDigital { case 0: sb.AppendLine("\tDevice uses a maximum of 1mA for reading at maximum voltage"); + break; case 1: sb.AppendLine("\tDevice uses a maximum of 5mA for reading at maximum voltage"); + break; case 2: sb.AppendLine("\tDevice uses a maximum of 10mA for reading at maximum voltage"); + break; case 3: sb.AppendLine("\tDevice uses a maximum of 25mA for reading at maximum voltage"); + break; case 4: sb.AppendLine("\tDevice uses a maximum of 35mA for reading at maximum voltage"); + break; case 5: sb.AppendLine("\tDevice uses a maximum of 45mA for reading at maximum voltage"); + break; case 6: sb.AppendLine("\tDevice uses a maximum of 80mA for reading at maximum voltage"); + break; case 7: sb.AppendLine("\tDevice uses a maximum of 200mA for reading at maximum voltage"); + break; } @@ -431,27 +512,35 @@ namespace DiscImageChef.Decoders.SecureDigital { case 0: sb.AppendLine("\tDevice uses a maximum of 0.5mA for writing at minimum voltage"); + break; case 1: sb.AppendLine("\tDevice uses a maximum of 1mA for writing at minimum voltage"); + break; case 2: sb.AppendLine("\tDevice uses a maximum of 5mA for writing at minimum voltage"); + break; case 3: sb.AppendLine("\tDevice uses a maximum of 10mA for writing at minimum voltage"); + break; case 4: sb.AppendLine("\tDevice uses a maximum of 25mA for writing at minimum voltage"); + break; case 5: sb.AppendLine("\tDevice uses a maximum of 35mA for writing at minimum voltage"); + break; case 6: sb.AppendLine("\tDevice uses a maximum of 60mA for writing at minimum voltage"); + break; case 7: sb.AppendLine("\tDevice uses a maximum of 100mA for writing at minimum voltage"); + break; } @@ -459,31 +548,40 @@ namespace DiscImageChef.Decoders.SecureDigital { case 0: sb.AppendLine("\tDevice uses a maximum of 1mA for writing at maximum voltage"); + break; case 1: sb.AppendLine("\tDevice uses a maximum of 5mA for writing at maximum voltage"); + break; case 2: sb.AppendLine("\tDevice uses a maximum of 10mA for writing at maximum voltage"); + break; case 3: sb.AppendLine("\tDevice uses a maximum of 25mA for writing at maximum voltage"); + break; case 4: sb.AppendLine("\tDevice uses a maximum of 35mA for writing at maximum voltage"); + break; case 5: sb.AppendLine("\tDevice uses a maximum of 45mA for writing at maximum voltage"); + break; case 6: sb.AppendLine("\tDevice uses a maximum of 80mA for writing at maximum voltage"); + break; case 7: sb.AppendLine("\tDevice uses a maximum of 200mA for writing at maximum voltage"); + break; } - if(csd.EraseBlockEnable) sb.AppendLine("\tDevice can erase multiple blocks"); + if(csd.EraseBlockEnable) + sb.AppendLine("\tDevice can erase multiple blocks"); // TODO: Check specification sb.AppendFormat("\tDevice must erase a minimum of {0} blocks at a time", @@ -492,46 +590,57 @@ namespace DiscImageChef.Decoders.SecureDigital if(csd.WriteProtectGroupEnable) { sb.AppendLine("\tDevice can write protect regions"); + // TODO: Check specification unitFactor = Convert.ToDouble(csd.WriteProtectGroupSize); - sb.AppendFormat("\tDevice can write protect a minimum of {0} blocks at a time", (int)(result + 1)) - .AppendLine(); + + sb.AppendFormat("\tDevice can write protect a minimum of {0} blocks at a time", (int)(result + 1)). + AppendLine(); } - else sb.AppendLine("\tDevice can't write protect regions"); + else + sb.AppendLine("\tDevice can't write protect regions"); } - sb.AppendFormat("\tWriting is {0} times slower than reading", Math.Pow(2, csd.WriteSpeedFactor)) - .AppendLine(); + sb.AppendFormat("\tWriting is {0} times slower than reading", Math.Pow(2, csd.WriteSpeedFactor)). + AppendLine(); sb.AppendFormat("\tWrite block length is {0} bytes", Math.Pow(2, csd.WriteBlockLength)).AppendLine(); - if(csd.WritesPartialBlocks) sb.AppendLine("\tDevice allows writing partial blocks"); + if(csd.WritesPartialBlocks) + sb.AppendLine("\tDevice allows writing partial blocks"); - if(!csd.Copy) sb.AppendLine("\tDevice contents are original"); + if(!csd.Copy) + sb.AppendLine("\tDevice contents are original"); - if(csd.PermanentWriteProtect) sb.AppendLine("\tDevice is permanently write protected"); + if(csd.PermanentWriteProtect) + sb.AppendLine("\tDevice is permanently write protected"); - if(csd.TemporaryWriteProtect) sb.AppendLine("\tDevice is temporarily write protected"); + if(csd.TemporaryWriteProtect) + sb.AppendLine("\tDevice is temporarily write protected"); if(!csd.FileFormatGroup) switch(csd.FileFormat) { case 0: sb.AppendLine("\tDevice is formatted like a hard disk"); + break; case 1: sb.AppendLine("\tDevice is formatted like a floppy disk using Microsoft FAT"); + break; case 2: sb.AppendLine("\tDevice uses Universal File Format"); + break; default: sb.AppendFormat("\tDevice uses unknown file format code {0}", csd.FileFormat).AppendLine(); + break; } else - sb.AppendFormat("\tDevice uses unknown file format code {0} and file format group 1", csd.FileFormat) - .AppendLine(); + sb.AppendFormat("\tDevice uses unknown file format code {0} and file format group 1", csd.FileFormat). + AppendLine(); sb.AppendFormat("\tCSD CRC: 0x{0:X2}", csd.CRC).AppendLine(); diff --git a/SecureDigital/OCR.cs b/SecureDigital/OCR.cs index 87dfcc4..a93023d 100644 --- a/SecureDigital/OCR.cs +++ b/SecureDigital/OCR.cs @@ -36,74 +36,90 @@ using System.Text; namespace DiscImageChef.Decoders.SecureDigital { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "UnassignedField.Global")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "UnassignedField.Global"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] public class OCR { - public bool PowerUp; public bool CCS; - public bool UHS; + public bool LowPower; public bool OneEight; + public bool PowerUp; public bool ThreeFive; public bool ThreeFour; + public bool ThreeOne; public bool ThreeThree; public bool ThreeTwo; - public bool ThreeOne; public bool ThreeZero; - public bool TwoNine; public bool TwoEight; + public bool TwoNine; public bool TwoSeven; - public bool LowPower; + public bool UHS; } - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static partial class Decoders { - public static OCR DecodeOCR(uint response) => - new OCR - { - PowerUp = (response & 0x80000000) == 0x80000000, - CCS = (response & 0x40000000) == 0x40000000, - UHS = (response & 0x20000000) == 0x20000000, - OneEight = (response & 0x01000000) == 0x01000000, - ThreeFive = (response & 0x00800000) == 0x00800000, - ThreeFour = (response & 0x00400000) == 0x00400000, - ThreeThree = (response & 0x00200000) == 0x00200000, - ThreeTwo = (response & 0x00100000) == 0x00100000, - ThreeOne = (response & 0x00080000) == 0x00080000, - ThreeZero = (response & 0x00040000) == 0x00040000, - TwoNine = (response & 0x00020000) == 0x00020000, - TwoEight = (response & 0x00010000) == 0x00010000, - TwoSeven = (response & 0x00008000) == 0x00008000, - LowPower = (response & 0x00000080) == 0x00000080 - }; + public static OCR DecodeOCR(uint response) => new OCR + { + PowerUp = (response & 0x80000000) == 0x80000000, CCS = (response & 0x40000000) == 0x40000000, + UHS = (response & 0x20000000) == 0x20000000, OneEight = (response & 0x01000000) == 0x01000000, + ThreeFive = (response & 0x00800000) == 0x00800000, ThreeFour = (response & 0x00400000) == 0x00400000, + ThreeThree = (response & 0x00200000) == 0x00200000, ThreeTwo = (response & 0x00100000) == 0x00100000, + ThreeOne = (response & 0x00080000) == 0x00080000, ThreeZero = (response & 0x00040000) == 0x00040000, + TwoNine = (response & 0x00020000) == 0x00020000, TwoEight = (response & 0x00010000) == 0x00010000, + TwoSeven = (response & 0x00008000) == 0x00008000, LowPower = (response & 0x00000080) == 0x00000080 + }; public static OCR DecodeOCR(byte[] response) => response?.Length != 4 ? null : DecodeOCR(BitConverter.ToUInt32(response, 0)); public static string PrettifyOCR(OCR ocr) { - if(ocr == null) return null; + if(ocr == null) + return null; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendLine("SecureDigital Operation Conditions Register:"); - if(!ocr.PowerUp) sb.AppendLine("\tDevice is powering up"); - if(ocr.CCS) sb.AppendLine("\tDevice is SDHC, SDXC or higher"); - if(ocr.UHS) sb.AppendLine("\tDevice is UHS-II or higher"); - if(ocr.ThreeFive) sb.AppendLine("\tDevice can work with supply 3.5~3.6V"); - if(ocr.ThreeFour) sb.AppendLine("\tDevice can work with supply 3.4~3.5V"); - if(ocr.ThreeThree) sb.AppendLine("\tDevice can work with supply 3.3~3.4V"); - if(ocr.ThreeTwo) sb.AppendLine("\tDevice can work with supply 3.2~3.3V"); - if(ocr.ThreeOne) sb.AppendLine("\tDevice can work with supply 3.1~3.2V"); - if(ocr.TwoNine) sb.AppendLine("\tDevice can work with supply 2.9~3.0V"); - if(ocr.TwoEight) sb.AppendLine("\tDevice can work with supply 2.8~2.9V"); - if(ocr.TwoSeven) sb.AppendLine("\tDevice can work with supply 2.7~2.8V"); - if(ocr.OneEight) sb.AppendLine("\tDevice can switch to work with 1.8V supply"); - if(ocr.LowPower) sb.AppendLine("\tDevice is in low power mode"); + + if(!ocr.PowerUp) + sb.AppendLine("\tDevice is powering up"); + + if(ocr.CCS) + sb.AppendLine("\tDevice is SDHC, SDXC or higher"); + + if(ocr.UHS) + sb.AppendLine("\tDevice is UHS-II or higher"); + + if(ocr.ThreeFive) + sb.AppendLine("\tDevice can work with supply 3.5~3.6V"); + + if(ocr.ThreeFour) + sb.AppendLine("\tDevice can work with supply 3.4~3.5V"); + + if(ocr.ThreeThree) + sb.AppendLine("\tDevice can work with supply 3.3~3.4V"); + + if(ocr.ThreeTwo) + sb.AppendLine("\tDevice can work with supply 3.2~3.3V"); + + if(ocr.ThreeOne) + sb.AppendLine("\tDevice can work with supply 3.1~3.2V"); + + if(ocr.TwoNine) + sb.AppendLine("\tDevice can work with supply 2.9~3.0V"); + + if(ocr.TwoEight) + sb.AppendLine("\tDevice can work with supply 2.8~2.9V"); + + if(ocr.TwoSeven) + sb.AppendLine("\tDevice can work with supply 2.7~2.8V"); + + if(ocr.OneEight) + sb.AppendLine("\tDevice can switch to work with 1.8V supply"); + + if(ocr.LowPower) + sb.AppendLine("\tDevice is in low power mode"); return sb.ToString(); } diff --git a/SecureDigital/SCR.cs b/SecureDigital/SCR.cs index 4fe1438..8fe3e8d 100644 --- a/SecureDigital/SCR.cs +++ b/SecureDigital/SCR.cs @@ -36,32 +36,30 @@ using System.Text; namespace DiscImageChef.Decoders.SecureDigital { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] public class SCR { - public byte Structure; - public byte Spec; - public bool DataStatusAfterErase; - public byte Security; public byte BusWidth; - public bool Spec3; + public byte CommandSupport; + public bool DataStatusAfterErase; public byte ExtendedSecurity; + public byte[] ManufacturerReserved; + public byte Security; + public byte Spec; + public bool Spec3; public bool Spec4; public byte SpecX; - public byte CommandSupport; - public byte[] ManufacturerReserved; + public byte Structure; } - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "InconsistentNaming")] + [SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "InconsistentNaming")] public static partial class Decoders { public static SCR DecodeSCR(uint[] response) { - if(response?.Length != 2) return null; + if(response?.Length != 2) + return null; byte[] data = new byte[8]; @@ -75,22 +73,22 @@ namespace DiscImageChef.Decoders.SecureDigital public static SCR DecodeSCR(byte[] response) { - if(response?.Length != 8) return null; + if(response?.Length != 8) + return null; - SCR scr = new SCR + var scr = new SCR { - Structure = (byte)((response[0] & 0xF0) >> 4), - Spec = (byte)(response[0] & 0x0F), - DataStatusAfterErase = (response[1] & 0x80) == 0x80, + Structure = (byte)((response[0] & 0xF0) >> 4), Spec = (byte)(response[0] & 0x0F), + DataStatusAfterErase = (response[1] & 0x80) == 0x80, Security = (byte)((response[1] & 0x70) >> 4), BusWidth = (byte)(response[1] & 0x0F), Spec3 = (response[2] & 0x80) == 0x80, ExtendedSecurity = (byte)((response[2] & 0x78) >> 3), Spec4 = (response[2] & 0x04) == 0x04, SpecX = (byte)(((response[2] & 0x03) << 2) + ((response[3] & 0xC0) >> 6)), - CommandSupport = (byte)(response[3] & 0x0F), - ManufacturerReserved = new byte[4] + CommandSupport = (byte)(response[3] & 0x0F), ManufacturerReserved = new byte[4] }; + Array.Copy(response, 4, scr.ManufacturerReserved, 0, 4); return scr; @@ -98,63 +96,98 @@ namespace DiscImageChef.Decoders.SecureDigital public static string PrettifySCR(SCR scr) { - if(scr == null) return null; + if(scr == null) + return null; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.AppendLine("SecureDigital Device Configuration Register:"); - if(scr.Structure != 0) sb.AppendFormat("\tUnknown register version {0}", scr.Structure).AppendLine(); + if(scr.Structure != 0) + sb.AppendFormat("\tUnknown register version {0}", scr.Structure).AppendLine(); - if(scr.Spec == 0 && scr.Spec3 == false && scr.Spec4 == false && scr.SpecX == 0) + if(scr.Spec == 0 && + scr.Spec3 == false && + scr.Spec4 == false && + scr.SpecX == 0) sb.AppendLine("\tDevice follows SecureDigital Physical Layer Specification version 1.0x"); - else if(scr.Spec == 1 && scr.Spec3 == false && scr.Spec4 == false && scr.SpecX == 0) + else if(scr.Spec == 1 && + scr.Spec3 == false && + scr.Spec4 == false && + scr.SpecX == 0) sb.AppendLine("\tDevice follows SecureDigital Physical Layer Specification version 1.10"); - else if(scr.Spec == 2 && scr.Spec3 == false && scr.Spec4 == false && scr.SpecX == 0) + else if(scr.Spec == 2 && + scr.Spec3 == false && + scr.Spec4 == false && + scr.SpecX == 0) sb.AppendLine("\tDevice follows SecureDigital Physical Layer Specification version 2.00"); - else if(scr.Spec == 2 && scr.Spec3 && scr.Spec4 == false && scr.SpecX == 0) + else if(scr.Spec == 2 && + scr.Spec3 && + scr.Spec4 == false && + scr.SpecX == 0) sb.AppendLine("\tDevice follows SecureDigital Physical Layer Specification version 3.0x"); - else if(scr.Spec == 2 && scr.Spec3 && scr.Spec4 && scr.SpecX == 0) + else if(scr.Spec == 2 && + scr.Spec3 && + scr.Spec4 && + scr.SpecX == 0) sb.AppendLine("\tDevice follows SecureDigital Physical Layer Specification version 4.xx"); - else if(scr.Spec == 2 && scr.Spec3 && scr.SpecX == 1) + else if(scr.Spec == 2 && + scr.Spec3 && + scr.SpecX == 1) sb.AppendLine("\tDevice follows SecureDigital Physical Layer Specification version 5.xx"); else - sb - .AppendFormat("\tDevice follows SecureDigital Physical Layer Specification with unknown version {0}.{1}.{2}.{3}", + sb. + AppendFormat("\tDevice follows SecureDigital Physical Layer Specification with unknown version {0}.{1}.{2}.{3}", scr.Spec, scr.Spec3, scr.Spec4, scr.SpecX).AppendLine(); + switch(scr.Security) { case 0: sb.AppendLine("\tDevice does not support CPRM"); + break; case 1: sb.AppendLine("\tDevice does not use CPRM"); + break; case 2: sb.AppendLine("\tDevice uses CPRM according to specification version 1.01"); + break; case 3: sb.AppendLine("\tDevice uses CPRM according to specification version 2.00"); + break; case 4: sb.AppendLine("\tDevice uses CPRM according to specification version 3.xx"); + break; default: - sb.AppendFormat("\tDevice uses unknown CPRM specification with code {0}", scr.Security) - .AppendLine(); + sb.AppendFormat("\tDevice uses unknown CPRM specification with code {0}", scr.Security). + AppendLine(); + break; } - if((scr.BusWidth & 0x01) == 0x01) sb.AppendLine("\tDevice supports 1-bit data bus"); - if((scr.BusWidth & 0x04) == 0x04) sb.AppendLine("\tDevice supports 4-bit data bus"); + if((scr.BusWidth & 0x01) == 0x01) + sb.AppendLine("\tDevice supports 1-bit data bus"); - if(scr.ExtendedSecurity != 0) sb.AppendLine("\tDevice supports extended security"); + if((scr.BusWidth & 0x04) == 0x04) + sb.AppendLine("\tDevice supports 4-bit data bus"); + + if(scr.ExtendedSecurity != 0) + sb.AppendLine("\tDevice supports extended security"); if((scr.CommandSupport & 0x08) == 0x08) sb.AppendLine("\tDevice supports extension register multi-block commands"); + if((scr.CommandSupport & 0x04) == 0x04) sb.AppendLine("\tDevice supports extension register single-block commands"); - if((scr.CommandSupport & 0x02) == 0x02) sb.AppendLine("\tDevice supports set block count command"); - if((scr.CommandSupport & 0x01) == 0x01) sb.AppendLine("\tDevice supports speed class control command"); + + if((scr.CommandSupport & 0x02) == 0x02) + sb.AppendLine("\tDevice supports set block count command"); + + if((scr.CommandSupport & 0x01) == 0x01) + sb.AppendLine("\tDevice supports speed class control command"); return sb.ToString(); } diff --git a/SecureDigital/VendorString.cs b/SecureDigital/VendorString.cs index cccbbef..7b7c843 100644 --- a/SecureDigital/VendorString.cs +++ b/SecureDigital/VendorString.cs @@ -38,11 +38,11 @@ namespace DiscImageChef.Decoders.SecureDigital { switch(sdVendorId) { - case 0x02: return "Kingston"; - case 0x03: return "Sandisk"; - case 0x27: return "CnMemory"; - case 0xAA: return "QEMU"; - default: return $"Unknown manufacturer ID 0x{sdVendorId:X2}"; + case 0x02: return"Kingston"; + case 0x03: return"Sandisk"; + case 0x27: return"CnMemory"; + case 0xAA: return"QEMU"; + default: return$"Unknown manufacturer ID 0x{sdVendorId:X2}"; } } } diff --git a/Sega/CD.cs b/Sega/CD.cs index 0755a67..7788c14 100644 --- a/Sega/CD.cs +++ b/Sega/CD.cs @@ -40,11 +40,257 @@ using Marshal = DiscImageChef.Helpers.Marshal; namespace DiscImageChef.Decoders.Sega { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static class CD { + public static IPBin? DecodeIPBin(byte[] ipbin_sector) + { + if(ipbin_sector == null) + return null; + + if(ipbin_sector.Length < 512) + return null; + + var ipbin = Marshal.ByteArrayToStructureLittleEndian(ipbin_sector); + + DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.volume_name = \"{0}\"", + Encoding.ASCII.GetString(ipbin.volume_name)); + + DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.system_name = \"{0}\"", + Encoding.ASCII.GetString(ipbin.system_name)); + + DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.volume_version = \"{0:X}\"", + ipbin.volume_version); + + DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.volume_type = 0x{0:X8}", + ipbin.volume_type); + + DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.system_version = 0x{0:X8}", + ipbin.system_version); + + DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.ip_address = 0x{0:X8}", ipbin.ip_address); + DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.ip_loadsize = {0}", ipbin.ip_loadsize); + + DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.ip_entry_address = 0x{0:X8}", + ipbin.ip_entry_address); + + DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.ip_work_ram_size = {0}", + ipbin.ip_work_ram_size); + + DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.sp_address = 0x{0:X8}", ipbin.sp_address); + DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.sp_loadsize = {0}", ipbin.sp_loadsize); + + DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.sp_entry_address = 0x{0:X8}", + ipbin.sp_entry_address); + + DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.sp_work_ram_size = {0}", + ipbin.sp_work_ram_size); + + DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.release_date = \"{0}\"", + Encoding.ASCII.GetString(ipbin.release_date)); + + DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.release_date2 = \"{0}\"", + Encoding.ASCII.GetString(ipbin.release_date2)); + + DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.developer_code = \"{0}\"", + Encoding.ASCII.GetString(ipbin.developer_code)); + + DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.domestic_title = \"{0}\"", + Encoding.ASCII.GetString(ipbin.domestic_title)); + + DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.overseas_title = \"{0}\"", + Encoding.ASCII.GetString(ipbin.overseas_title)); + + DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.product_code = \"{0}\"", + Encoding.ASCII.GetString(ipbin.product_code)); + + DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.peripherals = \"{0}\"", + Encoding.ASCII.GetString(ipbin.peripherals)); + + DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.region_codes = \"{0}\"", + Encoding.ASCII.GetString(ipbin.region_codes)); + + string id = Encoding.ASCII.GetString(ipbin.SegaHardwareID); + + return id == "SEGADISCSYSTEM " || id == "SEGADATADISC " || id == "SEGAOS " ? ipbin + : (IPBin?)null; + } + + public static string Prettify(IPBin? decoded) + { + if(decoded == null) + return null; + + IPBin ipbin = decoded.Value; + + var IPBinInformation = new StringBuilder(); + + IPBinInformation.AppendLine("--------------------------------"); + IPBinInformation.AppendLine("SEGA IP.BIN INFORMATION:"); + IPBinInformation.AppendLine("--------------------------------"); + + // Decoding all data + DateTime ipbindate = DateTime.MinValue; + CultureInfo provider = CultureInfo.InvariantCulture; + + try + { + ipbindate = DateTime.ParseExact(Encoding.ASCII.GetString(ipbin.release_date), "MMddyyyy", provider); + } + catch + { + try + { + ipbindate = DateTime.ParseExact(Encoding.ASCII.GetString(ipbin.release_date2), "yyyy.MMM", + provider); + } + #pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body + catch + { + // ignored + } + #pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body + } + + /* + switch (Encoding.ASCII.GetString(application_type)) + { + case "GM": + IPBinInformation.AppendLine("Disc is a game."); + break; + case "AI": + IPBinInformation.AppendLine("Disc is an application."); + break; + default: + IPBinInformation.AppendLine("Disc is from unknown type."); + break; + } + */ + + IPBinInformation.AppendFormat("Volume name: {0}", Encoding.ASCII.GetString(ipbin.volume_name)).AppendLine(); + + //IPBinInformation.AppendFormat("Volume version: {0}", Encoding.ASCII.GetString(ipbin.volume_version)).AppendLine(); + //IPBinInformation.AppendFormat("{0}", Encoding.ASCII.GetString(ipbin.volume_type)).AppendLine(); + IPBinInformation.AppendFormat("System name: {0}", Encoding.ASCII.GetString(ipbin.system_name)).AppendLine(); + + //IPBinInformation.AppendFormat("System version: {0}", Encoding.ASCII.GetString(ipbin.system_version)).AppendLine(); + IPBinInformation.AppendFormat("Initial program address: 0x{0:X8}", ipbin.ip_address).AppendLine(); + IPBinInformation.AppendFormat("Initial program load size: {0} bytes", ipbin.ip_loadsize).AppendLine(); + + IPBinInformation.AppendFormat("Initial program entry address: 0x{0:X8}", ipbin.ip_entry_address). + AppendLine(); + + IPBinInformation.AppendFormat("Initial program work RAM: {0} bytes", ipbin.ip_work_ram_size).AppendLine(); + IPBinInformation.AppendFormat("System program address: 0x{0:X8}", ipbin.sp_address).AppendLine(); + IPBinInformation.AppendFormat("System program load size: {0} bytes", ipbin.sp_loadsize).AppendLine(); + + IPBinInformation.AppendFormat("System program entry address: 0x{0:X8}", ipbin.sp_entry_address). + AppendLine(); + + IPBinInformation.AppendFormat("System program work RAM: {0} bytes", ipbin.sp_work_ram_size).AppendLine(); + + if(ipbindate != DateTime.MinValue) + IPBinInformation.AppendFormat("Release date: {0}", ipbindate).AppendLine(); + + //IPBinInformation.AppendFormat("Release date (other format): {0}", Encoding.ASCII.GetString(release_date2)).AppendLine(); + IPBinInformation.AppendFormat("Hardware ID: {0}", Encoding.ASCII.GetString(ipbin.hardware_id)).AppendLine(); + + IPBinInformation.AppendFormat("Developer code: {0}", Encoding.ASCII.GetString(ipbin.developer_code)). + AppendLine(); + + IPBinInformation.AppendFormat("Domestic title: {0}", Encoding.ASCII.GetString(ipbin.domestic_title)). + AppendLine(); + + IPBinInformation.AppendFormat("Overseas title: {0}", Encoding.ASCII.GetString(ipbin.overseas_title)). + AppendLine(); + + IPBinInformation.AppendFormat("Product code: {0}", Encoding.ASCII.GetString(ipbin.product_code)). + AppendLine(); + + IPBinInformation.AppendFormat("Peripherals:").AppendLine(); + + foreach(byte peripheral in ipbin.peripherals) + switch((char)peripheral) + { + case'A': + IPBinInformation.AppendLine("Game supports analog controller."); + + break; + case'B': + IPBinInformation.AppendLine("Game supports trackball."); + + break; + case'G': + IPBinInformation.AppendLine("Game supports light gun."); + + break; + case'J': + IPBinInformation.AppendLine("Game supports JoyPad."); + + break; + case'K': + IPBinInformation.AppendLine("Game supports keyboard."); + + break; + case'M': + IPBinInformation.AppendLine("Game supports mouse."); + + break; + case'O': + IPBinInformation.AppendLine("Game supports Master System's JoyPad."); + + break; + case'P': + IPBinInformation.AppendLine("Game supports printer interface."); + + break; + case'R': + IPBinInformation.AppendLine("Game supports serial (RS-232C) interface."); + + break; + case'T': + IPBinInformation.AppendLine("Game supports tablet interface."); + + break; + case'V': + IPBinInformation.AppendLine("Game supports paddle controller."); + + break; + case' ': break; + default: + IPBinInformation.AppendFormat("Game supports unknown peripheral {0}.", peripheral).AppendLine(); + + break; + } + + IPBinInformation.AppendLine("Regions supported:"); + + foreach(byte region in ipbin.region_codes) + switch((char)region) + { + case'J': + IPBinInformation.AppendLine("Japanese NTSC."); + + break; + case'U': + IPBinInformation.AppendLine("USA NTSC."); + + break; + case'E': + IPBinInformation.AppendLine("Europe PAL."); + + break; + case' ': break; + default: + IPBinInformation.AppendFormat("Game supports unknown region {0}.", region).AppendLine(); + + break; + } + + return IPBinInformation.ToString(); + } + // TODO: Check if it is big or little endian [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct IPBin @@ -128,197 +374,5 @@ namespace DiscImageChef.Decoders.Sega [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] region_codes; } - - public static IPBin? DecodeIPBin(byte[] ipbin_sector) - { - if(ipbin_sector == null) return null; - - if(ipbin_sector.Length < 512) return null; - - IPBin ipbin = Marshal.ByteArrayToStructureLittleEndian(ipbin_sector); - - DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.volume_name = \"{0}\"", - Encoding.ASCII.GetString(ipbin.volume_name)); - DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.system_name = \"{0}\"", - Encoding.ASCII.GetString(ipbin.system_name)); - DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.volume_version = \"{0:X}\"", - ipbin.volume_version); - DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.volume_type = 0x{0:X8}", - ipbin.volume_type); - DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.system_version = 0x{0:X8}", - ipbin.system_version); - DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.ip_address = 0x{0:X8}", ipbin.ip_address); - DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.ip_loadsize = {0}", ipbin.ip_loadsize); - DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.ip_entry_address = 0x{0:X8}", - ipbin.ip_entry_address); - DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.ip_work_ram_size = {0}", - ipbin.ip_work_ram_size); - DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.sp_address = 0x{0:X8}", ipbin.sp_address); - DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.sp_loadsize = {0}", ipbin.sp_loadsize); - DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.sp_entry_address = 0x{0:X8}", - ipbin.sp_entry_address); - DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.sp_work_ram_size = {0}", - ipbin.sp_work_ram_size); - DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.release_date = \"{0}\"", - Encoding.ASCII.GetString(ipbin.release_date)); - DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.release_date2 = \"{0}\"", - Encoding.ASCII.GetString(ipbin.release_date2)); - DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.developer_code = \"{0}\"", - Encoding.ASCII.GetString(ipbin.developer_code)); - DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.domestic_title = \"{0}\"", - Encoding.ASCII.GetString(ipbin.domestic_title)); - DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.overseas_title = \"{0}\"", - Encoding.ASCII.GetString(ipbin.overseas_title)); - DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.product_code = \"{0}\"", - Encoding.ASCII.GetString(ipbin.product_code)); - DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.peripherals = \"{0}\"", - Encoding.ASCII.GetString(ipbin.peripherals)); - DicConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.region_codes = \"{0}\"", - Encoding.ASCII.GetString(ipbin.region_codes)); - - string id = Encoding.ASCII.GetString(ipbin.SegaHardwareID); - - return id == "SEGADISCSYSTEM " || id == "SEGADATADISC " || id == "SEGAOS " - ? ipbin - : (IPBin?)null; - } - - public static string Prettify(IPBin? decoded) - { - if(decoded == null) return null; - - IPBin ipbin = decoded.Value; - - StringBuilder IPBinInformation = new StringBuilder(); - - IPBinInformation.AppendLine("--------------------------------"); - IPBinInformation.AppendLine("SEGA IP.BIN INFORMATION:"); - IPBinInformation.AppendLine("--------------------------------"); - - // Decoding all data - DateTime ipbindate = DateTime.MinValue; - CultureInfo provider = CultureInfo.InvariantCulture; - try { ipbindate = DateTime.ParseExact(Encoding.ASCII.GetString(ipbin.release_date), "MMddyyyy", provider); } - catch - { - try - { - ipbindate = DateTime.ParseExact(Encoding.ASCII.GetString(ipbin.release_date2), "yyyy.MMM", - provider); - } - #pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body - catch - { - // ignored - } - #pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body - } - - /* - switch (Encoding.ASCII.GetString(application_type)) - { - case "GM": - IPBinInformation.AppendLine("Disc is a game."); - break; - case "AI": - IPBinInformation.AppendLine("Disc is an application."); - break; - default: - IPBinInformation.AppendLine("Disc is from unknown type."); - break; - } - */ - - IPBinInformation.AppendFormat("Volume name: {0}", Encoding.ASCII.GetString(ipbin.volume_name)).AppendLine(); - //IPBinInformation.AppendFormat("Volume version: {0}", Encoding.ASCII.GetString(ipbin.volume_version)).AppendLine(); - //IPBinInformation.AppendFormat("{0}", Encoding.ASCII.GetString(ipbin.volume_type)).AppendLine(); - IPBinInformation.AppendFormat("System name: {0}", Encoding.ASCII.GetString(ipbin.system_name)).AppendLine(); - //IPBinInformation.AppendFormat("System version: {0}", Encoding.ASCII.GetString(ipbin.system_version)).AppendLine(); - IPBinInformation.AppendFormat("Initial program address: 0x{0:X8}", ipbin.ip_address).AppendLine(); - IPBinInformation.AppendFormat("Initial program load size: {0} bytes", ipbin.ip_loadsize).AppendLine(); - IPBinInformation.AppendFormat("Initial program entry address: 0x{0:X8}", ipbin.ip_entry_address) - .AppendLine(); - IPBinInformation.AppendFormat("Initial program work RAM: {0} bytes", ipbin.ip_work_ram_size).AppendLine(); - IPBinInformation.AppendFormat("System program address: 0x{0:X8}", ipbin.sp_address).AppendLine(); - IPBinInformation.AppendFormat("System program load size: {0} bytes", ipbin.sp_loadsize).AppendLine(); - IPBinInformation.AppendFormat("System program entry address: 0x{0:X8}", ipbin.sp_entry_address) - .AppendLine(); - IPBinInformation.AppendFormat("System program work RAM: {0} bytes", ipbin.sp_work_ram_size).AppendLine(); - if(ipbindate != DateTime.MinValue) - IPBinInformation.AppendFormat("Release date: {0}", ipbindate).AppendLine(); - //IPBinInformation.AppendFormat("Release date (other format): {0}", Encoding.ASCII.GetString(release_date2)).AppendLine(); - IPBinInformation.AppendFormat("Hardware ID: {0}", Encoding.ASCII.GetString(ipbin.hardware_id)).AppendLine(); - IPBinInformation.AppendFormat("Developer code: {0}", Encoding.ASCII.GetString(ipbin.developer_code)) - .AppendLine(); - IPBinInformation.AppendFormat("Domestic title: {0}", Encoding.ASCII.GetString(ipbin.domestic_title)) - .AppendLine(); - IPBinInformation.AppendFormat("Overseas title: {0}", Encoding.ASCII.GetString(ipbin.overseas_title)) - .AppendLine(); - IPBinInformation.AppendFormat("Product code: {0}", Encoding.ASCII.GetString(ipbin.product_code)) - .AppendLine(); - IPBinInformation.AppendFormat("Peripherals:").AppendLine(); - foreach(byte peripheral in ipbin.peripherals) - switch((char)peripheral) - { - case 'A': - IPBinInformation.AppendLine("Game supports analog controller."); - break; - case 'B': - IPBinInformation.AppendLine("Game supports trackball."); - break; - case 'G': - IPBinInformation.AppendLine("Game supports light gun."); - break; - case 'J': - IPBinInformation.AppendLine("Game supports JoyPad."); - break; - case 'K': - IPBinInformation.AppendLine("Game supports keyboard."); - break; - case 'M': - IPBinInformation.AppendLine("Game supports mouse."); - break; - case 'O': - IPBinInformation.AppendLine("Game supports Master System's JoyPad."); - break; - case 'P': - IPBinInformation.AppendLine("Game supports printer interface."); - break; - case 'R': - IPBinInformation.AppendLine("Game supports serial (RS-232C) interface."); - break; - case 'T': - IPBinInformation.AppendLine("Game supports tablet interface."); - break; - case 'V': - IPBinInformation.AppendLine("Game supports paddle controller."); - break; - case ' ': break; - default: - IPBinInformation.AppendFormat("Game supports unknown peripheral {0}.", peripheral).AppendLine(); - break; - } - - IPBinInformation.AppendLine("Regions supported:"); - foreach(byte region in ipbin.region_codes) - switch((char)region) - { - case 'J': - IPBinInformation.AppendLine("Japanese NTSC."); - break; - case 'U': - IPBinInformation.AppendLine("USA NTSC."); - break; - case 'E': - IPBinInformation.AppendLine("Europe PAL."); - break; - case ' ': break; - default: - IPBinInformation.AppendFormat("Game supports unknown region {0}.", region).AppendLine(); - break; - } - - return IPBinInformation.ToString(); - } } } \ No newline at end of file diff --git a/Sega/Dreamcast.cs b/Sega/Dreamcast.cs index 16e0d09..57f82ea 100644 --- a/Sega/Dreamcast.cs +++ b/Sega/Dreamcast.cs @@ -40,11 +40,222 @@ using Marshal = DiscImageChef.Helpers.Marshal; namespace DiscImageChef.Decoders.Sega { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static class Dreamcast { + public static IPBin? DecodeIPBin(byte[] ipbin_sector) + { + if(ipbin_sector == null) + return null; + + if(ipbin_sector.Length < 512) + return null; + + var ipbin = Marshal.ByteArrayToStructureLittleEndian(ipbin_sector); + + DicConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.maker_id = \"{0}\"", + Encoding.ASCII.GetString(ipbin.maker_id)); + + DicConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.spare_space1 = \"{0}\"", + (char)ipbin.spare_space1); + + DicConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.dreamcast_media = \"{0}\"", + Encoding.ASCII.GetString(ipbin.dreamcast_media)); + + DicConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.disc_no = {0}", (char)ipbin.disc_no); + + DicConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.disc_no_separator = \"{0}\"", + (char)ipbin.disc_no_separator); + + DicConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.disc_total_nos = \"{0}\"", + (char)ipbin.disc_total_nos); + + DicConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.spare_space2 = \"{0}\"", + Encoding.ASCII.GetString(ipbin.spare_space2)); + + DicConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.region_codes = \"{0}\"", + Encoding.ASCII.GetString(ipbin.region_codes)); + + DicConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.peripherals = \"{0}\"", + Encoding.ASCII.GetString(ipbin.peripherals)); + + DicConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.product_no = \"{0}\"", + Encoding.ASCII.GetString(ipbin.product_no)); + + DicConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.product_version = \"{0}\"", + Encoding.ASCII.GetString(ipbin.product_version)); + + DicConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.release_date = \"{0}\"", + Encoding.ASCII.GetString(ipbin.release_date)); + + DicConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.spare_space3 = \"{0}\"", + (char)ipbin.spare_space3); + + DicConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.boot_filename = \"{0}\"", + Encoding.ASCII.GetString(ipbin.boot_filename)); + + DicConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.producer = \"{0}\"", + Encoding.ASCII.GetString(ipbin.producer)); + + DicConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.product_name = \"{0}\"", + Encoding.ASCII.GetString(ipbin.product_name)); + + return Encoding.ASCII.GetString(ipbin.SegaHardwareID) == "SEGA SEGAKATANA " ? ipbin : (IPBin?)null; + } + + public static string Prettify(IPBin? decoded) + { + if(decoded == null) + return null; + + IPBin ipbin = decoded.Value; + + var IPBinInformation = new StringBuilder(); + + IPBinInformation.AppendLine("--------------------------------"); + IPBinInformation.AppendLine("SEGA IP.BIN INFORMATION:"); + IPBinInformation.AppendLine("--------------------------------"); + + // Decoding all data + DateTime ipbindate; + CultureInfo provider = CultureInfo.InvariantCulture; + ipbindate = DateTime.ParseExact(Encoding.ASCII.GetString(ipbin.release_date), "yyyyMMdd", provider); + + IPBinInformation.AppendFormat("Product name: {0}", Encoding.ASCII.GetString(ipbin.product_name)). + AppendLine(); + + IPBinInformation.AppendFormat("Product version: {0}", Encoding.ASCII.GetString(ipbin.product_version)). + AppendLine(); + + IPBinInformation.AppendFormat("Product CRC: 0x{0:X8}", ipbin.dreamcast_crc).AppendLine(); + IPBinInformation.AppendFormat("Producer: {0}", Encoding.ASCII.GetString(ipbin.producer)).AppendLine(); + + IPBinInformation.AppendFormat("Disc media: {0}", Encoding.ASCII.GetString(ipbin.dreamcast_media)). + AppendLine(); + + IPBinInformation.AppendFormat("Disc number {0} of {1}", (char)ipbin.disc_no, (char)ipbin.disc_total_nos). + AppendLine(); + + IPBinInformation.AppendFormat("Release date: {0}", ipbindate).AppendLine(); + + switch(Encoding.ASCII.GetString(ipbin.boot_filename)) + { + case"1ST_READ.BIN": + IPBinInformation.AppendLine("Disc boots natively."); + + break; + case"0WINCE.BIN ": + IPBinInformation.AppendLine("Disc boots using Windows CE."); + + break; + default: + IPBinInformation.AppendFormat("Disc boots using unknown loader: {0}.", + Encoding.ASCII.GetString(ipbin.boot_filename)).AppendLine(); + + break; + } + + IPBinInformation.AppendLine("Regions supported:"); + + foreach(byte region in ipbin.region_codes) + switch((char)region) + { + case'J': + IPBinInformation.AppendLine("Japanese NTSC."); + + break; + case'U': + IPBinInformation.AppendLine("North America NTSC."); + + break; + case'E': + IPBinInformation.AppendLine("Europe PAL."); + + break; + case' ': break; + default: + IPBinInformation.AppendFormat("Game supports unknown region {0}.", region).AppendLine(); + + break; + } + + int iPeripherals = int.Parse(Encoding.ASCII.GetString(ipbin.peripherals), NumberStyles.HexNumber); + + if((iPeripherals & 0x00000001) == 0x00000001) + IPBinInformation.AppendLine("Game uses Windows CE."); + + IPBinInformation.AppendFormat("Peripherals:").AppendLine(); + + if((iPeripherals & 0x00000010) == 0x00000010) + IPBinInformation.AppendLine("Game supports the VGA Box."); + + if((iPeripherals & 0x00000100) == 0x00000100) + IPBinInformation.AppendLine("Game supports other expansion."); + + if((iPeripherals & 0x00000200) == 0x00000200) + IPBinInformation.AppendLine("Game supports Puru Puru pack."); + + if((iPeripherals & 0x00000400) == 0x00000400) + IPBinInformation.AppendLine("Game supports Mike Device."); + + if((iPeripherals & 0x00000800) == 0x00000800) + IPBinInformation.AppendLine("Game supports Memory Card."); + + if((iPeripherals & 0x00001000) == 0x00001000) + IPBinInformation.AppendLine("Game requires A + B + Start buttons and D-Pad."); + + if((iPeripherals & 0x00002000) == 0x00002000) + IPBinInformation.AppendLine("Game requires C button."); + + if((iPeripherals & 0x00004000) == 0x00004000) + IPBinInformation.AppendLine("Game requires D button."); + + if((iPeripherals & 0x00008000) == 0x00008000) + IPBinInformation.AppendLine("Game requires X button."); + + if((iPeripherals & 0x00010000) == 0x00010000) + IPBinInformation.AppendLine("Game requires Y button."); + + if((iPeripherals & 0x00020000) == 0x00020000) + IPBinInformation.AppendLine("Game requires Z button."); + + if((iPeripherals & 0x00040000) == 0x00040000) + IPBinInformation.AppendLine("Game requires expanded direction buttons."); + + if((iPeripherals & 0x00080000) == 0x00080000) + IPBinInformation.AppendLine("Game requires analog R trigger."); + + if((iPeripherals & 0x00100000) == 0x00100000) + IPBinInformation.AppendLine("Game requires analog L trigger."); + + if((iPeripherals & 0x00200000) == 0x00200000) + IPBinInformation.AppendLine("Game requires analog horizontal controller."); + + if((iPeripherals & 0x00400000) == 0x00400000) + IPBinInformation.AppendLine("Game requires analog vertical controller."); + + if((iPeripherals & 0x00800000) == 0x00800000) + IPBinInformation.AppendLine("Game requires expanded analog horizontal controller."); + + if((iPeripherals & 0x01000000) == 0x01000000) + IPBinInformation.AppendLine("Game requires expanded analog vertical controller."); + + if((iPeripherals & 0x02000000) == 0x02000000) + IPBinInformation.AppendLine("Game supports Gun."); + + if((iPeripherals & 0x04000000) == 0x04000000) + IPBinInformation.AppendLine("Game supports Keyboard."); + + if((iPeripherals & 0x08000000) == 0x08000000) + IPBinInformation.AppendLine("Game supports Mouse."); + + if((iPeripherals & 0xEE) != 0) + IPBinInformation.AppendFormat("Game supports unknown peripherals mask {0:X2}", iPeripherals & 0xEE); + + return IPBinInformation.ToString(); + } + [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct IPBin { @@ -103,150 +314,5 @@ namespace DiscImageChef.Decoders.Sega [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] public byte[] product_name; } - - public static IPBin? DecodeIPBin(byte[] ipbin_sector) - { - if(ipbin_sector == null) return null; - - if(ipbin_sector.Length < 512) return null; - - IPBin ipbin = Marshal.ByteArrayToStructureLittleEndian(ipbin_sector); - - DicConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.maker_id = \"{0}\"", - Encoding.ASCII.GetString(ipbin.maker_id)); - DicConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.spare_space1 = \"{0}\"", - (char)ipbin.spare_space1); - DicConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.dreamcast_media = \"{0}\"", - Encoding.ASCII.GetString(ipbin.dreamcast_media)); - DicConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.disc_no = {0}", (char)ipbin.disc_no); - DicConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.disc_no_separator = \"{0}\"", - (char)ipbin.disc_no_separator); - DicConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.disc_total_nos = \"{0}\"", - (char)ipbin.disc_total_nos); - DicConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.spare_space2 = \"{0}\"", - Encoding.ASCII.GetString(ipbin.spare_space2)); - DicConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.region_codes = \"{0}\"", - Encoding.ASCII.GetString(ipbin.region_codes)); - DicConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.peripherals = \"{0}\"", - Encoding.ASCII.GetString(ipbin.peripherals)); - DicConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.product_no = \"{0}\"", - Encoding.ASCII.GetString(ipbin.product_no)); - DicConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.product_version = \"{0}\"", - Encoding.ASCII.GetString(ipbin.product_version)); - DicConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.release_date = \"{0}\"", - Encoding.ASCII.GetString(ipbin.release_date)); - DicConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.spare_space3 = \"{0}\"", - (char)ipbin.spare_space3); - DicConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.boot_filename = \"{0}\"", - Encoding.ASCII.GetString(ipbin.boot_filename)); - DicConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.producer = \"{0}\"", - Encoding.ASCII.GetString(ipbin.producer)); - DicConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.product_name = \"{0}\"", - Encoding.ASCII.GetString(ipbin.product_name)); - - return Encoding.ASCII.GetString(ipbin.SegaHardwareID) == "SEGA SEGAKATANA " ? ipbin : (IPBin?)null; - } - - public static string Prettify(IPBin? decoded) - { - if(decoded == null) return null; - - IPBin ipbin = decoded.Value; - - StringBuilder IPBinInformation = new StringBuilder(); - - IPBinInformation.AppendLine("--------------------------------"); - IPBinInformation.AppendLine("SEGA IP.BIN INFORMATION:"); - IPBinInformation.AppendLine("--------------------------------"); - - // Decoding all data - DateTime ipbindate; - CultureInfo provider = CultureInfo.InvariantCulture; - ipbindate = DateTime.ParseExact(Encoding.ASCII.GetString(ipbin.release_date), "yyyyMMdd", provider); - IPBinInformation.AppendFormat("Product name: {0}", Encoding.ASCII.GetString(ipbin.product_name)) - .AppendLine(); - IPBinInformation.AppendFormat("Product version: {0}", Encoding.ASCII.GetString(ipbin.product_version)) - .AppendLine(); - IPBinInformation.AppendFormat("Product CRC: 0x{0:X8}", ipbin.dreamcast_crc).AppendLine(); - IPBinInformation.AppendFormat("Producer: {0}", Encoding.ASCII.GetString(ipbin.producer)).AppendLine(); - IPBinInformation.AppendFormat("Disc media: {0}", Encoding.ASCII.GetString(ipbin.dreamcast_media)) - .AppendLine(); - IPBinInformation.AppendFormat("Disc number {0} of {1}", (char)ipbin.disc_no, (char)ipbin.disc_total_nos) - .AppendLine(); - IPBinInformation.AppendFormat("Release date: {0}", ipbindate).AppendLine(); - switch(Encoding.ASCII.GetString(ipbin.boot_filename)) - { - case "1ST_READ.BIN": - IPBinInformation.AppendLine("Disc boots natively."); - break; - case "0WINCE.BIN ": - IPBinInformation.AppendLine("Disc boots using Windows CE."); - break; - default: - IPBinInformation.AppendFormat("Disc boots using unknown loader: {0}.", - Encoding.ASCII.GetString(ipbin.boot_filename)).AppendLine(); - break; - } - - IPBinInformation.AppendLine("Regions supported:"); - foreach(byte region in ipbin.region_codes) - switch((char)region) - { - case 'J': - IPBinInformation.AppendLine("Japanese NTSC."); - break; - case 'U': - IPBinInformation.AppendLine("North America NTSC."); - break; - case 'E': - IPBinInformation.AppendLine("Europe PAL."); - break; - case ' ': break; - default: - IPBinInformation.AppendFormat("Game supports unknown region {0}.", region).AppendLine(); - break; - } - - int iPeripherals = int.Parse(Encoding.ASCII.GetString(ipbin.peripherals), NumberStyles.HexNumber); - - if((iPeripherals & 0x00000001) == 0x00000001) IPBinInformation.AppendLine("Game uses Windows CE."); - - IPBinInformation.AppendFormat("Peripherals:").AppendLine(); - - if((iPeripherals & 0x00000010) == 0x00000010) IPBinInformation.AppendLine("Game supports the VGA Box."); - if((iPeripherals & 0x00000100) == 0x00000100) IPBinInformation.AppendLine("Game supports other expansion."); - if((iPeripherals & 0x00000200) == 0x00000200) IPBinInformation.AppendLine("Game supports Puru Puru pack."); - if((iPeripherals & 0x00000400) == 0x00000400) IPBinInformation.AppendLine("Game supports Mike Device."); - if((iPeripherals & 0x00000800) == 0x00000800) IPBinInformation.AppendLine("Game supports Memory Card."); - if((iPeripherals & 0x00001000) == 0x00001000) - IPBinInformation.AppendLine("Game requires A + B + Start buttons and D-Pad."); - if((iPeripherals & 0x00002000) == 0x00002000) IPBinInformation.AppendLine("Game requires C button."); - if((iPeripherals & 0x00004000) == 0x00004000) IPBinInformation.AppendLine("Game requires D button."); - if((iPeripherals & 0x00008000) == 0x00008000) IPBinInformation.AppendLine("Game requires X button."); - if((iPeripherals & 0x00010000) == 0x00010000) IPBinInformation.AppendLine("Game requires Y button."); - if((iPeripherals & 0x00020000) == 0x00020000) IPBinInformation.AppendLine("Game requires Z button."); - if((iPeripherals & 0x00040000) == 0x00040000) - IPBinInformation.AppendLine("Game requires expanded direction buttons."); - if((iPeripherals & 0x00080000) == 0x00080000) - IPBinInformation.AppendLine("Game requires analog R trigger."); - if((iPeripherals & 0x00100000) == 0x00100000) - IPBinInformation.AppendLine("Game requires analog L trigger."); - if((iPeripherals & 0x00200000) == 0x00200000) - IPBinInformation.AppendLine("Game requires analog horizontal controller."); - if((iPeripherals & 0x00400000) == 0x00400000) - IPBinInformation.AppendLine("Game requires analog vertical controller."); - if((iPeripherals & 0x00800000) == 0x00800000) - IPBinInformation.AppendLine("Game requires expanded analog horizontal controller."); - if((iPeripherals & 0x01000000) == 0x01000000) - IPBinInformation.AppendLine("Game requires expanded analog vertical controller."); - if((iPeripherals & 0x02000000) == 0x02000000) IPBinInformation.AppendLine("Game supports Gun."); - if((iPeripherals & 0x04000000) == 0x04000000) IPBinInformation.AppendLine("Game supports Keyboard."); - if((iPeripherals & 0x08000000) == 0x08000000) IPBinInformation.AppendLine("Game supports Mouse."); - - if((iPeripherals & 0xEE) != 0) - IPBinInformation.AppendFormat("Game supports unknown peripherals mask {0:X2}", iPeripherals & 0xEE); - - return IPBinInformation.ToString(); - } } } \ No newline at end of file diff --git a/Sega/Saturn.cs b/Sega/Saturn.cs index b6a7625..0c87a48 100644 --- a/Sega/Saturn.cs +++ b/Sega/Saturn.cs @@ -40,11 +40,160 @@ using Marshal = DiscImageChef.Helpers.Marshal; namespace DiscImageChef.Decoders.Sega { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public static class Saturn { + public static IPBin? DecodeIPBin(byte[] ipbin_sector) + { + if(ipbin_sector == null) + return null; + + if(ipbin_sector.Length < 512) + return null; + + var ipbin = Marshal.ByteArrayToStructureLittleEndian(ipbin_sector); + + DicConsole.DebugWriteLine("Saturn IP.BIN Decoder", "saturn_ipbin.maker_id = \"{0}\"", + Encoding.ASCII.GetString(ipbin.maker_id)); + + DicConsole.DebugWriteLine("Saturn IP.BIN Decoder", "saturn_ipbin.product_no = \"{0}\"", + Encoding.ASCII.GetString(ipbin.product_no)); + + DicConsole.DebugWriteLine("Saturn IP.BIN Decoder", "saturn_ipbin.product_version = \"{0}\"", + Encoding.ASCII.GetString(ipbin.product_version)); + + DicConsole.DebugWriteLine("Saturn IP.BIN Decoder", "saturn_ipbin.release_datedate = \"{0}\"", + Encoding.ASCII.GetString(ipbin.release_date)); + + DicConsole.DebugWriteLine("Saturn IP.BIN Decoder", "saturn_ipbin.saturn_media = \"{0}\"", + Encoding.ASCII.GetString(ipbin.saturn_media)); + + DicConsole.DebugWriteLine("Saturn IP.BIN Decoder", "saturn_ipbin.disc_no = {0}", (char)ipbin.disc_no); + + DicConsole.DebugWriteLine("Saturn IP.BIN Decoder", "saturn_ipbin.disc_no_separator = \"{0}\"", + (char)ipbin.disc_no_separator); + + DicConsole.DebugWriteLine("Saturn IP.BIN Decoder", "saturn_ipbin.disc_total_nos = {0}", + (char)ipbin.disc_total_nos); + + DicConsole.DebugWriteLine("Saturn IP.BIN Decoder", "saturn_ipbin.release_date = \"{0}\"", + Encoding.ASCII.GetString(ipbin.release_date)); + + DicConsole.DebugWriteLine("Saturn IP.BIN Decoder", "saturn_ipbin.spare_space1 = \"{0}\"", + Encoding.ASCII.GetString(ipbin.spare_space1)); + + DicConsole.DebugWriteLine("Saturn IP.BIN Decoder", "saturn_ipbin.region_codes = \"{0}\"", + Encoding.ASCII.GetString(ipbin.region_codes)); + + DicConsole.DebugWriteLine("Saturn IP.BIN Decoder", "saturn_ipbin.peripherals = \"{0}\"", + Encoding.ASCII.GetString(ipbin.peripherals)); + + DicConsole.DebugWriteLine("Saturn IP.BIN Decoder", "saturn_ipbin.product_name = \"{0}\"", + Encoding.ASCII.GetString(ipbin.product_name)); + + return Encoding.ASCII.GetString(ipbin.SegaHardwareID) == "SEGA SEGASATURN " ? ipbin : (IPBin?)null; + } + + public static string Prettify(IPBin? decoded) + { + if(decoded == null) + return null; + + IPBin ipbin = decoded.Value; + + var IPBinInformation = new StringBuilder(); + + IPBinInformation.AppendLine("--------------------------------"); + IPBinInformation.AppendLine("SEGA IP.BIN INFORMATION:"); + IPBinInformation.AppendLine("--------------------------------"); + + // Decoding all data + DateTime ipbindate; + CultureInfo provider = CultureInfo.InvariantCulture; + ipbindate = DateTime.ParseExact(Encoding.ASCII.GetString(ipbin.release_date), "yyyyMMdd", provider); + + IPBinInformation.AppendFormat("Product name: {0}", Encoding.ASCII.GetString(ipbin.product_name)). + AppendLine(); + + IPBinInformation.AppendFormat("Product number: {0}", Encoding.ASCII.GetString(ipbin.product_no)). + AppendLine(); + + IPBinInformation.AppendFormat("Product version: {0}", Encoding.ASCII.GetString(ipbin.product_version)). + AppendLine(); + + IPBinInformation.AppendFormat("Release date: {0}", ipbindate).AppendLine(); + + IPBinInformation.AppendFormat("Disc number {0} of {1}", (char)ipbin.disc_no, (char)ipbin.disc_total_nos). + AppendLine(); + + IPBinInformation.AppendFormat("Peripherals:").AppendLine(); + + foreach(byte peripheral in ipbin.peripherals) + switch((char)peripheral) + { + case'A': + IPBinInformation.AppendLine("Game supports analog controller."); + + break; + case'J': + IPBinInformation.AppendLine("Game supports JoyPad."); + + break; + case'K': + IPBinInformation.AppendLine("Game supports keyboard."); + + break; + case'M': + IPBinInformation.AppendLine("Game supports mouse."); + + break; + case'S': + IPBinInformation.AppendLine("Game supports analog steering controller."); + + break; + case'T': + IPBinInformation.AppendLine("Game supports multitap."); + + break; + case' ': break; + default: + IPBinInformation.AppendFormat("Game supports unknown peripheral {0}.", peripheral).AppendLine(); + + break; + } + + IPBinInformation.AppendLine("Regions supported:"); + + foreach(byte region in ipbin.region_codes) + switch((char)region) + { + case'J': + IPBinInformation.AppendLine("Japanese NTSC."); + + break; + case'U': + IPBinInformation.AppendLine("North America NTSC."); + + break; + case'E': + IPBinInformation.AppendLine("Europe PAL."); + + break; + case'T': + IPBinInformation.AppendLine("Asia NTSC."); + + break; + case' ': break; + default: + IPBinInformation.AppendFormat("Game supports unknown region {0}.", region).AppendLine(); + + break; + } + + return IPBinInformation.ToString(); + } + [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct IPBin { @@ -85,121 +234,5 @@ namespace DiscImageChef.Decoders.Sega [MarshalAs(UnmanagedType.ByValArray, SizeConst = 112)] public byte[] product_name; } - - public static IPBin? DecodeIPBin(byte[] ipbin_sector) - { - if(ipbin_sector == null) return null; - - if(ipbin_sector.Length < 512) return null; - - IPBin ipbin = Marshal.ByteArrayToStructureLittleEndian(ipbin_sector); - - DicConsole.DebugWriteLine("Saturn IP.BIN Decoder", "saturn_ipbin.maker_id = \"{0}\"", - Encoding.ASCII.GetString(ipbin.maker_id)); - DicConsole.DebugWriteLine("Saturn IP.BIN Decoder", "saturn_ipbin.product_no = \"{0}\"", - Encoding.ASCII.GetString(ipbin.product_no)); - DicConsole.DebugWriteLine("Saturn IP.BIN Decoder", "saturn_ipbin.product_version = \"{0}\"", - Encoding.ASCII.GetString(ipbin.product_version)); - DicConsole.DebugWriteLine("Saturn IP.BIN Decoder", "saturn_ipbin.release_datedate = \"{0}\"", - Encoding.ASCII.GetString(ipbin.release_date)); - DicConsole.DebugWriteLine("Saturn IP.BIN Decoder", "saturn_ipbin.saturn_media = \"{0}\"", - Encoding.ASCII.GetString(ipbin.saturn_media)); - DicConsole.DebugWriteLine("Saturn IP.BIN Decoder", "saturn_ipbin.disc_no = {0}", (char)ipbin.disc_no); - DicConsole.DebugWriteLine("Saturn IP.BIN Decoder", "saturn_ipbin.disc_no_separator = \"{0}\"", - (char)ipbin.disc_no_separator); - DicConsole.DebugWriteLine("Saturn IP.BIN Decoder", "saturn_ipbin.disc_total_nos = {0}", - (char)ipbin.disc_total_nos); - DicConsole.DebugWriteLine("Saturn IP.BIN Decoder", "saturn_ipbin.release_date = \"{0}\"", - Encoding.ASCII.GetString(ipbin.release_date)); - DicConsole.DebugWriteLine("Saturn IP.BIN Decoder", "saturn_ipbin.spare_space1 = \"{0}\"", - Encoding.ASCII.GetString(ipbin.spare_space1)); - DicConsole.DebugWriteLine("Saturn IP.BIN Decoder", "saturn_ipbin.region_codes = \"{0}\"", - Encoding.ASCII.GetString(ipbin.region_codes)); - DicConsole.DebugWriteLine("Saturn IP.BIN Decoder", "saturn_ipbin.peripherals = \"{0}\"", - Encoding.ASCII.GetString(ipbin.peripherals)); - DicConsole.DebugWriteLine("Saturn IP.BIN Decoder", "saturn_ipbin.product_name = \"{0}\"", - Encoding.ASCII.GetString(ipbin.product_name)); - - return Encoding.ASCII.GetString(ipbin.SegaHardwareID) == "SEGA SEGASATURN " ? ipbin : (IPBin?)null; - } - - public static string Prettify(IPBin? decoded) - { - if(decoded == null) return null; - - IPBin ipbin = decoded.Value; - - StringBuilder IPBinInformation = new StringBuilder(); - - IPBinInformation.AppendLine("--------------------------------"); - IPBinInformation.AppendLine("SEGA IP.BIN INFORMATION:"); - IPBinInformation.AppendLine("--------------------------------"); - - // Decoding all data - DateTime ipbindate; - CultureInfo provider = CultureInfo.InvariantCulture; - ipbindate = DateTime.ParseExact(Encoding.ASCII.GetString(ipbin.release_date), "yyyyMMdd", provider); - IPBinInformation.AppendFormat("Product name: {0}", Encoding.ASCII.GetString(ipbin.product_name)) - .AppendLine(); - IPBinInformation.AppendFormat("Product number: {0}", Encoding.ASCII.GetString(ipbin.product_no)) - .AppendLine(); - IPBinInformation.AppendFormat("Product version: {0}", Encoding.ASCII.GetString(ipbin.product_version)) - .AppendLine(); - IPBinInformation.AppendFormat("Release date: {0}", ipbindate).AppendLine(); - IPBinInformation.AppendFormat("Disc number {0} of {1}", (char)ipbin.disc_no, (char)ipbin.disc_total_nos) - .AppendLine(); - - IPBinInformation.AppendFormat("Peripherals:").AppendLine(); - foreach(byte peripheral in ipbin.peripherals) - switch((char)peripheral) - { - case 'A': - IPBinInformation.AppendLine("Game supports analog controller."); - break; - case 'J': - IPBinInformation.AppendLine("Game supports JoyPad."); - break; - case 'K': - IPBinInformation.AppendLine("Game supports keyboard."); - break; - case 'M': - IPBinInformation.AppendLine("Game supports mouse."); - break; - case 'S': - IPBinInformation.AppendLine("Game supports analog steering controller."); - break; - case 'T': - IPBinInformation.AppendLine("Game supports multitap."); - break; - case ' ': break; - default: - IPBinInformation.AppendFormat("Game supports unknown peripheral {0}.", peripheral).AppendLine(); - break; - } - - IPBinInformation.AppendLine("Regions supported:"); - foreach(byte region in ipbin.region_codes) - switch((char)region) - { - case 'J': - IPBinInformation.AppendLine("Japanese NTSC."); - break; - case 'U': - IPBinInformation.AppendLine("North America NTSC."); - break; - case 'E': - IPBinInformation.AppendLine("Europe PAL."); - break; - case 'T': - IPBinInformation.AppendLine("Asia NTSC."); - break; - case ' ': break; - default: - IPBinInformation.AppendFormat("Game supports unknown region {0}.", region).AppendLine(); - break; - } - - return IPBinInformation.ToString(); - } } } \ No newline at end of file diff --git a/Xbox/DMI.cs b/Xbox/DMI.cs index 4938b89..7ff93fa 100644 --- a/Xbox/DMI.cs +++ b/Xbox/DMI.cs @@ -36,29 +36,33 @@ using System.Text; namespace DiscImageChef.Decoders.Xbox { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] public static class DMI { public static bool IsXbox(byte[] dmi) { - if(dmi?.Length != 2052) return false; + if(dmi?.Length != 2052) + return false; // Version is 1 - if(BitConverter.ToUInt32(dmi, 4) != 1) return false; + if(BitConverter.ToUInt32(dmi, 4) != 1) + return false; // Catalogue number is two letters, five numbers, one letter for(int i = 12; i < 14; i++) - if(dmi[i] < 0x41 || dmi[i] > 0x5A) + if(dmi[i] < 0x41 || + dmi[i] > 0x5A) return false; for(int i = 14; i < 19; i++) - if(dmi[i] < 0x30 || dmi[i] > 0x39) + if(dmi[i] < 0x30 || + dmi[i] > 0x39) return false; - if(dmi[19] < 0x41 || dmi[19] > 0x5A) return false; + if(dmi[19] < 0x41 || + dmi[19] > 0x5A) + return false; long timestamp = BitConverter.ToInt64(dmi, 20); @@ -68,7 +72,8 @@ namespace DiscImageChef.Decoders.Xbox public static bool IsXbox360(byte[] dmi) { - if(dmi?.Length != 2052) return false; + if(dmi?.Length != 2052) + return false; uint signature = BitConverter.ToUInt32(dmi, 0x7EC); @@ -76,97 +81,17 @@ namespace DiscImageChef.Decoders.Xbox return signature == 0x584F4258; } - public struct XboxDMI - { - /// - /// Bytes 0 to 1 - /// Data length - /// - public ushort DataLength; - /// - /// Byte 2 - /// Reserved - /// - public byte Reserved1; - /// - /// Byte 3 - /// Reserved - /// - public byte Reserved2; - - /// - /// Bytes 4 to 7 - /// 0x01 in XGD - /// - public uint Version; - - /// - /// Bytes 12 to 16 - /// Catalogue number in XX-XXXXX-X - /// - public string CatalogNumber; - - /// - /// Bytes 20 to 27 - /// DMI timestamp - /// - public long Timestamp; - } - - public struct Xbox360DMI - { - /// - /// Bytes 0 to 1 - /// Data length - /// - public ushort DataLength; - /// - /// Byte 2 - /// Reserved - /// - public byte Reserved1; - /// - /// Byte 3 - /// Reserved - /// - public byte Reserved2; - - /// - /// Bytes 4 to 7 - /// 0x02 in XGD2 and XGD3 - /// - public uint Version; - - /// - /// Bytes 20 to 27 - /// DMI timestamp - /// - public long Timestamp; - - /// - /// Bytes 36 to 51 - /// Media ID in hex XXXXXXXXXXXX-XXXXXXXX - /// - public byte[] MediaID; - - /// - /// Bytes 68 to 83 - /// Catalogue number in XX-XXXX-XX-XXY-XXX, Y not always exists - /// - public string CatalogNumber; - } - public static XboxDMI? DecodeXbox(byte[] response) { bool isXbox = IsXbox(response); - if(!isXbox) return null; - XboxDMI dmi = new XboxDMI + if(!isXbox) + return null; + + var dmi = new XboxDMI { - DataLength = (ushort)((response[0] << 8) + response[1]), - Reserved1 = response[2], - Reserved2 = response[3], - Version = BitConverter.ToUInt32(response, 4), + DataLength = (ushort)((response[0] << 8) + response[1]), Reserved1 = response[2], + Reserved2 = response[3], Version = BitConverter.ToUInt32(response, 4), Timestamp = BitConverter.ToInt64(response, 20) }; @@ -180,16 +105,15 @@ namespace DiscImageChef.Decoders.Xbox public static Xbox360DMI? DecodeXbox360(byte[] response) { bool isX360 = IsXbox360(response); - if(!isX360) return null; - Xbox360DMI dmi = new Xbox360DMI + if(!isX360) + return null; + + var dmi = new Xbox360DMI { - DataLength = (ushort)((response[0] << 8) + response[1]), - Reserved1 = response[2], - Reserved2 = response[3], - Version = BitConverter.ToUInt32(response, 4), - Timestamp = BitConverter.ToInt64(response, 20), - MediaID = new byte[16] + DataLength = (ushort)((response[0] << 8) + response[1]), Reserved1 = response[2], + Reserved2 = response[3], Version = BitConverter.ToUInt32(response, 4), + Timestamp = BitConverter.ToInt64(response, 20), MediaID = new byte[16] }; Array.Copy(response, 36, dmi.MediaID, 0, 16); @@ -202,16 +126,21 @@ namespace DiscImageChef.Decoders.Xbox public static string PrettifyXbox(XboxDMI? dmi) { - if(dmi == null) return null; + if(dmi == null) + return null; - XboxDMI decoded = dmi.Value; - StringBuilder sb = new StringBuilder(); + XboxDMI decoded = dmi.Value; + var sb = new StringBuilder(); sb.Append("Catalogue number: "); - for(int i = 0; i < 2; i++) sb.AppendFormat("{0}", decoded.CatalogNumber[i]); + + for(int i = 0; i < 2; i++) + sb.AppendFormat("{0}", decoded.CatalogNumber[i]); sb.Append("-"); - for(int i = 2; i < 7; i++) sb.AppendFormat("{0}", decoded.CatalogNumber[i]); + + for(int i = 2; i < 7; i++) + sb.AppendFormat("{0}", decoded.CatalogNumber[i]); sb.Append("-"); sb.AppendFormat("{0}", decoded.CatalogNumber[7]); @@ -224,36 +153,49 @@ namespace DiscImageChef.Decoders.Xbox public static string PrettifyXbox360(Xbox360DMI? dmi) { - if(dmi == null) return null; + if(dmi == null) + return null; - Xbox360DMI decoded = dmi.Value; - StringBuilder sb = new StringBuilder(); + Xbox360DMI decoded = dmi.Value; + var sb = new StringBuilder(); sb.Append("Catalogue number: "); - for(int i = 0; i < 2; i++) sb.AppendFormat("{0}", decoded.CatalogNumber[i]); + + for(int i = 0; i < 2; i++) + sb.AppendFormat("{0}", decoded.CatalogNumber[i]); sb.Append("-"); - for(int i = 2; i < 6; i++) sb.AppendFormat("{0}", decoded.CatalogNumber[i]); + + for(int i = 2; i < 6; i++) + sb.AppendFormat("{0}", decoded.CatalogNumber[i]); sb.Append("-"); - for(int i = 6; i < 8; i++) sb.AppendFormat("{0}", decoded.CatalogNumber[i]); + + for(int i = 6; i < 8; i++) + sb.AppendFormat("{0}", decoded.CatalogNumber[i]); sb.Append("-"); switch(decoded.CatalogNumber.Length) { case 13: - for(int i = 8; i < 10; i++) sb.AppendFormat("{0}", decoded.CatalogNumber[i]); + for(int i = 8; i < 10; i++) + sb.AppendFormat("{0}", decoded.CatalogNumber[i]); sb.Append("-"); - for(int i = 10; i < 13; i++) sb.AppendFormat("{0}", decoded.CatalogNumber[i]); + + for(int i = 10; i < 13; i++) + sb.AppendFormat("{0}", decoded.CatalogNumber[i]); break; case 14: - for(int i = 8; i < 11; i++) sb.AppendFormat("{0}", decoded.CatalogNumber[i]); + for(int i = 8; i < 11; i++) + sb.AppendFormat("{0}", decoded.CatalogNumber[i]); sb.Append("-"); - for(int i = 11; i < 14; i++) sb.AppendFormat("{0}", decoded.CatalogNumber[i]); + + for(int i = 11; i < 14; i++) + sb.AppendFormat("{0}", decoded.CatalogNumber[i]); break; default: @@ -261,6 +203,7 @@ namespace DiscImageChef.Decoders.Xbox sb.AppendFormat("{0}", decoded.CatalogNumber[i]); sb.Append("-"); + for(int i = decoded.CatalogNumber.Length - 3; i < decoded.CatalogNumber.Length; i++) sb.AppendFormat("{0}", decoded.CatalogNumber[i]); @@ -270,10 +213,14 @@ namespace DiscImageChef.Decoders.Xbox sb.AppendLine(); sb.Append("Media ID: "); - for(int i = 0; i < 12; i++) sb.AppendFormat("{0:X2}", decoded.MediaID[i]); + + for(int i = 0; i < 12; i++) + sb.AppendFormat("{0:X2}", decoded.MediaID[i]); sb.Append("-"); - for(int i = 12; i < 16; i++) sb.AppendFormat("{0:X2}", decoded.MediaID[i]); + + for(int i = 12; i < 16; i++) + sb.AppendFormat("{0:X2}", decoded.MediaID[i]); sb.AppendLine(); @@ -285,5 +232,46 @@ namespace DiscImageChef.Decoders.Xbox public static string PrettifyXbox(byte[] response) => PrettifyXbox(DecodeXbox(response)); public static string PrettifyXbox360(byte[] response) => PrettifyXbox360(DecodeXbox360(response)); + + public struct XboxDMI + { + /// Bytes 0 to 1 Data length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + + /// Bytes 4 to 7 0x01 in XGD + public uint Version; + + /// Bytes 12 to 16 Catalogue number in XX-XXXXX-X + public string CatalogNumber; + + /// Bytes 20 to 27 DMI timestamp + public long Timestamp; + } + + public struct Xbox360DMI + { + /// Bytes 0 to 1 Data length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + + /// Bytes 4 to 7 0x02 in XGD2 and XGD3 + public uint Version; + + /// Bytes 20 to 27 DMI timestamp + public long Timestamp; + + /// Bytes 36 to 51 Media ID in hex XXXXXXXXXXXX-XXXXXXXX + public byte[] MediaID; + + /// Bytes 68 to 83 Catalogue number in XX-XXXX-XX-XXY-XXX, Y not always exists + public string CatalogNumber; + } } } \ No newline at end of file diff --git a/Xbox/SS.cs b/Xbox/SS.cs index b2f8930..ee7bc9d 100644 --- a/Xbox/SS.cs +++ b/Xbox/SS.cs @@ -37,204 +37,31 @@ using DiscImageChef.Decoders.DVD; namespace DiscImageChef.Decoders.Xbox { - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "MemberCanBeInternal")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - [SuppressMessage("ReSharper", "NotAccessedField.Global")] + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] public static class SS { - public struct SecuritySector - { - /// - /// Byte 0, bits 7 to 4 - /// Disk category field - /// - public DiskCategory DiskCategory; - /// - /// Byte 0, bits 3 to 0 - /// Media version - /// - public byte PartVersion; - /// - /// Byte 1, bits 7 to 4 - /// 120mm if 0, 80mm if 1. If UMD (60mm) 0 also. Reserved rest of values - /// - public DVDSize DiscSize; - /// - /// Byte 1, bits 3 to 0 - /// Maximum data rate - /// - public MaximumRateField MaximumRate; - /// - /// Byte 2, bit 7 - /// Reserved - /// - public bool Reserved3; - /// - /// Byte 2, bits 6 to 5 - /// Number of layers - /// - public byte Layers; - /// - /// Byte 2, bit 4 - /// Track path - /// - public bool TrackPath; - /// - /// Byte 2, bits 3 to 0 - /// Layer type - /// - public LayerTypeFieldMask LayerType; - /// - /// Byte 3, bits 7 to 4 - /// Linear density field - /// - public LinearDensityField LinearDensity; - /// - /// Byte 3, bits 3 to 0 - /// Track density field - /// - public TrackDensityField TrackDensity; - /// - /// Bytes 4 to 7 - /// PSN where Data Area starts - /// - public uint DataAreaStartPSN; - /// - /// Bytes 8 to 11 - /// PSN where Data Area ends - /// - public uint DataAreaEndPSN; - /// - /// Bytes 12 to 15 - /// PSN where Data Area ends in Layer 0 - /// - public uint Layer0EndPSN; - - /// - /// Byte 27 - /// Always 0x06 on XGD3 - /// - public byte Unknown1; - /// - /// Bytes 256 to 283 - /// Unknown, XGD2 and XGD3 - /// - public byte[] Unknown2; - /// - /// Bytes 284 to 719 - /// Unknown, XGD3 - /// - public byte[] Unknown3; - /// - /// Bytes 720 to 723 - /// Unknown - /// - public byte[] Unknown4; - /// - /// Bytes 724 to 767 - /// Unknown, XGD3 - /// - public byte[] Unknown5; - /// - /// Byte 768 - /// Version of challenge table - /// - public byte ChallengeTableVersion; - /// - /// Byte 769 - /// Number of challenge entries - /// - public byte NoChallengeEntries; - /// - /// Bytes 770 to 1022 - /// Unknown - /// - public ChallengeEntry[] ChallengeEntries; - /// - /// Byte 1023 - /// Unknown - /// - public byte Unknown6; - /// - /// Bytes 1052 to 1099 - /// Unknown, XGD1 only - /// - public byte[] Unknown7; - /// - /// Bytes 1120 to 1135 - /// Unknown, XGD2 and XGD3 - /// - public byte[] Unknown8; - /// - /// Bytes 1180 to 1195 - /// Unknown - /// - public byte[] Unknown9; - /// - /// Bytes 1208 to 1511 - /// Unknown - /// - public byte[] Unknown10; - /// - /// Bytes 1528 to 1632 - /// - public byte[] Unknown11; - /// - /// Bytes 1633 to 1839 - /// Security extents, 23 entries of 9 bytes - /// - public SecuritySectorExtent[] Extents; - /// - /// Bytes 1840 to 2047 - /// Copy of the security extents, 23 entries of 9 bytes - /// - public SecuritySectorExtent[] ExtentsCopy; - } - - public struct SecuritySectorExtent - { - /// - /// Bytes 0 to 2 - /// Unknown - /// - public uint Unknown; - /// - /// Bytes 3 to 5 - /// Start PSN of this security extent - /// - public uint StartPSN; - /// - /// Bytes 6 to 8 - /// End PSN of this security extent - /// - public uint EndPSN; - } - - public struct ChallengeEntry - { - public byte Level; - public byte ChallengeId; - public uint ChallengeValue; - public byte ResponseModifier; - public uint ResponseValue; - } - public static SecuritySector? Decode(byte[] response) { - if(response == null) return null; + if(response == null) + return null; - if(response.Length < 2048) return null; + if(response.Length < 2048) + return null; - SecuritySector ss = new SecuritySector + var ss = new SecuritySector { - DiskCategory = (DiskCategory)((response[0] & 0xF0) >> 4), - PartVersion = (byte)(response[0] & 0x0F), - DiscSize = (DVDSize)((response[1] & 0xF0) >> 4), - MaximumRate = (MaximumRateField)(response[1] & 0x0F), - Reserved3 = (response[2] & 0x80) == 0x80, - Layers = (byte)((response[2] & 0x60) >> 5), - TrackPath = (response[2] & 0x08) == 0x08, + DiskCategory = (DiskCategory)((response[0] & 0xF0) >> 4), + PartVersion = (byte)(response[0] & 0x0F), + DiscSize = (DVDSize)((response[1] & 0xF0) >> 4), + MaximumRate = (MaximumRateField)(response[1] & 0x0F), + Reserved3 = + (response[2] & 0x80) == + 0x80, + Layers = (byte)((response[2] & 0x60) >> 5), + TrackPath = + (response[2] & 0x08) == + 0x08, LayerType = (LayerTypeFieldMask)(response[2] & 0x07), LinearDensity = (LinearDensityField)((response[3] & 0xF0) >> 4), TrackDensity = (TrackDensityField)(response[3] & 0x0F), @@ -244,22 +71,15 @@ namespace DiscImageChef.Decoders.Xbox (uint)((response[8] << 24) + (response[9] << 16) + (response[10] << 8) + response[11]), Layer0EndPSN = (uint)((response[12] << 24) + (response[13] << 16) + (response[14] << 8) + response[15]), - Unknown1 = response[27], - Unknown2 = new byte[28], - Unknown3 = new byte[436], - Unknown4 = new byte[4], - Unknown5 = new byte[43], - ChallengeTableVersion = response[768], - NoChallengeEntries = response[769], - ChallengeEntries = new ChallengeEntry[23], - Unknown6 = response[1023], - Unknown7 = new byte[48], - Unknown8 = new byte[16], - Unknown9 = new byte[16], - Unknown10 = new byte[303], - Unknown11 = new byte[104], - Extents = new SecuritySectorExtent[23], - ExtentsCopy = new SecuritySectorExtent[23] + Unknown1 = response[27], Unknown2 = new byte[28], + Unknown3 = new byte[436], Unknown4 = new byte[4], + Unknown5 = new byte[43], ChallengeTableVersion = response[768], + NoChallengeEntries = response[769], + ChallengeEntries = new ChallengeEntry[23], Unknown6 = response[1023], + Unknown7 = new byte[48], + Unknown8 = new byte[16], Unknown9 = new byte[16], + Unknown10 = new byte[303], Unknown11 = new byte[104], + Extents = new SecuritySectorExtent[23], ExtentsCopy = new SecuritySectorExtent[23] }; Array.Copy(response, 256, ss.Unknown2, 0, 28); @@ -270,30 +90,27 @@ namespace DiscImageChef.Decoders.Xbox for(int i = 0; i < 23; i++) ss.ChallengeEntries[i] = new ChallengeEntry { - Level = response[770 + i * 11 + 0], - ChallengeId = response[770 + i * 11 + 1], - ChallengeValue = - (uint)((response[770 + i * 11 + 2] << 24) + (response[770 + i * 11 + 3] << 16) + - (response[770 + i * 11 + 4] << 8) + response[770 + i * 11 + 5]), + Level = response[770 + i * 11 + 0], ChallengeId = response[770 + i * 11 + 1], + ChallengeValue = (uint)((response[770 + i * 11 + 2] << 24) + (response[770 + i * 11 + 3] << 16) + + (response[770 + i * 11 + 4] << 8) + response[770 + i * 11 + 5]), ResponseModifier = response[770 + i * 11 + 6], ResponseValue = (uint)((response[770 + i * 11 + 7] << 24) + (response[770 + i * 11 + 8] << 16) + (response[770 + i * 11 + 9] << 8) + response[770 + i * 11 + 10]) }; - Array.Copy(response, 1052, ss.Unknown7, 0, 48); - Array.Copy(response, 1120, ss.Unknown8, 0, 16); - Array.Copy(response, 1180, ss.Unknown9, 0, 16); + Array.Copy(response, 1052, ss.Unknown7, 0, 48); + Array.Copy(response, 1120, ss.Unknown8, 0, 16); + Array.Copy(response, 1180, ss.Unknown9, 0, 16); Array.Copy(response, 1208, ss.Unknown10, 0, 303); Array.Copy(response, 1528, ss.Unknown11, 0, 104); + for(int i = 0; i < 23; i++) ss.Extents[i] = new SecuritySectorExtent { - Unknown = - (uint)((response[1633 + i * 9 + 0] << 16) + (response[1633 + i * 9 + 1] << 8) + - response[1633 + i * 9 + 2]), - StartPSN = - (uint)((response[1633 + i * 9 + 3] << 16) + (response[1633 + i * 9 + 4] << 8) + - response[1633 + i * 9 + 5]), + Unknown = (uint)((response[1633 + i * 9 + 0] << 16) + (response[1633 + i * 9 + 1] << 8) + + response[1633 + i * 9 + 2]), + StartPSN = (uint)((response[1633 + i * 9 + 3] << 16) + (response[1633 + i * 9 + 4] << 8) + + response[1633 + i * 9 + 5]), EndPSN = (uint)((response[1633 + i * 9 + 6] << 16) + (response[1633 + i * 9 + 7] << 8) + response[1633 + i * 9 + 8]) }; @@ -301,12 +118,10 @@ namespace DiscImageChef.Decoders.Xbox for(int i = 0; i < 23; i++) ss.ExtentsCopy[i] = new SecuritySectorExtent { - Unknown = - (uint)((response[1840 + i * 9 + 0] << 16) + (response[1840 + i * 9 + 1] << 8) + - response[1840 + i * 9 + 2]), - StartPSN = - (uint)((response[1840 + i * 9 + 3] << 16) + (response[1840 + i * 9 + 4] << 8) + - response[1840 + i * 9 + 5]), + Unknown = (uint)((response[1840 + i * 9 + 0] << 16) + (response[1840 + i * 9 + 1] << 8) + + response[1840 + i * 9 + 2]), + StartPSN = (uint)((response[1840 + i * 9 + 3] << 16) + (response[1840 + i * 9 + 4] << 8) + + response[1840 + i * 9 + 5]), EndPSN = (uint)((response[1840 + i * 9 + 6] << 16) + (response[1840 + i * 9 + 7] << 8) + response[1840 + i * 9 + 8]) }; @@ -316,22 +131,27 @@ namespace DiscImageChef.Decoders.Xbox public static string Prettify(SecuritySector? ss) { - if(ss == null) return null; + if(ss == null) + return null; SecuritySector decoded = ss.Value; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); string sizeString; + switch(decoded.DiscSize) { case DVDSize.Eighty: sizeString = "80mm"; + break; case DVDSize.OneTwenty: sizeString = "120mm"; + break; default: sizeString = $"unknown size identifier {decoded.DiscSize}"; + break; } @@ -341,14 +161,17 @@ namespace DiscImageChef.Decoders.Xbox { case DiskCategory.DVDPRWDL: sb.AppendFormat(categorySentence, sizeString, "Xbox Game Disc", decoded.PartVersion).AppendLine(); + break; case DiskCategory.DVDPRDL: - sb.AppendFormat(categorySentence, sizeString, "Xbox 360 Game Disc", decoded.PartVersion) - .AppendLine(); + sb.AppendFormat(categorySentence, sizeString, "Xbox 360 Game Disc", decoded.PartVersion). + AppendLine(); + break; default: - sb.AppendFormat(categorySentence, sizeString, "unknown disc type", decoded.PartVersion) - .AppendLine(); + sb.AppendFormat(categorySentence, sizeString, "unknown disc type", decoded.PartVersion). + AppendLine(); + break; } @@ -356,57 +179,77 @@ namespace DiscImageChef.Decoders.Xbox { case MaximumRateField.TwoMbps: sb.AppendLine("Disc maximum transfer rate is 2,52 Mbit/sec."); + break; case MaximumRateField.FiveMbps: sb.AppendLine("Disc maximum transfer rate is 5,04 Mbit/sec."); + break; case MaximumRateField.TenMbps: sb.AppendLine("Disc maximum transfer rate is 10,08 Mbit/sec."); + break; case MaximumRateField.TwentyMbps: sb.AppendLine("Disc maximum transfer rate is 20,16 Mbit/sec."); + break; case MaximumRateField.ThirtyMbps: sb.AppendLine("Disc maximum transfer rate is 30,24 Mbit/sec."); + break; case MaximumRateField.Unspecified: sb.AppendLine("Disc maximum transfer rate is unspecified."); + break; default: - sb.AppendFormat("Disc maximum transfer rate is specified by unknown key {0}", decoded.MaximumRate) - .AppendLine(); + sb.AppendFormat("Disc maximum transfer rate is specified by unknown key {0}", decoded.MaximumRate). + AppendLine(); + break; } sb.AppendFormat("Disc has {0} layers", decoded.Layers + 1).AppendLine(); - if(decoded.TrackPath && decoded.Layers == 1) sb.AppendLine("Layers are in parallel track path"); - else if(!decoded.TrackPath && decoded.Layers == 1) sb.AppendLine("Layers are in opposite track path"); + + if(decoded.TrackPath && + decoded.Layers == 1) + sb.AppendLine("Layers are in parallel track path"); + else if(!decoded.TrackPath && + decoded.Layers == 1) + sb.AppendLine("Layers are in opposite track path"); switch(decoded.LinearDensity) { case LinearDensityField.TwoSix: sb.AppendLine("Pitch size is 0,267 μm/bit"); + break; case LinearDensityField.TwoNine: sb.AppendLine("Pitch size is 0,147 μm/bit"); + break; case LinearDensityField.FourZero: sb.AppendLine("Pitch size is between 0,409 μm/bit and 0,435 μm/bit"); + break; case LinearDensityField.TwoEight: sb.AppendLine("Pitch size is between 0,140 μm/bit and 0,148 μm/bit"); + break; case LinearDensityField.OneFive: sb.AppendLine("Pitch size is 0,153 μm/bit"); + break; case LinearDensityField.OneThree: sb.AppendLine("Pitch size is between 0,130 μm/bit and 0,140 μm/bit"); + break; case LinearDensityField.ThreeFive: sb.AppendLine("Pitch size is 0,353 μm/bit"); + break; default: sb.AppendFormat("Unknown pitch size key {0}", decoded.LinearDensity).AppendLine(); + break; } @@ -414,21 +257,27 @@ namespace DiscImageChef.Decoders.Xbox { case TrackDensityField.Seven: sb.AppendLine("Track size is 0,74 μm"); + break; case TrackDensityField.Eight: sb.AppendLine("Track size is 0,80 μm"); + break; case TrackDensityField.Six: sb.AppendLine("Track size is 0,615 μm"); + break; case TrackDensityField.Four: sb.AppendLine("Track size is 0,40 μm"); + break; case TrackDensityField.Three: sb.AppendLine("Track size is 0,34 μm"); + break; default: sb.AppendFormat("Unknown track size key {0}", decoded.LinearDensity).AppendLine(); + break; } @@ -437,14 +286,18 @@ namespace DiscImageChef.Decoders.Xbox { sb.AppendFormat("Data area starts at PSN {0:X}h", decoded.DataAreaStartPSN).AppendLine(); sb.AppendFormat("Data area ends at PSN {0:X}h", decoded.DataAreaEndPSN).AppendLine(); - if(decoded.Layers == 1 && !decoded.TrackPath) + + if(decoded.Layers == 1 && + !decoded.TrackPath) sb.AppendFormat("Layer 0 ends at PSN {0:X}h", decoded.Layer0EndPSN).AppendLine(); } else sb.AppendLine("Disc is empty"); - else sb.AppendLine("Disc is empty"); + else + sb.AppendLine("Disc is empty"); sb.AppendLine("Challenges:"); + foreach(ChallengeEntry entry in decoded.ChallengeEntries) { sb.AppendFormat("\tChallenge ID: {0}", entry.ChallengeId).AppendLine(); @@ -462,5 +315,87 @@ namespace DiscImageChef.Decoders.Xbox } public static string Prettify(byte[] response) => Prettify(Decode(response)); + + public struct SecuritySector + { + /// Byte 0, bits 7 to 4 Disk category field + public DiskCategory DiskCategory; + /// Byte 0, bits 3 to 0 Media version + public byte PartVersion; + /// Byte 1, bits 7 to 4 120mm if 0, 80mm if 1. If UMD (60mm) 0 also. Reserved rest of values + public DVDSize DiscSize; + /// Byte 1, bits 3 to 0 Maximum data rate + public MaximumRateField MaximumRate; + /// Byte 2, bit 7 Reserved + public bool Reserved3; + /// Byte 2, bits 6 to 5 Number of layers + public byte Layers; + /// Byte 2, bit 4 Track path + public bool TrackPath; + /// Byte 2, bits 3 to 0 Layer type + public LayerTypeFieldMask LayerType; + /// Byte 3, bits 7 to 4 Linear density field + public LinearDensityField LinearDensity; + /// Byte 3, bits 3 to 0 Track density field + public TrackDensityField TrackDensity; + /// Bytes 4 to 7 PSN where Data Area starts + public uint DataAreaStartPSN; + /// Bytes 8 to 11 PSN where Data Area ends + public uint DataAreaEndPSN; + /// Bytes 12 to 15 PSN where Data Area ends in Layer 0 + public uint Layer0EndPSN; + + /// Byte 27 Always 0x06 on XGD3 + public byte Unknown1; + /// Bytes 256 to 283 Unknown, XGD2 and XGD3 + public byte[] Unknown2; + /// Bytes 284 to 719 Unknown, XGD3 + public byte[] Unknown3; + /// Bytes 720 to 723 Unknown + public byte[] Unknown4; + /// Bytes 724 to 767 Unknown, XGD3 + public byte[] Unknown5; + /// Byte 768 Version of challenge table + public byte ChallengeTableVersion; + /// Byte 769 Number of challenge entries + public byte NoChallengeEntries; + /// Bytes 770 to 1022 Unknown + public ChallengeEntry[] ChallengeEntries; + /// Byte 1023 Unknown + public byte Unknown6; + /// Bytes 1052 to 1099 Unknown, XGD1 only + public byte[] Unknown7; + /// Bytes 1120 to 1135 Unknown, XGD2 and XGD3 + public byte[] Unknown8; + /// Bytes 1180 to 1195 Unknown + public byte[] Unknown9; + /// Bytes 1208 to 1511 Unknown + public byte[] Unknown10; + /// Bytes 1528 to 1632 + public byte[] Unknown11; + /// Bytes 1633 to 1839 Security extents, 23 entries of 9 bytes + public SecuritySectorExtent[] Extents; + /// Bytes 1840 to 2047 Copy of the security extents, 23 entries of 9 bytes + public SecuritySectorExtent[] ExtentsCopy; + } + + public struct SecuritySectorExtent + { + /// Bytes 0 to 2 Unknown + public uint Unknown; + /// Bytes 3 to 5 Start PSN of this security extent + public uint StartPSN; + /// Bytes 6 to 8 End PSN of this security extent + public uint EndPSN; + } + + public struct ChallengeEntry + { + public byte Level; + public byte ChallengeId; + public uint ChallengeValue; + public byte ResponseModifier; + public uint ResponseValue; + } } } \ No newline at end of file