From 9dff1f8a541e7255c6efb7b7d0514dd73333d731 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Sun, 21 Jan 2018 21:56:09 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9BFix=20sending=20READ=20LONG=20comma?= =?UTF-8?q?nds=20to=20ATA=20devices,=20thanks=20to=20supporting=20SET=20FE?= =?UTF-8?q?ATURES=20command.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DiscImageChef.Core/Devices/Report/ATA.cs | 593 +++++++++++------- .../Device/AtaCommands/AtaCHS.cs | 150 +++-- DiscImageChef.Devices/Enums.cs | 203 ++++-- DiscImageChef.Tests.Devices/ATA/Ata28.cs | 148 +++-- DiscImageChef.Tests.Devices/ATA/AtaCHS.cs | 296 +++++++-- 5 files changed, 936 insertions(+), 454 deletions(-) diff --git a/DiscImageChef.Core/Devices/Report/ATA.cs b/DiscImageChef.Core/Devices/Report/ATA.cs index 960589fc..d1f06a80 100644 --- a/DiscImageChef.Core/Devices/Report/ATA.cs +++ b/DiscImageChef.Core/Devices/Report/ATA.cs @@ -77,9 +77,9 @@ namespace DiscImageChef.Core.Devices.Report ConsoleKeyInfo pressedKey; if((ushort)ataId.GeneralConfiguration == 0x848A) { - report.CompactFlash = true; + report.CompactFlash = true; report.CompactFlashSpecified = true; - removable = false; + removable = false; } else if(!removable && ataId.GeneralConfiguration.HasFlag(Identify.GeneralConfigurationBit.Removable)) { @@ -107,394 +107,472 @@ namespace DiscImageChef.Core.Devices.Report if(!string.IsNullOrWhiteSpace(ataId.AdditionalPID)) { - report.ATA.AdditionalPID = ataId.AdditionalPID; + report.ATA.AdditionalPID = ataId.AdditionalPID; report.ATA.AdditionalPIDSpecified = true; } + if(ataId.APIOSupported != 0) { - report.ATA.APIOSupported = ataId.APIOSupported; + report.ATA.APIOSupported = ataId.APIOSupported; report.ATA.APIOSupportedSpecified = true; } + if(ataId.BufferType != 0) { - report.ATA.BufferType = ataId.BufferType; + report.ATA.BufferType = ataId.BufferType; report.ATA.BufferTypeSpecified = true; } + if(ataId.BufferSize != 0) { - report.ATA.BufferSize = ataId.BufferSize; + report.ATA.BufferSize = ataId.BufferSize; report.ATA.BufferSizeSpecified = true; } + if(ataId.Capabilities != 0) { - report.ATA.Capabilities = ataId.Capabilities; + report.ATA.Capabilities = ataId.Capabilities; report.ATA.CapabilitiesSpecified = true; } + if(ataId.Capabilities2 != 0) { - report.ATA.Capabilities2 = ataId.Capabilities2; + report.ATA.Capabilities2 = ataId.Capabilities2; report.ATA.Capabilities2Specified = true; } + if(ataId.Capabilities3 != 0) { - report.ATA.Capabilities3 = ataId.Capabilities3; + report.ATA.Capabilities3 = ataId.Capabilities3; report.ATA.Capabilities3Specified = true; } + if(ataId.CFAPowerMode != 0) { - report.ATA.CFAPowerMode = ataId.CFAPowerMode; + report.ATA.CFAPowerMode = ataId.CFAPowerMode; report.ATA.CFAPowerModeSpecified = true; } + if(ataId.CommandSet != 0) { - report.ATA.CommandSet = ataId.CommandSet; + report.ATA.CommandSet = ataId.CommandSet; report.ATA.CommandSetSpecified = true; } + if(ataId.CommandSet2 != 0) { - report.ATA.CommandSet2 = ataId.CommandSet2; + report.ATA.CommandSet2 = ataId.CommandSet2; report.ATA.CommandSet2Specified = true; } + if(ataId.CommandSet3 != 0) { - report.ATA.CommandSet3 = ataId.CommandSet3; + report.ATA.CommandSet3 = ataId.CommandSet3; report.ATA.CommandSet3Specified = true; } + if(ataId.CommandSet4 != 0) { - report.ATA.CommandSet4 = ataId.CommandSet4; + report.ATA.CommandSet4 = ataId.CommandSet4; report.ATA.CommandSet4Specified = true; } + if(ataId.CommandSet5 != 0) { - report.ATA.CommandSet5 = ataId.CommandSet5; + report.ATA.CommandSet5 = ataId.CommandSet5; report.ATA.CommandSet5Specified = true; } + if(ataId.CurrentAAM != 0) { - report.ATA.CurrentAAM = ataId.CurrentAAM; + report.ATA.CurrentAAM = ataId.CurrentAAM; report.ATA.CurrentAAMSpecified = true; } + if(ataId.CurrentAPM != 0) { - report.ATA.CurrentAPM = ataId.CurrentAPM; + report.ATA.CurrentAPM = ataId.CurrentAPM; report.ATA.CurrentAPMSpecified = true; } + if(ataId.DataSetMgmt != 0) { - report.ATA.DataSetMgmt = ataId.DataSetMgmt; + report.ATA.DataSetMgmt = ataId.DataSetMgmt; report.ATA.DataSetMgmtSpecified = true; } + if(ataId.DataSetMgmtSize != 0) { - report.ATA.DataSetMgmtSize = ataId.DataSetMgmtSize; + report.ATA.DataSetMgmtSize = ataId.DataSetMgmtSize; report.ATA.DataSetMgmtSizeSpecified = true; } + if(ataId.DeviceFormFactor != 0) { - report.ATA.DeviceFormFactor = ataId.DeviceFormFactor; + report.ATA.DeviceFormFactor = ataId.DeviceFormFactor; report.ATA.DeviceFormFactorSpecified = true; } + if(ataId.DMAActive != 0) { - report.ATA.DMAActive = ataId.DMAActive; + report.ATA.DMAActive = ataId.DMAActive; report.ATA.DMAActiveSpecified = true; } + if(ataId.DMASupported != 0) { - report.ATA.DMASupported = ataId.DMASupported; + report.ATA.DMASupported = ataId.DMASupported; report.ATA.DMASupportedSpecified = true; } + if(ataId.DMATransferTimingMode != 0) { - report.ATA.DMATransferTimingMode = ataId.DMATransferTimingMode; + report.ATA.DMATransferTimingMode = ataId.DMATransferTimingMode; report.ATA.DMATransferTimingModeSpecified = true; } + if(ataId.EnhancedSecurityEraseTime != 0) { - report.ATA.EnhancedSecurityEraseTime = ataId.EnhancedSecurityEraseTime; + report.ATA.EnhancedSecurityEraseTime = ataId.EnhancedSecurityEraseTime; report.ATA.EnhancedSecurityEraseTimeSpecified = true; } + if(ataId.EnabledCommandSet != 0) { - report.ATA.EnabledCommandSet = ataId.EnabledCommandSet; + report.ATA.EnabledCommandSet = ataId.EnabledCommandSet; report.ATA.EnabledCommandSetSpecified = true; } + if(ataId.EnabledCommandSet2 != 0) { - report.ATA.EnabledCommandSet2 = ataId.EnabledCommandSet2; + report.ATA.EnabledCommandSet2 = ataId.EnabledCommandSet2; report.ATA.EnabledCommandSet2Specified = true; } + if(ataId.EnabledCommandSet3 != 0) { - report.ATA.EnabledCommandSet3 = ataId.EnabledCommandSet3; + report.ATA.EnabledCommandSet3 = ataId.EnabledCommandSet3; report.ATA.EnabledCommandSet3Specified = true; } + if(ataId.EnabledCommandSet4 != 0) { - report.ATA.EnabledCommandSet4 = ataId.EnabledCommandSet4; + report.ATA.EnabledCommandSet4 = ataId.EnabledCommandSet4; report.ATA.EnabledCommandSet4Specified = true; } + if(ataId.EnabledSATAFeatures != 0) { - report.ATA.EnabledSATAFeatures = ataId.EnabledSATAFeatures; + report.ATA.EnabledSATAFeatures = ataId.EnabledSATAFeatures; report.ATA.EnabledSATAFeaturesSpecified = true; } + if(ataId.ExtendedUserSectors != 0) { - report.ATA.ExtendedUserSectors = ataId.ExtendedUserSectors; + report.ATA.ExtendedUserSectors = ataId.ExtendedUserSectors; report.ATA.ExtendedUserSectorsSpecified = true; } + if(ataId.FreeFallSensitivity != 0) { - report.ATA.FreeFallSensitivity = ataId.FreeFallSensitivity; + report.ATA.FreeFallSensitivity = ataId.FreeFallSensitivity; report.ATA.FreeFallSensitivitySpecified = true; } + if(!string.IsNullOrWhiteSpace(ataId.FirmwareRevision)) { - report.ATA.FirmwareRevision = ataId.FirmwareRevision; + report.ATA.FirmwareRevision = ataId.FirmwareRevision; report.ATA.FirmwareRevisionSpecified = true; } + if(ataId.GeneralConfiguration != 0) { - report.ATA.GeneralConfiguration = ataId.GeneralConfiguration; + report.ATA.GeneralConfiguration = ataId.GeneralConfiguration; report.ATA.GeneralConfigurationSpecified = true; } + if(ataId.HardwareResetResult != 0) { - report.ATA.HardwareResetResult = ataId.HardwareResetResult; + report.ATA.HardwareResetResult = ataId.HardwareResetResult; report.ATA.HardwareResetResultSpecified = true; } + if(ataId.InterseekDelay != 0) { - report.ATA.InterseekDelay = ataId.InterseekDelay; + report.ATA.InterseekDelay = ataId.InterseekDelay; report.ATA.InterseekDelaySpecified = true; } + if(ataId.MajorVersion != 0) { - report.ATA.MajorVersion = ataId.MajorVersion; + report.ATA.MajorVersion = ataId.MajorVersion; report.ATA.MajorVersionSpecified = true; } + if(ataId.MasterPasswordRevisionCode != 0) { - report.ATA.MasterPasswordRevisionCode = ataId.MasterPasswordRevisionCode; + report.ATA.MasterPasswordRevisionCode = ataId.MasterPasswordRevisionCode; report.ATA.MasterPasswordRevisionCodeSpecified = true; } + if(ataId.MaxDownloadMicroMode3 != 0) { - report.ATA.MaxDownloadMicroMode3 = ataId.MaxDownloadMicroMode3; + report.ATA.MaxDownloadMicroMode3 = ataId.MaxDownloadMicroMode3; report.ATA.MaxDownloadMicroMode3Specified = true; } + if(ataId.MaxQueueDepth != 0) { - report.ATA.MaxQueueDepth = ataId.MaxQueueDepth; + report.ATA.MaxQueueDepth = ataId.MaxQueueDepth; report.ATA.MaxQueueDepthSpecified = true; } + if(ataId.MDMAActive != 0) { - report.ATA.MDMAActive = ataId.MDMAActive; + report.ATA.MDMAActive = ataId.MDMAActive; report.ATA.MDMAActiveSpecified = true; } + if(ataId.MDMASupported != 0) { - report.ATA.MDMASupported = ataId.MDMASupported; + report.ATA.MDMASupported = ataId.MDMASupported; report.ATA.MDMASupportedSpecified = true; } + if(ataId.MinDownloadMicroMode3 != 0) { - report.ATA.MinDownloadMicroMode3 = ataId.MinDownloadMicroMode3; + report.ATA.MinDownloadMicroMode3 = ataId.MinDownloadMicroMode3; report.ATA.MinDownloadMicroMode3Specified = true; } + if(ataId.MinMDMACycleTime != 0) { - report.ATA.MinMDMACycleTime = ataId.MinMDMACycleTime; + report.ATA.MinMDMACycleTime = ataId.MinMDMACycleTime; report.ATA.MinMDMACycleTimeSpecified = true; } + if(ataId.MinorVersion != 0) { - report.ATA.MinorVersion = ataId.MinorVersion; + report.ATA.MinorVersion = ataId.MinorVersion; report.ATA.MinorVersionSpecified = true; } + if(ataId.MinPIOCycleTimeNoFlow != 0) { - report.ATA.MinPIOCycleTimeNoFlow = ataId.MinPIOCycleTimeNoFlow; + report.ATA.MinPIOCycleTimeNoFlow = ataId.MinPIOCycleTimeNoFlow; report.ATA.MinPIOCycleTimeNoFlowSpecified = true; } + if(ataId.MinPIOCycleTimeFlow != 0) { - report.ATA.MinPIOCycleTimeFlow = ataId.MinPIOCycleTimeFlow; + report.ATA.MinPIOCycleTimeFlow = ataId.MinPIOCycleTimeFlow; report.ATA.MinPIOCycleTimeFlowSpecified = true; } + if(!string.IsNullOrWhiteSpace(ataId.Model)) { - report.ATA.Model = ataId.Model; + report.ATA.Model = ataId.Model; report.ATA.ModelSpecified = true; } + if(ataId.MultipleMaxSectors != 0) { - report.ATA.MultipleMaxSectors = ataId.MultipleMaxSectors; + report.ATA.MultipleMaxSectors = ataId.MultipleMaxSectors; report.ATA.MultipleMaxSectorsSpecified = true; } + if(ataId.MultipleSectorNumber != 0) { - report.ATA.MultipleSectorNumber = ataId.MultipleSectorNumber; + report.ATA.MultipleSectorNumber = ataId.MultipleSectorNumber; report.ATA.MultipleSectorNumberSpecified = true; } + if(ataId.NVCacheCaps != 0) { - report.ATA.NVCacheCaps = ataId.NVCacheCaps; + report.ATA.NVCacheCaps = ataId.NVCacheCaps; report.ATA.NVCacheCapsSpecified = true; } + if(ataId.NVCacheSize != 0) { - report.ATA.NVCacheSize = ataId.NVCacheSize; + report.ATA.NVCacheSize = ataId.NVCacheSize; report.ATA.NVCacheSizeSpecified = true; } + if(ataId.NVCacheWriteSpeed != 0) { - report.ATA.NVCacheWriteSpeed = ataId.NVCacheWriteSpeed; + report.ATA.NVCacheWriteSpeed = ataId.NVCacheWriteSpeed; report.ATA.NVCacheWriteSpeedSpecified = true; } + if(ataId.NVEstimatedSpinUp != 0) { - report.ATA.NVEstimatedSpinUp = ataId.NVEstimatedSpinUp; + report.ATA.NVEstimatedSpinUp = ataId.NVEstimatedSpinUp; report.ATA.NVEstimatedSpinUpSpecified = true; } + if(ataId.PacketBusRelease != 0) { - report.ATA.PacketBusRelease = ataId.PacketBusRelease; + report.ATA.PacketBusRelease = ataId.PacketBusRelease; report.ATA.PacketBusReleaseSpecified = true; } + if(ataId.PIOTransferTimingMode != 0) { - report.ATA.PIOTransferTimingMode = ataId.PIOTransferTimingMode; + report.ATA.PIOTransferTimingMode = ataId.PIOTransferTimingMode; report.ATA.PIOTransferTimingModeSpecified = true; } + if(ataId.RecommendedAAM != 0) { - report.ATA.RecommendedAAM = ataId.RecommendedAAM; + report.ATA.RecommendedAAM = ataId.RecommendedAAM; report.ATA.RecommendedAAMSpecified = true; } + if(ataId.RecMDMACycleTime != 0) { - report.ATA.RecommendedMDMACycleTime = ataId.RecMDMACycleTime; + report.ATA.RecommendedMDMACycleTime = ataId.RecMDMACycleTime; report.ATA.RecommendedMDMACycleTimeSpecified = true; } + if(ataId.RemovableStatusSet != 0) { - report.ATA.RemovableStatusSet = ataId.RemovableStatusSet; + report.ATA.RemovableStatusSet = ataId.RemovableStatusSet; report.ATA.RemovableStatusSetSpecified = true; } + if(ataId.SATACapabilities != 0) { - report.ATA.SATACapabilities = ataId.SATACapabilities; + report.ATA.SATACapabilities = ataId.SATACapabilities; report.ATA.SATACapabilitiesSpecified = true; } + if(ataId.SATACapabilities2 != 0) { - report.ATA.SATACapabilities2 = ataId.SATACapabilities2; + report.ATA.SATACapabilities2 = ataId.SATACapabilities2; report.ATA.SATACapabilities2Specified = true; } + if(ataId.SATAFeatures != 0) { - report.ATA.SATAFeatures = ataId.SATAFeatures; + report.ATA.SATAFeatures = ataId.SATAFeatures; report.ATA.SATAFeaturesSpecified = true; } + if(ataId.SCTCommandTransport != 0) { - report.ATA.SCTCommandTransport = ataId.SCTCommandTransport; + report.ATA.SCTCommandTransport = ataId.SCTCommandTransport; report.ATA.SCTCommandTransportSpecified = true; } + if(ataId.SectorsPerCard != 0) { - report.ATA.SectorsPerCard = ataId.SectorsPerCard; + report.ATA.SectorsPerCard = ataId.SectorsPerCard; report.ATA.SectorsPerCardSpecified = true; } + if(ataId.SecurityEraseTime != 0) { - report.ATA.SecurityEraseTime = ataId.SecurityEraseTime; + report.ATA.SecurityEraseTime = ataId.SecurityEraseTime; report.ATA.SecurityEraseTimeSpecified = true; } + if(ataId.SecurityStatus != 0) { - report.ATA.SecurityStatus = ataId.SecurityStatus; + report.ATA.SecurityStatus = ataId.SecurityStatus; report.ATA.SecurityStatusSpecified = true; } + if(ataId.ServiceBusyClear != 0) { - report.ATA.ServiceBusyClear = ataId.ServiceBusyClear; + report.ATA.ServiceBusyClear = ataId.ServiceBusyClear; report.ATA.ServiceBusyClearSpecified = true; } + if(ataId.SpecificConfiguration != 0) { - report.ATA.SpecificConfiguration = ataId.SpecificConfiguration; + report.ATA.SpecificConfiguration = ataId.SpecificConfiguration; report.ATA.SpecificConfigurationSpecified = true; } + if(ataId.StreamAccessLatency != 0) { - report.ATA.StreamAccessLatency = ataId.StreamAccessLatency; + report.ATA.StreamAccessLatency = ataId.StreamAccessLatency; report.ATA.StreamAccessLatencySpecified = true; } + if(ataId.StreamMinReqSize != 0) { - report.ATA.StreamMinReqSize = ataId.StreamMinReqSize; + report.ATA.StreamMinReqSize = ataId.StreamMinReqSize; report.ATA.StreamMinReqSizeSpecified = true; } + if(ataId.StreamPerformanceGranularity != 0) { - report.ATA.StreamPerformanceGranularity = ataId.StreamPerformanceGranularity; + report.ATA.StreamPerformanceGranularity = ataId.StreamPerformanceGranularity; report.ATA.StreamPerformanceGranularitySpecified = true; } + if(ataId.StreamTransferTimeDMA != 0) { - report.ATA.StreamTransferTimeDMA = ataId.StreamTransferTimeDMA; + report.ATA.StreamTransferTimeDMA = ataId.StreamTransferTimeDMA; report.ATA.StreamTransferTimeDMASpecified = true; } + if(ataId.StreamTransferTimePIO != 0) { - report.ATA.StreamTransferTimePIO = ataId.StreamTransferTimePIO; + report.ATA.StreamTransferTimePIO = ataId.StreamTransferTimePIO; report.ATA.StreamTransferTimePIOSpecified = true; } + if(ataId.TransportMajorVersion != 0) { - report.ATA.TransportMajorVersion = ataId.TransportMajorVersion; + report.ATA.TransportMajorVersion = ataId.TransportMajorVersion; report.ATA.TransportMajorVersionSpecified = true; } + if(ataId.TransportMinorVersion != 0) { - report.ATA.TransportMinorVersion = ataId.TransportMinorVersion; + report.ATA.TransportMinorVersion = ataId.TransportMinorVersion; report.ATA.TransportMinorVersionSpecified = true; } + if(ataId.TrustedComputing != 0) { - report.ATA.TrustedComputing = ataId.TrustedComputing; + report.ATA.TrustedComputing = ataId.TrustedComputing; report.ATA.TrustedComputingSpecified = true; } + if(ataId.UDMAActive != 0) { - report.ATA.UDMAActive = ataId.UDMAActive; + report.ATA.UDMAActive = ataId.UDMAActive; report.ATA.UDMAActiveSpecified = true; } + if(ataId.UDMASupported != 0) { - report.ATA.UDMASupported = ataId.UDMASupported; + report.ATA.UDMASupported = ataId.UDMASupported; report.ATA.UDMASupportedSpecified = true; } + if(ataId.WRVMode != 0) { - report.ATA.WRVMode = ataId.WRVMode; + report.ATA.WRVMode = ataId.WRVMode; report.ATA.WRVModeSpecified = true; } + if(ataId.WRVSectorCountMode3 != 0) { - report.ATA.WRVSectorCountMode3 = ataId.WRVSectorCountMode3; + report.ATA.WRVSectorCountMode3 = ataId.WRVSectorCountMode3; report.ATA.WRVSectorCountMode3Specified = true; } + if(ataId.WRVSectorCountMode2 != 0) { - report.ATA.WRVSectorCountMode2 = ataId.WRVSectorCountMode2; + report.ATA.WRVSectorCountMode2 = ataId.WRVSectorCountMode2; report.ATA.WRVSectorCountMode2Specified = true; } + if(debug) report.ATA.Identify = buffer; if(removable) @@ -524,8 +602,8 @@ namespace DiscImageChef.Core.Devices.Report mediaTest.Model = System.Console.ReadLine(); mediaTest.ManufacturerSpecified = true; - mediaTest.ModelSpecified = true; - mediaTest.MediaIsRecognized = true; + mediaTest.ModelSpecified = true; + mediaTest.MediaIsRecognized = true; DicConsole.WriteLine("Querying ATA IDENTIFY..."); dev.AtaIdentify(out buffer, out _, TIMEOUT, out _); @@ -536,12 +614,13 @@ namespace DiscImageChef.Core.Devices.Report if(ataId.UnformattedBPT != 0) { - mediaTest.UnformattedBPT = ataId.UnformattedBPT; + mediaTest.UnformattedBPT = ataId.UnformattedBPT; mediaTest.UnformattedBPTSpecified = true; } + if(ataId.UnformattedBPS != 0) { - mediaTest.UnformattedBPS = ataId.UnformattedBPS; + mediaTest.UnformattedBPS = ataId.UnformattedBPS; mediaTest.UnformattedBPSSpecified = true; } @@ -550,10 +629,10 @@ namespace DiscImageChef.Core.Devices.Report mediaTest.CHS = new chsType { Cylinders = ataId.Cylinders, - Heads = ataId.Heads, - Sectors = ataId.SectorsPerTrack + Heads = ataId.Heads, + Sectors = ataId.SectorsPerTrack }; - mediaTest.Blocks = (ulong)(ataId.Cylinders * ataId.Heads * ataId.SectorsPerTrack); + mediaTest.Blocks = (ulong)(ataId.Cylinders * ataId.Heads * ataId.SectorsPerTrack); mediaTest.BlocksSpecified = true; } @@ -562,8 +641,8 @@ namespace DiscImageChef.Core.Devices.Report mediaTest.CurrentCHS = new chsType { Cylinders = ataId.CurrentCylinders, - Heads = ataId.CurrentHeads, - Sectors = ataId.CurrentSectorsPerTrack + Heads = ataId.CurrentHeads, + Sectors = ataId.CurrentSectorsPerTrack }; if(mediaTest.Blocks == 0) mediaTest.Blocks = @@ -573,31 +652,31 @@ namespace DiscImageChef.Core.Devices.Report if(ataId.Capabilities.HasFlag(Identify.CapabilitiesBit.LBASupport)) { - mediaTest.LBASectors = ataId.LBASectors; + mediaTest.LBASectors = ataId.LBASectors; mediaTest.LBASectorsSpecified = true; - mediaTest.Blocks = ataId.LBASectors; - mediaTest.BlocksSpecified = true; + mediaTest.Blocks = ataId.LBASectors; + mediaTest.BlocksSpecified = true; } if(ataId.CommandSet2.HasFlag(Identify.CommandSetBit2.LBA48)) { - mediaTest.LBA48Sectors = ataId.LBA48Sectors; + mediaTest.LBA48Sectors = ataId.LBA48Sectors; mediaTest.LBA48SectorsSpecified = true; - mediaTest.Blocks = ataId.LBA48Sectors; - mediaTest.BlocksSpecified = true; + mediaTest.Blocks = ataId.LBA48Sectors; + mediaTest.BlocksSpecified = true; } - if(ataId.NominalRotationRate != 0x0000 && ataId.NominalRotationRate != 0xFFFF) + if(ataId.NominalRotationRate != 0x0000 && ataId.NominalRotationRate != 0xFFFF) if(ataId.NominalRotationRate == 0x0001) { - mediaTest.SolidStateDevice = true; + mediaTest.SolidStateDevice = true; mediaTest.SolidStateDeviceSpecified = true; } else { - mediaTest.SolidStateDevice = false; - mediaTest.SolidStateDeviceSpecified = true; - mediaTest.NominalRotationRate = ataId.NominalRotationRate; + mediaTest.SolidStateDevice = false; + mediaTest.SolidStateDeviceSpecified = true; + mediaTest.NominalRotationRate = ataId.NominalRotationRate; mediaTest.NominalRotationRateSpecified = true; } @@ -606,89 +685,92 @@ namespace DiscImageChef.Core.Devices.Report 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 = ataId.LogicalSectorWords * 2; + else logicalsectorsize = 512; - if((ataId.PhysLogSectorSize & 0x2000) == 0x2000) - physicalsectorsize = (uint)(logicalsectorsize * ((1 << ataId.PhysLogSectorSize) & 0xF)); + if((ataId.PhysLogSectorSize & + 0x2000) == 0x2000) + physicalsectorsize = + (uint)(logicalsectorsize * ((1 << ataId.PhysLogSectorSize) & 0xF)); else physicalsectorsize = logicalsectorsize; } else { - logicalsectorsize = 512; + logicalsectorsize = 512; physicalsectorsize = 512; } - mediaTest.BlockSize = logicalsectorsize; + mediaTest.BlockSize = logicalsectorsize; mediaTest.BlockSizeSpecified = true; if(physicalsectorsize != logicalsectorsize) { - mediaTest.PhysicalBlockSize = physicalsectorsize; + mediaTest.PhysicalBlockSize = physicalsectorsize; mediaTest.PhysicalBlockSizeSpecified = true; if((ataId.LogicalAlignment & 0x8000) == 0x0000 && (ataId.LogicalAlignment & 0x4000) == 0x4000) { - mediaTest.LogicalAlignment = (ushort)(ataId.LogicalAlignment & 0x3FFF); + mediaTest.LogicalAlignment = (ushort)(ataId.LogicalAlignment & 0x3FFF); mediaTest.LogicalAlignmentSpecified = true; } } if(ataId.EccBytes != 0x0000 && ataId.EccBytes != 0xFFFF) { - mediaTest.LongBlockSize = logicalsectorsize + ataId.EccBytes; + mediaTest.LongBlockSize = logicalsectorsize + ataId.EccBytes; mediaTest.LongBlockSizeSpecified = true; } - if(ataId.UnformattedBPS > logicalsectorsize && + if(ataId.UnformattedBPS > logicalsectorsize && (!mediaTest.LongBlockSizeSpecified || mediaTest.LongBlockSize == 516)) { - mediaTest.LongBlockSize = ataId.UnformattedBPS; + mediaTest.LongBlockSize = ataId.UnformattedBPS; mediaTest.LongBlockSizeSpecified = true; } - if(ataId.CommandSet3.HasFlag(Identify.CommandSetBit3.MustBeSet) && + if(ataId.CommandSet3.HasFlag(Identify.CommandSetBit3.MustBeSet) && !ataId.CommandSet3.HasFlag(Identify.CommandSetBit3.MustBeClear) && ataId.EnabledCommandSet3.HasFlag(Identify.CommandSetBit3.MediaSerial)) { - mediaTest.CanReadMediaSerial = true; + mediaTest.CanReadMediaSerial = true; mediaTest.CanReadMediaSerialSpecified = true; if(!string.IsNullOrWhiteSpace(ataId.MediaManufacturer)) { - mediaTest.Manufacturer = ataId.MediaManufacturer; + mediaTest.Manufacturer = ataId.MediaManufacturer; mediaTest.ManufacturerSpecified = true; } } - mediaTest.SupportsReadLbaSpecified = true; - mediaTest.SupportsReadRetryLbaSpecified = true; - mediaTest.SupportsReadDmaLbaSpecified = true; - mediaTest.SupportsReadDmaRetryLbaSpecified = true; - mediaTest.SupportsReadLongLbaSpecified = true; + mediaTest.SupportsReadLbaSpecified = true; + mediaTest.SupportsReadRetryLbaSpecified = true; + mediaTest.SupportsReadDmaLbaSpecified = true; + mediaTest.SupportsReadDmaRetryLbaSpecified = true; + mediaTest.SupportsReadLongLbaSpecified = true; mediaTest.SupportsReadLongRetryLbaSpecified = true; - mediaTest.SupportsSeekLbaSpecified = true; + mediaTest.SupportsSeekLbaSpecified = true; - mediaTest.SupportsReadLba48Specified = true; + mediaTest.SupportsReadLba48Specified = true; mediaTest.SupportsReadDmaLba48Specified = true; - mediaTest.SupportsReadSpecified = true; - mediaTest.SupportsReadRetrySpecified = true; - mediaTest.SupportsReadDmaSpecified = true; - mediaTest.SupportsReadDmaRetrySpecified = true; - mediaTest.SupportsReadLongSpecified = true; + mediaTest.SupportsReadSpecified = true; + mediaTest.SupportsReadRetrySpecified = true; + mediaTest.SupportsReadDmaSpecified = true; + mediaTest.SupportsReadDmaRetrySpecified = true; + mediaTest.SupportsReadLongSpecified = true; mediaTest.SupportsReadLongRetrySpecified = true; - mediaTest.SupportsSeekSpecified = true; + mediaTest.SupportsSeekSpecified = true; ulong checkCorrectRead = BitConverter.ToUInt64(buffer, 0); - bool sense; + bool sense; DicConsole.WriteLine("Trying READ SECTOR(S) in CHS mode..."); sense = dev.Read(out byte[] readBuf, out AtaErrorRegistersChs errorChs, false, 0, 0, 1, 1, TIMEOUT, out _); mediaTest.SupportsRead = !sense && (errorChs.Status & 0x01) != 0x01 && errorChs.Error == 0 && - readBuf.Length > 0; + readBuf.Length > 0; DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense, errorChs.Status, errorChs.Error, readBuf.Length); @@ -697,9 +779,10 @@ namespace DiscImageChef.Core.Devices.Report "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", readBuf); DicConsole.WriteLine("Trying READ SECTOR(S) RETRY in CHS mode..."); - sense = dev.Read(out readBuf, out errorChs, true, 0, 0, 1, 1, TIMEOUT, out _); + sense = + dev.Read(out readBuf, out errorChs, true, 0, 0, 1, 1, TIMEOUT, out _); mediaTest.SupportsReadRetry = !sense && (errorChs.Status & 0x01) != 0x01 && - errorChs.Error == 0 && readBuf.Length > 0; + errorChs.Error == 0 && readBuf.Length > 0; DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense, errorChs.Status, errorChs.Error, readBuf.Length); @@ -708,9 +791,10 @@ namespace DiscImageChef.Core.Devices.Report "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", readBuf); DicConsole.WriteLine("Trying READ DMA in CHS mode..."); - sense = dev.ReadDma(out readBuf, out errorChs, false, 0, 0, 1, 1, TIMEOUT, out _); + sense = + dev.ReadDma(out readBuf, out errorChs, false, 0, 0, 1, 1, TIMEOUT, out _); mediaTest.SupportsReadDma = !sense && (errorChs.Status & 0x01) != 0x01 && errorChs.Error == 0 && - readBuf.Length > 0; + readBuf.Length > 0; DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense, errorChs.Status, errorChs.Error, readBuf.Length); @@ -719,9 +803,11 @@ namespace DiscImageChef.Core.Devices.Report "read results", readBuf); DicConsole.WriteLine("Trying READ DMA RETRY in CHS mode..."); - sense = dev.ReadDma(out readBuf, out errorChs, true, 0, 0, 1, 1, TIMEOUT, out _); + sense = + dev.ReadDma(out readBuf, out errorChs, true, 0, 0, 1, 1, TIMEOUT, out _); mediaTest.SupportsReadDmaRetry = !sense && (errorChs.Status & 0x01) != 0x01 && - errorChs.Error == 0 && readBuf.Length > 0; + errorChs.Error == 0 && + readBuf.Length > 0; DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense, errorChs.Status, errorChs.Error, readBuf.Length); @@ -730,15 +816,16 @@ namespace DiscImageChef.Core.Devices.Report "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", readBuf); DicConsole.WriteLine("Trying SEEK in CHS mode..."); - sense = dev.Seek(out errorChs, 0, 0, 1, TIMEOUT, out _); + sense = dev.Seek(out errorChs, 0, 0, 1, TIMEOUT, out _); mediaTest.SupportsSeek = !sense && (errorChs.Status & 0x01) != 0x01 && errorChs.Error == 0; DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}", sense, errorChs.Status, errorChs.Error); DicConsole.WriteLine("Trying READ SECTOR(S) in LBA mode..."); - sense = dev.Read(out readBuf, out AtaErrorRegistersLba28 errorLba, false, 0, 1, TIMEOUT, out _); + sense = dev.Read(out readBuf, out AtaErrorRegistersLba28 errorLba, false, 0, + 1, TIMEOUT, out _); mediaTest.SupportsReadLba = !sense && (errorLba.Status & 0x01) != 0x01 && errorLba.Error == 0 && - readBuf.Length > 0; + readBuf.Length > 0; DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense, errorChs.Status, errorChs.Error, readBuf.Length); @@ -747,9 +834,11 @@ namespace DiscImageChef.Core.Devices.Report "read results", readBuf); DicConsole.WriteLine("Trying READ SECTOR(S) RETRY in LBA mode..."); - sense = dev.Read(out readBuf, out errorLba, true, 0, 1, TIMEOUT, out _); + sense = + dev.Read(out readBuf, out errorLba, true, 0, 1, TIMEOUT, out _); mediaTest.SupportsReadRetryLba = !sense && (errorLba.Status & 0x01) != 0x01 && - errorLba.Error == 0 && readBuf.Length > 0; + errorLba.Error == 0 && + readBuf.Length > 0; DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense, errorChs.Status, errorChs.Error, readBuf.Length); @@ -758,9 +847,10 @@ namespace DiscImageChef.Core.Devices.Report "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", readBuf); DicConsole.WriteLine("Trying READ DMA in LBA mode..."); - sense = dev.ReadDma(out readBuf, out errorLba, false, 0, 1, TIMEOUT, out _); + sense = + dev.ReadDma(out readBuf, out errorLba, false, 0, 1, TIMEOUT, out _); mediaTest.SupportsReadDmaLba = !sense && (errorLba.Status & 0x01) != 0x01 && - errorLba.Error == 0 && readBuf.Length > 0; + errorLba.Error == 0 && readBuf.Length > 0; DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense, errorChs.Status, errorChs.Error, readBuf.Length); @@ -769,7 +859,8 @@ namespace DiscImageChef.Core.Devices.Report "read results", readBuf); DicConsole.WriteLine("Trying READ DMA RETRY in LBA mode..."); - sense = dev.ReadDma(out readBuf, out errorLba, true, 0, 1, TIMEOUT, out _); + sense = + dev.ReadDma(out readBuf, out errorLba, true, 0, 1, TIMEOUT, out _); mediaTest.SupportsReadDmaRetryLba = !sense && (errorLba.Status & 0x01) != 0x01 && errorLba.Error == 0 && readBuf.Length > 0; DicConsole.DebugWriteLine("ATA Report", @@ -780,15 +871,17 @@ namespace DiscImageChef.Core.Devices.Report "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", readBuf); DicConsole.WriteLine("Trying SEEK in LBA mode..."); - sense = dev.Seek(out errorLba, 0, TIMEOUT, out _); + sense = dev.Seek(out errorLba, 0, TIMEOUT, out _); mediaTest.SupportsSeekLba = !sense && (errorLba.Status & 0x01) != 0x01 && errorLba.Error == 0; DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}", sense, errorChs.Status, errorChs.Error); DicConsole.WriteLine("Trying READ SECTOR(S) in LBA48 mode..."); - sense = dev.Read(out readBuf, out AtaErrorRegistersLba48 errorLba48, 0, 1, TIMEOUT, out _); + sense = + dev.Read(out readBuf, out AtaErrorRegistersLba48 errorLba48, 0, 1, TIMEOUT, out _); mediaTest.SupportsReadLba48 = !sense && (errorLba48.Status & 0x01) != 0x01 && - errorLba48.Error == 0 && readBuf.Length > 0; + errorLba48.Error == 0 && + readBuf.Length > 0; DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense, errorChs.Status, errorChs.Error, readBuf.Length); @@ -797,9 +890,10 @@ namespace DiscImageChef.Core.Devices.Report "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", readBuf); DicConsole.WriteLine("Trying READ DMA in LBA48 mode..."); - sense = dev.ReadDma(out readBuf, out errorLba48, 0, 1, TIMEOUT, out _); + sense = dev.ReadDma(out readBuf, out errorLba48, 0, 1, TIMEOUT, out _); mediaTest.SupportsReadDmaLba48 = !sense && (errorLba48.Status & 0x01) != 0x01 && - errorLba48.Error == 0 && readBuf.Length > 0; + errorLba48.Error == 0 && + readBuf.Length > 0; DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense, errorChs.Status, errorChs.Error, readBuf.Length); @@ -807,12 +901,37 @@ namespace DiscImageChef.Core.Devices.Report DataFile.WriteTo("ATA Report", "readdma48", "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", readBuf); + // Send SET FEATURES before sending READ LONG commands, retrieve IDENTIFY again and + // check if ECC size changed. Sector is set to 1 because without it most drives just return + // CORRECTABLE ERROR for this command. + dev.SetFeatures(out _, AtaFeatures.EnableReadLongVendorLength, 0, 0, 1, 0, TIMEOUT, out _); + + dev.AtaIdentify(out buffer, out _, TIMEOUT, out _); + if(Identify.Decode(buffer).HasValue) + { + mediaTest.LongBlockSizeSpecified = false; + + ataId = Identify.Decode(buffer).Value; + if(ataId.EccBytes != 0x0000 && ataId.EccBytes != 0xFFFF) + { + mediaTest.LongBlockSize = logicalsectorsize + ataId.EccBytes; + mediaTest.LongBlockSizeSpecified = true; + } + + if(ataId.UnformattedBPS > logicalsectorsize && + (!mediaTest.LongBlockSizeSpecified || mediaTest.LongBlockSize == 516)) + { + mediaTest.LongBlockSize = ataId.UnformattedBPS; + mediaTest.LongBlockSizeSpecified = true; + } + } + DicConsole.WriteLine("Trying READ LONG in CHS mode..."); sense = dev.ReadLong(out readBuf, out errorChs, false, 0, 0, 1, mediaTest.LongBlockSize, TIMEOUT, out _); mediaTest.SupportsReadLong = !sense && (errorChs.Status & 0x01) != 0x01 && - errorChs.Error == 0 && readBuf.Length > 0 && - BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead; + errorChs.Error == 0 && readBuf.Length > 0 && + BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead; DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense, errorChs.Status, errorChs.Error, readBuf.Length); @@ -825,7 +944,7 @@ namespace DiscImageChef.Core.Devices.Report out _); mediaTest.SupportsReadLongRetry = !sense && (errorChs.Status & 0x01) != 0x01 && errorChs.Error == 0 && readBuf.Length > 0 && - BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead; + BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead; DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense, errorChs.Status, errorChs.Error, readBuf.Length); @@ -837,8 +956,9 @@ namespace DiscImageChef.Core.Devices.Report sense = dev.ReadLong(out readBuf, out errorLba, false, 0, mediaTest.LongBlockSize, TIMEOUT, out _); mediaTest.SupportsReadLongLba = !sense && (errorLba.Status & 0x01) != 0x01 && - errorLba.Error == 0 && readBuf.Length > 0 && - BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead; + errorLba.Error == 0 && + readBuf.Length > 0 && + BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead; DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense, errorChs.Status, errorChs.Error, readBuf.Length); @@ -851,7 +971,7 @@ namespace DiscImageChef.Core.Devices.Report out _); mediaTest.SupportsReadLongRetryLba = !sense && (errorLba.Status & 0x01) != 0x01 && errorLba.Error == 0 && readBuf.Length > 0 && - BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead; + BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead; DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense, errorChs.Status, errorChs.Error, readBuf.Length); @@ -872,12 +992,13 @@ namespace DiscImageChef.Core.Devices.Report if(ataId.UnformattedBPT != 0) { - report.ATA.ReadCapabilities.UnformattedBPT = ataId.UnformattedBPT; + report.ATA.ReadCapabilities.UnformattedBPT = ataId.UnformattedBPT; report.ATA.ReadCapabilities.UnformattedBPTSpecified = true; } + if(ataId.UnformattedBPS != 0) { - report.ATA.ReadCapabilities.UnformattedBPS = ataId.UnformattedBPS; + report.ATA.ReadCapabilities.UnformattedBPS = ataId.UnformattedBPS; report.ATA.ReadCapabilities.UnformattedBPSSpecified = true; } @@ -886,10 +1007,11 @@ namespace DiscImageChef.Core.Devices.Report report.ATA.ReadCapabilities.CHS = new chsType { Cylinders = ataId.Cylinders, - Heads = ataId.Heads, - Sectors = ataId.SectorsPerTrack + Heads = ataId.Heads, + Sectors = ataId.SectorsPerTrack }; - report.ATA.ReadCapabilities.Blocks = (ulong)(ataId.Cylinders * ataId.Heads * ataId.SectorsPerTrack); + report.ATA.ReadCapabilities.Blocks = + (ulong)(ataId.Cylinders * ataId.Heads * ataId.SectorsPerTrack); report.ATA.ReadCapabilities.BlocksSpecified = true; } @@ -898,8 +1020,8 @@ namespace DiscImageChef.Core.Devices.Report report.ATA.ReadCapabilities.CurrentCHS = new chsType { Cylinders = ataId.CurrentCylinders, - Heads = ataId.CurrentHeads, - Sectors = ataId.CurrentSectorsPerTrack + Heads = ataId.CurrentHeads, + Sectors = ataId.CurrentSectorsPerTrack }; report.ATA.ReadCapabilities.Blocks = (ulong)(ataId.CurrentCylinders * ataId.CurrentHeads * ataId.CurrentSectorsPerTrack); @@ -908,31 +1030,31 @@ namespace DiscImageChef.Core.Devices.Report if(ataId.Capabilities.HasFlag(Identify.CapabilitiesBit.LBASupport)) { - report.ATA.ReadCapabilities.LBASectors = ataId.LBASectors; + report.ATA.ReadCapabilities.LBASectors = ataId.LBASectors; report.ATA.ReadCapabilities.LBASectorsSpecified = true; - report.ATA.ReadCapabilities.Blocks = ataId.LBASectors; - report.ATA.ReadCapabilities.BlocksSpecified = true; + report.ATA.ReadCapabilities.Blocks = ataId.LBASectors; + report.ATA.ReadCapabilities.BlocksSpecified = true; } if(ataId.CommandSet2.HasFlag(Identify.CommandSetBit2.LBA48)) { - report.ATA.ReadCapabilities.LBA48Sectors = ataId.LBA48Sectors; + report.ATA.ReadCapabilities.LBA48Sectors = ataId.LBA48Sectors; report.ATA.ReadCapabilities.LBA48SectorsSpecified = true; - report.ATA.ReadCapabilities.Blocks = ataId.LBA48Sectors; - report.ATA.ReadCapabilities.BlocksSpecified = true; + report.ATA.ReadCapabilities.Blocks = ataId.LBA48Sectors; + report.ATA.ReadCapabilities.BlocksSpecified = true; } - if(ataId.NominalRotationRate != 0x0000 && ataId.NominalRotationRate != 0xFFFF) + if(ataId.NominalRotationRate != 0x0000 && ataId.NominalRotationRate != 0xFFFF) if(ataId.NominalRotationRate == 0x0001) { - report.ATA.ReadCapabilities.SolidStateDevice = true; + report.ATA.ReadCapabilities.SolidStateDevice = true; report.ATA.ReadCapabilities.SolidStateDeviceSpecified = true; } else { - report.ATA.ReadCapabilities.SolidStateDevice = false; - report.ATA.ReadCapabilities.SolidStateDeviceSpecified = true; - report.ATA.ReadCapabilities.NominalRotationRate = ataId.NominalRotationRate; + report.ATA.ReadCapabilities.SolidStateDevice = false; + report.ATA.ReadCapabilities.SolidStateDeviceSpecified = true; + report.ATA.ReadCapabilities.NominalRotationRate = ataId.NominalRotationRate; report.ATA.ReadCapabilities.NominalRotationRateSpecified = true; } @@ -941,37 +1063,41 @@ namespace DiscImageChef.Core.Devices.Report if((ataId.PhysLogSectorSize & 0x8000) == 0x0000 && (ataId.PhysLogSectorSize & 0x4000) == 0x4000) { if((ataId.PhysLogSectorSize & 0x1000) == 0x1000) - if(ataId.LogicalSectorWords <= 255 || ataId.LogicalAlignment == 0xFFFF) logicalsectorsize = 512; - else logicalsectorsize = ataId.LogicalSectorWords * 2; - else logicalsectorsize = 512; + if(ataId.LogicalSectorWords <= 255 || ataId.LogicalAlignment == 0xFFFF) + logicalsectorsize = 512; + else + logicalsectorsize = ataId.LogicalSectorWords * 2; + else logicalsectorsize = 512; - if((ataId.PhysLogSectorSize & 0x2000) == 0x2000) - physicalsectorsize = logicalsectorsize * (uint)Math.Pow(2, ataId.PhysLogSectorSize & 0xF); + if((ataId.PhysLogSectorSize & 0x2000) == + 0x2000) + physicalsectorsize = logicalsectorsize * (uint)Math.Pow(2, ataId.PhysLogSectorSize & 0xF); else physicalsectorsize = logicalsectorsize; } else { - logicalsectorsize = 512; + logicalsectorsize = 512; physicalsectorsize = 512; } - report.ATA.ReadCapabilities.BlockSize = logicalsectorsize; + report.ATA.ReadCapabilities.BlockSize = logicalsectorsize; report.ATA.ReadCapabilities.BlockSizeSpecified = true; if(physicalsectorsize != logicalsectorsize) { - report.ATA.ReadCapabilities.PhysicalBlockSize = physicalsectorsize; + report.ATA.ReadCapabilities.PhysicalBlockSize = physicalsectorsize; report.ATA.ReadCapabilities.PhysicalBlockSizeSpecified = true; if((ataId.LogicalAlignment & 0x8000) == 0x0000 && (ataId.LogicalAlignment & 0x4000) == 0x4000) { - report.ATA.ReadCapabilities.LogicalAlignment = (ushort)(ataId.LogicalAlignment & 0x3FFF); + report.ATA.ReadCapabilities.LogicalAlignment = + (ushort)(ataId.LogicalAlignment & 0x3FFF); report.ATA.ReadCapabilities.LogicalAlignmentSpecified = true; } } if(ataId.EccBytes != 0x0000 && ataId.EccBytes != 0xFFFF) { - report.ATA.ReadCapabilities.LongBlockSize = logicalsectorsize + ataId.EccBytes; + report.ATA.ReadCapabilities.LongBlockSize = logicalsectorsize + ataId.EccBytes; report.ATA.ReadCapabilities.LongBlockSizeSpecified = true; } @@ -979,44 +1105,44 @@ namespace DiscImageChef.Core.Devices.Report (!report.ATA.ReadCapabilities.LongBlockSizeSpecified || report.ATA.ReadCapabilities.LongBlockSize == 516)) { - report.ATA.ReadCapabilities.LongBlockSize = ataId.UnformattedBPS; + report.ATA.ReadCapabilities.LongBlockSize = ataId.UnformattedBPS; report.ATA.ReadCapabilities.LongBlockSizeSpecified = true; } - if(ataId.CommandSet3.HasFlag(Identify.CommandSetBit3.MustBeSet) && + if(ataId.CommandSet3.HasFlag(Identify.CommandSetBit3.MustBeSet) && !ataId.CommandSet3.HasFlag(Identify.CommandSetBit3.MustBeClear) && ataId.EnabledCommandSet3.HasFlag(Identify.CommandSetBit3.MediaSerial)) { - report.ATA.ReadCapabilities.CanReadMediaSerial = true; + report.ATA.ReadCapabilities.CanReadMediaSerial = true; report.ATA.ReadCapabilities.CanReadMediaSerialSpecified = true; if(!string.IsNullOrWhiteSpace(ataId.MediaManufacturer)) { - report.ATA.ReadCapabilities.Manufacturer = ataId.MediaManufacturer; + report.ATA.ReadCapabilities.Manufacturer = ataId.MediaManufacturer; report.ATA.ReadCapabilities.ManufacturerSpecified = true; } } - report.ATA.ReadCapabilities.SupportsReadLbaSpecified = true; - report.ATA.ReadCapabilities.SupportsReadRetryLbaSpecified = true; - report.ATA.ReadCapabilities.SupportsReadDmaLbaSpecified = true; - report.ATA.ReadCapabilities.SupportsReadDmaRetryLbaSpecified = true; - report.ATA.ReadCapabilities.SupportsReadLongLbaSpecified = true; + report.ATA.ReadCapabilities.SupportsReadLbaSpecified = true; + report.ATA.ReadCapabilities.SupportsReadRetryLbaSpecified = true; + report.ATA.ReadCapabilities.SupportsReadDmaLbaSpecified = true; + report.ATA.ReadCapabilities.SupportsReadDmaRetryLbaSpecified = true; + report.ATA.ReadCapabilities.SupportsReadLongLbaSpecified = true; report.ATA.ReadCapabilities.SupportsReadLongRetryLbaSpecified = true; - report.ATA.ReadCapabilities.SupportsSeekLbaSpecified = true; + report.ATA.ReadCapabilities.SupportsSeekLbaSpecified = true; - report.ATA.ReadCapabilities.SupportsReadLba48Specified = true; + report.ATA.ReadCapabilities.SupportsReadLba48Specified = true; report.ATA.ReadCapabilities.SupportsReadDmaLba48Specified = true; - report.ATA.ReadCapabilities.SupportsReadSpecified = true; - report.ATA.ReadCapabilities.SupportsReadRetrySpecified = true; - report.ATA.ReadCapabilities.SupportsReadDmaSpecified = true; - report.ATA.ReadCapabilities.SupportsReadDmaRetrySpecified = true; - report.ATA.ReadCapabilities.SupportsReadLongSpecified = true; + report.ATA.ReadCapabilities.SupportsReadSpecified = true; + report.ATA.ReadCapabilities.SupportsReadRetrySpecified = true; + report.ATA.ReadCapabilities.SupportsReadDmaSpecified = true; + report.ATA.ReadCapabilities.SupportsReadDmaRetrySpecified = true; + report.ATA.ReadCapabilities.SupportsReadLongSpecified = true; report.ATA.ReadCapabilities.SupportsReadLongRetrySpecified = true; - report.ATA.ReadCapabilities.SupportsSeekSpecified = true; + report.ATA.ReadCapabilities.SupportsSeekSpecified = true; ulong checkCorrectRead = BitConverter.ToUInt64(buffer, 0); - bool sense; + bool sense; DicConsole.WriteLine("Trying READ SECTOR(S) in CHS mode..."); sense = dev.Read(out byte[] readBuf, out AtaErrorRegistersChs errorChs, false, 0, 0, 1, 1, TIMEOUT, @@ -1031,7 +1157,8 @@ namespace DiscImageChef.Core.Devices.Report "read results", readBuf); DicConsole.WriteLine("Trying READ SECTOR(S) RETRY in CHS mode..."); - sense = dev.Read(out readBuf, out errorChs, true, 0, 0, 1, 1, TIMEOUT, out _); + sense = + dev.Read(out readBuf, out errorChs, true, 0, 0, 1, 1, TIMEOUT, out _); report.ATA.ReadCapabilities.SupportsReadRetry = !sense && (errorChs.Status & 0x01) != 0x01 && errorChs.Error == 0 && readBuf.Length > 0; DicConsole.DebugWriteLine("ATA Report", @@ -1042,7 +1169,8 @@ namespace DiscImageChef.Core.Devices.Report "read results", readBuf); DicConsole.WriteLine("Trying READ DMA in CHS mode..."); - sense = dev.ReadDma(out readBuf, out errorChs, false, 0, 0, 1, 1, TIMEOUT, out _); + sense = + dev.ReadDma(out readBuf, out errorChs, false, 0, 0, 1, 1, TIMEOUT, out _); report.ATA.ReadCapabilities.SupportsReadDma = !sense && (errorChs.Status & 0x01) != 0x01 && errorChs.Error == 0 && readBuf.Length > 0; DicConsole.DebugWriteLine("ATA Report", @@ -1053,7 +1181,8 @@ namespace DiscImageChef.Core.Devices.Report readBuf); DicConsole.WriteLine("Trying READ DMA RETRY in CHS mode..."); - sense = dev.ReadDma(out readBuf, out errorChs, true, 0, 0, 1, 1, TIMEOUT, out _); + sense = + dev.ReadDma(out readBuf, out errorChs, true, 0, 0, 1, 1, TIMEOUT, out _); report.ATA.ReadCapabilities.SupportsReadDmaRetry = !sense && (errorChs.Status & 0x01) != 0x01 && errorChs.Error == 0 && readBuf.Length > 0; DicConsole.DebugWriteLine("ATA Report", @@ -1064,14 +1193,15 @@ namespace DiscImageChef.Core.Devices.Report "read results", readBuf); DicConsole.WriteLine("Trying SEEK in CHS mode..."); - sense = dev.Seek(out errorChs, 0, 0, 1, TIMEOUT, out _); + sense = dev.Seek(out errorChs, 0, 0, 1, TIMEOUT, out _); report.ATA.ReadCapabilities.SupportsSeek = !sense && (errorChs.Status & 0x01) != 0x01 && errorChs.Error == 0; DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}", sense, errorChs.Status, errorChs.Error); DicConsole.WriteLine("Trying READ SECTOR(S) in LBA mode..."); - sense = dev.Read(out readBuf, out AtaErrorRegistersLba28 errorLba, false, 0, 1, TIMEOUT, out _); + sense = + dev.Read(out readBuf, out AtaErrorRegistersLba28 errorLba, false, 0, 1, TIMEOUT, out _); report.ATA.ReadCapabilities.SupportsReadLba = !sense && (errorLba.Status & 0x01) != 0x01 && errorLba.Error == 0 && readBuf.Length > 0; DicConsole.DebugWriteLine("ATA Report", @@ -1082,7 +1212,8 @@ namespace DiscImageChef.Core.Devices.Report readBuf); DicConsole.WriteLine("Trying READ SECTOR(S) RETRY in LBA mode..."); - sense = dev.Read(out readBuf, out errorLba, true, 0, 1, TIMEOUT, out _); + sense = + dev.Read(out readBuf, out errorLba, true, 0, 1, TIMEOUT, out _); report.ATA.ReadCapabilities.SupportsReadRetryLba = !sense && (errorLba.Status & 0x01) != 0x01 && errorLba.Error == 0 && readBuf.Length > 0; DicConsole.DebugWriteLine("ATA Report", @@ -1093,7 +1224,8 @@ namespace DiscImageChef.Core.Devices.Report "read results", readBuf); DicConsole.WriteLine("Trying READ DMA in LBA mode..."); - sense = dev.ReadDma(out readBuf, out errorLba, false, 0, 1, TIMEOUT, out _); + sense = + dev.ReadDma(out readBuf, out errorLba, false, 0, 1, TIMEOUT, out _); report.ATA.ReadCapabilities.SupportsReadDmaLba = !sense && (errorLba.Status & 0x01) != 0x01 && errorLba.Error == 0 && readBuf.Length > 0; DicConsole.DebugWriteLine("ATA Report", @@ -1104,7 +1236,8 @@ namespace DiscImageChef.Core.Devices.Report readBuf); DicConsole.WriteLine("Trying READ DMA RETRY in LBA mode..."); - sense = dev.ReadDma(out readBuf, out errorLba, true, 0, 1, TIMEOUT, out _); + sense = + dev.ReadDma(out readBuf, out errorLba, true, 0, 1, TIMEOUT, out _); report.ATA.ReadCapabilities.SupportsReadDmaRetryLba = !sense && (errorLba.Status & 0x01) != 0x01 && errorLba.Error == 0 && readBuf.Length > 0; DicConsole.DebugWriteLine("ATA Report", @@ -1115,14 +1248,15 @@ namespace DiscImageChef.Core.Devices.Report "read results", readBuf); DicConsole.WriteLine("Trying SEEK in LBA mode..."); - sense = dev.Seek(out errorLba, 0, TIMEOUT, out _); + sense = dev.Seek(out errorLba, 0, TIMEOUT, out _); report.ATA.ReadCapabilities.SupportsSeekLba = !sense && (errorLba.Status & 0x01) != 0x01 && errorLba.Error == 0; DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}", sense, errorLba.Status, errorLba.Error); DicConsole.WriteLine("Trying READ SECTOR(S) in LBA48 mode..."); - sense = dev.Read(out readBuf, out AtaErrorRegistersLba48 errorLba48, 0, 1, TIMEOUT, out _); + sense = + dev.Read(out readBuf, out AtaErrorRegistersLba48 errorLba48, 0, 1, TIMEOUT, out _); report.ATA.ReadCapabilities.SupportsReadLba48 = !sense && (errorLba48.Status & 0x01) != 0x01 && errorLba48.Error == 0 && readBuf.Length > 0; DicConsole.DebugWriteLine("ATA Report", @@ -1133,7 +1267,8 @@ namespace DiscImageChef.Core.Devices.Report "read results", readBuf); DicConsole.WriteLine("Trying READ DMA in LBA48 mode..."); - sense = dev.ReadDma(out readBuf, out errorLba48, 0, 1, TIMEOUT, out _); + sense = + dev.ReadDma(out readBuf, out errorLba48, 0, 1, TIMEOUT, out _); report.ATA.ReadCapabilities.SupportsReadDmaLba48 = !sense && (errorLba48.Status & 0x01) != 0x01 && errorLba48.Error == 0 && readBuf.Length > 0; DicConsole.DebugWriteLine("ATA Report", @@ -1143,12 +1278,38 @@ namespace DiscImageChef.Core.Devices.Report DataFile.WriteTo("ATA Report", "readdma48", "_debug_" + report.ATA.Model + ".bin", "read results", readBuf); + // Send SET FEATURES before sending READ LONG commands, retrieve IDENTIFY again and + // check if ECC size changed. Sector is set to 1 because without it most drives just return + // CORRECTABLE ERROR for this command. + dev.SetFeatures(out _, AtaFeatures.EnableReadLongVendorLength, 0, 0, 1, 0, TIMEOUT, out _); + + dev.AtaIdentify(out buffer, out _, TIMEOUT, out _); + if(Identify.Decode(buffer).HasValue) + { + report.ATA.ReadCapabilities.LongBlockSizeSpecified = false; + + ataId = Identify.Decode(buffer).Value; + if(ataId.EccBytes != 0x0000 && ataId.EccBytes != 0xFFFF) + { + report.ATA.ReadCapabilities.LongBlockSize = logicalsectorsize + ataId.EccBytes; + report.ATA.ReadCapabilities.LongBlockSizeSpecified = true; + } + + if(ataId.UnformattedBPS > logicalsectorsize && + (!report.ATA.ReadCapabilities.LongBlockSizeSpecified || + report.ATA.ReadCapabilities.LongBlockSize == 516)) + { + report.ATA.ReadCapabilities.LongBlockSize = ataId.UnformattedBPS; + report.ATA.ReadCapabilities.LongBlockSizeSpecified = true; + } + } + DicConsole.WriteLine("Trying READ LONG in CHS mode..."); sense = dev.ReadLong(out readBuf, out errorChs, false, 0, 0, 1, report.ATA.ReadCapabilities.LongBlockSize, TIMEOUT, out _); report.ATA.ReadCapabilities.SupportsReadLong = !sense && (errorChs.Status & 0x01) != 0x01 && errorChs.Error == 0 && readBuf.Length > 0 && - BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead; + BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead; DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense, errorChs.Status, errorChs.Error, readBuf.Length); @@ -1161,7 +1322,7 @@ namespace DiscImageChef.Core.Devices.Report report.ATA.ReadCapabilities.LongBlockSize, TIMEOUT, out _); report.ATA.ReadCapabilities.SupportsReadLongRetry = !sense && (errorChs.Status & 0x01) != 0x01 && errorChs.Error == 0 && readBuf.Length > 0 && - BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead; + BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead; DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense, errorChs.Status, errorChs.Error, readBuf.Length); @@ -1174,7 +1335,7 @@ namespace DiscImageChef.Core.Devices.Report TIMEOUT, out _); report.ATA.ReadCapabilities.SupportsReadLongLba = !sense && (errorLba.Status & 0x01) != 0x01 && errorLba.Error == 0 && readBuf.Length > 0 && - BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead; + BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead; DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense, errorLba.Status, errorLba.Error, readBuf.Length); @@ -1187,7 +1348,7 @@ namespace DiscImageChef.Core.Devices.Report TIMEOUT, out _); report.ATA.ReadCapabilities.SupportsReadLongRetryLba = !sense && (errorLba.Status & 0x01) != 0x01 && errorLba.Error == 0 && readBuf.Length > 0 && - BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead; + BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead; DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense, errorLba.Status, errorLba.Error, readBuf.Length); diff --git a/DiscImageChef.Devices/Device/AtaCommands/AtaCHS.cs b/DiscImageChef.Devices/Device/AtaCommands/AtaCHS.cs index 50b178a8..e015ff30 100644 --- a/DiscImageChef.Devices/Device/AtaCommands/AtaCHS.cs +++ b/DiscImageChef.Devices/Device/AtaCommands/AtaCHS.cs @@ -83,11 +83,12 @@ namespace DiscImageChef.Devices public bool AtaIdentify(out byte[] buffer, out AtaErrorRegistersChs statusRegisters, uint timeout, out double duration) { - buffer = new byte[512]; + buffer = new byte[512]; AtaRegistersChs registers = new AtaRegistersChs {Command = (byte)AtaCommands.IdentifyDevice}; - LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn, - AtaTransferRegister.NoTransfer, ref buffer, timeout, false, out duration, + LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn, + AtaTransferRegister.NoTransfer, ref buffer, timeout, false, + out duration, out bool sense); Error = LastError != 0; @@ -96,27 +97,31 @@ namespace DiscImageChef.Devices return sense; } - public bool ReadDma(out byte[] buffer, out AtaErrorRegistersChs statusRegisters, ushort cylinder, byte head, - byte sector, byte count, uint timeout, out double duration) + public bool ReadDma(out byte[] buffer, out AtaErrorRegistersChs statusRegisters, ushort cylinder, + byte head, + byte sector, byte count, uint timeout, + out double duration) { return ReadDma(out buffer, out statusRegisters, true, cylinder, head, sector, count, timeout, out duration); } public bool ReadDma(out byte[] buffer, out AtaErrorRegistersChs statusRegisters, bool retry, ushort cylinder, - byte head, byte sector, byte count, uint timeout, out double duration) + byte head, byte sector, byte count, uint timeout, + out double duration) { - buffer = count == 0 ? new byte[512 * 256] : new byte[512 * count]; + buffer = count == 0 ? new byte[512 * 256] : new byte[512 * count]; AtaRegistersChs registers = new AtaRegistersChs { - SectorCount = count, + SectorCount = count, CylinderHigh = (byte)((cylinder & 0xFF00) / 0x100), - CylinderLow = (byte)((cylinder & 0xFF) / 0x1), - DeviceHead = (byte)(head & 0x0F), - Sector = sector, - Command = retry ? (byte)AtaCommands.ReadDmaRetry : (byte)AtaCommands.ReadDma + CylinderLow = (byte)((cylinder & 0xFF) / 0x1), + DeviceHead = (byte)(head & 0x0F), + Sector = sector, + Command = retry ? (byte)AtaCommands.ReadDmaRetry : (byte)AtaCommands.ReadDma }; - LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.Dma, AtaTransferRegister.SectorCount, + LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.Dma, + AtaTransferRegister.SectorCount, ref buffer, timeout, true, out duration, out bool sense); Error = LastError != 0; @@ -126,21 +131,23 @@ namespace DiscImageChef.Devices } public bool ReadMultiple(out byte[] buffer, out AtaErrorRegistersChs statusRegisters, ushort cylinder, - byte head, byte sector, byte count, uint timeout, out double duration) + byte head, byte sector, byte count, + uint timeout, out double duration) { - buffer = count == 0 ? new byte[512 * 256] : new byte[512 * count]; + buffer = count == 0 ? new byte[512 * 256] : new byte[512 * count]; AtaRegistersChs registers = new AtaRegistersChs { - Command = (byte)AtaCommands.ReadMultiple, - SectorCount = count, + Command = (byte)AtaCommands.ReadMultiple, + SectorCount = count, CylinderHigh = (byte)((cylinder & 0xFF00) / 0x100), - CylinderLow = (byte)((cylinder & 0xFF) / 0x1), - DeviceHead = (byte)(head & 0x0F), - Sector = sector + CylinderLow = (byte)((cylinder & 0xFF) / 0x1), + DeviceHead = (byte)(head & 0x0F), + Sector = sector }; - LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn, - AtaTransferRegister.SectorCount, ref buffer, timeout, true, out duration, + LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn, + AtaTransferRegister.SectorCount, ref buffer, timeout, true, + out duration, out bool sense); Error = LastError != 0; @@ -150,27 +157,30 @@ namespace DiscImageChef.Devices } public bool Read(out byte[] buffer, out AtaErrorRegistersChs statusRegisters, ushort cylinder, byte head, - byte sector, byte count, uint timeout, out double duration) + byte sector, byte count, uint timeout, + out double duration) { return Read(out buffer, out statusRegisters, true, cylinder, head, sector, count, timeout, out duration); } public bool Read(out byte[] buffer, out AtaErrorRegistersChs statusRegisters, bool retry, ushort cylinder, - byte head, byte sector, byte count, uint timeout, out double duration) + byte head, byte sector, byte count, uint timeout, + out double duration) { - buffer = count == 0 ? new byte[512 * 256] : new byte[512 * count]; + buffer = count == 0 ? new byte[512 * 256] : new byte[512 * count]; AtaRegistersChs registers = new AtaRegistersChs { - Command = retry ? (byte)AtaCommands.ReadRetry : (byte)AtaCommands.Read, - SectorCount = count, + Command = retry ? (byte)AtaCommands.ReadRetry : (byte)AtaCommands.Read, + SectorCount = count, CylinderHigh = (byte)((cylinder & 0xFF00) / 0x100), - CylinderLow = (byte)((cylinder & 0xFF) / 0x1), - DeviceHead = (byte)(head & 0x0F), - Sector = sector + CylinderLow = (byte)((cylinder & 0xFF) / 0x1), + DeviceHead = (byte)(head & 0x0F), + Sector = sector }; - LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn, - AtaTransferRegister.SectorCount, ref buffer, timeout, true, out duration, + LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn, + AtaTransferRegister.SectorCount, ref buffer, timeout, true, + out duration, out bool sense); Error = LastError != 0; @@ -179,29 +189,33 @@ namespace DiscImageChef.Devices return sense; } - public bool ReadLong(out byte[] buffer, out AtaErrorRegistersChs statusRegisters, ushort cylinder, byte head, - byte sector, uint blockSize, uint timeout, out double duration) + public bool ReadLong(out byte[] buffer, out AtaErrorRegistersChs statusRegisters, ushort cylinder, + byte head, + byte sector, uint blockSize, uint timeout, + out double duration) { return ReadLong(out buffer, out statusRegisters, true, cylinder, head, sector, blockSize, timeout, out duration); } - public bool ReadLong(out byte[] buffer, out AtaErrorRegistersChs statusRegisters, bool retry, ushort cylinder, - byte head, byte sector, uint blockSize, uint timeout, out double duration) + public bool ReadLong(out byte[] buffer, out AtaErrorRegistersChs statusRegisters, bool retry, ushort cylinder, + byte head, byte sector, uint blockSize, uint timeout, + out double duration) { - buffer = new byte[blockSize]; + buffer = new byte[blockSize]; AtaRegistersChs registers = new AtaRegistersChs { - Command = retry ? (byte)AtaCommands.ReadLongRetry : (byte)AtaCommands.ReadLong, - SectorCount = 1, + Command = retry ? (byte)AtaCommands.ReadLongRetry : (byte)AtaCommands.ReadLong, + SectorCount = 1, CylinderHigh = (byte)((cylinder & 0xFF00) / 0x100), - CylinderLow = (byte)((cylinder & 0xFF) / 0x1), - DeviceHead = (byte)(head & 0x0F), - Sector = sector + CylinderLow = (byte)((cylinder & 0xFF) / 0x1), + DeviceHead = (byte)(head & 0x0F), + Sector = sector }; - LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn, - AtaTransferRegister.SectorCount, ref buffer, timeout, true, out duration, + LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn, + AtaTransferRegister.SectorCount, ref buffer, timeout, true, + out duration, out bool sense); Error = LastError != 0; @@ -211,20 +225,20 @@ namespace DiscImageChef.Devices } public bool Seek(out AtaErrorRegistersChs statusRegisters, ushort cylinder, byte head, byte sector, - uint timeout, out double duration) + uint timeout, out double duration) { - byte[] buffer = new byte[0]; + byte[] buffer = new byte[0]; AtaRegistersChs registers = new AtaRegistersChs { - Command = (byte)AtaCommands.Seek, + Command = (byte)AtaCommands.Seek, CylinderHigh = (byte)((cylinder & 0xFF00) / 0x100), - CylinderLow = (byte)((cylinder & 0xFF) / 0x1), - DeviceHead = (byte)(head & 0x0F), - Sector = sector + CylinderLow = (byte)((cylinder & 0xFF) / 0x1), + DeviceHead = (byte)(head & 0x0F), + Sector = sector }; - LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.NonData, - AtaTransferRegister.NoTransfer, ref buffer, timeout, true, out duration, + LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.NonData, + AtaTransferRegister.NoTransfer, ref buffer, timeout, true, out duration, out bool sense); Error = LastError != 0; @@ -232,5 +246,37 @@ namespace DiscImageChef.Devices return sense; } + + public bool SetFeatures(out AtaErrorRegistersChs statusRegisters, AtaFeatures feature, uint timeout, + out double duration) + { + return SetFeatures(out statusRegisters, feature, 0, 0, 0, 0, timeout, out duration); + } + + public bool SetFeatures(out AtaErrorRegistersChs statusRegisters, AtaFeatures feature, ushort cylinder, + byte head, byte sector, byte sectorCount, + uint timeout, out double duration) + { + byte[] buffer = new byte[0]; + AtaRegistersChs registers = new AtaRegistersChs + { + Command = (byte)AtaCommands.SetFeatures, + CylinderHigh = (byte)((cylinder & 0xFF00) / 0x100), + CylinderLow = (byte)((cylinder & 0xFF) / 0x1), + DeviceHead = (byte)(head & 0x0F), + Sector = sector, + SectorCount = sectorCount, + Feature = (byte)feature + }; + + LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.NonData, + AtaTransferRegister.NoTransfer, ref buffer, timeout, true, out duration, + out bool sense); + Error = LastError != 0; + + DicConsole.DebugWriteLine("ATA Device", "SET FEATURES took {0} ms.", duration); + + return sense; + } } } \ No newline at end of file diff --git a/DiscImageChef.Devices/Enums.cs b/DiscImageChef.Devices/Enums.cs index 4d7dae87..afb635db 100644 --- a/DiscImageChef.Devices/Enums.cs +++ b/DiscImageChef.Devices/Enums.cs @@ -640,7 +640,7 @@ namespace DiscImageChef.Devices /// Requests SPC-4 style error data /// RequestSenseDataExt = 0x0B, - SanitizeCommands = 0xB4, + SanitizeCommands = 0xB4, /// /// Executes a Security Protocol command that does not require a transfer of data /// @@ -2394,7 +2394,7 @@ namespace DiscImageChef.Devices /// Sets the spindle speed to be used while reading/writing data to a CD /// SetCdSpeed = 0xDA, - WriteCdp = 0xE3, + WriteCdp = 0xE3, #endregion #region ATA Command Pass-Through @@ -2413,10 +2413,10 @@ namespace DiscImageChef.Devices #region 6-byte CDB aliases ModeSelect6 = ModeSelect, - ModeSense6 = ModeSense, - Read6 = Read, - Seek6 = Seek, - Write6 = Write, + ModeSense6 = ModeSense, + Read6 = Read, + Seek6 = Seek, + Write6 = Write, #endregion 6-byte CDB aliases #region SCSI Zoned Block Commands @@ -2431,19 +2431,19 @@ namespace DiscImageChef.Devices #endregion #region SCSI Commands with unknown meaning, mostly vendor specific - SetCdSpeedUnk = 0xB8, - WriteCdMsf = 0xA2, - WriteCd = 0xAA, - ReadDefectTag = 0xB7, - PlayCd = 0xBC, - SpareIn = 0xBC, - SpareOut = 0xBD, - WriteStream16 = 0x9A, - WriteAtomic = 0x9C, + SetCdSpeedUnk = 0xB8, + WriteCdMsf = 0xA2, + WriteCd = 0xAA, + ReadDefectTag = 0xB7, + PlayCd = 0xBC, + SpareIn = 0xBC, + SpareOut = 0xBD, + WriteStream16 = 0x9A, + WriteAtomic = 0x9C, ServiceActionBidirectional = 0x9D, - WriteLong2 = 0xEA, - UnknownCdCommand = 0xD4, - UnknownCdCommand2 = 0xD5, + WriteLong2 = 0xEA, + UnknownCdCommand = 0xD4, + UnknownCdCommand2 = 0xD5, #endregion SCSI Commands with unknown meaning, mostly vendor specific #region SEGA Packet Interface (all are 12-byte CDB) @@ -2841,7 +2841,7 @@ namespace DiscImageChef.Devices /// /// Drive shall return only the Feature Header with the chosen Feature Descriptor /// - Single = 0x02, + Single = 0x02, Reserved = 0x03 } @@ -3505,8 +3505,8 @@ namespace DiscImageChef.Devices /// The host sends the bus testing data pattern to a device (ADTC, R1) /// BusTestWrite = 19, - SpiReadOcr = 58, - SpicrcOnOff = 59, + SpiReadOcr = 58, + SpicrcOnOff = 59, #endregion Class 1 MMC Commands (Basic and read-stream) #region Class 2 MMC Commands (Block-oriented read) @@ -3742,35 +3742,35 @@ namespace DiscImageChef.Devices public enum MmcFlags : uint { ResponsePresent = 1 << 0, - Response136 = 1 << 1, - ResponseCrc = 1 << 2, - ResponseBusy = 1 << 3, - ResponseOpcode = 1 << 4, - CommandMask = 3 << 5, - CommandAc = 0 << 5, - CommandAdtc = 1 << 5, - CommandBc = 2 << 5, - CommandBcr = 3 << 5, - ResponseSpiS1 = 1 << 7, - ResponseSpiS2 = 1 << 8, - ResponseSpiB4 = 1 << 9, + Response136 = 1 << 1, + ResponseCrc = 1 << 2, + ResponseBusy = 1 << 3, + ResponseOpcode = 1 << 4, + CommandMask = 3 << 5, + CommandAc = 0 << 5, + CommandAdtc = 1 << 5, + CommandBc = 2 << 5, + CommandBcr = 3 << 5, + ResponseSpiS1 = 1 << 7, + ResponseSpiS2 = 1 << 8, + ResponseSpiB4 = 1 << 9, ResponseSpiBusy = 1 << 10, - ResponseNone = 0, - ResponseR1 = ResponsePresent | ResponseCrc | ResponseOpcode, - ResponseR1B = ResponsePresent | ResponseCrc | ResponseOpcode | ResponseBusy, - ResponseR2 = ResponsePresent | Response136 | ResponseCrc, - ResponseR3 = ResponsePresent, - ResponseR4 = ResponsePresent, - ResponseR5 = ResponsePresent | ResponseCrc | ResponseOpcode, - ResponseR6 = ResponsePresent | ResponseCrc | ResponseOpcode, - ResponseR7 = ResponsePresent | ResponseCrc | ResponseOpcode, - ResponseSpiR1 = ResponseSpiS1, - ResponseSpiR1B = ResponseSpiS1 | ResponseSpiBusy, - ResponseSpiR2 = ResponseSpiS1 | ResponseSpiS2, - ResponseSpiR3 = ResponseSpiS1 | ResponseSpiB4, - ResponseSpiR4 = ResponseSpiS1 | ResponseSpiB4, - ResponseSpiR5 = ResponseSpiS1 | ResponseSpiS2, - ResponseSpiR7 = ResponseSpiS1 | ResponseSpiB4 + ResponseNone = 0, + ResponseR1 = ResponsePresent | ResponseCrc | ResponseOpcode, + ResponseR1B = ResponsePresent | ResponseCrc | ResponseOpcode | ResponseBusy, + ResponseR2 = ResponsePresent | Response136 | ResponseCrc, + ResponseR3 = ResponsePresent, + ResponseR4 = ResponsePresent, + ResponseR5 = ResponsePresent | ResponseCrc | ResponseOpcode, + ResponseR6 = ResponsePresent | ResponseCrc | ResponseOpcode, + ResponseR7 = ResponsePresent | ResponseCrc | ResponseOpcode, + ResponseSpiR1 = ResponseSpiS1, + ResponseSpiR1B = ResponseSpiS1 | ResponseSpiBusy, + ResponseSpiR2 = ResponseSpiS1 | ResponseSpiS2, + ResponseSpiR3 = ResponseSpiS1 | ResponseSpiB4, + ResponseSpiR4 = ResponseSpiS1 | ResponseSpiB4, + ResponseSpiR5 = ResponseSpiS1 | ResponseSpiS2, + ResponseSpiR7 = ResponseSpiS1 | ResponseSpiB4 } [Flags] @@ -3818,10 +3818,111 @@ namespace DiscImageChef.Devices ErrorSkipping } + public enum AtaFeatures : byte + { + /// Enable 8-bit data transfers + Enable8Bit = 0x01, + /// Enable write cache + EnableWriteCache = 0x02, + /// Set transfer mode based on value in sector count register + SetTransferMode = 0x03, + /// Enable all automatic defect reassignment + EnableDefectReassignment = 0x04, + /// Enable advanced power management + EnableApm = 0x05, + /// Enable Power-Up In Standby feature set + EnablePowerUpInStandby = 0x06, + /// Power-Up In Standby feature set device spin-up + PowerUpInStandByFeature = 0x07, + /// Reserved for Address offset reserved area boot method technical report + AddressOffsetReserved = 0x09, + /// Enable CFA power mode 1 + EnableCfaPowerMode1 = 0x0A, + /// Enable Write-Read-Verify feature set + EnableWriteReadVerify = 0x0B, + /// Enable use of SATA feature + EnableSataFeature = 0x10, + /// Disable Media Status Notification + DisableMediaStatusNotification = 0x31, + /// Disable retry + DisableRetry = 0x33, + /// Enable Free-fall Control + EnableFreeFall = 0x41, + /// Enable Automatic Acoustic Management feature set + EnableAam = 0x42, + /// Set Maximum Host Interface Sector Times + SetMaximumHostInterfaceSectorTimes = 0x43, + /// Vendor unique length of ECC on read long/write long commands + EnableReadLongVendorLength = 0x44, + /// Extended Power conditions + ExtendedPowerConditions = 0x4A, + /// Set cache segments to sector count register value + SetCacheSegments = 0x54, + /// Disable read look-ahead feature + DisableReadLookAhead = 0x55, + /// Enable release interrupt + EnableReleaseInterrupt = 0x5D, + /// Enable SERVICE interrupt + EnableServiceInterrupt = 0x5E, + /// Long Physical Sector Alignment Error Reporting Control + LongPhysicalSectorErrorControl = 0x62, + /// Enable/Disable the DSN feature set + DsnFeature = 0x63, + /// Disable reverting to power on defaults + DisableRevertToDefaults = 0x66, + /// Disable ECC + DisableEcc = 0x77, + /// Disable 8-bit data transfers + Disable8Bit = 0x81, + /// Disable write cache + DisableWriteCache = 0x82, + /// Disable all automatic defect reassignment + DisableDefectReassignment = 0x84, + /// Disable advanced power management + DisableApm = 0x85, + /// Disable Power-Up In Standby feature set + DisablePowerUpInStandby = 0x86, + /// Enable ECC + EnableEcc = 0x88, + /// Reserved for Address offset reserved area boot method technical report + AddressOffsetReserved2 = 0x89, + /// Disable CFA power mode 1 + DisableCfaPowerMode1 = 0x8A, + /// Disable Write-Read-Verify feature set + DisableWriteReadVerify = 0x8B, + /// Disable use of SATA feature + DisableSataFeature = 0x90, + /// Enable Media Status Notification + EnableMediaStatusNotification = 0x95, + /// Enable retries + EnableRetries = 0x99, + /// Set device maximum average current + SetMaximumAverageCurrent = 0x9A, + /// Enable read look-ahead feature + EnableReadLookAhead = 0xAA, + /// Set maximum prefetch using sector count register value + SetMaximumPrefetch = 0xAB, + /// 4 bytes of ECC apply on read long/write long commands + DisableReadLongVendorLength = 0xBB, + /// Disable Free-fall Control + DisableFreeFall = 0xC1, + /// Disable Automatic Acoustic Management feature set + DisableAam = 0xC2, + /// Enable/Disable the Sense Data Reporting feature set + SenseDataReporting = 0xC3, + /// Enable reverting to power on defaults + EnableRevertToDefaults = 0xCC, + /// Disable release interrupt + DisableReleaseInterrupt = 0xDD, + /// Disable SERVICE interrupt + DisableServiceInterrupt = 0xDE, + VendorSpecific = 0xE0 + } + public enum KreonLockStates : byte { - Locked = 0, - Xtreme = 1, + Locked = 0, + Xtreme = 1, Wxripper = 2 } } \ No newline at end of file diff --git a/DiscImageChef.Tests.Devices/ATA/Ata28.cs b/DiscImageChef.Tests.Devices/ATA/Ata28.cs index 816a95fb..102f5cf8 100644 --- a/DiscImageChef.Tests.Devices/ATA/Ata28.cs +++ b/DiscImageChef.Tests.Devices/ATA/Ata28.cs @@ -119,9 +119,9 @@ namespace DiscImageChef.Tests.Devices.ATA menu: DicConsole.WriteLine("Device: {0}", devPath); DicConsole.WriteLine("Sending READ BUFFER to the device:"); - DicConsole.WriteLine("Command took {0} ms.", duration); - DicConsole.WriteLine("Sense is {0}.", sense); - DicConsole.WriteLine("Buffer is {0} bytes.", buffer?.Length.ToString() ?? "null"); + DicConsole.WriteLine("Command took {0} ms.", duration); + DicConsole.WriteLine("Sense is {0}.", sense); + DicConsole.WriteLine("Buffer is {0} bytes.", buffer?.Length.ToString() ?? "null"); DicConsole.WriteLine("Buffer is null or empty? {0}", ArrayHelpers.ArrayIsNullOrEmpty(buffer)); DicConsole.WriteLine(); DicConsole.WriteLine("Choose what to do:"); @@ -184,9 +184,9 @@ namespace DiscImageChef.Tests.Devices.ATA menu: DicConsole.WriteLine("Device: {0}", devPath); DicConsole.WriteLine("Sending READ BUFFER DMA to the device:"); - DicConsole.WriteLine("Command took {0} ms.", duration); - DicConsole.WriteLine("Sense is {0}.", sense); - DicConsole.WriteLine("Buffer is {0} bytes.", buffer?.Length.ToString() ?? "null"); + DicConsole.WriteLine("Command took {0} ms.", duration); + DicConsole.WriteLine("Sense is {0}.", sense); + DicConsole.WriteLine("Buffer is {0} bytes.", buffer?.Length.ToString() ?? "null"); DicConsole.WriteLine("Buffer is null or empty? {0}", ArrayHelpers.ArrayIsNullOrEmpty(buffer)); DicConsole.WriteLine(); DicConsole.WriteLine("Choose what to do:"); @@ -241,19 +241,19 @@ namespace DiscImageChef.Tests.Devices.ATA static void ReadDma(string devPath, Device dev, bool retries) { - uint lba = 0; - byte count = 1; + uint lba = 0; + byte count = 1; string strDev; - int item; + int item; parameters: while(true) { System.Console.Clear(); - DicConsole.WriteLine("Device: {0}", devPath); + DicConsole.WriteLine("Device: {0}", devPath); DicConsole.WriteLine("Parameters for READ DMA {0}command:", retries ? "WITH RETRIES " : ""); - DicConsole.WriteLine("LBA: {0}", lba); - DicConsole.WriteLine("Count: {0}", count); + DicConsole.WriteLine("LBA: {0}", lba); + DicConsole.WriteLine("Count: {0}", count); DicConsole.WriteLine(); DicConsole.WriteLine("Choose what to do:"); DicConsole.WriteLine("1.- Change parameters."); @@ -287,10 +287,11 @@ namespace DiscImageChef.Tests.Devices.ATA if(lba > 0xFFFFFFF) { DicConsole - .WriteLine("Logical block address cannot be bigger than {0}. Setting it to {0}...", - 0xFFFFFFF); + .WriteLine("Logical block address cannot be bigger than {0}. Setting it to {0}...", + 0xFFFFFFF); lba = 0xFFFFFFF; } + DicConsole.Write("How many sectors?: "); strDev = System.Console.ReadLine(); if(!byte.TryParse(strDev, out count)) @@ -311,12 +312,12 @@ namespace DiscImageChef.Tests.Devices.ATA dev.Timeout, out double duration); menu: - DicConsole.WriteLine("Device: {0}", devPath); + DicConsole.WriteLine("Device: {0}", devPath); DicConsole.WriteLine("Sending READ DMA {0}to the device:", retries ? "WITH RETRIES " : ""); - DicConsole.WriteLine("Command took {0} ms.", duration); - DicConsole.WriteLine("Sense is {0}.", sense); - DicConsole.WriteLine("Buffer is {0} bytes.", buffer?.Length.ToString() ?? "null"); - DicConsole.WriteLine("Buffer is null or empty? {0}", ArrayHelpers.ArrayIsNullOrEmpty(buffer)); + DicConsole.WriteLine("Command took {0} ms.", duration); + DicConsole.WriteLine("Sense is {0}.", sense); + DicConsole.WriteLine("Buffer is {0} bytes.", buffer?.Length.ToString() ?? "null"); + DicConsole.WriteLine("Buffer is null or empty? {0}", ArrayHelpers.ArrayIsNullOrEmpty(buffer)); DicConsole.WriteLine(); DicConsole.WriteLine("Choose what to do:"); DicConsole.WriteLine("1.- Print buffer."); @@ -342,7 +343,7 @@ namespace DiscImageChef.Tests.Devices.ATA return; case 1: System.Console.Clear(); - DicConsole.WriteLine("Device: {0}", devPath); + DicConsole.WriteLine("Device: {0}", devPath); DicConsole.WriteLine("READ DMA {0}response:", retries ? "WITH RETRIES " : ""); if(buffer != null) PrintHex.PrintHexArray(buffer, 64); DicConsole.WriteLine("Press any key to continue..."); @@ -352,7 +353,7 @@ namespace DiscImageChef.Tests.Devices.ATA goto menu; case 2: System.Console.Clear(); - DicConsole.WriteLine("Device: {0}", devPath); + DicConsole.WriteLine("Device: {0}", devPath); DicConsole.WriteLine("READ DMA {0}status registers:", retries ? "WITH RETRIES " : ""); DicConsole.Write("{0}", MainClass.DecodeAtaRegisters(errorRegisters)); DicConsole.WriteLine("Press any key to continue..."); @@ -372,19 +373,19 @@ namespace DiscImageChef.Tests.Devices.ATA static void ReadLong(string devPath, Device dev, bool retries) { - uint lba = 0; - uint blockSize = 1; + uint lba = 0; + uint blockSize = 1; string strDev; - int item; + int item; parameters: while(true) { System.Console.Clear(); - DicConsole.WriteLine("Device: {0}", devPath); + DicConsole.WriteLine("Device: {0}", devPath); DicConsole.WriteLine("Parameters for READ LONG {0}command:", retries ? "WITH RETRIES " : ""); - DicConsole.WriteLine("LBA: {0}", lba); - DicConsole.WriteLine("Block size: {0}", blockSize); + DicConsole.WriteLine("LBA: {0}", lba); + DicConsole.WriteLine("Block size: {0}", blockSize); DicConsole.WriteLine(); DicConsole.WriteLine("Choose what to do:"); DicConsole.WriteLine("1.- Change parameters."); @@ -418,10 +419,20 @@ namespace DiscImageChef.Tests.Devices.ATA if(lba > 0xFFFFFFF) { DicConsole - .WriteLine("Logical block address cannot be bigger than {0}. Setting it to {0}...", - 0xFFFFFFF); + .WriteLine("Logical block address cannot be bigger than {0}. Setting it to {0}...", + 0xFFFFFFF); lba = 0xFFFFFFF; } + + DicConsole.Write("How many bytes to expect?: "); + strDev = System.Console.ReadLine(); + if(!uint.TryParse(strDev, out blockSize)) + { + DicConsole.WriteLine("Not a number. Press any key to continue..."); + blockSize = 0; + System.Console.ReadKey(); + } + break; case 2: goto start; } @@ -433,12 +444,12 @@ namespace DiscImageChef.Tests.Devices.ATA blockSize, dev.Timeout, out double duration); menu: - DicConsole.WriteLine("Device: {0}", devPath); + DicConsole.WriteLine("Device: {0}", devPath); DicConsole.WriteLine("Sending READ LONG {0}to the device:", retries ? "WITH RETRIES " : ""); - DicConsole.WriteLine("Command took {0} ms.", duration); - DicConsole.WriteLine("Sense is {0}.", sense); - DicConsole.WriteLine("Buffer is {0} bytes.", buffer?.Length.ToString() ?? "null"); - DicConsole.WriteLine("Buffer is null or empty? {0}", ArrayHelpers.ArrayIsNullOrEmpty(buffer)); + DicConsole.WriteLine("Command took {0} ms.", duration); + DicConsole.WriteLine("Sense is {0}.", sense); + DicConsole.WriteLine("Buffer is {0} bytes.", buffer?.Length.ToString() ?? "null"); + DicConsole.WriteLine("Buffer is null or empty? {0}", ArrayHelpers.ArrayIsNullOrEmpty(buffer)); DicConsole.WriteLine(); DicConsole.WriteLine("Choose what to do:"); DicConsole.WriteLine("1.- Print buffer."); @@ -464,7 +475,7 @@ namespace DiscImageChef.Tests.Devices.ATA return; case 1: System.Console.Clear(); - DicConsole.WriteLine("Device: {0}", devPath); + DicConsole.WriteLine("Device: {0}", devPath); DicConsole.WriteLine("READ LONG {0}response:", retries ? "WITH RETRIES " : ""); if(buffer != null) PrintHex.PrintHexArray(buffer, 64); DicConsole.WriteLine("Press any key to continue..."); @@ -474,7 +485,7 @@ namespace DiscImageChef.Tests.Devices.ATA goto menu; case 2: System.Console.Clear(); - DicConsole.WriteLine("Device: {0}", devPath); + DicConsole.WriteLine("Device: {0}", devPath); DicConsole.WriteLine("READ LONG {0}status registers:", retries ? "WITH RETRIES " : ""); DicConsole.Write("{0}", MainClass.DecodeAtaRegisters(errorRegisters)); DicConsole.WriteLine("Press any key to continue..."); @@ -494,10 +505,10 @@ namespace DiscImageChef.Tests.Devices.ATA static void ReadMultiple(string devPath, Device dev) { - uint lba = 0; - byte count = 1; + uint lba = 0; + byte count = 1; string strDev; - int item; + int item; parameters: while(true) @@ -505,7 +516,7 @@ namespace DiscImageChef.Tests.Devices.ATA System.Console.Clear(); DicConsole.WriteLine("Device: {0}", devPath); DicConsole.WriteLine("Parameters for READ MULTIPLE command:"); - DicConsole.WriteLine("LBA: {0}", lba); + DicConsole.WriteLine("LBA: {0}", lba); DicConsole.WriteLine("Count: {0}", count); DicConsole.WriteLine(); DicConsole.WriteLine("Choose what to do:"); @@ -540,10 +551,11 @@ namespace DiscImageChef.Tests.Devices.ATA if(lba > 0xFFFFFFF) { DicConsole - .WriteLine("Logical block address cannot be bigger than {0}. Setting it to {0}...", - 0xFFFFFFF); + .WriteLine("Logical block address cannot be bigger than {0}. Setting it to {0}...", + 0xFFFFFFF); lba = 0xFFFFFFF; } + DicConsole.Write("How many sectors?: "); strDev = System.Console.ReadLine(); if(!byte.TryParse(strDev, out count)) @@ -566,9 +578,9 @@ namespace DiscImageChef.Tests.Devices.ATA menu: DicConsole.WriteLine("Device: {0}", devPath); DicConsole.WriteLine("Sending READ MULTIPLE to the device:"); - DicConsole.WriteLine("Command took {0} ms.", duration); - DicConsole.WriteLine("Sense is {0}.", sense); - DicConsole.WriteLine("Buffer is {0} bytes.", buffer?.Length.ToString() ?? "null"); + DicConsole.WriteLine("Command took {0} ms.", duration); + DicConsole.WriteLine("Sense is {0}.", sense); + DicConsole.WriteLine("Buffer is {0} bytes.", buffer?.Length.ToString() ?? "null"); DicConsole.WriteLine("Buffer is null or empty? {0}", ArrayHelpers.ArrayIsNullOrEmpty(buffer)); DicConsole.WriteLine(); DicConsole.WriteLine("Choose what to do:"); @@ -634,8 +646,8 @@ namespace DiscImageChef.Tests.Devices.ATA DicConsole.WriteLine("Device: {0}", devPath); DicConsole.WriteLine("Sending READ NATIVE MAX ADDRESS to the device:"); DicConsole.WriteLine("Command took {0} ms.", duration); - DicConsole.WriteLine("Sense is {0}.", sense); - DicConsole.WriteLine("Max LBA is {0}.", lba); + DicConsole.WriteLine("Sense is {0}.", sense); + DicConsole.WriteLine("Max LBA is {0}.", lba); DicConsole.WriteLine(); DicConsole.WriteLine("Choose what to do:"); DicConsole.WriteLine("1.- Decode error registers."); @@ -678,19 +690,19 @@ namespace DiscImageChef.Tests.Devices.ATA static void ReadSectors(string devPath, Device dev, bool retries) { - uint lba = 0; - byte count = 1; + uint lba = 0; + byte count = 1; string strDev; - int item; + int item; parameters: while(true) { System.Console.Clear(); - DicConsole.WriteLine("Device: {0}", devPath); + DicConsole.WriteLine("Device: {0}", devPath); DicConsole.WriteLine("Parameters for READ SECTORS {0}command:", retries ? "WITH RETRIES " : ""); - DicConsole.WriteLine("LBA: {0}", lba); - DicConsole.WriteLine("Count: {0}", count); + DicConsole.WriteLine("LBA: {0}", lba); + DicConsole.WriteLine("Count: {0}", count); DicConsole.WriteLine(); DicConsole.WriteLine("Choose what to do:"); DicConsole.WriteLine("1.- Change parameters."); @@ -724,10 +736,11 @@ namespace DiscImageChef.Tests.Devices.ATA if(lba > 0xFFFFFFF) { DicConsole - .WriteLine("Logical block address cannot be bigger than {0}. Setting it to {0}...", - 0xFFFFFFF); + .WriteLine("Logical block address cannot be bigger than {0}. Setting it to {0}...", + 0xFFFFFFF); lba = 0xFFFFFFF; } + DicConsole.Write("How many sectors?: "); strDev = System.Console.ReadLine(); if(!byte.TryParse(strDev, out count)) @@ -748,12 +761,12 @@ namespace DiscImageChef.Tests.Devices.ATA dev.Timeout, out double duration); menu: - DicConsole.WriteLine("Device: {0}", devPath); + DicConsole.WriteLine("Device: {0}", devPath); DicConsole.WriteLine("Sending READ SECTORS {0}to the device:", retries ? "WITH RETRIES " : ""); - DicConsole.WriteLine("Command took {0} ms.", duration); - DicConsole.WriteLine("Sense is {0}.", sense); - DicConsole.WriteLine("Buffer is {0} bytes.", buffer?.Length.ToString() ?? "null"); - DicConsole.WriteLine("Buffer is null or empty? {0}", ArrayHelpers.ArrayIsNullOrEmpty(buffer)); + DicConsole.WriteLine("Command took {0} ms.", duration); + DicConsole.WriteLine("Sense is {0}.", sense); + DicConsole.WriteLine("Buffer is {0} bytes.", buffer?.Length.ToString() ?? "null"); + DicConsole.WriteLine("Buffer is null or empty? {0}", ArrayHelpers.ArrayIsNullOrEmpty(buffer)); DicConsole.WriteLine(); DicConsole.WriteLine("Choose what to do:"); DicConsole.WriteLine("1.- Print buffer."); @@ -779,7 +792,7 @@ namespace DiscImageChef.Tests.Devices.ATA return; case 1: System.Console.Clear(); - DicConsole.WriteLine("Device: {0}", devPath); + DicConsole.WriteLine("Device: {0}", devPath); DicConsole.WriteLine("READ SECTORS {0}response:", retries ? "WITH RETRIES " : ""); if(buffer != null) PrintHex.PrintHexArray(buffer, 64); DicConsole.WriteLine("Press any key to continue..."); @@ -789,7 +802,7 @@ namespace DiscImageChef.Tests.Devices.ATA goto menu; case 2: System.Console.Clear(); - DicConsole.WriteLine("Device: {0}", devPath); + DicConsole.WriteLine("Device: {0}", devPath); DicConsole.WriteLine("READ SECTORS {0}status registers:", retries ? "WITH RETRIES " : ""); DicConsole.Write("{0}", MainClass.DecodeAtaRegisters(errorRegisters)); DicConsole.WriteLine("Press any key to continue..."); @@ -809,9 +822,9 @@ namespace DiscImageChef.Tests.Devices.ATA static void Seek(string devPath, Device dev) { - uint lba = 0; + uint lba = 0; string strDev; - int item; + int item; parameters: while(true) @@ -853,10 +866,11 @@ namespace DiscImageChef.Tests.Devices.ATA if(lba > 0xFFFFFFF) { DicConsole - .WriteLine("Logical block address cannot be bigger than {0}. Setting it to {0}...", - 0xFFFFFFF); + .WriteLine("Logical block address cannot be bigger than {0}. Setting it to {0}...", + 0xFFFFFFF); lba = 0xFFFFFFF; } + break; case 2: goto start; } @@ -870,7 +884,7 @@ namespace DiscImageChef.Tests.Devices.ATA DicConsole.WriteLine("Device: {0}", devPath); DicConsole.WriteLine("Sending SEEK to the device:"); DicConsole.WriteLine("Command took {0} ms.", duration); - DicConsole.WriteLine("Sense is {0}.", sense); + DicConsole.WriteLine("Sense is {0}.", sense); DicConsole.WriteLine(); DicConsole.WriteLine("Choose what to do:"); DicConsole.WriteLine("1.- Decode error registers."); diff --git a/DiscImageChef.Tests.Devices/ATA/AtaCHS.cs b/DiscImageChef.Tests.Devices/ATA/AtaCHS.cs index 9244503b..434291a9 100644 --- a/DiscImageChef.Tests.Devices/ATA/AtaCHS.cs +++ b/DiscImageChef.Tests.Devices/ATA/AtaCHS.cs @@ -50,6 +50,7 @@ namespace DiscImageChef.Tests.Devices.ATA DicConsole.WriteLine("7.- Send READ SECTORS command."); DicConsole.WriteLine("8.- Send READ SECTORS WITH RETRIES command."); DicConsole.WriteLine("9.- Send SEEK command."); + DicConsole.WriteLine("10.- Send SET FEATURES command."); DicConsole.WriteLine("0.- Return to ATA commands menu."); DicConsole.Write("Choose: "); @@ -93,6 +94,9 @@ namespace DiscImageChef.Tests.Devices.ATA case 9: Seek(devPath, dev); continue; + case 10: + SetFeatures(devPath, dev); + continue; default: DicConsole.WriteLine("Incorrect option. Press any key to continue..."); System.Console.ReadKey(); @@ -111,9 +115,9 @@ namespace DiscImageChef.Tests.Devices.ATA menu: DicConsole.WriteLine("Device: {0}", devPath); DicConsole.WriteLine("Sending IDENTIFY DEVICE to the device:"); - DicConsole.WriteLine("Command took {0} ms.", duration); - DicConsole.WriteLine("Sense is {0}.", sense); - DicConsole.WriteLine("Buffer is {0} bytes.", buffer?.Length.ToString() ?? "null"); + DicConsole.WriteLine("Command took {0} ms.", duration); + DicConsole.WriteLine("Sense is {0}.", sense); + DicConsole.WriteLine("Buffer is {0} bytes.", buffer?.Length.ToString() ?? "null"); DicConsole.WriteLine("Buffer is null or empty? {0}", ArrayHelpers.ArrayIsNullOrEmpty(buffer)); DicConsole.WriteLine(); DicConsole.WriteLine("Choose what to do:"); @@ -180,22 +184,22 @@ namespace DiscImageChef.Tests.Devices.ATA static void ReadDma(string devPath, Device dev, bool retries) { ushort cylinder = 0; - byte head = 0; - byte sector = 1; - byte count = 1; + byte head = 0; + byte sector = 1; + byte count = 1; string strDev; - int item; + int item; parameters: while(true) { System.Console.Clear(); - DicConsole.WriteLine("Device: {0}", devPath); + DicConsole.WriteLine("Device: {0}", devPath); DicConsole.WriteLine("Parameters for READ DMA {0}command:", retries ? "WITH RETRIES " : ""); - DicConsole.WriteLine("Cylinder: {0}", cylinder); - DicConsole.WriteLine("Head: {0}", head); - DicConsole.WriteLine("Sector: {0}", sector); - DicConsole.WriteLine("Count: {0}", count); + DicConsole.WriteLine("Cylinder: {0}", cylinder); + DicConsole.WriteLine("Head: {0}", head); + DicConsole.WriteLine("Sector: {0}", sector); + DicConsole.WriteLine("Count: {0}", count); DicConsole.WriteLine(); DicConsole.WriteLine("Choose what to do:"); DicConsole.WriteLine("1.- Change parameters."); @@ -241,6 +245,7 @@ namespace DiscImageChef.Tests.Devices.ATA DicConsole.WriteLine("Head cannot be bigger than 15. Setting it to 15..."); head = 15; } + DicConsole.Write("What sector?: "); strDev = System.Console.ReadLine(); if(!byte.TryParse(strDev, out sector)) @@ -271,12 +276,12 @@ namespace DiscImageChef.Tests.Devices.ATA head, sector, count, dev.Timeout, out double duration); menu: - DicConsole.WriteLine("Device: {0}", devPath); + DicConsole.WriteLine("Device: {0}", devPath); DicConsole.WriteLine("Sending READ DMA {0}to the device:", retries ? "WITH RETRIES " : ""); - DicConsole.WriteLine("Command took {0} ms.", duration); - DicConsole.WriteLine("Sense is {0}.", sense); - DicConsole.WriteLine("Buffer is {0} bytes.", buffer?.Length.ToString() ?? "null"); - DicConsole.WriteLine("Buffer is null or empty? {0}", ArrayHelpers.ArrayIsNullOrEmpty(buffer)); + DicConsole.WriteLine("Command took {0} ms.", duration); + DicConsole.WriteLine("Sense is {0}.", sense); + DicConsole.WriteLine("Buffer is {0} bytes.", buffer?.Length.ToString() ?? "null"); + DicConsole.WriteLine("Buffer is null or empty? {0}", ArrayHelpers.ArrayIsNullOrEmpty(buffer)); DicConsole.WriteLine(); DicConsole.WriteLine("Choose what to do:"); DicConsole.WriteLine("1.- Print buffer."); @@ -302,7 +307,7 @@ namespace DiscImageChef.Tests.Devices.ATA return; case 1: System.Console.Clear(); - DicConsole.WriteLine("Device: {0}", devPath); + DicConsole.WriteLine("Device: {0}", devPath); DicConsole.WriteLine("READ DMA {0}response:", retries ? "WITH RETRIES " : ""); if(buffer != null) PrintHex.PrintHexArray(buffer, 64); DicConsole.WriteLine("Press any key to continue..."); @@ -312,7 +317,7 @@ namespace DiscImageChef.Tests.Devices.ATA goto menu; case 2: System.Console.Clear(); - DicConsole.WriteLine("Device: {0}", devPath); + DicConsole.WriteLine("Device: {0}", devPath); DicConsole.WriteLine("READ DMA {0}status registers:", retries ? "WITH RETRIES " : ""); DicConsole.Write("{0}", MainClass.DecodeAtaRegisters(errorRegisters)); DicConsole.WriteLine("Press any key to continue..."); @@ -332,23 +337,23 @@ namespace DiscImageChef.Tests.Devices.ATA static void ReadLong(string devPath, Device dev, bool retries) { - ushort cylinder = 0; - byte head = 0; - byte sector = 1; - uint blockSize = 1; + ushort cylinder = 0; + byte head = 0; + byte sector = 1; + uint blockSize = 1; string strDev; - int item; + int item; parameters: while(true) { System.Console.Clear(); - DicConsole.WriteLine("Device: {0}", devPath); + DicConsole.WriteLine("Device: {0}", devPath); DicConsole.WriteLine("Parameters for READ LONG {0}command:", retries ? "WITH RETRIES " : ""); - DicConsole.WriteLine("Cylinder: {0}", cylinder); - DicConsole.WriteLine("Head: {0}", head); - DicConsole.WriteLine("Sector: {0}", sector); - DicConsole.WriteLine("Block size: {0}", blockSize); + DicConsole.WriteLine("Cylinder: {0}", cylinder); + DicConsole.WriteLine("Head: {0}", head); + DicConsole.WriteLine("Sector: {0}", sector); + DicConsole.WriteLine("Block size: {0}", blockSize); DicConsole.WriteLine(); DicConsole.WriteLine("Choose what to do:"); DicConsole.WriteLine("1.- Change parameters."); @@ -394,6 +399,7 @@ namespace DiscImageChef.Tests.Devices.ATA DicConsole.WriteLine("Head cannot be bigger than 15. Setting it to 15..."); head = 15; } + DicConsole.Write("What sector?: "); strDev = System.Console.ReadLine(); if(!byte.TryParse(strDev, out sector)) @@ -424,12 +430,12 @@ namespace DiscImageChef.Tests.Devices.ATA head, sector, blockSize, dev.Timeout, out double duration); menu: - DicConsole.WriteLine("Device: {0}", devPath); + DicConsole.WriteLine("Device: {0}", devPath); DicConsole.WriteLine("Sending READ LONG {0}to the device:", retries ? "WITH RETRIES " : ""); - DicConsole.WriteLine("Command took {0} ms.", duration); - DicConsole.WriteLine("Sense is {0}.", sense); - DicConsole.WriteLine("Buffer is {0} bytes.", buffer?.Length.ToString() ?? "null"); - DicConsole.WriteLine("Buffer is null or empty? {0}", ArrayHelpers.ArrayIsNullOrEmpty(buffer)); + DicConsole.WriteLine("Command took {0} ms.", duration); + DicConsole.WriteLine("Sense is {0}.", sense); + DicConsole.WriteLine("Buffer is {0} bytes.", buffer?.Length.ToString() ?? "null"); + DicConsole.WriteLine("Buffer is null or empty? {0}", ArrayHelpers.ArrayIsNullOrEmpty(buffer)); DicConsole.WriteLine(); DicConsole.WriteLine("Choose what to do:"); DicConsole.WriteLine("1.- Print buffer."); @@ -455,7 +461,7 @@ namespace DiscImageChef.Tests.Devices.ATA return; case 1: System.Console.Clear(); - DicConsole.WriteLine("Device: {0}", devPath); + DicConsole.WriteLine("Device: {0}", devPath); DicConsole.WriteLine("READ LONG {0}response:", retries ? "WITH RETRIES " : ""); if(buffer != null) PrintHex.PrintHexArray(buffer, 64); DicConsole.WriteLine("Press any key to continue..."); @@ -465,7 +471,7 @@ namespace DiscImageChef.Tests.Devices.ATA goto menu; case 2: System.Console.Clear(); - DicConsole.WriteLine("Device: {0}", devPath); + DicConsole.WriteLine("Device: {0}", devPath); DicConsole.WriteLine("READ LONG {0}status registers:", retries ? "WITH RETRIES " : ""); DicConsole.Write("{0}", MainClass.DecodeAtaRegisters(errorRegisters)); DicConsole.WriteLine("Press any key to continue..."); @@ -486,11 +492,11 @@ namespace DiscImageChef.Tests.Devices.ATA static void ReadMultiple(string devPath, Device dev) { ushort cylinder = 0; - byte head = 0; - byte sector = 1; - byte count = 1; + byte head = 0; + byte sector = 1; + byte count = 1; string strDev; - int item; + int item; parameters: while(true) @@ -499,9 +505,9 @@ namespace DiscImageChef.Tests.Devices.ATA DicConsole.WriteLine("Device: {0}", devPath); DicConsole.WriteLine("Parameters for READ MULTIPLE command:"); DicConsole.WriteLine("Cylinder: {0}", cylinder); - DicConsole.WriteLine("Head: {0}", head); - DicConsole.WriteLine("Sector: {0}", sector); - DicConsole.WriteLine("Count: {0}", count); + DicConsole.WriteLine("Head: {0}", head); + DicConsole.WriteLine("Sector: {0}", sector); + DicConsole.WriteLine("Count: {0}", count); DicConsole.WriteLine(); DicConsole.WriteLine("Choose what to do:"); DicConsole.WriteLine("1.- Change parameters."); @@ -547,6 +553,7 @@ namespace DiscImageChef.Tests.Devices.ATA DicConsole.WriteLine("Head cannot be bigger than 15. Setting it to 15..."); head = 15; } + DicConsole.Write("What sector?: "); strDev = System.Console.ReadLine(); if(!byte.TryParse(strDev, out sector)) @@ -579,9 +586,9 @@ namespace DiscImageChef.Tests.Devices.ATA menu: DicConsole.WriteLine("Device: {0}", devPath); DicConsole.WriteLine("Sending READ MULTIPLE to the device:"); - DicConsole.WriteLine("Command took {0} ms.", duration); - DicConsole.WriteLine("Sense is {0}.", sense); - DicConsole.WriteLine("Buffer is {0} bytes.", buffer?.Length.ToString() ?? "null"); + DicConsole.WriteLine("Command took {0} ms.", duration); + DicConsole.WriteLine("Sense is {0}.", sense); + DicConsole.WriteLine("Buffer is {0} bytes.", buffer?.Length.ToString() ?? "null"); DicConsole.WriteLine("Buffer is null or empty? {0}", ArrayHelpers.ArrayIsNullOrEmpty(buffer)); DicConsole.WriteLine(); DicConsole.WriteLine("Choose what to do:"); @@ -639,22 +646,22 @@ namespace DiscImageChef.Tests.Devices.ATA static void ReadSectors(string devPath, Device dev, bool retries) { ushort cylinder = 0; - byte head = 0; - byte sector = 1; - byte count = 1; + byte head = 0; + byte sector = 1; + byte count = 1; string strDev; - int item; + int item; parameters: while(true) { System.Console.Clear(); - DicConsole.WriteLine("Device: {0}", devPath); + DicConsole.WriteLine("Device: {0}", devPath); DicConsole.WriteLine("Parameters for READ SECTORS {0}command:", retries ? "WITH RETRIES " : ""); - DicConsole.WriteLine("Cylinder: {0}", cylinder); - DicConsole.WriteLine("Head: {0}", head); - DicConsole.WriteLine("Sector: {0}", sector); - DicConsole.WriteLine("Count: {0}", count); + DicConsole.WriteLine("Cylinder: {0}", cylinder); + DicConsole.WriteLine("Head: {0}", head); + DicConsole.WriteLine("Sector: {0}", sector); + DicConsole.WriteLine("Count: {0}", count); DicConsole.WriteLine(); DicConsole.WriteLine("Choose what to do:"); DicConsole.WriteLine("1.- Change parameters."); @@ -700,6 +707,7 @@ namespace DiscImageChef.Tests.Devices.ATA DicConsole.WriteLine("Head cannot be bigger than 15. Setting it to 15..."); head = 15; } + DicConsole.Write("What sector?: "); strDev = System.Console.ReadLine(); if(!byte.TryParse(strDev, out sector)) @@ -730,12 +738,12 @@ namespace DiscImageChef.Tests.Devices.ATA sector, count, dev.Timeout, out double duration); menu: - DicConsole.WriteLine("Device: {0}", devPath); + DicConsole.WriteLine("Device: {0}", devPath); DicConsole.WriteLine("Sending READ SECTORS {0}to the device:", retries ? "WITH RETRIES " : ""); - DicConsole.WriteLine("Command took {0} ms.", duration); - DicConsole.WriteLine("Sense is {0}.", sense); - DicConsole.WriteLine("Buffer is {0} bytes.", buffer?.Length.ToString() ?? "null"); - DicConsole.WriteLine("Buffer is null or empty? {0}", ArrayHelpers.ArrayIsNullOrEmpty(buffer)); + DicConsole.WriteLine("Command took {0} ms.", duration); + DicConsole.WriteLine("Sense is {0}.", sense); + DicConsole.WriteLine("Buffer is {0} bytes.", buffer?.Length.ToString() ?? "null"); + DicConsole.WriteLine("Buffer is null or empty? {0}", ArrayHelpers.ArrayIsNullOrEmpty(buffer)); DicConsole.WriteLine(); DicConsole.WriteLine("Choose what to do:"); DicConsole.WriteLine("1.- Print buffer."); @@ -761,7 +769,7 @@ namespace DiscImageChef.Tests.Devices.ATA return; case 1: System.Console.Clear(); - DicConsole.WriteLine("Device: {0}", devPath); + DicConsole.WriteLine("Device: {0}", devPath); DicConsole.WriteLine("READ SECTORS {0}response:", retries ? "WITH RETRIES " : ""); if(buffer != null) PrintHex.PrintHexArray(buffer, 64); DicConsole.WriteLine("Press any key to continue..."); @@ -771,7 +779,7 @@ namespace DiscImageChef.Tests.Devices.ATA goto menu; case 2: System.Console.Clear(); - DicConsole.WriteLine("Device: {0}", devPath); + DicConsole.WriteLine("Device: {0}", devPath); DicConsole.WriteLine("READ SECTORS {0}status registers:", retries ? "WITH RETRIES " : ""); DicConsole.Write("{0}", MainClass.DecodeAtaRegisters(errorRegisters)); DicConsole.WriteLine("Press any key to continue..."); @@ -792,10 +800,10 @@ namespace DiscImageChef.Tests.Devices.ATA static void Seek(string devPath, Device dev) { ushort cylinder = 0; - byte head = 0; - byte sector = 1; + byte head = 0; + byte sector = 1; string strDev; - int item; + int item; parameters: while(true) @@ -804,8 +812,8 @@ namespace DiscImageChef.Tests.Devices.ATA DicConsole.WriteLine("Device: {0}", devPath); DicConsole.WriteLine("Parameters for SEEK command:"); DicConsole.WriteLine("Cylinder: {0}", cylinder); - DicConsole.WriteLine("Head: {0}", head); - DicConsole.WriteLine("Sector: {0}", sector); + DicConsole.WriteLine("Head: {0}", head); + DicConsole.WriteLine("Sector: {0}", sector); DicConsole.WriteLine(); DicConsole.WriteLine("Choose what to do:"); DicConsole.WriteLine("1.- Change parameters."); @@ -851,6 +859,7 @@ namespace DiscImageChef.Tests.Devices.ATA DicConsole.WriteLine("Head cannot be bigger than 15. Setting it to 15..."); head = 15; } + DicConsole.Write("What sector?: "); strDev = System.Console.ReadLine(); if(!byte.TryParse(strDev, out sector)) @@ -874,7 +883,7 @@ namespace DiscImageChef.Tests.Devices.ATA DicConsole.WriteLine("Device: {0}", devPath); DicConsole.WriteLine("Sending SEEK to the device:"); DicConsole.WriteLine("Command took {0} ms.", duration); - DicConsole.WriteLine("Sense is {0}.", sense); + DicConsole.WriteLine("Sense is {0}.", sense); DicConsole.WriteLine(); DicConsole.WriteLine("Choose what to do:"); DicConsole.WriteLine("1.- Decode error registers."); @@ -916,5 +925,156 @@ namespace DiscImageChef.Tests.Devices.ATA goto menu; } } + + static void SetFeatures(string devPath, Device dev) + { + ushort cylinder = 0; + byte head = 0; + byte sector = 0; + byte feature = 0; + byte sectorCount = 0; + string strDev; + int item; + + parameters: + while(true) + { + System.Console.Clear(); + DicConsole.WriteLine("Device: {0}", devPath); + DicConsole.WriteLine("Parameters for SET FEATURES command:"); + DicConsole.WriteLine("Cylinder: {0}", cylinder); + DicConsole.WriteLine("Head: {0}", head); + DicConsole.WriteLine("Sector: {0}", sector); + DicConsole.WriteLine("Sector count: {0}", sectorCount); + DicConsole.WriteLine("Feature: 0x{0:X2}", feature); + DicConsole.WriteLine(); + DicConsole.WriteLine("Choose what to do:"); + DicConsole.WriteLine("1.- Change parameters."); + DicConsole.WriteLine("2.- Send command with these parameters."); + DicConsole.WriteLine("0.- Return to CHS ATA commands menu."); + + strDev = System.Console.ReadLine(); + if(!int.TryParse(strDev, out item)) + { + DicConsole.WriteLine("Not a number. Press any key to continue..."); + System.Console.ReadKey(); + continue; + } + + switch(item) + { + case 0: + DicConsole.WriteLine("Returning to CHS ATA commands menu..."); + return; + case 1: + DicConsole.Write("What cylinder?: "); + strDev = System.Console.ReadLine(); + if(!ushort.TryParse(strDev, out cylinder)) + { + DicConsole.WriteLine("Not a number. Press any key to continue..."); + cylinder = 0; + System.Console.ReadKey(); + continue; + } + + DicConsole.Write("What head?: "); + strDev = System.Console.ReadLine(); + if(!byte.TryParse(strDev, out head)) + { + DicConsole.WriteLine("Not a number. Press any key to continue..."); + head = 0; + System.Console.ReadKey(); + continue; + } + + if(head > 15) + { + DicConsole.WriteLine("Head cannot be bigger than 15. Setting it to 15..."); + head = 15; + } + + DicConsole.Write("What sector?: "); + strDev = System.Console.ReadLine(); + if(!byte.TryParse(strDev, out sector)) + { + DicConsole.WriteLine("Not a number. Press any key to continue..."); + sector = 0; + System.Console.ReadKey(); + } + + DicConsole.Write("What sector count?: "); + strDev = System.Console.ReadLine(); + if(!byte.TryParse(strDev, out sectorCount)) + { + DicConsole.WriteLine("Not a number. Press any key to continue..."); + sectorCount = 0; + System.Console.ReadKey(); + } + + DicConsole.Write("What feature?: "); + strDev = System.Console.ReadLine(); + if(!byte.TryParse(strDev, out feature)) + { + DicConsole.WriteLine("Not a number. Press any key to continue..."); + feature = 0; + System.Console.ReadKey(); + } + + break; + case 2: goto start; + } + } + + start: + System.Console.Clear(); + bool sense = dev.Seek(out AtaErrorRegistersChs errorRegisters, cylinder, head, sector, dev.Timeout, + out double duration); + + menu: + DicConsole.WriteLine("Device: {0}", devPath); + DicConsole.WriteLine("Sending SET FEATURES to the device:"); + DicConsole.WriteLine("Command took {0} ms.", duration); + DicConsole.WriteLine("Sense is {0}.", sense); + DicConsole.WriteLine(); + DicConsole.WriteLine("Choose what to do:"); + DicConsole.WriteLine("1.- Decode error registers."); + DicConsole.WriteLine("2.- Send command again."); + DicConsole.WriteLine("3.- Change parameters."); + DicConsole.WriteLine("0.- Return to CHS ATA commands menu."); + DicConsole.Write("Choose: "); + + strDev = System.Console.ReadLine(); + if(!int.TryParse(strDev, out item)) + { + DicConsole.WriteLine("Not a number. Press any key to continue..."); + System.Console.ReadKey(); + System.Console.Clear(); + goto menu; + } + + switch(item) + { + case 0: + DicConsole.WriteLine("Returning to CHS ATA commands menu..."); + return; + case 1: + System.Console.Clear(); + DicConsole.WriteLine("Device: {0}", devPath); + DicConsole.WriteLine("SET FEATURES status registers:"); + DicConsole.Write("{0}", MainClass.DecodeAtaRegisters(errorRegisters)); + DicConsole.WriteLine("Press any key to continue..."); + System.Console.ReadKey(); + System.Console.Clear(); + DicConsole.WriteLine("Device: {0}", devPath); + goto menu; + case 2: goto start; + case 3: goto parameters; + default: + DicConsole.WriteLine("Incorrect option. Press any key to continue..."); + System.Console.ReadKey(); + System.Console.Clear(); + goto menu; + } + } } } \ No newline at end of file