mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
REFACTOR: Possible 'System.InvalidOperationException'.
This commit is contained in:
@@ -83,225 +83,164 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
sense = dev.AtaIdentify(out byte[] cmdBuf, out AtaErrorRegistersCHS errorChs);
|
||||
if(!sense && Identify.Decode(cmdBuf).HasValue)
|
||||
{
|
||||
Identify.IdentifyDevice ataId = Identify.Decode(cmdBuf).Value;
|
||||
Identify.IdentifyDevice? ataIdNullable = Identify.Decode(cmdBuf);
|
||||
if(ataIdNullable != null) {
|
||||
Identify.IdentifyDevice ataId = ataIdNullable.Value;
|
||||
|
||||
CICMMetadataType sidecar =
|
||||
new CICMMetadataType {BlockMedia = new[] {new BlockMediaType()}};
|
||||
CICMMetadataType sidecar =
|
||||
new CICMMetadataType {BlockMedia = new[] {new BlockMediaType()}};
|
||||
|
||||
if(dev.IsUsb)
|
||||
{
|
||||
dumpLog.WriteLine("Reading USB descriptors.");
|
||||
sidecar.BlockMedia[0].USB = new USBType
|
||||
if(dev.IsUsb)
|
||||
{
|
||||
ProductID = dev.UsbProductId,
|
||||
VendorID = dev.UsbVendorId,
|
||||
Descriptors = new DumpType
|
||||
dumpLog.WriteLine("Reading USB descriptors.");
|
||||
sidecar.BlockMedia[0].USB = new USBType
|
||||
{
|
||||
Image = outputPrefix + ".usbdescriptors.bin",
|
||||
Size = dev.UsbDescriptors.Length,
|
||||
Checksums = Checksum.GetChecksums(dev.UsbDescriptors).ToArray()
|
||||
}
|
||||
};
|
||||
DataFile.WriteTo("ATA Dump", sidecar.BlockMedia[0].USB.Descriptors.Image, dev.UsbDescriptors);
|
||||
}
|
||||
|
||||
if(dev.IsPcmcia)
|
||||
{
|
||||
dumpLog.WriteLine("Reading PCMCIA CIS.");
|
||||
sidecar.BlockMedia[0].PCMCIA = new PCMCIAType
|
||||
{
|
||||
CIS = new DumpType
|
||||
{
|
||||
Image = outputPrefix + ".cis.bin",
|
||||
Size = dev.Cis.Length,
|
||||
Checksums = Checksum.GetChecksums(dev.Cis).ToArray()
|
||||
}
|
||||
};
|
||||
DataFile.WriteTo("ATA Dump", sidecar.BlockMedia[0].PCMCIA.CIS.Image, dev.Cis);
|
||||
dumpLog.WriteLine("Decoding PCMCIA CIS.");
|
||||
Tuple[] tuples = CIS.GetTuples(dev.Cis);
|
||||
if(tuples != null)
|
||||
foreach(Tuple tuple in tuples)
|
||||
switch(tuple.Code) {
|
||||
case TupleCodes.CISTPL_MANFID:
|
||||
ManufacturerIdentificationTuple manfid =
|
||||
CIS.DecodeManufacturerIdentificationTuple(tuple);
|
||||
|
||||
if(manfid != null)
|
||||
{
|
||||
sidecar.BlockMedia[0].PCMCIA.ManufacturerCode = manfid.ManufacturerID;
|
||||
sidecar.BlockMedia[0].PCMCIA.CardCode = manfid.CardID;
|
||||
sidecar.BlockMedia[0].PCMCIA.ManufacturerCodeSpecified = true;
|
||||
sidecar.BlockMedia[0].PCMCIA.CardCodeSpecified = true;
|
||||
}
|
||||
break;
|
||||
case TupleCodes.CISTPL_VERS_1:
|
||||
Level1VersionTuple vers = CIS.DecodeLevel1VersionTuple(tuple);
|
||||
|
||||
if(vers != null)
|
||||
{
|
||||
sidecar.BlockMedia[0].PCMCIA.Manufacturer = vers.Manufacturer;
|
||||
sidecar.BlockMedia[0].PCMCIA.ProductName = vers.Product;
|
||||
sidecar.BlockMedia[0].PCMCIA.Compliance =
|
||||
string.Format("{0}.{1}", vers.MajorVersion, vers.MinorVersion);
|
||||
sidecar.BlockMedia[0].PCMCIA.AdditionalInformation = vers.AdditionalInformation;
|
||||
}
|
||||
break;
|
||||
ProductID = dev.UsbProductId,
|
||||
VendorID = dev.UsbVendorId,
|
||||
Descriptors = new DumpType
|
||||
{
|
||||
Image = outputPrefix + ".usbdescriptors.bin",
|
||||
Size = dev.UsbDescriptors.Length,
|
||||
Checksums = Checksum.GetChecksums(dev.UsbDescriptors).ToArray()
|
||||
}
|
||||
}
|
||||
|
||||
sidecar.BlockMedia[0].ATA = new ATAType
|
||||
{
|
||||
Identify = new DumpType
|
||||
{
|
||||
Image = outputPrefix + ".identify.bin",
|
||||
Size = cmdBuf.Length,
|
||||
Checksums = Checksum.GetChecksums(cmdBuf).ToArray()
|
||||
}
|
||||
};
|
||||
DataFile.WriteTo("ATA Dump", sidecar.BlockMedia[0].ATA.Identify.Image, cmdBuf);
|
||||
|
||||
DateTime start;
|
||||
DateTime end;
|
||||
double totalDuration = 0;
|
||||
double totalChkDuration = 0;
|
||||
double currentSpeed = 0;
|
||||
double maxSpeed = double.MinValue;
|
||||
double minSpeed = double.MaxValue;
|
||||
Checksum dataChk;
|
||||
|
||||
aborted = false;
|
||||
System.Console.CancelKeyPress += (sender, e) => { e.Cancel = aborted = true; };
|
||||
|
||||
DataFile dumpFile;
|
||||
|
||||
// Initializate reader
|
||||
dumpLog.WriteLine("Initializing reader.");
|
||||
Reader ataReader = new Reader(dev, timeout, cmdBuf);
|
||||
// Fill reader blocks
|
||||
ulong blocks = ataReader.GetDeviceBlocks();
|
||||
// Check block sizes
|
||||
if(ataReader.GetBlockSize())
|
||||
{
|
||||
dumpLog.WriteLine("ERROR: Cannot get block size: {0}.", ataReader.ErrorMessage);
|
||||
DicConsole.ErrorWriteLine(ataReader.ErrorMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
uint blockSize = ataReader.LogicalBlockSize;
|
||||
uint physicalsectorsize = ataReader.PhysicalBlockSize;
|
||||
if(ataReader.FindReadCommand())
|
||||
{
|
||||
dumpLog.WriteLine("ERROR: Cannot find correct read command: {0}.", ataReader.ErrorMessage);
|
||||
DicConsole.ErrorWriteLine(ataReader.ErrorMessage);
|
||||
return;
|
||||
}
|
||||
// Check how many blocks to read, if error show and return
|
||||
if(ataReader.GetBlocksToRead())
|
||||
{
|
||||
dumpLog.WriteLine("ERROR: Cannot get blocks to read: {0}.", ataReader.ErrorMessage);
|
||||
DicConsole.ErrorWriteLine(ataReader.ErrorMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
uint blocksToRead = ataReader.BlocksToRead;
|
||||
ushort cylinders = ataReader.Cylinders;
|
||||
byte heads = ataReader.Heads;
|
||||
byte sectors = ataReader.Sectors;
|
||||
|
||||
dumpLog.WriteLine("Device reports {0} blocks ({1} bytes).", blocks, blocks * blockSize);
|
||||
dumpLog.WriteLine("Device reports {0} cylinders {1} heads {2} sectors per track.", cylinders, heads,
|
||||
sectors);
|
||||
dumpLog.WriteLine("Device can read {0} blocks at a time.", blocksToRead);
|
||||
dumpLog.WriteLine("Device reports {0} bytes per logical block.", blockSize);
|
||||
dumpLog.WriteLine("Device reports {0} bytes per physical block.", physicalsectorsize);
|
||||
|
||||
bool removable = false || !dev.IsCompactFlash &&
|
||||
ataId.GeneralConfiguration.HasFlag(Identify.GeneralConfigurationBit
|
||||
.Removable);
|
||||
DumpHardwareType currentTry = null;
|
||||
ExtentsULong extents = null;
|
||||
ResumeSupport.Process(ataReader.IsLba, removable, blocks, dev.Manufacturer, dev.Model, dev.Serial,
|
||||
dev.PlatformId, ref resume, ref currentTry, ref extents);
|
||||
if(currentTry == null || extents == null)
|
||||
throw new Exception("Could not process resume file, not continuing...");
|
||||
|
||||
if(ataReader.IsLba)
|
||||
{
|
||||
DicConsole.WriteLine("Reading {0} sectors at a time.", blocksToRead);
|
||||
|
||||
mhddLog = new MhddLog(outputPrefix + ".mhddlog.bin", dev, blocks, blockSize, blocksToRead);
|
||||
ibgLog = new IbgLog(outputPrefix + ".ibg", currentProfile);
|
||||
dumpFile = new DataFile(outputPrefix + ".bin");
|
||||
if(resume.NextBlock > 0) dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
|
||||
|
||||
dumpFile.Seek(resume.NextBlock, blockSize);
|
||||
|
||||
start = DateTime.UtcNow;
|
||||
for(ulong i = resume.NextBlock; i < blocks; i += blocksToRead)
|
||||
{
|
||||
if(aborted)
|
||||
{
|
||||
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
|
||||
dumpLog.WriteLine("Aborted!");
|
||||
break;
|
||||
}
|
||||
|
||||
if(blocks - i < blocksToRead) blocksToRead = (byte)(blocks - i);
|
||||
|
||||
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
|
||||
if(currentSpeed > maxSpeed && currentSpeed != 0) maxSpeed = currentSpeed;
|
||||
if(currentSpeed < minSpeed && currentSpeed != 0) minSpeed = currentSpeed;
|
||||
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
|
||||
|
||||
DicConsole.Write("\rReading sector {0} of {1} ({2:F3} MiB/sec.)", i, blocks, currentSpeed);
|
||||
|
||||
bool error = ataReader.ReadBlocks(out cmdBuf, i, blocksToRead, out duration);
|
||||
|
||||
if(!error)
|
||||
{
|
||||
mhddLog.Write(i, duration);
|
||||
ibgLog.Write(i, currentSpeed * 1024);
|
||||
dumpFile.Write(cmdBuf);
|
||||
extents.Add(i, blocksToRead, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(ulong b = i; b < i + blocksToRead; b++) resume.BadBlocks.Add(b);
|
||||
|
||||
if(duration < 500) mhddLog.Write(i, 65535);
|
||||
else mhddLog.Write(i, duration);
|
||||
|
||||
ibgLog.Write(i, 0);
|
||||
dumpFile.Write(new byte[blockSize * blocksToRead]);
|
||||
dumpLog.WriteLine("Error reading {0} blocks from block {1}.", blocksToRead, i);
|
||||
}
|
||||
|
||||
currentSpeed = (double)blockSize * blocksToRead / 1048576 / (duration / 1000);
|
||||
GC.Collect();
|
||||
resume.NextBlock = i + blocksToRead;
|
||||
};
|
||||
DataFile.WriteTo("ATA Dump", sidecar.BlockMedia[0].USB.Descriptors.Image, dev.UsbDescriptors);
|
||||
}
|
||||
|
||||
end = DateTime.Now;
|
||||
DicConsole.WriteLine();
|
||||
mhddLog.Close();
|
||||
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
|
||||
blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000),
|
||||
devicePath);
|
||||
dumpLog.WriteLine("Dump finished in {0} seconds.", (end - start).TotalSeconds);
|
||||
dumpLog.WriteLine("Average dump speed {0:F3} KiB/sec.",
|
||||
(double)blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000));
|
||||
|
||||
#region Error handling
|
||||
if(resume.BadBlocks.Count > 0 && !aborted)
|
||||
if(dev.IsPcmcia)
|
||||
{
|
||||
int pass = 0;
|
||||
bool forward = true;
|
||||
bool runningPersistent = false;
|
||||
dumpLog.WriteLine("Reading PCMCIA CIS.");
|
||||
sidecar.BlockMedia[0].PCMCIA = new PCMCIAType
|
||||
{
|
||||
CIS = new DumpType
|
||||
{
|
||||
Image = outputPrefix + ".cis.bin",
|
||||
Size = dev.Cis.Length,
|
||||
Checksums = Checksum.GetChecksums(dev.Cis).ToArray()
|
||||
}
|
||||
};
|
||||
DataFile.WriteTo("ATA Dump", sidecar.BlockMedia[0].PCMCIA.CIS.Image, dev.Cis);
|
||||
dumpLog.WriteLine("Decoding PCMCIA CIS.");
|
||||
Tuple[] tuples = CIS.GetTuples(dev.Cis);
|
||||
if(tuples != null)
|
||||
foreach(Tuple tuple in tuples)
|
||||
switch(tuple.Code) {
|
||||
case TupleCodes.CISTPL_MANFID:
|
||||
ManufacturerIdentificationTuple manfid =
|
||||
CIS.DecodeManufacturerIdentificationTuple(tuple);
|
||||
|
||||
repeatRetryLba:
|
||||
ulong[] tmpArray = resume.BadBlocks.ToArray();
|
||||
foreach(ulong badSector in tmpArray)
|
||||
if(manfid != null)
|
||||
{
|
||||
sidecar.BlockMedia[0].PCMCIA.ManufacturerCode = manfid.ManufacturerID;
|
||||
sidecar.BlockMedia[0].PCMCIA.CardCode = manfid.CardID;
|
||||
sidecar.BlockMedia[0].PCMCIA.ManufacturerCodeSpecified = true;
|
||||
sidecar.BlockMedia[0].PCMCIA.CardCodeSpecified = true;
|
||||
}
|
||||
break;
|
||||
case TupleCodes.CISTPL_VERS_1:
|
||||
Level1VersionTuple vers = CIS.DecodeLevel1VersionTuple(tuple);
|
||||
|
||||
if(vers != null)
|
||||
{
|
||||
sidecar.BlockMedia[0].PCMCIA.Manufacturer = vers.Manufacturer;
|
||||
sidecar.BlockMedia[0].PCMCIA.ProductName = vers.Product;
|
||||
sidecar.BlockMedia[0].PCMCIA.Compliance =
|
||||
string.Format("{0}.{1}", vers.MajorVersion, vers.MinorVersion);
|
||||
sidecar.BlockMedia[0].PCMCIA.AdditionalInformation = vers.AdditionalInformation;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sidecar.BlockMedia[0].ATA = new ATAType
|
||||
{
|
||||
Identify = new DumpType
|
||||
{
|
||||
Image = outputPrefix + ".identify.bin",
|
||||
Size = cmdBuf.Length,
|
||||
Checksums = Checksum.GetChecksums(cmdBuf).ToArray()
|
||||
}
|
||||
};
|
||||
DataFile.WriteTo("ATA Dump", sidecar.BlockMedia[0].ATA.Identify.Image, cmdBuf);
|
||||
|
||||
DateTime start;
|
||||
DateTime end;
|
||||
double totalDuration = 0;
|
||||
double totalChkDuration = 0;
|
||||
double currentSpeed = 0;
|
||||
double maxSpeed = double.MinValue;
|
||||
double minSpeed = double.MaxValue;
|
||||
Checksum dataChk;
|
||||
|
||||
aborted = false;
|
||||
System.Console.CancelKeyPress += (sender, e) => { e.Cancel = aborted = true; };
|
||||
|
||||
DataFile dumpFile;
|
||||
|
||||
// Initializate reader
|
||||
dumpLog.WriteLine("Initializing reader.");
|
||||
Reader ataReader = new Reader(dev, timeout, cmdBuf);
|
||||
// Fill reader blocks
|
||||
ulong blocks = ataReader.GetDeviceBlocks();
|
||||
// Check block sizes
|
||||
if(ataReader.GetBlockSize())
|
||||
{
|
||||
dumpLog.WriteLine("ERROR: Cannot get block size: {0}.", ataReader.ErrorMessage);
|
||||
DicConsole.ErrorWriteLine(ataReader.ErrorMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
uint blockSize = ataReader.LogicalBlockSize;
|
||||
uint physicalsectorsize = ataReader.PhysicalBlockSize;
|
||||
if(ataReader.FindReadCommand())
|
||||
{
|
||||
dumpLog.WriteLine("ERROR: Cannot find correct read command: {0}.", ataReader.ErrorMessage);
|
||||
DicConsole.ErrorWriteLine(ataReader.ErrorMessage);
|
||||
return;
|
||||
}
|
||||
// Check how many blocks to read, if error show and return
|
||||
if(ataReader.GetBlocksToRead())
|
||||
{
|
||||
dumpLog.WriteLine("ERROR: Cannot get blocks to read: {0}.", ataReader.ErrorMessage);
|
||||
DicConsole.ErrorWriteLine(ataReader.ErrorMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
uint blocksToRead = ataReader.BlocksToRead;
|
||||
ushort cylinders = ataReader.Cylinders;
|
||||
byte heads = ataReader.Heads;
|
||||
byte sectors = ataReader.Sectors;
|
||||
|
||||
dumpLog.WriteLine("Device reports {0} blocks ({1} bytes).", blocks, blocks * blockSize);
|
||||
dumpLog.WriteLine("Device reports {0} cylinders {1} heads {2} sectors per track.", cylinders, heads,
|
||||
sectors);
|
||||
dumpLog.WriteLine("Device can read {0} blocks at a time.", blocksToRead);
|
||||
dumpLog.WriteLine("Device reports {0} bytes per logical block.", blockSize);
|
||||
dumpLog.WriteLine("Device reports {0} bytes per physical block.", physicalsectorsize);
|
||||
|
||||
bool removable = false || !dev.IsCompactFlash &&
|
||||
ataId.GeneralConfiguration.HasFlag(Identify.GeneralConfigurationBit
|
||||
.Removable);
|
||||
DumpHardwareType currentTry = null;
|
||||
ExtentsULong extents = null;
|
||||
ResumeSupport.Process(ataReader.IsLba, removable, blocks, dev.Manufacturer, dev.Model, dev.Serial,
|
||||
dev.PlatformId, ref resume, ref currentTry, ref extents);
|
||||
if(currentTry == null || extents == null)
|
||||
throw new Exception("Could not process resume file, not continuing...");
|
||||
|
||||
if(ataReader.IsLba)
|
||||
{
|
||||
DicConsole.WriteLine("Reading {0} sectors at a time.", blocksToRead);
|
||||
|
||||
mhddLog = new MhddLog(outputPrefix + ".mhddlog.bin", dev, blocks, blockSize, blocksToRead);
|
||||
ibgLog = new IbgLog(outputPrefix + ".ibg", currentProfile);
|
||||
dumpFile = new DataFile(outputPrefix + ".bin");
|
||||
if(resume.NextBlock > 0) dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
|
||||
|
||||
dumpFile.Seek(resume.NextBlock, blockSize);
|
||||
|
||||
start = DateTime.UtcNow;
|
||||
for(ulong i = resume.NextBlock; i < blocks; i += blocksToRead)
|
||||
{
|
||||
if(aborted)
|
||||
{
|
||||
@@ -310,53 +249,61 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
break;
|
||||
}
|
||||
|
||||
DicConsole.Write("\rRetrying sector {0}, pass {1}, {3}{2}", badSector, pass + 1,
|
||||
forward ? "forward" : "reverse",
|
||||
runningPersistent ? "recovering partial data, " : "");
|
||||
if(blocks - i < blocksToRead) blocksToRead = (byte)(blocks - i);
|
||||
|
||||
bool error = ataReader.ReadBlock(out cmdBuf, badSector, out duration);
|
||||
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
|
||||
if(currentSpeed > maxSpeed && currentSpeed != 0) maxSpeed = currentSpeed;
|
||||
if(currentSpeed < minSpeed && currentSpeed != 0) minSpeed = currentSpeed;
|
||||
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
|
||||
|
||||
totalDuration += duration;
|
||||
DicConsole.Write("\rReading sector {0} of {1} ({2:F3} MiB/sec.)", i, blocks, currentSpeed);
|
||||
|
||||
bool error = ataReader.ReadBlocks(out cmdBuf, i, blocksToRead, out duration);
|
||||
|
||||
if(!error)
|
||||
{
|
||||
resume.BadBlocks.Remove(badSector);
|
||||
extents.Add(badSector);
|
||||
dumpFile.WriteAt(cmdBuf, badSector, blockSize);
|
||||
dumpLog.WriteLine("Correctly retried block {0} in pass {1}.", badSector, pass);
|
||||
mhddLog.Write(i, duration);
|
||||
ibgLog.Write(i, currentSpeed * 1024);
|
||||
dumpFile.Write(cmdBuf);
|
||||
extents.Add(i, blocksToRead, true);
|
||||
}
|
||||
else if(runningPersistent) dumpFile.WriteAt(cmdBuf, badSector, blockSize);
|
||||
}
|
||||
|
||||
if(pass < retryPasses && !aborted && resume.BadBlocks.Count > 0)
|
||||
{
|
||||
pass++;
|
||||
forward = !forward;
|
||||
resume.BadBlocks.Sort();
|
||||
resume.BadBlocks.Reverse();
|
||||
goto repeatRetryLba;
|
||||
else
|
||||
{
|
||||
for(ulong b = i; b < i + blocksToRead; b++) resume.BadBlocks.Add(b);
|
||||
|
||||
if(duration < 500) mhddLog.Write(i, 65535);
|
||||
else mhddLog.Write(i, duration);
|
||||
|
||||
ibgLog.Write(i, 0);
|
||||
dumpFile.Write(new byte[blockSize * blocksToRead]);
|
||||
dumpLog.WriteLine("Error reading {0} blocks from block {1}.", blocksToRead, i);
|
||||
}
|
||||
|
||||
currentSpeed = (double)blockSize * blocksToRead / 1048576 / (duration / 1000);
|
||||
GC.Collect();
|
||||
resume.NextBlock = i + blocksToRead;
|
||||
}
|
||||
|
||||
end = DateTime.Now;
|
||||
DicConsole.WriteLine();
|
||||
}
|
||||
#endregion Error handling LBA
|
||||
mhddLog.Close();
|
||||
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
|
||||
blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000),
|
||||
devicePath);
|
||||
dumpLog.WriteLine("Dump finished in {0} seconds.", (end - start).TotalSeconds);
|
||||
dumpLog.WriteLine("Average dump speed {0:F3} KiB/sec.",
|
||||
(double)blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000));
|
||||
|
||||
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
|
||||
}
|
||||
else
|
||||
{
|
||||
mhddLog = new MhddLog(outputPrefix + ".mhddlog.bin", dev, blocks, blockSize, blocksToRead);
|
||||
ibgLog = new IbgLog(outputPrefix + ".ibg", currentProfile);
|
||||
dumpFile = new DataFile(outputPrefix + ".bin");
|
||||
|
||||
ulong currentBlock = 0;
|
||||
blocks = (ulong)(cylinders * heads * sectors);
|
||||
start = DateTime.UtcNow;
|
||||
for(ushort cy = 0; cy < cylinders; cy++)
|
||||
{
|
||||
for(byte hd = 0; hd < heads; hd++)
|
||||
#region Error handling
|
||||
if(resume.BadBlocks.Count > 0 && !aborted)
|
||||
{
|
||||
for(byte sc = 1; sc < sectors; sc++)
|
||||
int pass = 0;
|
||||
bool forward = true;
|
||||
bool runningPersistent = false;
|
||||
|
||||
repeatRetryLba:
|
||||
ulong[] tmpArray = resume.BadBlocks.ToArray();
|
||||
foreach(ulong badSector in tmpArray)
|
||||
{
|
||||
if(aborted)
|
||||
{
|
||||
@@ -365,143 +312,233 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
break;
|
||||
}
|
||||
|
||||
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
|
||||
if(currentSpeed > maxSpeed && currentSpeed != 0) maxSpeed = currentSpeed;
|
||||
if(currentSpeed < minSpeed && currentSpeed != 0) minSpeed = currentSpeed;
|
||||
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
|
||||
DicConsole.Write("\rRetrying sector {0}, pass {1}, {3}{2}", badSector, pass + 1,
|
||||
forward ? "forward" : "reverse",
|
||||
runningPersistent ? "recovering partial data, " : "");
|
||||
|
||||
DicConsole.Write("\rReading cylinder {0} head {1} sector {2} ({3:F3} MiB/sec.)", cy, hd,
|
||||
sc, currentSpeed);
|
||||
|
||||
bool error = ataReader.ReadChs(out cmdBuf, cy, hd, sc, out duration);
|
||||
bool error = ataReader.ReadBlock(out cmdBuf, badSector, out duration);
|
||||
|
||||
totalDuration += duration;
|
||||
|
||||
if(!error)
|
||||
{
|
||||
mhddLog.Write(currentBlock, duration);
|
||||
ibgLog.Write(currentBlock, currentSpeed * 1024);
|
||||
dumpFile.Write(cmdBuf);
|
||||
extents.Add(currentBlock);
|
||||
dumpLog.WriteLine("Error reading cylinder {0} head {1} sector {2}.", cy, hd, sc);
|
||||
resume.BadBlocks.Remove(badSector);
|
||||
extents.Add(badSector);
|
||||
dumpFile.WriteAt(cmdBuf, badSector, blockSize);
|
||||
dumpLog.WriteLine("Correctly retried block {0} in pass {1}.", badSector, pass);
|
||||
}
|
||||
else
|
||||
else if(runningPersistent) dumpFile.WriteAt(cmdBuf, badSector, blockSize);
|
||||
}
|
||||
|
||||
if(pass < retryPasses && !aborted && resume.BadBlocks.Count > 0)
|
||||
{
|
||||
pass++;
|
||||
forward = !forward;
|
||||
resume.BadBlocks.Sort();
|
||||
resume.BadBlocks.Reverse();
|
||||
goto repeatRetryLba;
|
||||
}
|
||||
|
||||
DicConsole.WriteLine();
|
||||
}
|
||||
#endregion Error handling LBA
|
||||
|
||||
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
|
||||
}
|
||||
else
|
||||
{
|
||||
mhddLog = new MhddLog(outputPrefix + ".mhddlog.bin", dev, blocks, blockSize, blocksToRead);
|
||||
ibgLog = new IbgLog(outputPrefix + ".ibg", currentProfile);
|
||||
dumpFile = new DataFile(outputPrefix + ".bin");
|
||||
|
||||
ulong currentBlock = 0;
|
||||
blocks = (ulong)(cylinders * heads * sectors);
|
||||
start = DateTime.UtcNow;
|
||||
for(ushort cy = 0; cy < cylinders; cy++)
|
||||
{
|
||||
for(byte hd = 0; hd < heads; hd++)
|
||||
{
|
||||
for(byte sc = 1; sc < sectors; sc++)
|
||||
{
|
||||
resume.BadBlocks.Add(currentBlock);
|
||||
if(duration < 500) mhddLog.Write(currentBlock, 65535);
|
||||
else mhddLog.Write(currentBlock, duration);
|
||||
if(aborted)
|
||||
{
|
||||
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
|
||||
dumpLog.WriteLine("Aborted!");
|
||||
break;
|
||||
}
|
||||
|
||||
ibgLog.Write(currentBlock, 0);
|
||||
dumpFile.Write(new byte[blockSize]);
|
||||
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
|
||||
if(currentSpeed > maxSpeed && currentSpeed != 0) maxSpeed = currentSpeed;
|
||||
if(currentSpeed < minSpeed && currentSpeed != 0) minSpeed = currentSpeed;
|
||||
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
|
||||
|
||||
DicConsole.Write("\rReading cylinder {0} head {1} sector {2} ({3:F3} MiB/sec.)", cy, hd,
|
||||
sc, currentSpeed);
|
||||
|
||||
bool error = ataReader.ReadChs(out cmdBuf, cy, hd, sc, out duration);
|
||||
|
||||
totalDuration += duration;
|
||||
|
||||
if(!error)
|
||||
{
|
||||
mhddLog.Write(currentBlock, duration);
|
||||
ibgLog.Write(currentBlock, currentSpeed * 1024);
|
||||
dumpFile.Write(cmdBuf);
|
||||
extents.Add(currentBlock);
|
||||
dumpLog.WriteLine("Error reading cylinder {0} head {1} sector {2}.", cy, hd, sc);
|
||||
}
|
||||
else
|
||||
{
|
||||
resume.BadBlocks.Add(currentBlock);
|
||||
if(duration < 500) mhddLog.Write(currentBlock, 65535);
|
||||
else mhddLog.Write(currentBlock, duration);
|
||||
|
||||
ibgLog.Write(currentBlock, 0);
|
||||
dumpFile.Write(new byte[blockSize]);
|
||||
}
|
||||
|
||||
currentSpeed = blockSize / (double)1048576 / (duration / 1000);
|
||||
GC.Collect();
|
||||
|
||||
currentBlock++;
|
||||
}
|
||||
|
||||
currentSpeed = blockSize / (double)1048576 / (duration / 1000);
|
||||
GC.Collect();
|
||||
|
||||
currentBlock++;
|
||||
}
|
||||
}
|
||||
|
||||
end = DateTime.Now;
|
||||
DicConsole.WriteLine();
|
||||
mhddLog.Close();
|
||||
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
|
||||
blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000),
|
||||
devicePath);
|
||||
dumpLog.WriteLine("Dump finished in {0} seconds.", (end - start).TotalSeconds);
|
||||
dumpLog.WriteLine("Average dump speed {0:F3} KiB/sec.",
|
||||
(double)blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000));
|
||||
}
|
||||
|
||||
end = DateTime.Now;
|
||||
DicConsole.WriteLine();
|
||||
mhddLog.Close();
|
||||
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
|
||||
blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000),
|
||||
devicePath);
|
||||
dumpLog.WriteLine("Dump finished in {0} seconds.", (end - start).TotalSeconds);
|
||||
dumpLog.WriteLine("Average dump speed {0:F3} KiB/sec.",
|
||||
(double)blockSize * (double)(blocks + 1) / 1024 / (totalDuration / 1000));
|
||||
}
|
||||
dataChk = new Checksum();
|
||||
dumpFile.Seek(0, SeekOrigin.Begin);
|
||||
blocksToRead = 500;
|
||||
|
||||
dataChk = new Checksum();
|
||||
dumpFile.Seek(0, SeekOrigin.Begin);
|
||||
blocksToRead = 500;
|
||||
|
||||
dumpLog.WriteLine("Checksum starts.");
|
||||
for(ulong i = 0; i < blocks; i += blocksToRead)
|
||||
{
|
||||
if(aborted)
|
||||
dumpLog.WriteLine("Checksum starts.");
|
||||
for(ulong i = 0; i < blocks; i += blocksToRead)
|
||||
{
|
||||
dumpLog.WriteLine("Aborted!");
|
||||
break;
|
||||
}
|
||||
|
||||
if(blocks - i < blocksToRead) blocksToRead = (byte)(blocks - i);
|
||||
|
||||
DicConsole.Write("\rChecksumming sector {0} of {1} ({2:F3} MiB/sec.)", i, blocks, currentSpeed);
|
||||
|
||||
DateTime chkStart = DateTime.UtcNow;
|
||||
byte[] dataToCheck = new byte[blockSize * blocksToRead];
|
||||
dumpFile.Read(dataToCheck, 0, (int)(blockSize * blocksToRead));
|
||||
dataChk.Update(dataToCheck);
|
||||
DateTime chkEnd = DateTime.UtcNow;
|
||||
|
||||
double chkDuration = (chkEnd - chkStart).TotalMilliseconds;
|
||||
totalChkDuration += chkDuration;
|
||||
|
||||
currentSpeed = (double)blockSize * blocksToRead / 1048576 / (chkDuration / 1000);
|
||||
}
|
||||
|
||||
DicConsole.WriteLine();
|
||||
dumpFile.Close();
|
||||
end = DateTime.UtcNow;
|
||||
dumpLog.WriteLine("Checksum finished in {0} seconds.", (end - start).TotalSeconds);
|
||||
dumpLog.WriteLine("Average checksum speed {0:F3} KiB/sec.",
|
||||
(double)blockSize * (double)(blocks + 1) / 1024 / (totalChkDuration / 1000));
|
||||
|
||||
PluginBase plugins = new PluginBase();
|
||||
plugins.RegisterAllPlugins(encoding);
|
||||
ImagePlugin imageFormat;
|
||||
|
||||
FiltersList filtersList = new FiltersList();
|
||||
Filter inputFilter = filtersList.GetFilter(outputPrefix + ".bin");
|
||||
|
||||
if(inputFilter == null)
|
||||
{
|
||||
DicConsole.ErrorWriteLine("Cannot open file just created, this should not happen.");
|
||||
return;
|
||||
}
|
||||
|
||||
imageFormat = ImageFormat.Detect(inputFilter);
|
||||
PartitionType[] xmlFileSysInfo = null;
|
||||
|
||||
try { if(!imageFormat.OpenImage(inputFilter)) imageFormat = null; }
|
||||
catch { imageFormat = null; }
|
||||
|
||||
if(imageFormat != null)
|
||||
{
|
||||
dumpLog.WriteLine("Getting partitions.");
|
||||
List<Partition> partitions = Partitions.GetAll(imageFormat);
|
||||
Partitions.AddSchemesToStats(partitions);
|
||||
dumpLog.WriteLine("Found {0} partitions.", partitions.Count);
|
||||
|
||||
if(partitions.Count > 0)
|
||||
{
|
||||
xmlFileSysInfo = new PartitionType[partitions.Count];
|
||||
for(int i = 0; i < partitions.Count; i++)
|
||||
if(aborted)
|
||||
{
|
||||
xmlFileSysInfo[i] = new PartitionType
|
||||
dumpLog.WriteLine("Aborted!");
|
||||
break;
|
||||
}
|
||||
|
||||
if(blocks - i < blocksToRead) blocksToRead = (byte)(blocks - i);
|
||||
|
||||
DicConsole.Write("\rChecksumming sector {0} of {1} ({2:F3} MiB/sec.)", i, blocks, currentSpeed);
|
||||
|
||||
DateTime chkStart = DateTime.UtcNow;
|
||||
byte[] dataToCheck = new byte[blockSize * blocksToRead];
|
||||
dumpFile.Read(dataToCheck, 0, (int)(blockSize * blocksToRead));
|
||||
dataChk.Update(dataToCheck);
|
||||
DateTime chkEnd = DateTime.UtcNow;
|
||||
|
||||
double chkDuration = (chkEnd - chkStart).TotalMilliseconds;
|
||||
totalChkDuration += chkDuration;
|
||||
|
||||
currentSpeed = (double)blockSize * blocksToRead / 1048576 / (chkDuration / 1000);
|
||||
}
|
||||
|
||||
DicConsole.WriteLine();
|
||||
dumpFile.Close();
|
||||
end = DateTime.UtcNow;
|
||||
dumpLog.WriteLine("Checksum finished in {0} seconds.", (end - start).TotalSeconds);
|
||||
dumpLog.WriteLine("Average checksum speed {0:F3} KiB/sec.",
|
||||
(double)blockSize * (double)(blocks + 1) / 1024 / (totalChkDuration / 1000));
|
||||
|
||||
PluginBase plugins = new PluginBase();
|
||||
plugins.RegisterAllPlugins(encoding);
|
||||
ImagePlugin imageFormat;
|
||||
|
||||
FiltersList filtersList = new FiltersList();
|
||||
Filter inputFilter = filtersList.GetFilter(outputPrefix + ".bin");
|
||||
|
||||
if(inputFilter == null)
|
||||
{
|
||||
DicConsole.ErrorWriteLine("Cannot open file just created, this should not happen.");
|
||||
return;
|
||||
}
|
||||
|
||||
imageFormat = ImageFormat.Detect(inputFilter);
|
||||
PartitionType[] xmlFileSysInfo = null;
|
||||
|
||||
try { if(!imageFormat.OpenImage(inputFilter)) imageFormat = null; }
|
||||
catch { imageFormat = null; }
|
||||
|
||||
if(imageFormat != null)
|
||||
{
|
||||
dumpLog.WriteLine("Getting partitions.");
|
||||
List<Partition> partitions = Partitions.GetAll(imageFormat);
|
||||
Partitions.AddSchemesToStats(partitions);
|
||||
dumpLog.WriteLine("Found {0} partitions.", partitions.Count);
|
||||
|
||||
if(partitions.Count > 0)
|
||||
{
|
||||
xmlFileSysInfo = new PartitionType[partitions.Count];
|
||||
for(int i = 0; i < partitions.Count; i++)
|
||||
{
|
||||
Description = partitions[i].Description,
|
||||
EndSector = (int)(partitions[i].Start + partitions[i].Length - 1),
|
||||
Name = partitions[i].Name,
|
||||
Sequence = (int)partitions[i].Sequence,
|
||||
StartSector = (int)partitions[i].Start,
|
||||
Type = partitions[i].Type
|
||||
};
|
||||
xmlFileSysInfo[i] = new PartitionType
|
||||
{
|
||||
Description = partitions[i].Description,
|
||||
EndSector = (int)(partitions[i].Start + partitions[i].Length - 1),
|
||||
Name = partitions[i].Name,
|
||||
Sequence = (int)partitions[i].Sequence,
|
||||
StartSector = (int)partitions[i].Start,
|
||||
Type = partitions[i].Type
|
||||
};
|
||||
List<FileSystemType> lstFs = new List<FileSystemType>();
|
||||
dumpLog
|
||||
.WriteLine("Getting filesystems on partition {0}, starting at {1}, ending at {2}, with type {3}, under scheme {4}.",
|
||||
i, partitions[i].Start, partitions[i].End, partitions[i].Type,
|
||||
partitions[i].Scheme);
|
||||
|
||||
foreach(Filesystem plugin in plugins.PluginsList.Values)
|
||||
try
|
||||
{
|
||||
if(!plugin.Identify(imageFormat, partitions[i])) continue;
|
||||
|
||||
plugin.GetInformation(imageFormat, partitions[i], out string foo);
|
||||
lstFs.Add(plugin.XmlFSType);
|
||||
Statistics.AddFilesystem(plugin.XmlFSType.Type);
|
||||
dumpLog.WriteLine("Filesystem {0} found.", plugin.XmlFSType.Type);
|
||||
}
|
||||
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
|
||||
catch
|
||||
#pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body
|
||||
{
|
||||
//DicConsole.DebugWriteLine("Dump-media command", "Plugin {0} crashed", _plugin.Name);
|
||||
}
|
||||
|
||||
if(lstFs.Count > 0) xmlFileSysInfo[i].FileSystems = lstFs.ToArray();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dumpLog.WriteLine("Getting filesystem for whole device.");
|
||||
|
||||
xmlFileSysInfo = new PartitionType[1];
|
||||
xmlFileSysInfo[0] = new PartitionType {EndSector = (int)(blocks - 1), StartSector = 0};
|
||||
List<FileSystemType> lstFs = new List<FileSystemType>();
|
||||
dumpLog
|
||||
.WriteLine("Getting filesystems on partition {0}, starting at {1}, ending at {2}, with type {3}, under scheme {4}.",
|
||||
i, partitions[i].Start, partitions[i].End, partitions[i].Type,
|
||||
partitions[i].Scheme);
|
||||
|
||||
Partition wholePart = new Partition
|
||||
{
|
||||
Name = "Whole device",
|
||||
Length = blocks,
|
||||
Size = blocks * blockSize
|
||||
};
|
||||
|
||||
foreach(Filesystem plugin in plugins.PluginsList.Values)
|
||||
try
|
||||
{
|
||||
if(!plugin.Identify(imageFormat, partitions[i])) continue;
|
||||
if(!plugin.Identify(imageFormat, wholePart)) continue;
|
||||
|
||||
plugin.GetInformation(imageFormat, partitions[i], out string foo);
|
||||
plugin.GetInformation(imageFormat, wholePart, out string foo);
|
||||
lstFs.Add(plugin.XmlFSType);
|
||||
Statistics.AddFilesystem(plugin.XmlFSType.Type);
|
||||
dumpLog.WriteLine("Filesystem {0} found.", plugin.XmlFSType.Type);
|
||||
@@ -510,104 +547,70 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
catch
|
||||
#pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body
|
||||
{
|
||||
//DicConsole.DebugWriteLine("Dump-media command", "Plugin {0} crashed", _plugin.Name);
|
||||
//DicConsole.DebugWriteLine("Create-sidecar command", "Plugin {0} crashed", _plugin.Name);
|
||||
}
|
||||
|
||||
if(lstFs.Count > 0) xmlFileSysInfo[i].FileSystems = lstFs.ToArray();
|
||||
if(lstFs.Count > 0) xmlFileSysInfo[0].FileSystems = lstFs.ToArray();
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
sidecar.BlockMedia[0].Checksums = dataChk.End().ToArray();
|
||||
string xmlDskTyp, xmlDskSubTyp;
|
||||
if(dev.IsCompactFlash)
|
||||
MediaType.MediaTypeToString(CommonTypes.MediaType.CompactFlash, out xmlDskTyp, out xmlDskSubTyp);
|
||||
else if(dev.IsPcmcia)
|
||||
MediaType.MediaTypeToString(CommonTypes.MediaType.PCCardTypeI, out xmlDskTyp, out xmlDskSubTyp);
|
||||
else MediaType.MediaTypeToString(CommonTypes.MediaType.GENERIC_HDD, out xmlDskTyp, out xmlDskSubTyp);
|
||||
sidecar.BlockMedia[0].DiskType = xmlDskTyp;
|
||||
sidecar.BlockMedia[0].DiskSubType = xmlDskSubTyp;
|
||||
// TODO: Implement device firmware revision
|
||||
sidecar.BlockMedia[0].Image = new ImageType
|
||||
{
|
||||
dumpLog.WriteLine("Getting filesystem for whole device.");
|
||||
|
||||
xmlFileSysInfo = new PartitionType[1];
|
||||
xmlFileSysInfo[0] = new PartitionType {EndSector = (int)(blocks - 1), StartSector = 0};
|
||||
List<FileSystemType> lstFs = new List<FileSystemType>();
|
||||
|
||||
Partition wholePart = new Partition
|
||||
{
|
||||
Name = "Whole device",
|
||||
Length = blocks,
|
||||
Size = blocks * blockSize
|
||||
};
|
||||
|
||||
foreach(Filesystem plugin in plugins.PluginsList.Values)
|
||||
try
|
||||
{
|
||||
if(!plugin.Identify(imageFormat, wholePart)) continue;
|
||||
|
||||
plugin.GetInformation(imageFormat, wholePart, out string foo);
|
||||
lstFs.Add(plugin.XmlFSType);
|
||||
Statistics.AddFilesystem(plugin.XmlFSType.Type);
|
||||
dumpLog.WriteLine("Filesystem {0} found.", plugin.XmlFSType.Type);
|
||||
}
|
||||
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
|
||||
catch
|
||||
#pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body
|
||||
{
|
||||
//DicConsole.DebugWriteLine("Create-sidecar command", "Plugin {0} crashed", _plugin.Name);
|
||||
}
|
||||
|
||||
if(lstFs.Count > 0) xmlFileSysInfo[0].FileSystems = lstFs.ToArray();
|
||||
format = "Raw disk image (sector by sector copy)",
|
||||
Value = outputPrefix + ".bin"
|
||||
};
|
||||
sidecar.BlockMedia[0].Interface = "ATA";
|
||||
sidecar.BlockMedia[0].LogicalBlocks = (long)blocks;
|
||||
sidecar.BlockMedia[0].PhysicalBlockSize = (int)physicalsectorsize;
|
||||
sidecar.BlockMedia[0].LogicalBlockSize = (int)blockSize;
|
||||
sidecar.BlockMedia[0].Manufacturer = dev.Manufacturer;
|
||||
sidecar.BlockMedia[0].Model = dev.Model;
|
||||
sidecar.BlockMedia[0].Serial = dev.Serial;
|
||||
sidecar.BlockMedia[0].Size = (long)(blocks * blockSize);
|
||||
if(xmlFileSysInfo != null) sidecar.BlockMedia[0].FileSystemInformation = xmlFileSysInfo;
|
||||
if(cylinders > 0 && heads > 0 && sectors > 0)
|
||||
{
|
||||
sidecar.BlockMedia[0].Cylinders = cylinders;
|
||||
sidecar.BlockMedia[0].CylindersSpecified = true;
|
||||
sidecar.BlockMedia[0].Heads = heads;
|
||||
sidecar.BlockMedia[0].HeadsSpecified = true;
|
||||
sidecar.BlockMedia[0].SectorsPerTrack = sectors;
|
||||
sidecar.BlockMedia[0].SectorsPerTrackSpecified = true;
|
||||
}
|
||||
}
|
||||
|
||||
sidecar.BlockMedia[0].Checksums = dataChk.End().ToArray();
|
||||
string xmlDskTyp, xmlDskSubTyp;
|
||||
if(dev.IsCompactFlash)
|
||||
MediaType.MediaTypeToString(CommonTypes.MediaType.CompactFlash, out xmlDskTyp, out xmlDskSubTyp);
|
||||
else if(dev.IsPcmcia)
|
||||
MediaType.MediaTypeToString(CommonTypes.MediaType.PCCardTypeI, out xmlDskTyp, out xmlDskSubTyp);
|
||||
else MediaType.MediaTypeToString(CommonTypes.MediaType.GENERIC_HDD, out xmlDskTyp, out xmlDskSubTyp);
|
||||
sidecar.BlockMedia[0].DiskType = xmlDskTyp;
|
||||
sidecar.BlockMedia[0].DiskSubType = xmlDskSubTyp;
|
||||
// TODO: Implement device firmware revision
|
||||
sidecar.BlockMedia[0].Image = new ImageType
|
||||
{
|
||||
format = "Raw disk image (sector by sector copy)",
|
||||
Value = outputPrefix + ".bin"
|
||||
};
|
||||
sidecar.BlockMedia[0].Interface = "ATA";
|
||||
sidecar.BlockMedia[0].LogicalBlocks = (long)blocks;
|
||||
sidecar.BlockMedia[0].PhysicalBlockSize = (int)physicalsectorsize;
|
||||
sidecar.BlockMedia[0].LogicalBlockSize = (int)blockSize;
|
||||
sidecar.BlockMedia[0].Manufacturer = dev.Manufacturer;
|
||||
sidecar.BlockMedia[0].Model = dev.Model;
|
||||
sidecar.BlockMedia[0].Serial = dev.Serial;
|
||||
sidecar.BlockMedia[0].Size = (long)(blocks * blockSize);
|
||||
if(xmlFileSysInfo != null) sidecar.BlockMedia[0].FileSystemInformation = xmlFileSysInfo;
|
||||
if(cylinders > 0 && heads > 0 && sectors > 0)
|
||||
{
|
||||
sidecar.BlockMedia[0].Cylinders = cylinders;
|
||||
sidecar.BlockMedia[0].CylindersSpecified = true;
|
||||
sidecar.BlockMedia[0].Heads = heads;
|
||||
sidecar.BlockMedia[0].HeadsSpecified = true;
|
||||
sidecar.BlockMedia[0].SectorsPerTrack = sectors;
|
||||
sidecar.BlockMedia[0].SectorsPerTrackSpecified = true;
|
||||
}
|
||||
DicConsole.WriteLine();
|
||||
|
||||
DicConsole.WriteLine();
|
||||
DicConsole.WriteLine("Took a total of {0:F3} seconds ({1:F3} processing commands, {2:F3} checksumming).",
|
||||
(end - start).TotalSeconds, totalDuration / 1000, totalChkDuration / 1000);
|
||||
DicConsole.WriteLine("Avegare speed: {0:F3} MiB/sec.",
|
||||
(double)blockSize * (double)(blocks + 1) / 1048576 / (totalDuration / 1000));
|
||||
DicConsole.WriteLine("Fastest speed burst: {0:F3} MiB/sec.", maxSpeed);
|
||||
DicConsole.WriteLine("Slowest speed burst: {0:F3} MiB/sec.", minSpeed);
|
||||
DicConsole.WriteLine("{0} sectors could not be read.", resume.BadBlocks.Count);
|
||||
if(resume.BadBlocks.Count > 0) resume.BadBlocks.Sort();
|
||||
DicConsole.WriteLine();
|
||||
|
||||
DicConsole.WriteLine("Took a total of {0:F3} seconds ({1:F3} processing commands, {2:F3} checksumming).",
|
||||
(end - start).TotalSeconds, totalDuration / 1000, totalChkDuration / 1000);
|
||||
DicConsole.WriteLine("Avegare speed: {0:F3} MiB/sec.",
|
||||
(double)blockSize * (double)(blocks + 1) / 1048576 / (totalDuration / 1000));
|
||||
DicConsole.WriteLine("Fastest speed burst: {0:F3} MiB/sec.", maxSpeed);
|
||||
DicConsole.WriteLine("Slowest speed burst: {0:F3} MiB/sec.", minSpeed);
|
||||
DicConsole.WriteLine("{0} sectors could not be read.", resume.BadBlocks.Count);
|
||||
if(resume.BadBlocks.Count > 0) resume.BadBlocks.Sort();
|
||||
DicConsole.WriteLine();
|
||||
if(!aborted)
|
||||
{
|
||||
DicConsole.WriteLine("Writing metadata sidecar");
|
||||
|
||||
if(!aborted)
|
||||
{
|
||||
DicConsole.WriteLine("Writing metadata sidecar");
|
||||
FileStream xmlFs = new FileStream(outputPrefix + ".cicm.xml", FileMode.Create);
|
||||
|
||||
FileStream xmlFs = new FileStream(outputPrefix + ".cicm.xml", FileMode.Create);
|
||||
|
||||
XmlSerializer xmlSer =
|
||||
new XmlSerializer(typeof(CICMMetadataType));
|
||||
xmlSer.Serialize(xmlFs, sidecar);
|
||||
xmlFs.Close();
|
||||
XmlSerializer xmlSer =
|
||||
new XmlSerializer(typeof(CICMMetadataType));
|
||||
xmlSer.Serialize(xmlFs, sidecar);
|
||||
xmlFs.Close();
|
||||
}
|
||||
}
|
||||
|
||||
Statistics.AddMedia(CommonTypes.MediaType.GENERIC_HDD, true);
|
||||
|
||||
@@ -67,7 +67,8 @@ namespace DiscImageChef.Core.Devices
|
||||
switch(dev.Type)
|
||||
{
|
||||
case DeviceType.ATA:
|
||||
if(Identify.Decode(identification).HasValue) ataId = Identify.Decode(identification).Value;
|
||||
Identify.IdentifyDevice? ataIdNullable = Identify.Decode(identification);
|
||||
if(ataIdNullable.HasValue) ataId = ataIdNullable.Value;
|
||||
break;
|
||||
case DeviceType.NVMe: throw new NotImplementedException("NVMe devices not yet supported.");
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -54,404 +54,407 @@ namespace DiscImageChef.Core.Devices.Report
|
||||
|
||||
if(!Identify.Decode(buffer).HasValue) return;
|
||||
|
||||
Identify.IdentifyDevice atapiId = Identify.Decode(buffer).Value;
|
||||
Identify.IdentifyDevice? atapiIdNullable = Identify.Decode(buffer);
|
||||
if(atapiIdNullable != null) {
|
||||
Identify.IdentifyDevice atapiId = atapiIdNullable.Value;
|
||||
|
||||
report.ATAPI = new ataType();
|
||||
report.ATAPI = new ataType();
|
||||
|
||||
if(!string.IsNullOrWhiteSpace(atapiId.AdditionalPID))
|
||||
{
|
||||
report.ATAPI.AdditionalPID = atapiId.AdditionalPID;
|
||||
report.ATAPI.AdditionalPIDSpecified = true;
|
||||
}
|
||||
if(atapiId.APIOSupported != 0)
|
||||
{
|
||||
report.ATAPI.APIOSupported = atapiId.APIOSupported;
|
||||
report.ATAPI.APIOSupportedSpecified = true;
|
||||
}
|
||||
if(atapiId.ATAPIByteCount != 0)
|
||||
{
|
||||
report.ATAPI.ATAPIByteCount = atapiId.ATAPIByteCount;
|
||||
report.ATAPI.ATAPIByteCountSpecified = true;
|
||||
}
|
||||
if(atapiId.BufferType != 0)
|
||||
{
|
||||
report.ATAPI.BufferType = atapiId.BufferType;
|
||||
report.ATAPI.BufferTypeSpecified = true;
|
||||
}
|
||||
if(atapiId.BufferSize != 0)
|
||||
{
|
||||
report.ATAPI.BufferSize = atapiId.BufferSize;
|
||||
report.ATAPI.BufferSizeSpecified = true;
|
||||
}
|
||||
if(atapiId.Capabilities != 0)
|
||||
{
|
||||
report.ATAPI.Capabilities = atapiId.Capabilities;
|
||||
report.ATAPI.CapabilitiesSpecified = true;
|
||||
}
|
||||
if(atapiId.Capabilities2 != 0)
|
||||
{
|
||||
report.ATAPI.Capabilities2 = atapiId.Capabilities2;
|
||||
report.ATAPI.Capabilities2Specified = true;
|
||||
}
|
||||
if(atapiId.Capabilities3 != 0)
|
||||
{
|
||||
report.ATAPI.Capabilities3 = atapiId.Capabilities3;
|
||||
report.ATAPI.Capabilities3Specified = true;
|
||||
}
|
||||
if(atapiId.CFAPowerMode != 0)
|
||||
{
|
||||
report.ATAPI.CFAPowerMode = atapiId.CFAPowerMode;
|
||||
report.ATAPI.CFAPowerModeSpecified = true;
|
||||
}
|
||||
if(atapiId.CommandSet != 0)
|
||||
{
|
||||
report.ATAPI.CommandSet = atapiId.CommandSet;
|
||||
report.ATAPI.CommandSetSpecified = true;
|
||||
}
|
||||
if(atapiId.CommandSet2 != 0)
|
||||
{
|
||||
report.ATAPI.CommandSet2 = atapiId.CommandSet2;
|
||||
report.ATAPI.CommandSet2Specified = true;
|
||||
}
|
||||
if(atapiId.CommandSet3 != 0)
|
||||
{
|
||||
report.ATAPI.CommandSet3 = atapiId.CommandSet3;
|
||||
report.ATAPI.CommandSet3Specified = true;
|
||||
}
|
||||
if(atapiId.CommandSet4 != 0)
|
||||
{
|
||||
report.ATAPI.CommandSet4 = atapiId.CommandSet4;
|
||||
report.ATAPI.CommandSet4Specified = true;
|
||||
}
|
||||
if(atapiId.CommandSet5 != 0)
|
||||
{
|
||||
report.ATAPI.CommandSet5 = atapiId.CommandSet5;
|
||||
report.ATAPI.CommandSet5Specified = true;
|
||||
}
|
||||
if(atapiId.CurrentAAM != 0)
|
||||
{
|
||||
report.ATAPI.CurrentAAM = atapiId.CurrentAAM;
|
||||
report.ATAPI.CurrentAAMSpecified = true;
|
||||
}
|
||||
if(atapiId.CurrentAPM != 0)
|
||||
{
|
||||
report.ATAPI.CurrentAPM = atapiId.CurrentAPM;
|
||||
report.ATAPI.CurrentAPMSpecified = true;
|
||||
}
|
||||
if(atapiId.DataSetMgmt != 0)
|
||||
{
|
||||
report.ATAPI.DataSetMgmt = atapiId.DataSetMgmt;
|
||||
report.ATAPI.DataSetMgmtSpecified = true;
|
||||
}
|
||||
if(atapiId.DataSetMgmtSize != 0)
|
||||
{
|
||||
report.ATAPI.DataSetMgmtSize = atapiId.DataSetMgmtSize;
|
||||
report.ATAPI.DataSetMgmtSizeSpecified = true;
|
||||
}
|
||||
if(atapiId.DeviceFormFactor != 0)
|
||||
{
|
||||
report.ATAPI.DeviceFormFactor = atapiId.DeviceFormFactor;
|
||||
report.ATAPI.DeviceFormFactorSpecified = true;
|
||||
}
|
||||
if(atapiId.DMAActive != 0)
|
||||
{
|
||||
report.ATAPI.DMAActive = atapiId.DMAActive;
|
||||
report.ATAPI.DMAActiveSpecified = true;
|
||||
}
|
||||
if(atapiId.DMASupported != 0)
|
||||
{
|
||||
report.ATAPI.DMASupported = atapiId.DMASupported;
|
||||
report.ATAPI.DMASupportedSpecified = true;
|
||||
}
|
||||
if(atapiId.DMATransferTimingMode != 0)
|
||||
{
|
||||
report.ATAPI.DMATransferTimingMode = atapiId.DMATransferTimingMode;
|
||||
report.ATAPI.DMATransferTimingModeSpecified = true;
|
||||
}
|
||||
if(atapiId.EnhancedSecurityEraseTime != 0)
|
||||
{
|
||||
report.ATAPI.EnhancedSecurityEraseTime = atapiId.EnhancedSecurityEraseTime;
|
||||
report.ATAPI.EnhancedSecurityEraseTimeSpecified = true;
|
||||
}
|
||||
if(atapiId.EnabledCommandSet != 0)
|
||||
{
|
||||
report.ATAPI.EnabledCommandSet = atapiId.EnabledCommandSet;
|
||||
report.ATAPI.EnabledCommandSetSpecified = true;
|
||||
}
|
||||
if(atapiId.EnabledCommandSet2 != 0)
|
||||
{
|
||||
report.ATAPI.EnabledCommandSet2 = atapiId.EnabledCommandSet2;
|
||||
report.ATAPI.EnabledCommandSet2Specified = true;
|
||||
}
|
||||
if(atapiId.EnabledCommandSet3 != 0)
|
||||
{
|
||||
report.ATAPI.EnabledCommandSet3 = atapiId.EnabledCommandSet3;
|
||||
report.ATAPI.EnabledCommandSet3Specified = true;
|
||||
}
|
||||
if(atapiId.EnabledCommandSet4 != 0)
|
||||
{
|
||||
report.ATAPI.EnabledCommandSet4 = atapiId.EnabledCommandSet4;
|
||||
report.ATAPI.EnabledCommandSet4Specified = true;
|
||||
}
|
||||
if(atapiId.EnabledSATAFeatures != 0)
|
||||
{
|
||||
report.ATAPI.EnabledSATAFeatures = atapiId.EnabledSATAFeatures;
|
||||
report.ATAPI.EnabledSATAFeaturesSpecified = true;
|
||||
}
|
||||
if(atapiId.ExtendedUserSectors != 0)
|
||||
{
|
||||
report.ATAPI.ExtendedUserSectors = atapiId.ExtendedUserSectors;
|
||||
report.ATAPI.ExtendedUserSectorsSpecified = true;
|
||||
}
|
||||
if(atapiId.FreeFallSensitivity != 0)
|
||||
{
|
||||
report.ATAPI.FreeFallSensitivity = atapiId.FreeFallSensitivity;
|
||||
report.ATAPI.FreeFallSensitivitySpecified = true;
|
||||
}
|
||||
if(!string.IsNullOrWhiteSpace(atapiId.FirmwareRevision))
|
||||
{
|
||||
report.ATAPI.FirmwareRevision = atapiId.FirmwareRevision;
|
||||
report.ATAPI.FirmwareRevisionSpecified = true;
|
||||
}
|
||||
if(atapiId.GeneralConfiguration != 0)
|
||||
{
|
||||
report.ATAPI.GeneralConfiguration = atapiId.GeneralConfiguration;
|
||||
report.ATAPI.GeneralConfigurationSpecified = true;
|
||||
}
|
||||
if(atapiId.HardwareResetResult != 0)
|
||||
{
|
||||
report.ATAPI.HardwareResetResult = atapiId.HardwareResetResult;
|
||||
report.ATAPI.HardwareResetResultSpecified = true;
|
||||
}
|
||||
if(atapiId.InterseekDelay != 0)
|
||||
{
|
||||
report.ATAPI.InterseekDelay = atapiId.InterseekDelay;
|
||||
report.ATAPI.InterseekDelaySpecified = true;
|
||||
}
|
||||
if(atapiId.MajorVersion != 0)
|
||||
{
|
||||
report.ATAPI.MajorVersion = atapiId.MajorVersion;
|
||||
report.ATAPI.MajorVersionSpecified = true;
|
||||
}
|
||||
if(atapiId.MasterPasswordRevisionCode != 0)
|
||||
{
|
||||
report.ATAPI.MasterPasswordRevisionCode = atapiId.MasterPasswordRevisionCode;
|
||||
report.ATAPI.MasterPasswordRevisionCodeSpecified = true;
|
||||
}
|
||||
if(atapiId.MaxDownloadMicroMode3 != 0)
|
||||
{
|
||||
report.ATAPI.MaxDownloadMicroMode3 = atapiId.MaxDownloadMicroMode3;
|
||||
report.ATAPI.MaxDownloadMicroMode3Specified = true;
|
||||
}
|
||||
if(atapiId.MaxQueueDepth != 0)
|
||||
{
|
||||
report.ATAPI.MaxQueueDepth = atapiId.MaxQueueDepth;
|
||||
report.ATAPI.MaxQueueDepthSpecified = true;
|
||||
}
|
||||
if(atapiId.MDMAActive != 0)
|
||||
{
|
||||
report.ATAPI.MDMAActive = atapiId.MDMAActive;
|
||||
report.ATAPI.MDMAActiveSpecified = true;
|
||||
}
|
||||
if(atapiId.MDMASupported != 0)
|
||||
{
|
||||
report.ATAPI.MDMASupported = atapiId.MDMASupported;
|
||||
report.ATAPI.MDMASupportedSpecified = true;
|
||||
}
|
||||
if(atapiId.MinDownloadMicroMode3 != 0)
|
||||
{
|
||||
report.ATAPI.MinDownloadMicroMode3 = atapiId.MinDownloadMicroMode3;
|
||||
report.ATAPI.MinDownloadMicroMode3Specified = true;
|
||||
}
|
||||
if(atapiId.MinMDMACycleTime != 0)
|
||||
{
|
||||
report.ATAPI.MinMDMACycleTime = atapiId.MinMDMACycleTime;
|
||||
report.ATAPI.MinMDMACycleTimeSpecified = true;
|
||||
}
|
||||
if(atapiId.MinorVersion != 0)
|
||||
{
|
||||
report.ATAPI.MinorVersion = atapiId.MinorVersion;
|
||||
report.ATAPI.MinorVersionSpecified = true;
|
||||
}
|
||||
if(atapiId.MinPIOCycleTimeNoFlow != 0)
|
||||
{
|
||||
report.ATAPI.MinPIOCycleTimeNoFlow = atapiId.MinPIOCycleTimeNoFlow;
|
||||
report.ATAPI.MinPIOCycleTimeNoFlowSpecified = true;
|
||||
}
|
||||
if(atapiId.MinPIOCycleTimeFlow != 0)
|
||||
{
|
||||
report.ATAPI.MinPIOCycleTimeFlow = atapiId.MinPIOCycleTimeFlow;
|
||||
report.ATAPI.MinPIOCycleTimeFlowSpecified = true;
|
||||
}
|
||||
if(!string.IsNullOrWhiteSpace(atapiId.Model))
|
||||
{
|
||||
report.ATAPI.Model = atapiId.Model;
|
||||
report.ATAPI.ModelSpecified = true;
|
||||
}
|
||||
if(atapiId.MultipleMaxSectors != 0)
|
||||
{
|
||||
report.ATAPI.MultipleMaxSectors = atapiId.MultipleMaxSectors;
|
||||
report.ATAPI.MultipleMaxSectorsSpecified = true;
|
||||
}
|
||||
if(atapiId.MultipleSectorNumber != 0)
|
||||
{
|
||||
report.ATAPI.MultipleSectorNumber = atapiId.MultipleSectorNumber;
|
||||
report.ATAPI.MultipleSectorNumberSpecified = true;
|
||||
}
|
||||
if(atapiId.NVCacheCaps != 0)
|
||||
{
|
||||
report.ATAPI.NVCacheCaps = atapiId.NVCacheCaps;
|
||||
report.ATAPI.NVCacheCapsSpecified = true;
|
||||
}
|
||||
if(atapiId.NVCacheSize != 0)
|
||||
{
|
||||
report.ATAPI.NVCacheSize = atapiId.NVCacheSize;
|
||||
report.ATAPI.NVCacheSizeSpecified = true;
|
||||
}
|
||||
if(atapiId.NVCacheWriteSpeed != 0)
|
||||
{
|
||||
report.ATAPI.NVCacheWriteSpeed = atapiId.NVCacheWriteSpeed;
|
||||
report.ATAPI.NVCacheWriteSpeedSpecified = true;
|
||||
}
|
||||
if(atapiId.NVEstimatedSpinUp != 0)
|
||||
{
|
||||
report.ATAPI.NVEstimatedSpinUp = atapiId.NVEstimatedSpinUp;
|
||||
report.ATAPI.NVEstimatedSpinUpSpecified = true;
|
||||
}
|
||||
if(atapiId.PacketBusRelease != 0)
|
||||
{
|
||||
report.ATAPI.PacketBusRelease = atapiId.PacketBusRelease;
|
||||
report.ATAPI.PacketBusReleaseSpecified = true;
|
||||
}
|
||||
if(atapiId.PIOTransferTimingMode != 0)
|
||||
{
|
||||
report.ATAPI.PIOTransferTimingMode = atapiId.PIOTransferTimingMode;
|
||||
report.ATAPI.PIOTransferTimingModeSpecified = true;
|
||||
}
|
||||
if(atapiId.RecommendedAAM != 0)
|
||||
{
|
||||
report.ATAPI.RecommendedAAM = atapiId.RecommendedAAM;
|
||||
report.ATAPI.RecommendedAAMSpecified = true;
|
||||
}
|
||||
if(atapiId.RecMDMACycleTime != 0)
|
||||
{
|
||||
report.ATAPI.RecommendedMDMACycleTime = atapiId.RecMDMACycleTime;
|
||||
report.ATAPI.RecommendedMDMACycleTimeSpecified = true;
|
||||
}
|
||||
if(atapiId.RemovableStatusSet != 0)
|
||||
{
|
||||
report.ATAPI.RemovableStatusSet = atapiId.RemovableStatusSet;
|
||||
report.ATAPI.RemovableStatusSetSpecified = true;
|
||||
}
|
||||
if(atapiId.SATACapabilities != 0)
|
||||
{
|
||||
report.ATAPI.SATACapabilities = atapiId.SATACapabilities;
|
||||
report.ATAPI.SATACapabilitiesSpecified = true;
|
||||
}
|
||||
if(atapiId.SATACapabilities2 != 0)
|
||||
{
|
||||
report.ATAPI.SATACapabilities2 = atapiId.SATACapabilities2;
|
||||
report.ATAPI.SATACapabilities2Specified = true;
|
||||
}
|
||||
if(atapiId.SATAFeatures != 0)
|
||||
{
|
||||
report.ATAPI.SATAFeatures = atapiId.SATAFeatures;
|
||||
report.ATAPI.SATAFeaturesSpecified = true;
|
||||
}
|
||||
if(atapiId.SCTCommandTransport != 0)
|
||||
{
|
||||
report.ATAPI.SCTCommandTransport = atapiId.SCTCommandTransport;
|
||||
report.ATAPI.SCTCommandTransportSpecified = true;
|
||||
}
|
||||
if(atapiId.SectorsPerCard != 0)
|
||||
{
|
||||
report.ATAPI.SectorsPerCard = atapiId.SectorsPerCard;
|
||||
report.ATAPI.SectorsPerCardSpecified = true;
|
||||
}
|
||||
if(atapiId.SecurityEraseTime != 0)
|
||||
{
|
||||
report.ATAPI.SecurityEraseTime = atapiId.SecurityEraseTime;
|
||||
report.ATAPI.SecurityEraseTimeSpecified = true;
|
||||
}
|
||||
if(atapiId.SecurityStatus != 0)
|
||||
{
|
||||
report.ATAPI.SecurityStatus = atapiId.SecurityStatus;
|
||||
report.ATAPI.SecurityStatusSpecified = true;
|
||||
}
|
||||
if(atapiId.ServiceBusyClear != 0)
|
||||
{
|
||||
report.ATAPI.ServiceBusyClear = atapiId.ServiceBusyClear;
|
||||
report.ATAPI.ServiceBusyClearSpecified = true;
|
||||
}
|
||||
if(atapiId.SpecificConfiguration != 0)
|
||||
{
|
||||
report.ATAPI.SpecificConfiguration = atapiId.SpecificConfiguration;
|
||||
report.ATAPI.SpecificConfigurationSpecified = true;
|
||||
}
|
||||
if(atapiId.StreamAccessLatency != 0)
|
||||
{
|
||||
report.ATAPI.StreamAccessLatency = atapiId.StreamAccessLatency;
|
||||
report.ATAPI.StreamAccessLatencySpecified = true;
|
||||
}
|
||||
if(atapiId.StreamMinReqSize != 0)
|
||||
{
|
||||
report.ATAPI.StreamMinReqSize = atapiId.StreamMinReqSize;
|
||||
report.ATAPI.StreamMinReqSizeSpecified = true;
|
||||
}
|
||||
if(atapiId.StreamPerformanceGranularity != 0)
|
||||
{
|
||||
report.ATAPI.StreamPerformanceGranularity = atapiId.StreamPerformanceGranularity;
|
||||
report.ATAPI.StreamPerformanceGranularitySpecified = true;
|
||||
}
|
||||
if(atapiId.StreamTransferTimeDMA != 0)
|
||||
{
|
||||
report.ATAPI.StreamTransferTimeDMA = atapiId.StreamTransferTimeDMA;
|
||||
report.ATAPI.StreamTransferTimeDMASpecified = true;
|
||||
}
|
||||
if(atapiId.StreamTransferTimePIO != 0)
|
||||
{
|
||||
report.ATAPI.StreamTransferTimePIO = atapiId.StreamTransferTimePIO;
|
||||
report.ATAPI.StreamTransferTimePIOSpecified = true;
|
||||
}
|
||||
if(atapiId.TransportMajorVersion != 0)
|
||||
{
|
||||
report.ATAPI.TransportMajorVersion = atapiId.TransportMajorVersion;
|
||||
report.ATAPI.TransportMajorVersionSpecified = true;
|
||||
}
|
||||
if(atapiId.TransportMinorVersion != 0)
|
||||
{
|
||||
report.ATAPI.TransportMinorVersion = atapiId.TransportMinorVersion;
|
||||
report.ATAPI.TransportMinorVersionSpecified = true;
|
||||
}
|
||||
if(atapiId.TrustedComputing != 0)
|
||||
{
|
||||
report.ATAPI.TrustedComputing = atapiId.TrustedComputing;
|
||||
report.ATAPI.TrustedComputingSpecified = true;
|
||||
}
|
||||
if(atapiId.UDMAActive != 0)
|
||||
{
|
||||
report.ATAPI.UDMAActive = atapiId.UDMAActive;
|
||||
report.ATAPI.UDMAActiveSpecified = true;
|
||||
}
|
||||
if(atapiId.UDMASupported != 0)
|
||||
{
|
||||
report.ATAPI.UDMASupported = atapiId.UDMASupported;
|
||||
report.ATAPI.UDMASupportedSpecified = true;
|
||||
}
|
||||
if(atapiId.WRVMode != 0)
|
||||
{
|
||||
report.ATAPI.WRVMode = atapiId.WRVMode;
|
||||
report.ATAPI.WRVModeSpecified = true;
|
||||
}
|
||||
if(atapiId.WRVSectorCountMode3 != 0)
|
||||
{
|
||||
report.ATAPI.WRVSectorCountMode3 = atapiId.WRVSectorCountMode3;
|
||||
report.ATAPI.WRVSectorCountMode3Specified = true;
|
||||
}
|
||||
if(atapiId.WRVSectorCountMode2 != 0)
|
||||
{
|
||||
report.ATAPI.WRVSectorCountMode2 = atapiId.WRVSectorCountMode2;
|
||||
report.ATAPI.WRVSectorCountMode2Specified = true;
|
||||
if(!string.IsNullOrWhiteSpace(atapiId.AdditionalPID))
|
||||
{
|
||||
report.ATAPI.AdditionalPID = atapiId.AdditionalPID;
|
||||
report.ATAPI.AdditionalPIDSpecified = true;
|
||||
}
|
||||
if(atapiId.APIOSupported != 0)
|
||||
{
|
||||
report.ATAPI.APIOSupported = atapiId.APIOSupported;
|
||||
report.ATAPI.APIOSupportedSpecified = true;
|
||||
}
|
||||
if(atapiId.ATAPIByteCount != 0)
|
||||
{
|
||||
report.ATAPI.ATAPIByteCount = atapiId.ATAPIByteCount;
|
||||
report.ATAPI.ATAPIByteCountSpecified = true;
|
||||
}
|
||||
if(atapiId.BufferType != 0)
|
||||
{
|
||||
report.ATAPI.BufferType = atapiId.BufferType;
|
||||
report.ATAPI.BufferTypeSpecified = true;
|
||||
}
|
||||
if(atapiId.BufferSize != 0)
|
||||
{
|
||||
report.ATAPI.BufferSize = atapiId.BufferSize;
|
||||
report.ATAPI.BufferSizeSpecified = true;
|
||||
}
|
||||
if(atapiId.Capabilities != 0)
|
||||
{
|
||||
report.ATAPI.Capabilities = atapiId.Capabilities;
|
||||
report.ATAPI.CapabilitiesSpecified = true;
|
||||
}
|
||||
if(atapiId.Capabilities2 != 0)
|
||||
{
|
||||
report.ATAPI.Capabilities2 = atapiId.Capabilities2;
|
||||
report.ATAPI.Capabilities2Specified = true;
|
||||
}
|
||||
if(atapiId.Capabilities3 != 0)
|
||||
{
|
||||
report.ATAPI.Capabilities3 = atapiId.Capabilities3;
|
||||
report.ATAPI.Capabilities3Specified = true;
|
||||
}
|
||||
if(atapiId.CFAPowerMode != 0)
|
||||
{
|
||||
report.ATAPI.CFAPowerMode = atapiId.CFAPowerMode;
|
||||
report.ATAPI.CFAPowerModeSpecified = true;
|
||||
}
|
||||
if(atapiId.CommandSet != 0)
|
||||
{
|
||||
report.ATAPI.CommandSet = atapiId.CommandSet;
|
||||
report.ATAPI.CommandSetSpecified = true;
|
||||
}
|
||||
if(atapiId.CommandSet2 != 0)
|
||||
{
|
||||
report.ATAPI.CommandSet2 = atapiId.CommandSet2;
|
||||
report.ATAPI.CommandSet2Specified = true;
|
||||
}
|
||||
if(atapiId.CommandSet3 != 0)
|
||||
{
|
||||
report.ATAPI.CommandSet3 = atapiId.CommandSet3;
|
||||
report.ATAPI.CommandSet3Specified = true;
|
||||
}
|
||||
if(atapiId.CommandSet4 != 0)
|
||||
{
|
||||
report.ATAPI.CommandSet4 = atapiId.CommandSet4;
|
||||
report.ATAPI.CommandSet4Specified = true;
|
||||
}
|
||||
if(atapiId.CommandSet5 != 0)
|
||||
{
|
||||
report.ATAPI.CommandSet5 = atapiId.CommandSet5;
|
||||
report.ATAPI.CommandSet5Specified = true;
|
||||
}
|
||||
if(atapiId.CurrentAAM != 0)
|
||||
{
|
||||
report.ATAPI.CurrentAAM = atapiId.CurrentAAM;
|
||||
report.ATAPI.CurrentAAMSpecified = true;
|
||||
}
|
||||
if(atapiId.CurrentAPM != 0)
|
||||
{
|
||||
report.ATAPI.CurrentAPM = atapiId.CurrentAPM;
|
||||
report.ATAPI.CurrentAPMSpecified = true;
|
||||
}
|
||||
if(atapiId.DataSetMgmt != 0)
|
||||
{
|
||||
report.ATAPI.DataSetMgmt = atapiId.DataSetMgmt;
|
||||
report.ATAPI.DataSetMgmtSpecified = true;
|
||||
}
|
||||
if(atapiId.DataSetMgmtSize != 0)
|
||||
{
|
||||
report.ATAPI.DataSetMgmtSize = atapiId.DataSetMgmtSize;
|
||||
report.ATAPI.DataSetMgmtSizeSpecified = true;
|
||||
}
|
||||
if(atapiId.DeviceFormFactor != 0)
|
||||
{
|
||||
report.ATAPI.DeviceFormFactor = atapiId.DeviceFormFactor;
|
||||
report.ATAPI.DeviceFormFactorSpecified = true;
|
||||
}
|
||||
if(atapiId.DMAActive != 0)
|
||||
{
|
||||
report.ATAPI.DMAActive = atapiId.DMAActive;
|
||||
report.ATAPI.DMAActiveSpecified = true;
|
||||
}
|
||||
if(atapiId.DMASupported != 0)
|
||||
{
|
||||
report.ATAPI.DMASupported = atapiId.DMASupported;
|
||||
report.ATAPI.DMASupportedSpecified = true;
|
||||
}
|
||||
if(atapiId.DMATransferTimingMode != 0)
|
||||
{
|
||||
report.ATAPI.DMATransferTimingMode = atapiId.DMATransferTimingMode;
|
||||
report.ATAPI.DMATransferTimingModeSpecified = true;
|
||||
}
|
||||
if(atapiId.EnhancedSecurityEraseTime != 0)
|
||||
{
|
||||
report.ATAPI.EnhancedSecurityEraseTime = atapiId.EnhancedSecurityEraseTime;
|
||||
report.ATAPI.EnhancedSecurityEraseTimeSpecified = true;
|
||||
}
|
||||
if(atapiId.EnabledCommandSet != 0)
|
||||
{
|
||||
report.ATAPI.EnabledCommandSet = atapiId.EnabledCommandSet;
|
||||
report.ATAPI.EnabledCommandSetSpecified = true;
|
||||
}
|
||||
if(atapiId.EnabledCommandSet2 != 0)
|
||||
{
|
||||
report.ATAPI.EnabledCommandSet2 = atapiId.EnabledCommandSet2;
|
||||
report.ATAPI.EnabledCommandSet2Specified = true;
|
||||
}
|
||||
if(atapiId.EnabledCommandSet3 != 0)
|
||||
{
|
||||
report.ATAPI.EnabledCommandSet3 = atapiId.EnabledCommandSet3;
|
||||
report.ATAPI.EnabledCommandSet3Specified = true;
|
||||
}
|
||||
if(atapiId.EnabledCommandSet4 != 0)
|
||||
{
|
||||
report.ATAPI.EnabledCommandSet4 = atapiId.EnabledCommandSet4;
|
||||
report.ATAPI.EnabledCommandSet4Specified = true;
|
||||
}
|
||||
if(atapiId.EnabledSATAFeatures != 0)
|
||||
{
|
||||
report.ATAPI.EnabledSATAFeatures = atapiId.EnabledSATAFeatures;
|
||||
report.ATAPI.EnabledSATAFeaturesSpecified = true;
|
||||
}
|
||||
if(atapiId.ExtendedUserSectors != 0)
|
||||
{
|
||||
report.ATAPI.ExtendedUserSectors = atapiId.ExtendedUserSectors;
|
||||
report.ATAPI.ExtendedUserSectorsSpecified = true;
|
||||
}
|
||||
if(atapiId.FreeFallSensitivity != 0)
|
||||
{
|
||||
report.ATAPI.FreeFallSensitivity = atapiId.FreeFallSensitivity;
|
||||
report.ATAPI.FreeFallSensitivitySpecified = true;
|
||||
}
|
||||
if(!string.IsNullOrWhiteSpace(atapiId.FirmwareRevision))
|
||||
{
|
||||
report.ATAPI.FirmwareRevision = atapiId.FirmwareRevision;
|
||||
report.ATAPI.FirmwareRevisionSpecified = true;
|
||||
}
|
||||
if(atapiId.GeneralConfiguration != 0)
|
||||
{
|
||||
report.ATAPI.GeneralConfiguration = atapiId.GeneralConfiguration;
|
||||
report.ATAPI.GeneralConfigurationSpecified = true;
|
||||
}
|
||||
if(atapiId.HardwareResetResult != 0)
|
||||
{
|
||||
report.ATAPI.HardwareResetResult = atapiId.HardwareResetResult;
|
||||
report.ATAPI.HardwareResetResultSpecified = true;
|
||||
}
|
||||
if(atapiId.InterseekDelay != 0)
|
||||
{
|
||||
report.ATAPI.InterseekDelay = atapiId.InterseekDelay;
|
||||
report.ATAPI.InterseekDelaySpecified = true;
|
||||
}
|
||||
if(atapiId.MajorVersion != 0)
|
||||
{
|
||||
report.ATAPI.MajorVersion = atapiId.MajorVersion;
|
||||
report.ATAPI.MajorVersionSpecified = true;
|
||||
}
|
||||
if(atapiId.MasterPasswordRevisionCode != 0)
|
||||
{
|
||||
report.ATAPI.MasterPasswordRevisionCode = atapiId.MasterPasswordRevisionCode;
|
||||
report.ATAPI.MasterPasswordRevisionCodeSpecified = true;
|
||||
}
|
||||
if(atapiId.MaxDownloadMicroMode3 != 0)
|
||||
{
|
||||
report.ATAPI.MaxDownloadMicroMode3 = atapiId.MaxDownloadMicroMode3;
|
||||
report.ATAPI.MaxDownloadMicroMode3Specified = true;
|
||||
}
|
||||
if(atapiId.MaxQueueDepth != 0)
|
||||
{
|
||||
report.ATAPI.MaxQueueDepth = atapiId.MaxQueueDepth;
|
||||
report.ATAPI.MaxQueueDepthSpecified = true;
|
||||
}
|
||||
if(atapiId.MDMAActive != 0)
|
||||
{
|
||||
report.ATAPI.MDMAActive = atapiId.MDMAActive;
|
||||
report.ATAPI.MDMAActiveSpecified = true;
|
||||
}
|
||||
if(atapiId.MDMASupported != 0)
|
||||
{
|
||||
report.ATAPI.MDMASupported = atapiId.MDMASupported;
|
||||
report.ATAPI.MDMASupportedSpecified = true;
|
||||
}
|
||||
if(atapiId.MinDownloadMicroMode3 != 0)
|
||||
{
|
||||
report.ATAPI.MinDownloadMicroMode3 = atapiId.MinDownloadMicroMode3;
|
||||
report.ATAPI.MinDownloadMicroMode3Specified = true;
|
||||
}
|
||||
if(atapiId.MinMDMACycleTime != 0)
|
||||
{
|
||||
report.ATAPI.MinMDMACycleTime = atapiId.MinMDMACycleTime;
|
||||
report.ATAPI.MinMDMACycleTimeSpecified = true;
|
||||
}
|
||||
if(atapiId.MinorVersion != 0)
|
||||
{
|
||||
report.ATAPI.MinorVersion = atapiId.MinorVersion;
|
||||
report.ATAPI.MinorVersionSpecified = true;
|
||||
}
|
||||
if(atapiId.MinPIOCycleTimeNoFlow != 0)
|
||||
{
|
||||
report.ATAPI.MinPIOCycleTimeNoFlow = atapiId.MinPIOCycleTimeNoFlow;
|
||||
report.ATAPI.MinPIOCycleTimeNoFlowSpecified = true;
|
||||
}
|
||||
if(atapiId.MinPIOCycleTimeFlow != 0)
|
||||
{
|
||||
report.ATAPI.MinPIOCycleTimeFlow = atapiId.MinPIOCycleTimeFlow;
|
||||
report.ATAPI.MinPIOCycleTimeFlowSpecified = true;
|
||||
}
|
||||
if(!string.IsNullOrWhiteSpace(atapiId.Model))
|
||||
{
|
||||
report.ATAPI.Model = atapiId.Model;
|
||||
report.ATAPI.ModelSpecified = true;
|
||||
}
|
||||
if(atapiId.MultipleMaxSectors != 0)
|
||||
{
|
||||
report.ATAPI.MultipleMaxSectors = atapiId.MultipleMaxSectors;
|
||||
report.ATAPI.MultipleMaxSectorsSpecified = true;
|
||||
}
|
||||
if(atapiId.MultipleSectorNumber != 0)
|
||||
{
|
||||
report.ATAPI.MultipleSectorNumber = atapiId.MultipleSectorNumber;
|
||||
report.ATAPI.MultipleSectorNumberSpecified = true;
|
||||
}
|
||||
if(atapiId.NVCacheCaps != 0)
|
||||
{
|
||||
report.ATAPI.NVCacheCaps = atapiId.NVCacheCaps;
|
||||
report.ATAPI.NVCacheCapsSpecified = true;
|
||||
}
|
||||
if(atapiId.NVCacheSize != 0)
|
||||
{
|
||||
report.ATAPI.NVCacheSize = atapiId.NVCacheSize;
|
||||
report.ATAPI.NVCacheSizeSpecified = true;
|
||||
}
|
||||
if(atapiId.NVCacheWriteSpeed != 0)
|
||||
{
|
||||
report.ATAPI.NVCacheWriteSpeed = atapiId.NVCacheWriteSpeed;
|
||||
report.ATAPI.NVCacheWriteSpeedSpecified = true;
|
||||
}
|
||||
if(atapiId.NVEstimatedSpinUp != 0)
|
||||
{
|
||||
report.ATAPI.NVEstimatedSpinUp = atapiId.NVEstimatedSpinUp;
|
||||
report.ATAPI.NVEstimatedSpinUpSpecified = true;
|
||||
}
|
||||
if(atapiId.PacketBusRelease != 0)
|
||||
{
|
||||
report.ATAPI.PacketBusRelease = atapiId.PacketBusRelease;
|
||||
report.ATAPI.PacketBusReleaseSpecified = true;
|
||||
}
|
||||
if(atapiId.PIOTransferTimingMode != 0)
|
||||
{
|
||||
report.ATAPI.PIOTransferTimingMode = atapiId.PIOTransferTimingMode;
|
||||
report.ATAPI.PIOTransferTimingModeSpecified = true;
|
||||
}
|
||||
if(atapiId.RecommendedAAM != 0)
|
||||
{
|
||||
report.ATAPI.RecommendedAAM = atapiId.RecommendedAAM;
|
||||
report.ATAPI.RecommendedAAMSpecified = true;
|
||||
}
|
||||
if(atapiId.RecMDMACycleTime != 0)
|
||||
{
|
||||
report.ATAPI.RecommendedMDMACycleTime = atapiId.RecMDMACycleTime;
|
||||
report.ATAPI.RecommendedMDMACycleTimeSpecified = true;
|
||||
}
|
||||
if(atapiId.RemovableStatusSet != 0)
|
||||
{
|
||||
report.ATAPI.RemovableStatusSet = atapiId.RemovableStatusSet;
|
||||
report.ATAPI.RemovableStatusSetSpecified = true;
|
||||
}
|
||||
if(atapiId.SATACapabilities != 0)
|
||||
{
|
||||
report.ATAPI.SATACapabilities = atapiId.SATACapabilities;
|
||||
report.ATAPI.SATACapabilitiesSpecified = true;
|
||||
}
|
||||
if(atapiId.SATACapabilities2 != 0)
|
||||
{
|
||||
report.ATAPI.SATACapabilities2 = atapiId.SATACapabilities2;
|
||||
report.ATAPI.SATACapabilities2Specified = true;
|
||||
}
|
||||
if(atapiId.SATAFeatures != 0)
|
||||
{
|
||||
report.ATAPI.SATAFeatures = atapiId.SATAFeatures;
|
||||
report.ATAPI.SATAFeaturesSpecified = true;
|
||||
}
|
||||
if(atapiId.SCTCommandTransport != 0)
|
||||
{
|
||||
report.ATAPI.SCTCommandTransport = atapiId.SCTCommandTransport;
|
||||
report.ATAPI.SCTCommandTransportSpecified = true;
|
||||
}
|
||||
if(atapiId.SectorsPerCard != 0)
|
||||
{
|
||||
report.ATAPI.SectorsPerCard = atapiId.SectorsPerCard;
|
||||
report.ATAPI.SectorsPerCardSpecified = true;
|
||||
}
|
||||
if(atapiId.SecurityEraseTime != 0)
|
||||
{
|
||||
report.ATAPI.SecurityEraseTime = atapiId.SecurityEraseTime;
|
||||
report.ATAPI.SecurityEraseTimeSpecified = true;
|
||||
}
|
||||
if(atapiId.SecurityStatus != 0)
|
||||
{
|
||||
report.ATAPI.SecurityStatus = atapiId.SecurityStatus;
|
||||
report.ATAPI.SecurityStatusSpecified = true;
|
||||
}
|
||||
if(atapiId.ServiceBusyClear != 0)
|
||||
{
|
||||
report.ATAPI.ServiceBusyClear = atapiId.ServiceBusyClear;
|
||||
report.ATAPI.ServiceBusyClearSpecified = true;
|
||||
}
|
||||
if(atapiId.SpecificConfiguration != 0)
|
||||
{
|
||||
report.ATAPI.SpecificConfiguration = atapiId.SpecificConfiguration;
|
||||
report.ATAPI.SpecificConfigurationSpecified = true;
|
||||
}
|
||||
if(atapiId.StreamAccessLatency != 0)
|
||||
{
|
||||
report.ATAPI.StreamAccessLatency = atapiId.StreamAccessLatency;
|
||||
report.ATAPI.StreamAccessLatencySpecified = true;
|
||||
}
|
||||
if(atapiId.StreamMinReqSize != 0)
|
||||
{
|
||||
report.ATAPI.StreamMinReqSize = atapiId.StreamMinReqSize;
|
||||
report.ATAPI.StreamMinReqSizeSpecified = true;
|
||||
}
|
||||
if(atapiId.StreamPerformanceGranularity != 0)
|
||||
{
|
||||
report.ATAPI.StreamPerformanceGranularity = atapiId.StreamPerformanceGranularity;
|
||||
report.ATAPI.StreamPerformanceGranularitySpecified = true;
|
||||
}
|
||||
if(atapiId.StreamTransferTimeDMA != 0)
|
||||
{
|
||||
report.ATAPI.StreamTransferTimeDMA = atapiId.StreamTransferTimeDMA;
|
||||
report.ATAPI.StreamTransferTimeDMASpecified = true;
|
||||
}
|
||||
if(atapiId.StreamTransferTimePIO != 0)
|
||||
{
|
||||
report.ATAPI.StreamTransferTimePIO = atapiId.StreamTransferTimePIO;
|
||||
report.ATAPI.StreamTransferTimePIOSpecified = true;
|
||||
}
|
||||
if(atapiId.TransportMajorVersion != 0)
|
||||
{
|
||||
report.ATAPI.TransportMajorVersion = atapiId.TransportMajorVersion;
|
||||
report.ATAPI.TransportMajorVersionSpecified = true;
|
||||
}
|
||||
if(atapiId.TransportMinorVersion != 0)
|
||||
{
|
||||
report.ATAPI.TransportMinorVersion = atapiId.TransportMinorVersion;
|
||||
report.ATAPI.TransportMinorVersionSpecified = true;
|
||||
}
|
||||
if(atapiId.TrustedComputing != 0)
|
||||
{
|
||||
report.ATAPI.TrustedComputing = atapiId.TrustedComputing;
|
||||
report.ATAPI.TrustedComputingSpecified = true;
|
||||
}
|
||||
if(atapiId.UDMAActive != 0)
|
||||
{
|
||||
report.ATAPI.UDMAActive = atapiId.UDMAActive;
|
||||
report.ATAPI.UDMAActiveSpecified = true;
|
||||
}
|
||||
if(atapiId.UDMASupported != 0)
|
||||
{
|
||||
report.ATAPI.UDMASupported = atapiId.UDMASupported;
|
||||
report.ATAPI.UDMASupportedSpecified = true;
|
||||
}
|
||||
if(atapiId.WRVMode != 0)
|
||||
{
|
||||
report.ATAPI.WRVMode = atapiId.WRVMode;
|
||||
report.ATAPI.WRVModeSpecified = true;
|
||||
}
|
||||
if(atapiId.WRVSectorCountMode3 != 0)
|
||||
{
|
||||
report.ATAPI.WRVSectorCountMode3 = atapiId.WRVSectorCountMode3;
|
||||
report.ATAPI.WRVSectorCountMode3Specified = true;
|
||||
}
|
||||
if(atapiId.WRVSectorCountMode2 != 0)
|
||||
{
|
||||
report.ATAPI.WRVSectorCountMode2 = atapiId.WRVSectorCountMode2;
|
||||
report.ATAPI.WRVSectorCountMode2Specified = true;
|
||||
}
|
||||
}
|
||||
if(debug) report.ATAPI.Identify = buffer;
|
||||
}
|
||||
|
||||
@@ -58,8 +58,6 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
sense = dev.AtaIdentify(out cmdBuf, out errorChs);
|
||||
if(!sense && Identify.Decode(cmdBuf).HasValue)
|
||||
{
|
||||
Identify.IdentifyDevice ataId = Identify.Decode(cmdBuf).Value;
|
||||
|
||||
// Initializate reader
|
||||
Reader ataReader = new Reader(dev, timeout, cmdBuf);
|
||||
// Fill reader blocks
|
||||
|
||||
Reference in New Issue
Block a user