🐛Fix sending READ LONG commands to ATA devices, thanks to supporting SET FEATURES command.

This commit is contained in:
2018-01-21 21:56:09 +00:00
parent bc06e19fd9
commit 9dff1f8a54
5 changed files with 936 additions and 454 deletions

View File

@@ -110,391 +110,469 @@ namespace DiscImageChef.Core.Devices.Report
report.ATA.AdditionalPID = ataId.AdditionalPID;
report.ATA.AdditionalPIDSpecified = true;
}
if(ataId.APIOSupported != 0)
{
report.ATA.APIOSupported = ataId.APIOSupported;
report.ATA.APIOSupportedSpecified = true;
}
if(ataId.BufferType != 0)
{
report.ATA.BufferType = ataId.BufferType;
report.ATA.BufferTypeSpecified = true;
}
if(ataId.BufferSize != 0)
{
report.ATA.BufferSize = ataId.BufferSize;
report.ATA.BufferSizeSpecified = true;
}
if(ataId.Capabilities != 0)
{
report.ATA.Capabilities = ataId.Capabilities;
report.ATA.CapabilitiesSpecified = true;
}
if(ataId.Capabilities2 != 0)
{
report.ATA.Capabilities2 = ataId.Capabilities2;
report.ATA.Capabilities2Specified = true;
}
if(ataId.Capabilities3 != 0)
{
report.ATA.Capabilities3 = ataId.Capabilities3;
report.ATA.Capabilities3Specified = true;
}
if(ataId.CFAPowerMode != 0)
{
report.ATA.CFAPowerMode = ataId.CFAPowerMode;
report.ATA.CFAPowerModeSpecified = true;
}
if(ataId.CommandSet != 0)
{
report.ATA.CommandSet = ataId.CommandSet;
report.ATA.CommandSetSpecified = true;
}
if(ataId.CommandSet2 != 0)
{
report.ATA.CommandSet2 = ataId.CommandSet2;
report.ATA.CommandSet2Specified = true;
}
if(ataId.CommandSet3 != 0)
{
report.ATA.CommandSet3 = ataId.CommandSet3;
report.ATA.CommandSet3Specified = true;
}
if(ataId.CommandSet4 != 0)
{
report.ATA.CommandSet4 = ataId.CommandSet4;
report.ATA.CommandSet4Specified = true;
}
if(ataId.CommandSet5 != 0)
{
report.ATA.CommandSet5 = ataId.CommandSet5;
report.ATA.CommandSet5Specified = true;
}
if(ataId.CurrentAAM != 0)
{
report.ATA.CurrentAAM = ataId.CurrentAAM;
report.ATA.CurrentAAMSpecified = true;
}
if(ataId.CurrentAPM != 0)
{
report.ATA.CurrentAPM = ataId.CurrentAPM;
report.ATA.CurrentAPMSpecified = true;
}
if(ataId.DataSetMgmt != 0)
{
report.ATA.DataSetMgmt = ataId.DataSetMgmt;
report.ATA.DataSetMgmtSpecified = true;
}
if(ataId.DataSetMgmtSize != 0)
{
report.ATA.DataSetMgmtSize = ataId.DataSetMgmtSize;
report.ATA.DataSetMgmtSizeSpecified = true;
}
if(ataId.DeviceFormFactor != 0)
{
report.ATA.DeviceFormFactor = ataId.DeviceFormFactor;
report.ATA.DeviceFormFactorSpecified = true;
}
if(ataId.DMAActive != 0)
{
report.ATA.DMAActive = ataId.DMAActive;
report.ATA.DMAActiveSpecified = true;
}
if(ataId.DMASupported != 0)
{
report.ATA.DMASupported = ataId.DMASupported;
report.ATA.DMASupportedSpecified = true;
}
if(ataId.DMATransferTimingMode != 0)
{
report.ATA.DMATransferTimingMode = ataId.DMATransferTimingMode;
report.ATA.DMATransferTimingModeSpecified = true;
}
if(ataId.EnhancedSecurityEraseTime != 0)
{
report.ATA.EnhancedSecurityEraseTime = ataId.EnhancedSecurityEraseTime;
report.ATA.EnhancedSecurityEraseTimeSpecified = true;
}
if(ataId.EnabledCommandSet != 0)
{
report.ATA.EnabledCommandSet = ataId.EnabledCommandSet;
report.ATA.EnabledCommandSetSpecified = true;
}
if(ataId.EnabledCommandSet2 != 0)
{
report.ATA.EnabledCommandSet2 = ataId.EnabledCommandSet2;
report.ATA.EnabledCommandSet2Specified = true;
}
if(ataId.EnabledCommandSet3 != 0)
{
report.ATA.EnabledCommandSet3 = ataId.EnabledCommandSet3;
report.ATA.EnabledCommandSet3Specified = true;
}
if(ataId.EnabledCommandSet4 != 0)
{
report.ATA.EnabledCommandSet4 = ataId.EnabledCommandSet4;
report.ATA.EnabledCommandSet4Specified = true;
}
if(ataId.EnabledSATAFeatures != 0)
{
report.ATA.EnabledSATAFeatures = ataId.EnabledSATAFeatures;
report.ATA.EnabledSATAFeaturesSpecified = true;
}
if(ataId.ExtendedUserSectors != 0)
{
report.ATA.ExtendedUserSectors = ataId.ExtendedUserSectors;
report.ATA.ExtendedUserSectorsSpecified = true;
}
if(ataId.FreeFallSensitivity != 0)
{
report.ATA.FreeFallSensitivity = ataId.FreeFallSensitivity;
report.ATA.FreeFallSensitivitySpecified = true;
}
if(!string.IsNullOrWhiteSpace(ataId.FirmwareRevision))
{
report.ATA.FirmwareRevision = ataId.FirmwareRevision;
report.ATA.FirmwareRevisionSpecified = true;
}
if(ataId.GeneralConfiguration != 0)
{
report.ATA.GeneralConfiguration = ataId.GeneralConfiguration;
report.ATA.GeneralConfigurationSpecified = true;
}
if(ataId.HardwareResetResult != 0)
{
report.ATA.HardwareResetResult = ataId.HardwareResetResult;
report.ATA.HardwareResetResultSpecified = true;
}
if(ataId.InterseekDelay != 0)
{
report.ATA.InterseekDelay = ataId.InterseekDelay;
report.ATA.InterseekDelaySpecified = true;
}
if(ataId.MajorVersion != 0)
{
report.ATA.MajorVersion = ataId.MajorVersion;
report.ATA.MajorVersionSpecified = true;
}
if(ataId.MasterPasswordRevisionCode != 0)
{
report.ATA.MasterPasswordRevisionCode = ataId.MasterPasswordRevisionCode;
report.ATA.MasterPasswordRevisionCodeSpecified = true;
}
if(ataId.MaxDownloadMicroMode3 != 0)
{
report.ATA.MaxDownloadMicroMode3 = ataId.MaxDownloadMicroMode3;
report.ATA.MaxDownloadMicroMode3Specified = true;
}
if(ataId.MaxQueueDepth != 0)
{
report.ATA.MaxQueueDepth = ataId.MaxQueueDepth;
report.ATA.MaxQueueDepthSpecified = true;
}
if(ataId.MDMAActive != 0)
{
report.ATA.MDMAActive = ataId.MDMAActive;
report.ATA.MDMAActiveSpecified = true;
}
if(ataId.MDMASupported != 0)
{
report.ATA.MDMASupported = ataId.MDMASupported;
report.ATA.MDMASupportedSpecified = true;
}
if(ataId.MinDownloadMicroMode3 != 0)
{
report.ATA.MinDownloadMicroMode3 = ataId.MinDownloadMicroMode3;
report.ATA.MinDownloadMicroMode3Specified = true;
}
if(ataId.MinMDMACycleTime != 0)
{
report.ATA.MinMDMACycleTime = ataId.MinMDMACycleTime;
report.ATA.MinMDMACycleTimeSpecified = true;
}
if(ataId.MinorVersion != 0)
{
report.ATA.MinorVersion = ataId.MinorVersion;
report.ATA.MinorVersionSpecified = true;
}
if(ataId.MinPIOCycleTimeNoFlow != 0)
{
report.ATA.MinPIOCycleTimeNoFlow = ataId.MinPIOCycleTimeNoFlow;
report.ATA.MinPIOCycleTimeNoFlowSpecified = true;
}
if(ataId.MinPIOCycleTimeFlow != 0)
{
report.ATA.MinPIOCycleTimeFlow = ataId.MinPIOCycleTimeFlow;
report.ATA.MinPIOCycleTimeFlowSpecified = true;
}
if(!string.IsNullOrWhiteSpace(ataId.Model))
{
report.ATA.Model = ataId.Model;
report.ATA.ModelSpecified = true;
}
if(ataId.MultipleMaxSectors != 0)
{
report.ATA.MultipleMaxSectors = ataId.MultipleMaxSectors;
report.ATA.MultipleMaxSectorsSpecified = true;
}
if(ataId.MultipleSectorNumber != 0)
{
report.ATA.MultipleSectorNumber = ataId.MultipleSectorNumber;
report.ATA.MultipleSectorNumberSpecified = true;
}
if(ataId.NVCacheCaps != 0)
{
report.ATA.NVCacheCaps = ataId.NVCacheCaps;
report.ATA.NVCacheCapsSpecified = true;
}
if(ataId.NVCacheSize != 0)
{
report.ATA.NVCacheSize = ataId.NVCacheSize;
report.ATA.NVCacheSizeSpecified = true;
}
if(ataId.NVCacheWriteSpeed != 0)
{
report.ATA.NVCacheWriteSpeed = ataId.NVCacheWriteSpeed;
report.ATA.NVCacheWriteSpeedSpecified = true;
}
if(ataId.NVEstimatedSpinUp != 0)
{
report.ATA.NVEstimatedSpinUp = ataId.NVEstimatedSpinUp;
report.ATA.NVEstimatedSpinUpSpecified = true;
}
if(ataId.PacketBusRelease != 0)
{
report.ATA.PacketBusRelease = ataId.PacketBusRelease;
report.ATA.PacketBusReleaseSpecified = true;
}
if(ataId.PIOTransferTimingMode != 0)
{
report.ATA.PIOTransferTimingMode = ataId.PIOTransferTimingMode;
report.ATA.PIOTransferTimingModeSpecified = true;
}
if(ataId.RecommendedAAM != 0)
{
report.ATA.RecommendedAAM = ataId.RecommendedAAM;
report.ATA.RecommendedAAMSpecified = true;
}
if(ataId.RecMDMACycleTime != 0)
{
report.ATA.RecommendedMDMACycleTime = ataId.RecMDMACycleTime;
report.ATA.RecommendedMDMACycleTimeSpecified = true;
}
if(ataId.RemovableStatusSet != 0)
{
report.ATA.RemovableStatusSet = ataId.RemovableStatusSet;
report.ATA.RemovableStatusSetSpecified = true;
}
if(ataId.SATACapabilities != 0)
{
report.ATA.SATACapabilities = ataId.SATACapabilities;
report.ATA.SATACapabilitiesSpecified = true;
}
if(ataId.SATACapabilities2 != 0)
{
report.ATA.SATACapabilities2 = ataId.SATACapabilities2;
report.ATA.SATACapabilities2Specified = true;
}
if(ataId.SATAFeatures != 0)
{
report.ATA.SATAFeatures = ataId.SATAFeatures;
report.ATA.SATAFeaturesSpecified = true;
}
if(ataId.SCTCommandTransport != 0)
{
report.ATA.SCTCommandTransport = ataId.SCTCommandTransport;
report.ATA.SCTCommandTransportSpecified = true;
}
if(ataId.SectorsPerCard != 0)
{
report.ATA.SectorsPerCard = ataId.SectorsPerCard;
report.ATA.SectorsPerCardSpecified = true;
}
if(ataId.SecurityEraseTime != 0)
{
report.ATA.SecurityEraseTime = ataId.SecurityEraseTime;
report.ATA.SecurityEraseTimeSpecified = true;
}
if(ataId.SecurityStatus != 0)
{
report.ATA.SecurityStatus = ataId.SecurityStatus;
report.ATA.SecurityStatusSpecified = true;
}
if(ataId.ServiceBusyClear != 0)
{
report.ATA.ServiceBusyClear = ataId.ServiceBusyClear;
report.ATA.ServiceBusyClearSpecified = true;
}
if(ataId.SpecificConfiguration != 0)
{
report.ATA.SpecificConfiguration = ataId.SpecificConfiguration;
report.ATA.SpecificConfigurationSpecified = true;
}
if(ataId.StreamAccessLatency != 0)
{
report.ATA.StreamAccessLatency = ataId.StreamAccessLatency;
report.ATA.StreamAccessLatencySpecified = true;
}
if(ataId.StreamMinReqSize != 0)
{
report.ATA.StreamMinReqSize = ataId.StreamMinReqSize;
report.ATA.StreamMinReqSizeSpecified = true;
}
if(ataId.StreamPerformanceGranularity != 0)
{
report.ATA.StreamPerformanceGranularity = ataId.StreamPerformanceGranularity;
report.ATA.StreamPerformanceGranularitySpecified = true;
}
if(ataId.StreamTransferTimeDMA != 0)
{
report.ATA.StreamTransferTimeDMA = ataId.StreamTransferTimeDMA;
report.ATA.StreamTransferTimeDMASpecified = true;
}
if(ataId.StreamTransferTimePIO != 0)
{
report.ATA.StreamTransferTimePIO = ataId.StreamTransferTimePIO;
report.ATA.StreamTransferTimePIOSpecified = true;
}
if(ataId.TransportMajorVersion != 0)
{
report.ATA.TransportMajorVersion = ataId.TransportMajorVersion;
report.ATA.TransportMajorVersionSpecified = true;
}
if(ataId.TransportMinorVersion != 0)
{
report.ATA.TransportMinorVersion = ataId.TransportMinorVersion;
report.ATA.TransportMinorVersionSpecified = true;
}
if(ataId.TrustedComputing != 0)
{
report.ATA.TrustedComputing = ataId.TrustedComputing;
report.ATA.TrustedComputingSpecified = true;
}
if(ataId.UDMAActive != 0)
{
report.ATA.UDMAActive = ataId.UDMAActive;
report.ATA.UDMAActiveSpecified = true;
}
if(ataId.UDMASupported != 0)
{
report.ATA.UDMASupported = ataId.UDMASupported;
report.ATA.UDMASupportedSpecified = true;
}
if(ataId.WRVMode != 0)
{
report.ATA.WRVMode = ataId.WRVMode;
report.ATA.WRVModeSpecified = true;
}
if(ataId.WRVSectorCountMode3 != 0)
{
report.ATA.WRVSectorCountMode3 = ataId.WRVSectorCountMode3;
report.ATA.WRVSectorCountMode3Specified = true;
}
if(ataId.WRVSectorCountMode2 != 0)
{
report.ATA.WRVSectorCountMode2 = ataId.WRVSectorCountMode2;
report.ATA.WRVSectorCountMode2Specified = true;
}
if(debug) report.ATA.Identify = buffer;
if(removable)
@@ -539,6 +617,7 @@ namespace DiscImageChef.Core.Devices.Report
mediaTest.UnformattedBPT = ataId.UnformattedBPT;
mediaTest.UnformattedBPTSpecified = true;
}
if(ataId.UnformattedBPS != 0)
{
mediaTest.UnformattedBPS = ataId.UnformattedBPS;
@@ -608,11 +687,14 @@ namespace DiscImageChef.Core.Devices.Report
if((ataId.PhysLogSectorSize & 0x1000) == 0x1000)
if(ataId.LogicalSectorWords <= 255 || ataId.LogicalAlignment == 0xFFFF)
logicalsectorsize = 512;
else logicalsectorsize = ataId.LogicalSectorWords * 2;
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
@@ -697,7 +779,8 @@ 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;
DicConsole.DebugWriteLine("ATA Report",
@@ -708,7 +791,8 @@ 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;
DicConsole.DebugWriteLine("ATA Report",
@@ -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);
@@ -736,7 +822,8 @@ namespace DiscImageChef.Core.Devices.Report
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;
DicConsole.DebugWriteLine("ATA Report",
@@ -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,7 +847,8 @@ 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;
DicConsole.DebugWriteLine("ATA Report",
@@ -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",
@@ -786,9 +877,11 @@ namespace DiscImageChef.Core.Devices.Report
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);
@@ -799,7 +892,8 @@ namespace DiscImageChef.Core.Devices.Report
DicConsole.WriteLine("Trying READ DMA in LBA48 mode...");
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,6 +901,31 @@ 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 _);
@@ -837,7 +956,8 @@ 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 &&
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}",
@@ -875,6 +995,7 @@ namespace DiscImageChef.Core.Devices.Report
report.ATA.ReadCapabilities.UnformattedBPT = ataId.UnformattedBPT;
report.ATA.ReadCapabilities.UnformattedBPTSpecified = true;
}
if(ataId.UnformattedBPS != 0)
{
report.ATA.ReadCapabilities.UnformattedBPS = ataId.UnformattedBPS;
@@ -889,7 +1010,8 @@ namespace DiscImageChef.Core.Devices.Report
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;
}
@@ -941,11 +1063,14 @@ 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;
if(ataId.LogicalSectorWords <= 255 || ataId.LogicalAlignment == 0xFFFF)
logicalsectorsize = 512;
else
logicalsectorsize = ataId.LogicalSectorWords * 2;
else logicalsectorsize = 512;
if((ataId.PhysLogSectorSize & 0x2000) == 0x2000)
if((ataId.PhysLogSectorSize & 0x2000) ==
0x2000)
physicalsectorsize = logicalsectorsize * (uint)Math.Pow(2, ataId.PhysLogSectorSize & 0xF);
else physicalsectorsize = logicalsectorsize;
}
@@ -964,7 +1089,8 @@ namespace DiscImageChef.Core.Devices.Report
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;
}
}
@@ -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",
@@ -1071,7 +1200,8 @@ namespace DiscImageChef.Core.Devices.Report
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",
@@ -1122,7 +1255,8 @@ namespace DiscImageChef.Core.Devices.Report
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,6 +1278,32 @@ 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 _);

View File

@@ -87,7 +87,8 @@ namespace DiscImageChef.Devices
AtaRegistersChs registers = new AtaRegistersChs {Command = (byte)AtaCommands.IdentifyDevice};
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn,
AtaTransferRegister.NoTransfer, ref buffer, timeout, false, out duration,
AtaTransferRegister.NoTransfer, ref buffer, timeout, false,
out duration,
out bool sense);
Error = LastError != 0;
@@ -96,14 +97,17 @@ 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];
AtaRegistersChs registers = new AtaRegistersChs
@@ -116,7 +120,8 @@ namespace DiscImageChef.Devices
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,7 +131,8 @@ 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];
AtaRegistersChs registers = new AtaRegistersChs
@@ -140,7 +146,8 @@ namespace DiscImageChef.Devices
};
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn,
AtaTransferRegister.SectorCount, ref buffer, timeout, true, out duration,
AtaTransferRegister.SectorCount, ref buffer, timeout, true,
out duration,
out bool sense);
Error = LastError != 0;
@@ -150,13 +157,15 @@ 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];
AtaRegistersChs registers = new AtaRegistersChs
@@ -170,7 +179,8 @@ namespace DiscImageChef.Devices
};
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn,
AtaTransferRegister.SectorCount, ref buffer, timeout, true, out duration,
AtaTransferRegister.SectorCount, ref buffer, timeout, true,
out duration,
out bool sense);
Error = LastError != 0;
@@ -179,15 +189,18 @@ 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)
byte head, byte sector, uint blockSize, uint timeout,
out double duration)
{
buffer = new byte[blockSize];
AtaRegistersChs registers = new AtaRegistersChs
@@ -201,7 +214,8 @@ namespace DiscImageChef.Devices
};
LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn,
AtaTransferRegister.SectorCount, ref buffer, timeout, true, out duration,
AtaTransferRegister.SectorCount, 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;
}
}
}

View File

@@ -3818,6 +3818,107 @@ namespace DiscImageChef.Devices
ErrorSkipping
}
public enum AtaFeatures : byte
{
/// <summary>Enable 8-bit data transfers</summary>
Enable8Bit = 0x01,
/// <summary>Enable write cache</summary>
EnableWriteCache = 0x02,
/// <summary>Set transfer mode based on value in sector count register</summary>
SetTransferMode = 0x03,
/// <summary>Enable all automatic defect reassignment</summary>
EnableDefectReassignment = 0x04,
/// <summary>Enable advanced power management</summary>
EnableApm = 0x05,
/// <summary>Enable Power-Up In Standby feature set</summary>
EnablePowerUpInStandby = 0x06,
/// <summary>Power-Up In Standby feature set device spin-up</summary>
PowerUpInStandByFeature = 0x07,
/// <summary>Reserved for Address offset reserved area boot method technical report</summary>
AddressOffsetReserved = 0x09,
/// <summary>Enable CFA power mode 1</summary>
EnableCfaPowerMode1 = 0x0A,
/// <summary>Enable Write-Read-Verify feature set</summary>
EnableWriteReadVerify = 0x0B,
/// <summary>Enable use of SATA feature</summary>
EnableSataFeature = 0x10,
/// <summary>Disable Media Status Notification</summary>
DisableMediaStatusNotification = 0x31,
/// <summary>Disable retry</summary>
DisableRetry = 0x33,
/// <summary>Enable Free-fall Control</summary>
EnableFreeFall = 0x41,
/// <summary>Enable Automatic Acoustic Management feature set</summary>
EnableAam = 0x42,
/// <summary>Set Maximum Host Interface Sector Times</summary>
SetMaximumHostInterfaceSectorTimes = 0x43,
/// <summary>Vendor unique length of ECC on read long/write long commands</summary>
EnableReadLongVendorLength = 0x44,
/// <summary>Extended Power conditions</summary>
ExtendedPowerConditions = 0x4A,
/// <summary>Set cache segments to sector count register value</summary>
SetCacheSegments = 0x54,
/// <summary>Disable read look-ahead feature</summary>
DisableReadLookAhead = 0x55,
/// <summary>Enable release interrupt</summary>
EnableReleaseInterrupt = 0x5D,
/// <summary>Enable SERVICE interrupt</summary>
EnableServiceInterrupt = 0x5E,
/// <summary>Long Physical Sector Alignment Error Reporting Control</summary>
LongPhysicalSectorErrorControl = 0x62,
/// <summary>Enable/Disable the DSN feature set</summary>
DsnFeature = 0x63,
/// <summary>Disable reverting to power on defaults</summary>
DisableRevertToDefaults = 0x66,
/// <summary>Disable ECC</summary>
DisableEcc = 0x77,
/// <summary>Disable 8-bit data transfers</summary>
Disable8Bit = 0x81,
/// <summary>Disable write cache</summary>
DisableWriteCache = 0x82,
/// <summary>Disable all automatic defect reassignment</summary>
DisableDefectReassignment = 0x84,
/// <summary>Disable advanced power management</summary>
DisableApm = 0x85,
/// <summary>Disable Power-Up In Standby feature set</summary>
DisablePowerUpInStandby = 0x86,
/// <summary>Enable ECC</summary>
EnableEcc = 0x88,
/// <summary>Reserved for Address offset reserved area boot method technical report</summary>
AddressOffsetReserved2 = 0x89,
/// <summary>Disable CFA power mode 1</summary>
DisableCfaPowerMode1 = 0x8A,
/// <summary>Disable Write-Read-Verify feature set</summary>
DisableWriteReadVerify = 0x8B,
/// <summary>Disable use of SATA feature</summary>
DisableSataFeature = 0x90,
/// <summary>Enable Media Status Notification</summary>
EnableMediaStatusNotification = 0x95,
/// <summary>Enable retries</summary>
EnableRetries = 0x99,
/// <summary>Set device maximum average current</summary>
SetMaximumAverageCurrent = 0x9A,
/// <summary>Enable read look-ahead feature</summary>
EnableReadLookAhead = 0xAA,
/// <summary>Set maximum prefetch using sector count register value</summary>
SetMaximumPrefetch = 0xAB,
/// <summary>4 bytes of ECC apply on read long/write long commands</summary>
DisableReadLongVendorLength = 0xBB,
/// <summary>Disable Free-fall Control</summary>
DisableFreeFall = 0xC1,
/// <summary>Disable Automatic Acoustic Management feature set</summary>
DisableAam = 0xC2,
/// <summary>Enable/Disable the Sense Data Reporting feature set</summary>
SenseDataReporting = 0xC3,
/// <summary>Enable reverting to power on defaults</summary>
EnableRevertToDefaults = 0xCC,
/// <summary>Disable release interrupt</summary>
DisableReleaseInterrupt = 0xDD,
/// <summary>Disable SERVICE interrupt</summary>
DisableServiceInterrupt = 0xDE,
VendorSpecific = 0xE0
}
public enum KreonLockStates : byte
{
Locked = 0,

View File

@@ -291,6 +291,7 @@ namespace DiscImageChef.Tests.Devices.ATA
0xFFFFFFF);
lba = 0xFFFFFFF;
}
DicConsole.Write("How many sectors?: ");
strDev = System.Console.ReadLine();
if(!byte.TryParse(strDev, out count))
@@ -422,6 +423,16 @@ namespace DiscImageChef.Tests.Devices.ATA
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;
}
@@ -544,6 +555,7 @@ namespace DiscImageChef.Tests.Devices.ATA
0xFFFFFFF);
lba = 0xFFFFFFF;
}
DicConsole.Write("How many sectors?: ");
strDev = System.Console.ReadLine();
if(!byte.TryParse(strDev, out count))
@@ -728,6 +740,7 @@ namespace DiscImageChef.Tests.Devices.ATA
0xFFFFFFF);
lba = 0xFFFFFFF;
}
DicConsole.Write("How many sectors?: ");
strDev = System.Console.ReadLine();
if(!byte.TryParse(strDev, out count))
@@ -857,6 +870,7 @@ namespace DiscImageChef.Tests.Devices.ATA
0xFFFFFFF);
lba = 0xFFFFFFF;
}
break;
case 2: goto start;
}

View File

@@ -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();
@@ -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))
@@ -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))
@@ -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))
@@ -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))
@@ -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))
@@ -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;
}
}
}
}