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);
|
sense = dev.AtaIdentify(out byte[] cmdBuf, out AtaErrorRegistersCHS errorChs);
|
||||||
if(!sense && Identify.Decode(cmdBuf).HasValue)
|
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 =
|
CICMMetadataType sidecar =
|
||||||
new CICMMetadataType {BlockMedia = new[] {new BlockMediaType()}};
|
new CICMMetadataType {BlockMedia = new[] {new BlockMediaType()}};
|
||||||
|
|
||||||
if(dev.IsUsb)
|
if(dev.IsUsb)
|
||||||
{
|
|
||||||
dumpLog.WriteLine("Reading USB descriptors.");
|
|
||||||
sidecar.BlockMedia[0].USB = new USBType
|
|
||||||
{
|
{
|
||||||
ProductID = dev.UsbProductId,
|
dumpLog.WriteLine("Reading USB descriptors.");
|
||||||
VendorID = dev.UsbVendorId,
|
sidecar.BlockMedia[0].USB = new USBType
|
||||||
Descriptors = new DumpType
|
|
||||||
{
|
{
|
||||||
Image = outputPrefix + ".usbdescriptors.bin",
|
ProductID = dev.UsbProductId,
|
||||||
Size = dev.UsbDescriptors.Length,
|
VendorID = dev.UsbVendorId,
|
||||||
Checksums = Checksum.GetChecksums(dev.UsbDescriptors).ToArray()
|
Descriptors = new DumpType
|
||||||
}
|
{
|
||||||
};
|
Image = outputPrefix + ".usbdescriptors.bin",
|
||||||
DataFile.WriteTo("ATA Dump", sidecar.BlockMedia[0].USB.Descriptors.Image, dev.UsbDescriptors);
|
Size = dev.UsbDescriptors.Length,
|
||||||
}
|
Checksums = Checksum.GetChecksums(dev.UsbDescriptors).ToArray()
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
DataFile.WriteTo("ATA Dump", sidecar.BlockMedia[0].USB.Descriptors.Image, dev.UsbDescriptors);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
end = DateTime.Now;
|
if(dev.IsPcmcia)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
int pass = 0;
|
dumpLog.WriteLine("Reading PCMCIA CIS.");
|
||||||
bool forward = true;
|
sidecar.BlockMedia[0].PCMCIA = new PCMCIAType
|
||||||
bool runningPersistent = false;
|
{
|
||||||
|
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:
|
if(manfid != null)
|
||||||
ulong[] tmpArray = resume.BadBlocks.ToArray();
|
{
|
||||||
foreach(ulong badSector in tmpArray)
|
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)
|
if(aborted)
|
||||||
{
|
{
|
||||||
@@ -310,53 +249,61 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
DicConsole.Write("\rRetrying sector {0}, pass {1}, {3}{2}", badSector, pass + 1,
|
if(blocks - i < blocksToRead) blocksToRead = (byte)(blocks - i);
|
||||||
forward ? "forward" : "reverse",
|
|
||||||
runningPersistent ? "recovering partial data, " : "");
|
|
||||||
|
|
||||||
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)
|
if(!error)
|
||||||
{
|
{
|
||||||
resume.BadBlocks.Remove(badSector);
|
mhddLog.Write(i, duration);
|
||||||
extents.Add(badSector);
|
ibgLog.Write(i, currentSpeed * 1024);
|
||||||
dumpFile.WriteAt(cmdBuf, badSector, blockSize);
|
dumpFile.Write(cmdBuf);
|
||||||
dumpLog.WriteLine("Correctly retried block {0} in pass {1}.", badSector, pass);
|
extents.Add(i, blocksToRead, true);
|
||||||
}
|
}
|
||||||
else if(runningPersistent) dumpFile.WriteAt(cmdBuf, badSector, blockSize);
|
else
|
||||||
}
|
{
|
||||||
|
for(ulong b = i; b < i + blocksToRead; b++) resume.BadBlocks.Add(b);
|
||||||
if(pass < retryPasses && !aborted && resume.BadBlocks.Count > 0)
|
|
||||||
{
|
if(duration < 500) mhddLog.Write(i, 65535);
|
||||||
pass++;
|
else mhddLog.Write(i, duration);
|
||||||
forward = !forward;
|
|
||||||
resume.BadBlocks.Sort();
|
ibgLog.Write(i, 0);
|
||||||
resume.BadBlocks.Reverse();
|
dumpFile.Write(new byte[blockSize * blocksToRead]);
|
||||||
goto repeatRetryLba;
|
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();
|
DicConsole.WriteLine();
|
||||||
}
|
mhddLog.Close();
|
||||||
#endregion Error handling LBA
|
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);
|
#region Error handling
|
||||||
}
|
if(resume.BadBlocks.Count > 0 && !aborted)
|
||||||
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++)
|
int pass = 0;
|
||||||
|
bool forward = true;
|
||||||
|
bool runningPersistent = false;
|
||||||
|
|
||||||
|
repeatRetryLba:
|
||||||
|
ulong[] tmpArray = resume.BadBlocks.ToArray();
|
||||||
|
foreach(ulong badSector in tmpArray)
|
||||||
{
|
{
|
||||||
if(aborted)
|
if(aborted)
|
||||||
{
|
{
|
||||||
@@ -365,143 +312,233 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
|
DicConsole.Write("\rRetrying sector {0}, pass {1}, {3}{2}", badSector, pass + 1,
|
||||||
if(currentSpeed > maxSpeed && currentSpeed != 0) maxSpeed = currentSpeed;
|
forward ? "forward" : "reverse",
|
||||||
if(currentSpeed < minSpeed && currentSpeed != 0) minSpeed = currentSpeed;
|
runningPersistent ? "recovering partial data, " : "");
|
||||||
#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,
|
bool error = ataReader.ReadBlock(out cmdBuf, badSector, out duration);
|
||||||
sc, currentSpeed);
|
|
||||||
|
|
||||||
bool error = ataReader.ReadChs(out cmdBuf, cy, hd, sc, out duration);
|
|
||||||
|
|
||||||
totalDuration += duration;
|
totalDuration += duration;
|
||||||
|
|
||||||
if(!error)
|
if(!error)
|
||||||
{
|
{
|
||||||
mhddLog.Write(currentBlock, duration);
|
resume.BadBlocks.Remove(badSector);
|
||||||
ibgLog.Write(currentBlock, currentSpeed * 1024);
|
extents.Add(badSector);
|
||||||
dumpFile.Write(cmdBuf);
|
dumpFile.WriteAt(cmdBuf, badSector, blockSize);
|
||||||
extents.Add(currentBlock);
|
dumpLog.WriteLine("Correctly retried block {0} in pass {1}.", badSector, pass);
|
||||||
dumpLog.WriteLine("Error reading cylinder {0} head {1} sector {2}.", cy, hd, sc);
|
|
||||||
}
|
}
|
||||||
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(aborted)
|
||||||
if(duration < 500) mhddLog.Write(currentBlock, 65535);
|
{
|
||||||
else mhddLog.Write(currentBlock, duration);
|
currentTry.Extents = ExtentsConverter.ToMetadata(extents);
|
||||||
|
dumpLog.WriteLine("Aborted!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
ibgLog.Write(currentBlock, 0);
|
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
|
||||||
dumpFile.Write(new byte[blockSize]);
|
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;
|
dataChk = new Checksum();
|
||||||
DicConsole.WriteLine();
|
dumpFile.Seek(0, SeekOrigin.Begin);
|
||||||
mhddLog.Close();
|
blocksToRead = 500;
|
||||||
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();
|
dumpLog.WriteLine("Checksum starts.");
|
||||||
dumpFile.Seek(0, SeekOrigin.Begin);
|
for(ulong i = 0; i < blocks; i += blocksToRead)
|
||||||
blocksToRead = 500;
|
|
||||||
|
|
||||||
dumpLog.WriteLine("Checksum starts.");
|
|
||||||
for(ulong i = 0; i < blocks; i += blocksToRead)
|
|
||||||
{
|
|
||||||
if(aborted)
|
|
||||||
{
|
{
|
||||||
dumpLog.WriteLine("Aborted!");
|
if(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++)
|
|
||||||
{
|
{
|
||||||
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,
|
xmlFileSysInfo[i] = new PartitionType
|
||||||
EndSector = (int)(partitions[i].Start + partitions[i].Length - 1),
|
{
|
||||||
Name = partitions[i].Name,
|
Description = partitions[i].Description,
|
||||||
Sequence = (int)partitions[i].Sequence,
|
EndSector = (int)(partitions[i].Start + partitions[i].Length - 1),
|
||||||
StartSector = (int)partitions[i].Start,
|
Name = partitions[i].Name,
|
||||||
Type = partitions[i].Type
|
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>();
|
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}.",
|
Partition wholePart = new Partition
|
||||||
i, partitions[i].Start, partitions[i].End, partitions[i].Type,
|
{
|
||||||
partitions[i].Scheme);
|
Name = "Whole device",
|
||||||
|
Length = blocks,
|
||||||
|
Size = blocks * blockSize
|
||||||
|
};
|
||||||
|
|
||||||
foreach(Filesystem plugin in plugins.PluginsList.Values)
|
foreach(Filesystem plugin in plugins.PluginsList.Values)
|
||||||
try
|
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);
|
lstFs.Add(plugin.XmlFSType);
|
||||||
Statistics.AddFilesystem(plugin.XmlFSType.Type);
|
Statistics.AddFilesystem(plugin.XmlFSType.Type);
|
||||||
dumpLog.WriteLine("Filesystem {0} found.", plugin.XmlFSType.Type);
|
dumpLog.WriteLine("Filesystem {0} found.", plugin.XmlFSType.Type);
|
||||||
@@ -510,104 +547,70 @@ namespace DiscImageChef.Core.Devices.Dumping
|
|||||||
catch
|
catch
|
||||||
#pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body
|
#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.");
|
format = "Raw disk image (sector by sector copy)",
|
||||||
|
Value = outputPrefix + ".bin"
|
||||||
xmlFileSysInfo = new PartitionType[1];
|
};
|
||||||
xmlFileSysInfo[0] = new PartitionType {EndSector = (int)(blocks - 1), StartSector = 0};
|
sidecar.BlockMedia[0].Interface = "ATA";
|
||||||
List<FileSystemType> lstFs = new List<FileSystemType>();
|
sidecar.BlockMedia[0].LogicalBlocks = (long)blocks;
|
||||||
|
sidecar.BlockMedia[0].PhysicalBlockSize = (int)physicalsectorsize;
|
||||||
Partition wholePart = new Partition
|
sidecar.BlockMedia[0].LogicalBlockSize = (int)blockSize;
|
||||||
{
|
sidecar.BlockMedia[0].Manufacturer = dev.Manufacturer;
|
||||||
Name = "Whole device",
|
sidecar.BlockMedia[0].Model = dev.Model;
|
||||||
Length = blocks,
|
sidecar.BlockMedia[0].Serial = dev.Serial;
|
||||||
Size = blocks * blockSize
|
sidecar.BlockMedia[0].Size = (long)(blocks * blockSize);
|
||||||
};
|
if(xmlFileSysInfo != null) sidecar.BlockMedia[0].FileSystemInformation = xmlFileSysInfo;
|
||||||
|
if(cylinders > 0 && heads > 0 && sectors > 0)
|
||||||
foreach(Filesystem plugin in plugins.PluginsList.Values)
|
{
|
||||||
try
|
sidecar.BlockMedia[0].Cylinders = cylinders;
|
||||||
{
|
sidecar.BlockMedia[0].CylindersSpecified = true;
|
||||||
if(!plugin.Identify(imageFormat, wholePart)) continue;
|
sidecar.BlockMedia[0].Heads = heads;
|
||||||
|
sidecar.BlockMedia[0].HeadsSpecified = true;
|
||||||
plugin.GetInformation(imageFormat, wholePart, out string foo);
|
sidecar.BlockMedia[0].SectorsPerTrack = sectors;
|
||||||
lstFs.Add(plugin.XmlFSType);
|
sidecar.BlockMedia[0].SectorsPerTrackSpecified = true;
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
sidecar.BlockMedia[0].Checksums = dataChk.End().ToArray();
|
DicConsole.WriteLine();
|
||||||
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("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).",
|
if(!aborted)
|
||||||
(end - start).TotalSeconds, totalDuration / 1000, totalChkDuration / 1000);
|
{
|
||||||
DicConsole.WriteLine("Avegare speed: {0:F3} MiB/sec.",
|
DicConsole.WriteLine("Writing metadata sidecar");
|
||||||
(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)
|
FileStream xmlFs = new FileStream(outputPrefix + ".cicm.xml", FileMode.Create);
|
||||||
{
|
|
||||||
DicConsole.WriteLine("Writing metadata sidecar");
|
|
||||||
|
|
||||||
FileStream xmlFs = new FileStream(outputPrefix + ".cicm.xml", FileMode.Create);
|
XmlSerializer xmlSer =
|
||||||
|
new XmlSerializer(typeof(CICMMetadataType));
|
||||||
XmlSerializer xmlSer =
|
xmlSer.Serialize(xmlFs, sidecar);
|
||||||
new XmlSerializer(typeof(CICMMetadataType));
|
xmlFs.Close();
|
||||||
xmlSer.Serialize(xmlFs, sidecar);
|
}
|
||||||
xmlFs.Close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Statistics.AddMedia(CommonTypes.MediaType.GENERIC_HDD, true);
|
Statistics.AddMedia(CommonTypes.MediaType.GENERIC_HDD, true);
|
||||||
|
|||||||
@@ -67,7 +67,8 @@ namespace DiscImageChef.Core.Devices
|
|||||||
switch(dev.Type)
|
switch(dev.Type)
|
||||||
{
|
{
|
||||||
case DeviceType.ATA:
|
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;
|
break;
|
||||||
case DeviceType.NVMe: throw new NotImplementedException("NVMe devices not yet supported.");
|
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;
|
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))
|
if(!string.IsNullOrWhiteSpace(atapiId.AdditionalPID))
|
||||||
{
|
{
|
||||||
report.ATAPI.AdditionalPID = atapiId.AdditionalPID;
|
report.ATAPI.AdditionalPID = atapiId.AdditionalPID;
|
||||||
report.ATAPI.AdditionalPIDSpecified = true;
|
report.ATAPI.AdditionalPIDSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.APIOSupported != 0)
|
if(atapiId.APIOSupported != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.APIOSupported = atapiId.APIOSupported;
|
report.ATAPI.APIOSupported = atapiId.APIOSupported;
|
||||||
report.ATAPI.APIOSupportedSpecified = true;
|
report.ATAPI.APIOSupportedSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.ATAPIByteCount != 0)
|
if(atapiId.ATAPIByteCount != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.ATAPIByteCount = atapiId.ATAPIByteCount;
|
report.ATAPI.ATAPIByteCount = atapiId.ATAPIByteCount;
|
||||||
report.ATAPI.ATAPIByteCountSpecified = true;
|
report.ATAPI.ATAPIByteCountSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.BufferType != 0)
|
if(atapiId.BufferType != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.BufferType = atapiId.BufferType;
|
report.ATAPI.BufferType = atapiId.BufferType;
|
||||||
report.ATAPI.BufferTypeSpecified = true;
|
report.ATAPI.BufferTypeSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.BufferSize != 0)
|
if(atapiId.BufferSize != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.BufferSize = atapiId.BufferSize;
|
report.ATAPI.BufferSize = atapiId.BufferSize;
|
||||||
report.ATAPI.BufferSizeSpecified = true;
|
report.ATAPI.BufferSizeSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.Capabilities != 0)
|
if(atapiId.Capabilities != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.Capabilities = atapiId.Capabilities;
|
report.ATAPI.Capabilities = atapiId.Capabilities;
|
||||||
report.ATAPI.CapabilitiesSpecified = true;
|
report.ATAPI.CapabilitiesSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.Capabilities2 != 0)
|
if(atapiId.Capabilities2 != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.Capabilities2 = atapiId.Capabilities2;
|
report.ATAPI.Capabilities2 = atapiId.Capabilities2;
|
||||||
report.ATAPI.Capabilities2Specified = true;
|
report.ATAPI.Capabilities2Specified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.Capabilities3 != 0)
|
if(atapiId.Capabilities3 != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.Capabilities3 = atapiId.Capabilities3;
|
report.ATAPI.Capabilities3 = atapiId.Capabilities3;
|
||||||
report.ATAPI.Capabilities3Specified = true;
|
report.ATAPI.Capabilities3Specified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.CFAPowerMode != 0)
|
if(atapiId.CFAPowerMode != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.CFAPowerMode = atapiId.CFAPowerMode;
|
report.ATAPI.CFAPowerMode = atapiId.CFAPowerMode;
|
||||||
report.ATAPI.CFAPowerModeSpecified = true;
|
report.ATAPI.CFAPowerModeSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.CommandSet != 0)
|
if(atapiId.CommandSet != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.CommandSet = atapiId.CommandSet;
|
report.ATAPI.CommandSet = atapiId.CommandSet;
|
||||||
report.ATAPI.CommandSetSpecified = true;
|
report.ATAPI.CommandSetSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.CommandSet2 != 0)
|
if(atapiId.CommandSet2 != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.CommandSet2 = atapiId.CommandSet2;
|
report.ATAPI.CommandSet2 = atapiId.CommandSet2;
|
||||||
report.ATAPI.CommandSet2Specified = true;
|
report.ATAPI.CommandSet2Specified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.CommandSet3 != 0)
|
if(atapiId.CommandSet3 != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.CommandSet3 = atapiId.CommandSet3;
|
report.ATAPI.CommandSet3 = atapiId.CommandSet3;
|
||||||
report.ATAPI.CommandSet3Specified = true;
|
report.ATAPI.CommandSet3Specified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.CommandSet4 != 0)
|
if(atapiId.CommandSet4 != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.CommandSet4 = atapiId.CommandSet4;
|
report.ATAPI.CommandSet4 = atapiId.CommandSet4;
|
||||||
report.ATAPI.CommandSet4Specified = true;
|
report.ATAPI.CommandSet4Specified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.CommandSet5 != 0)
|
if(atapiId.CommandSet5 != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.CommandSet5 = atapiId.CommandSet5;
|
report.ATAPI.CommandSet5 = atapiId.CommandSet5;
|
||||||
report.ATAPI.CommandSet5Specified = true;
|
report.ATAPI.CommandSet5Specified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.CurrentAAM != 0)
|
if(atapiId.CurrentAAM != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.CurrentAAM = atapiId.CurrentAAM;
|
report.ATAPI.CurrentAAM = atapiId.CurrentAAM;
|
||||||
report.ATAPI.CurrentAAMSpecified = true;
|
report.ATAPI.CurrentAAMSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.CurrentAPM != 0)
|
if(atapiId.CurrentAPM != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.CurrentAPM = atapiId.CurrentAPM;
|
report.ATAPI.CurrentAPM = atapiId.CurrentAPM;
|
||||||
report.ATAPI.CurrentAPMSpecified = true;
|
report.ATAPI.CurrentAPMSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.DataSetMgmt != 0)
|
if(atapiId.DataSetMgmt != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.DataSetMgmt = atapiId.DataSetMgmt;
|
report.ATAPI.DataSetMgmt = atapiId.DataSetMgmt;
|
||||||
report.ATAPI.DataSetMgmtSpecified = true;
|
report.ATAPI.DataSetMgmtSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.DataSetMgmtSize != 0)
|
if(atapiId.DataSetMgmtSize != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.DataSetMgmtSize = atapiId.DataSetMgmtSize;
|
report.ATAPI.DataSetMgmtSize = atapiId.DataSetMgmtSize;
|
||||||
report.ATAPI.DataSetMgmtSizeSpecified = true;
|
report.ATAPI.DataSetMgmtSizeSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.DeviceFormFactor != 0)
|
if(atapiId.DeviceFormFactor != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.DeviceFormFactor = atapiId.DeviceFormFactor;
|
report.ATAPI.DeviceFormFactor = atapiId.DeviceFormFactor;
|
||||||
report.ATAPI.DeviceFormFactorSpecified = true;
|
report.ATAPI.DeviceFormFactorSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.DMAActive != 0)
|
if(atapiId.DMAActive != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.DMAActive = atapiId.DMAActive;
|
report.ATAPI.DMAActive = atapiId.DMAActive;
|
||||||
report.ATAPI.DMAActiveSpecified = true;
|
report.ATAPI.DMAActiveSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.DMASupported != 0)
|
if(atapiId.DMASupported != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.DMASupported = atapiId.DMASupported;
|
report.ATAPI.DMASupported = atapiId.DMASupported;
|
||||||
report.ATAPI.DMASupportedSpecified = true;
|
report.ATAPI.DMASupportedSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.DMATransferTimingMode != 0)
|
if(atapiId.DMATransferTimingMode != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.DMATransferTimingMode = atapiId.DMATransferTimingMode;
|
report.ATAPI.DMATransferTimingMode = atapiId.DMATransferTimingMode;
|
||||||
report.ATAPI.DMATransferTimingModeSpecified = true;
|
report.ATAPI.DMATransferTimingModeSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.EnhancedSecurityEraseTime != 0)
|
if(atapiId.EnhancedSecurityEraseTime != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.EnhancedSecurityEraseTime = atapiId.EnhancedSecurityEraseTime;
|
report.ATAPI.EnhancedSecurityEraseTime = atapiId.EnhancedSecurityEraseTime;
|
||||||
report.ATAPI.EnhancedSecurityEraseTimeSpecified = true;
|
report.ATAPI.EnhancedSecurityEraseTimeSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.EnabledCommandSet != 0)
|
if(atapiId.EnabledCommandSet != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.EnabledCommandSet = atapiId.EnabledCommandSet;
|
report.ATAPI.EnabledCommandSet = atapiId.EnabledCommandSet;
|
||||||
report.ATAPI.EnabledCommandSetSpecified = true;
|
report.ATAPI.EnabledCommandSetSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.EnabledCommandSet2 != 0)
|
if(atapiId.EnabledCommandSet2 != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.EnabledCommandSet2 = atapiId.EnabledCommandSet2;
|
report.ATAPI.EnabledCommandSet2 = atapiId.EnabledCommandSet2;
|
||||||
report.ATAPI.EnabledCommandSet2Specified = true;
|
report.ATAPI.EnabledCommandSet2Specified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.EnabledCommandSet3 != 0)
|
if(atapiId.EnabledCommandSet3 != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.EnabledCommandSet3 = atapiId.EnabledCommandSet3;
|
report.ATAPI.EnabledCommandSet3 = atapiId.EnabledCommandSet3;
|
||||||
report.ATAPI.EnabledCommandSet3Specified = true;
|
report.ATAPI.EnabledCommandSet3Specified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.EnabledCommandSet4 != 0)
|
if(atapiId.EnabledCommandSet4 != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.EnabledCommandSet4 = atapiId.EnabledCommandSet4;
|
report.ATAPI.EnabledCommandSet4 = atapiId.EnabledCommandSet4;
|
||||||
report.ATAPI.EnabledCommandSet4Specified = true;
|
report.ATAPI.EnabledCommandSet4Specified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.EnabledSATAFeatures != 0)
|
if(atapiId.EnabledSATAFeatures != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.EnabledSATAFeatures = atapiId.EnabledSATAFeatures;
|
report.ATAPI.EnabledSATAFeatures = atapiId.EnabledSATAFeatures;
|
||||||
report.ATAPI.EnabledSATAFeaturesSpecified = true;
|
report.ATAPI.EnabledSATAFeaturesSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.ExtendedUserSectors != 0)
|
if(atapiId.ExtendedUserSectors != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.ExtendedUserSectors = atapiId.ExtendedUserSectors;
|
report.ATAPI.ExtendedUserSectors = atapiId.ExtendedUserSectors;
|
||||||
report.ATAPI.ExtendedUserSectorsSpecified = true;
|
report.ATAPI.ExtendedUserSectorsSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.FreeFallSensitivity != 0)
|
if(atapiId.FreeFallSensitivity != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.FreeFallSensitivity = atapiId.FreeFallSensitivity;
|
report.ATAPI.FreeFallSensitivity = atapiId.FreeFallSensitivity;
|
||||||
report.ATAPI.FreeFallSensitivitySpecified = true;
|
report.ATAPI.FreeFallSensitivitySpecified = true;
|
||||||
}
|
}
|
||||||
if(!string.IsNullOrWhiteSpace(atapiId.FirmwareRevision))
|
if(!string.IsNullOrWhiteSpace(atapiId.FirmwareRevision))
|
||||||
{
|
{
|
||||||
report.ATAPI.FirmwareRevision = atapiId.FirmwareRevision;
|
report.ATAPI.FirmwareRevision = atapiId.FirmwareRevision;
|
||||||
report.ATAPI.FirmwareRevisionSpecified = true;
|
report.ATAPI.FirmwareRevisionSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.GeneralConfiguration != 0)
|
if(atapiId.GeneralConfiguration != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.GeneralConfiguration = atapiId.GeneralConfiguration;
|
report.ATAPI.GeneralConfiguration = atapiId.GeneralConfiguration;
|
||||||
report.ATAPI.GeneralConfigurationSpecified = true;
|
report.ATAPI.GeneralConfigurationSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.HardwareResetResult != 0)
|
if(atapiId.HardwareResetResult != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.HardwareResetResult = atapiId.HardwareResetResult;
|
report.ATAPI.HardwareResetResult = atapiId.HardwareResetResult;
|
||||||
report.ATAPI.HardwareResetResultSpecified = true;
|
report.ATAPI.HardwareResetResultSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.InterseekDelay != 0)
|
if(atapiId.InterseekDelay != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.InterseekDelay = atapiId.InterseekDelay;
|
report.ATAPI.InterseekDelay = atapiId.InterseekDelay;
|
||||||
report.ATAPI.InterseekDelaySpecified = true;
|
report.ATAPI.InterseekDelaySpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.MajorVersion != 0)
|
if(atapiId.MajorVersion != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.MajorVersion = atapiId.MajorVersion;
|
report.ATAPI.MajorVersion = atapiId.MajorVersion;
|
||||||
report.ATAPI.MajorVersionSpecified = true;
|
report.ATAPI.MajorVersionSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.MasterPasswordRevisionCode != 0)
|
if(atapiId.MasterPasswordRevisionCode != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.MasterPasswordRevisionCode = atapiId.MasterPasswordRevisionCode;
|
report.ATAPI.MasterPasswordRevisionCode = atapiId.MasterPasswordRevisionCode;
|
||||||
report.ATAPI.MasterPasswordRevisionCodeSpecified = true;
|
report.ATAPI.MasterPasswordRevisionCodeSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.MaxDownloadMicroMode3 != 0)
|
if(atapiId.MaxDownloadMicroMode3 != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.MaxDownloadMicroMode3 = atapiId.MaxDownloadMicroMode3;
|
report.ATAPI.MaxDownloadMicroMode3 = atapiId.MaxDownloadMicroMode3;
|
||||||
report.ATAPI.MaxDownloadMicroMode3Specified = true;
|
report.ATAPI.MaxDownloadMicroMode3Specified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.MaxQueueDepth != 0)
|
if(atapiId.MaxQueueDepth != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.MaxQueueDepth = atapiId.MaxQueueDepth;
|
report.ATAPI.MaxQueueDepth = atapiId.MaxQueueDepth;
|
||||||
report.ATAPI.MaxQueueDepthSpecified = true;
|
report.ATAPI.MaxQueueDepthSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.MDMAActive != 0)
|
if(atapiId.MDMAActive != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.MDMAActive = atapiId.MDMAActive;
|
report.ATAPI.MDMAActive = atapiId.MDMAActive;
|
||||||
report.ATAPI.MDMAActiveSpecified = true;
|
report.ATAPI.MDMAActiveSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.MDMASupported != 0)
|
if(atapiId.MDMASupported != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.MDMASupported = atapiId.MDMASupported;
|
report.ATAPI.MDMASupported = atapiId.MDMASupported;
|
||||||
report.ATAPI.MDMASupportedSpecified = true;
|
report.ATAPI.MDMASupportedSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.MinDownloadMicroMode3 != 0)
|
if(atapiId.MinDownloadMicroMode3 != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.MinDownloadMicroMode3 = atapiId.MinDownloadMicroMode3;
|
report.ATAPI.MinDownloadMicroMode3 = atapiId.MinDownloadMicroMode3;
|
||||||
report.ATAPI.MinDownloadMicroMode3Specified = true;
|
report.ATAPI.MinDownloadMicroMode3Specified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.MinMDMACycleTime != 0)
|
if(atapiId.MinMDMACycleTime != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.MinMDMACycleTime = atapiId.MinMDMACycleTime;
|
report.ATAPI.MinMDMACycleTime = atapiId.MinMDMACycleTime;
|
||||||
report.ATAPI.MinMDMACycleTimeSpecified = true;
|
report.ATAPI.MinMDMACycleTimeSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.MinorVersion != 0)
|
if(atapiId.MinorVersion != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.MinorVersion = atapiId.MinorVersion;
|
report.ATAPI.MinorVersion = atapiId.MinorVersion;
|
||||||
report.ATAPI.MinorVersionSpecified = true;
|
report.ATAPI.MinorVersionSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.MinPIOCycleTimeNoFlow != 0)
|
if(atapiId.MinPIOCycleTimeNoFlow != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.MinPIOCycleTimeNoFlow = atapiId.MinPIOCycleTimeNoFlow;
|
report.ATAPI.MinPIOCycleTimeNoFlow = atapiId.MinPIOCycleTimeNoFlow;
|
||||||
report.ATAPI.MinPIOCycleTimeNoFlowSpecified = true;
|
report.ATAPI.MinPIOCycleTimeNoFlowSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.MinPIOCycleTimeFlow != 0)
|
if(atapiId.MinPIOCycleTimeFlow != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.MinPIOCycleTimeFlow = atapiId.MinPIOCycleTimeFlow;
|
report.ATAPI.MinPIOCycleTimeFlow = atapiId.MinPIOCycleTimeFlow;
|
||||||
report.ATAPI.MinPIOCycleTimeFlowSpecified = true;
|
report.ATAPI.MinPIOCycleTimeFlowSpecified = true;
|
||||||
}
|
}
|
||||||
if(!string.IsNullOrWhiteSpace(atapiId.Model))
|
if(!string.IsNullOrWhiteSpace(atapiId.Model))
|
||||||
{
|
{
|
||||||
report.ATAPI.Model = atapiId.Model;
|
report.ATAPI.Model = atapiId.Model;
|
||||||
report.ATAPI.ModelSpecified = true;
|
report.ATAPI.ModelSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.MultipleMaxSectors != 0)
|
if(atapiId.MultipleMaxSectors != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.MultipleMaxSectors = atapiId.MultipleMaxSectors;
|
report.ATAPI.MultipleMaxSectors = atapiId.MultipleMaxSectors;
|
||||||
report.ATAPI.MultipleMaxSectorsSpecified = true;
|
report.ATAPI.MultipleMaxSectorsSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.MultipleSectorNumber != 0)
|
if(atapiId.MultipleSectorNumber != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.MultipleSectorNumber = atapiId.MultipleSectorNumber;
|
report.ATAPI.MultipleSectorNumber = atapiId.MultipleSectorNumber;
|
||||||
report.ATAPI.MultipleSectorNumberSpecified = true;
|
report.ATAPI.MultipleSectorNumberSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.NVCacheCaps != 0)
|
if(atapiId.NVCacheCaps != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.NVCacheCaps = atapiId.NVCacheCaps;
|
report.ATAPI.NVCacheCaps = atapiId.NVCacheCaps;
|
||||||
report.ATAPI.NVCacheCapsSpecified = true;
|
report.ATAPI.NVCacheCapsSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.NVCacheSize != 0)
|
if(atapiId.NVCacheSize != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.NVCacheSize = atapiId.NVCacheSize;
|
report.ATAPI.NVCacheSize = atapiId.NVCacheSize;
|
||||||
report.ATAPI.NVCacheSizeSpecified = true;
|
report.ATAPI.NVCacheSizeSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.NVCacheWriteSpeed != 0)
|
if(atapiId.NVCacheWriteSpeed != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.NVCacheWriteSpeed = atapiId.NVCacheWriteSpeed;
|
report.ATAPI.NVCacheWriteSpeed = atapiId.NVCacheWriteSpeed;
|
||||||
report.ATAPI.NVCacheWriteSpeedSpecified = true;
|
report.ATAPI.NVCacheWriteSpeedSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.NVEstimatedSpinUp != 0)
|
if(atapiId.NVEstimatedSpinUp != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.NVEstimatedSpinUp = atapiId.NVEstimatedSpinUp;
|
report.ATAPI.NVEstimatedSpinUp = atapiId.NVEstimatedSpinUp;
|
||||||
report.ATAPI.NVEstimatedSpinUpSpecified = true;
|
report.ATAPI.NVEstimatedSpinUpSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.PacketBusRelease != 0)
|
if(atapiId.PacketBusRelease != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.PacketBusRelease = atapiId.PacketBusRelease;
|
report.ATAPI.PacketBusRelease = atapiId.PacketBusRelease;
|
||||||
report.ATAPI.PacketBusReleaseSpecified = true;
|
report.ATAPI.PacketBusReleaseSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.PIOTransferTimingMode != 0)
|
if(atapiId.PIOTransferTimingMode != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.PIOTransferTimingMode = atapiId.PIOTransferTimingMode;
|
report.ATAPI.PIOTransferTimingMode = atapiId.PIOTransferTimingMode;
|
||||||
report.ATAPI.PIOTransferTimingModeSpecified = true;
|
report.ATAPI.PIOTransferTimingModeSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.RecommendedAAM != 0)
|
if(atapiId.RecommendedAAM != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.RecommendedAAM = atapiId.RecommendedAAM;
|
report.ATAPI.RecommendedAAM = atapiId.RecommendedAAM;
|
||||||
report.ATAPI.RecommendedAAMSpecified = true;
|
report.ATAPI.RecommendedAAMSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.RecMDMACycleTime != 0)
|
if(atapiId.RecMDMACycleTime != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.RecommendedMDMACycleTime = atapiId.RecMDMACycleTime;
|
report.ATAPI.RecommendedMDMACycleTime = atapiId.RecMDMACycleTime;
|
||||||
report.ATAPI.RecommendedMDMACycleTimeSpecified = true;
|
report.ATAPI.RecommendedMDMACycleTimeSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.RemovableStatusSet != 0)
|
if(atapiId.RemovableStatusSet != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.RemovableStatusSet = atapiId.RemovableStatusSet;
|
report.ATAPI.RemovableStatusSet = atapiId.RemovableStatusSet;
|
||||||
report.ATAPI.RemovableStatusSetSpecified = true;
|
report.ATAPI.RemovableStatusSetSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.SATACapabilities != 0)
|
if(atapiId.SATACapabilities != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.SATACapabilities = atapiId.SATACapabilities;
|
report.ATAPI.SATACapabilities = atapiId.SATACapabilities;
|
||||||
report.ATAPI.SATACapabilitiesSpecified = true;
|
report.ATAPI.SATACapabilitiesSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.SATACapabilities2 != 0)
|
if(atapiId.SATACapabilities2 != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.SATACapabilities2 = atapiId.SATACapabilities2;
|
report.ATAPI.SATACapabilities2 = atapiId.SATACapabilities2;
|
||||||
report.ATAPI.SATACapabilities2Specified = true;
|
report.ATAPI.SATACapabilities2Specified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.SATAFeatures != 0)
|
if(atapiId.SATAFeatures != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.SATAFeatures = atapiId.SATAFeatures;
|
report.ATAPI.SATAFeatures = atapiId.SATAFeatures;
|
||||||
report.ATAPI.SATAFeaturesSpecified = true;
|
report.ATAPI.SATAFeaturesSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.SCTCommandTransport != 0)
|
if(atapiId.SCTCommandTransport != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.SCTCommandTransport = atapiId.SCTCommandTransport;
|
report.ATAPI.SCTCommandTransport = atapiId.SCTCommandTransport;
|
||||||
report.ATAPI.SCTCommandTransportSpecified = true;
|
report.ATAPI.SCTCommandTransportSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.SectorsPerCard != 0)
|
if(atapiId.SectorsPerCard != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.SectorsPerCard = atapiId.SectorsPerCard;
|
report.ATAPI.SectorsPerCard = atapiId.SectorsPerCard;
|
||||||
report.ATAPI.SectorsPerCardSpecified = true;
|
report.ATAPI.SectorsPerCardSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.SecurityEraseTime != 0)
|
if(atapiId.SecurityEraseTime != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.SecurityEraseTime = atapiId.SecurityEraseTime;
|
report.ATAPI.SecurityEraseTime = atapiId.SecurityEraseTime;
|
||||||
report.ATAPI.SecurityEraseTimeSpecified = true;
|
report.ATAPI.SecurityEraseTimeSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.SecurityStatus != 0)
|
if(atapiId.SecurityStatus != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.SecurityStatus = atapiId.SecurityStatus;
|
report.ATAPI.SecurityStatus = atapiId.SecurityStatus;
|
||||||
report.ATAPI.SecurityStatusSpecified = true;
|
report.ATAPI.SecurityStatusSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.ServiceBusyClear != 0)
|
if(atapiId.ServiceBusyClear != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.ServiceBusyClear = atapiId.ServiceBusyClear;
|
report.ATAPI.ServiceBusyClear = atapiId.ServiceBusyClear;
|
||||||
report.ATAPI.ServiceBusyClearSpecified = true;
|
report.ATAPI.ServiceBusyClearSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.SpecificConfiguration != 0)
|
if(atapiId.SpecificConfiguration != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.SpecificConfiguration = atapiId.SpecificConfiguration;
|
report.ATAPI.SpecificConfiguration = atapiId.SpecificConfiguration;
|
||||||
report.ATAPI.SpecificConfigurationSpecified = true;
|
report.ATAPI.SpecificConfigurationSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.StreamAccessLatency != 0)
|
if(atapiId.StreamAccessLatency != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.StreamAccessLatency = atapiId.StreamAccessLatency;
|
report.ATAPI.StreamAccessLatency = atapiId.StreamAccessLatency;
|
||||||
report.ATAPI.StreamAccessLatencySpecified = true;
|
report.ATAPI.StreamAccessLatencySpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.StreamMinReqSize != 0)
|
if(atapiId.StreamMinReqSize != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.StreamMinReqSize = atapiId.StreamMinReqSize;
|
report.ATAPI.StreamMinReqSize = atapiId.StreamMinReqSize;
|
||||||
report.ATAPI.StreamMinReqSizeSpecified = true;
|
report.ATAPI.StreamMinReqSizeSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.StreamPerformanceGranularity != 0)
|
if(atapiId.StreamPerformanceGranularity != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.StreamPerformanceGranularity = atapiId.StreamPerformanceGranularity;
|
report.ATAPI.StreamPerformanceGranularity = atapiId.StreamPerformanceGranularity;
|
||||||
report.ATAPI.StreamPerformanceGranularitySpecified = true;
|
report.ATAPI.StreamPerformanceGranularitySpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.StreamTransferTimeDMA != 0)
|
if(atapiId.StreamTransferTimeDMA != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.StreamTransferTimeDMA = atapiId.StreamTransferTimeDMA;
|
report.ATAPI.StreamTransferTimeDMA = atapiId.StreamTransferTimeDMA;
|
||||||
report.ATAPI.StreamTransferTimeDMASpecified = true;
|
report.ATAPI.StreamTransferTimeDMASpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.StreamTransferTimePIO != 0)
|
if(atapiId.StreamTransferTimePIO != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.StreamTransferTimePIO = atapiId.StreamTransferTimePIO;
|
report.ATAPI.StreamTransferTimePIO = atapiId.StreamTransferTimePIO;
|
||||||
report.ATAPI.StreamTransferTimePIOSpecified = true;
|
report.ATAPI.StreamTransferTimePIOSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.TransportMajorVersion != 0)
|
if(atapiId.TransportMajorVersion != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.TransportMajorVersion = atapiId.TransportMajorVersion;
|
report.ATAPI.TransportMajorVersion = atapiId.TransportMajorVersion;
|
||||||
report.ATAPI.TransportMajorVersionSpecified = true;
|
report.ATAPI.TransportMajorVersionSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.TransportMinorVersion != 0)
|
if(atapiId.TransportMinorVersion != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.TransportMinorVersion = atapiId.TransportMinorVersion;
|
report.ATAPI.TransportMinorVersion = atapiId.TransportMinorVersion;
|
||||||
report.ATAPI.TransportMinorVersionSpecified = true;
|
report.ATAPI.TransportMinorVersionSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.TrustedComputing != 0)
|
if(atapiId.TrustedComputing != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.TrustedComputing = atapiId.TrustedComputing;
|
report.ATAPI.TrustedComputing = atapiId.TrustedComputing;
|
||||||
report.ATAPI.TrustedComputingSpecified = true;
|
report.ATAPI.TrustedComputingSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.UDMAActive != 0)
|
if(atapiId.UDMAActive != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.UDMAActive = atapiId.UDMAActive;
|
report.ATAPI.UDMAActive = atapiId.UDMAActive;
|
||||||
report.ATAPI.UDMAActiveSpecified = true;
|
report.ATAPI.UDMAActiveSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.UDMASupported != 0)
|
if(atapiId.UDMASupported != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.UDMASupported = atapiId.UDMASupported;
|
report.ATAPI.UDMASupported = atapiId.UDMASupported;
|
||||||
report.ATAPI.UDMASupportedSpecified = true;
|
report.ATAPI.UDMASupportedSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.WRVMode != 0)
|
if(atapiId.WRVMode != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.WRVMode = atapiId.WRVMode;
|
report.ATAPI.WRVMode = atapiId.WRVMode;
|
||||||
report.ATAPI.WRVModeSpecified = true;
|
report.ATAPI.WRVModeSpecified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.WRVSectorCountMode3 != 0)
|
if(atapiId.WRVSectorCountMode3 != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.WRVSectorCountMode3 = atapiId.WRVSectorCountMode3;
|
report.ATAPI.WRVSectorCountMode3 = atapiId.WRVSectorCountMode3;
|
||||||
report.ATAPI.WRVSectorCountMode3Specified = true;
|
report.ATAPI.WRVSectorCountMode3Specified = true;
|
||||||
}
|
}
|
||||||
if(atapiId.WRVSectorCountMode2 != 0)
|
if(atapiId.WRVSectorCountMode2 != 0)
|
||||||
{
|
{
|
||||||
report.ATAPI.WRVSectorCountMode2 = atapiId.WRVSectorCountMode2;
|
report.ATAPI.WRVSectorCountMode2 = atapiId.WRVSectorCountMode2;
|
||||||
report.ATAPI.WRVSectorCountMode2Specified = true;
|
report.ATAPI.WRVSectorCountMode2Specified = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(debug) report.ATAPI.Identify = buffer;
|
if(debug) report.ATAPI.Identify = buffer;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,8 +58,6 @@ namespace DiscImageChef.Core.Devices.Scanning
|
|||||||
sense = dev.AtaIdentify(out cmdBuf, out errorChs);
|
sense = dev.AtaIdentify(out cmdBuf, out errorChs);
|
||||||
if(!sense && Identify.Decode(cmdBuf).HasValue)
|
if(!sense && Identify.Decode(cmdBuf).HasValue)
|
||||||
{
|
{
|
||||||
Identify.IdentifyDevice ataId = Identify.Decode(cmdBuf).Value;
|
|
||||||
|
|
||||||
// Initializate reader
|
// Initializate reader
|
||||||
Reader ataReader = new Reader(dev, timeout, cmdBuf);
|
Reader ataReader = new Reader(dev, timeout, cmdBuf);
|
||||||
// Fill reader blocks
|
// Fill reader blocks
|
||||||
|
|||||||
Reference in New Issue
Block a user