mirror of
https://github.com/aaru-dps/Aaru.Server.git
synced 2025-12-16 19:24:27 +00:00
REFACTOR: Reformat code.
This commit is contained in:
@@ -50,7 +50,9 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
public class ATA
|
||||
{
|
||||
public static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, ref Metadata.Resume resume, ref DumpLog dumpLog, Encoding encoding)
|
||||
public static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force,
|
||||
bool dumpRaw, bool persistent, bool stopOnError, ref Metadata.Resume resume,
|
||||
ref DumpLog dumpLog, Encoding encoding)
|
||||
{
|
||||
bool aborted;
|
||||
MHDDLog mhddLog;
|
||||
@@ -60,8 +62,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
DicConsole.ErrorWriteLine("Raw dumping not yet supported in ATA devices.");
|
||||
|
||||
if(force)
|
||||
DicConsole.ErrorWriteLine("Continuing...");
|
||||
if(force) DicConsole.ErrorWriteLine("Continuing...");
|
||||
else
|
||||
{
|
||||
DicConsole.ErrorWriteLine("Aborting...");
|
||||
@@ -80,10 +81,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
Decoders.ATA.Identify.IdentifyDevice ataId = Decoders.ATA.Identify.Decode(cmdBuf).Value;
|
||||
|
||||
CICMMetadataType sidecar = new CICMMetadataType()
|
||||
{
|
||||
BlockMedia = new BlockMediaType[] { new BlockMediaType() }
|
||||
};
|
||||
CICMMetadataType sidecar =
|
||||
new CICMMetadataType() {BlockMedia = new BlockMediaType[] {new BlockMediaType()}};
|
||||
|
||||
if(dev.IsUSB)
|
||||
{
|
||||
@@ -123,7 +122,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
if(tuple.Code == TupleCodes.CISTPL_MANFID)
|
||||
{
|
||||
ManufacturerIdentificationTuple manfid = CIS.DecodeManufacturerIdentificationTuple(tuple);
|
||||
ManufacturerIdentificationTuple manfid =
|
||||
CIS.DecodeManufacturerIdentificationTuple(tuple);
|
||||
|
||||
if(manfid != null)
|
||||
{
|
||||
@@ -141,7 +141,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
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.Compliance =
|
||||
string.Format("{0}.{1}", vers.MajorVersion, vers.MinorVersion);
|
||||
sidecar.BlockMedia[0].PCMCIA.AdditionalInformation = vers.AdditionalInformation;
|
||||
}
|
||||
}
|
||||
@@ -170,10 +171,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
Checksum dataChk;
|
||||
|
||||
aborted = false;
|
||||
System.Console.CancelKeyPress += (sender, e) =>
|
||||
{
|
||||
e.Cancel = aborted = true;
|
||||
};
|
||||
System.Console.CancelKeyPress += (sender, e) => { e.Cancel = aborted = true; };
|
||||
|
||||
DataFile dumpFile;
|
||||
|
||||
@@ -189,6 +187,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DicConsole.ErrorWriteLine(ataReader.ErrorMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
uint blockSize = ataReader.LogicalBlockSize;
|
||||
uint physicalsectorsize = ataReader.PhysicalBlockSize;
|
||||
if(ataReader.FindReadCommand())
|
||||
@@ -204,21 +203,27 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
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 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(Decoders.ATA.Identify.GeneralConfigurationBit.Removable));
|
||||
bool removable = false || (!dev.IsCompactFlash &&
|
||||
ataId.GeneralConfiguration.HasFlag(Decoders.ATA.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);
|
||||
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...");
|
||||
|
||||
@@ -229,8 +234,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
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);
|
||||
if(resume.NextBlock > 0) dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
|
||||
|
||||
dumpFile.Seek(resume.NextBlock, blockSize);
|
||||
|
||||
@@ -244,14 +248,11 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
break;
|
||||
}
|
||||
|
||||
if((blocks - i) < blocksToRead)
|
||||
blocksToRead = (byte)(blocks - i);
|
||||
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;
|
||||
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);
|
||||
@@ -267,12 +268,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
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);
|
||||
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]);
|
||||
@@ -285,14 +284,18 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
GC.Collect();
|
||||
resume.NextBlock = i + blocksToRead;
|
||||
}
|
||||
|
||||
end = DateTime.Now;
|
||||
DicConsole.WriteLine();
|
||||
mhddLog.Close();
|
||||
#pragma warning disable IDE0004 // Cast is necessary, otherwise incorrect value is created
|
||||
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024, (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000), devicePath);
|
||||
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
|
||||
(((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000),
|
||||
devicePath);
|
||||
#pragma warning restore IDE0004 // Cast is necessary, otherwise incorrect value is created
|
||||
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));
|
||||
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)
|
||||
@@ -301,7 +304,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
bool forward = true;
|
||||
bool runningPersistent = false;
|
||||
|
||||
repeatRetryLba:
|
||||
repeatRetryLba:
|
||||
ulong[] tmpArray = resume.BadBlocks.ToArray();
|
||||
foreach(ulong badSector in tmpArray)
|
||||
{
|
||||
@@ -312,7 +315,9 @@ 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, " : "");
|
||||
DicConsole.Write("\rRetrying sector {0}, pass {1}, {3}{2}", badSector, pass + 1,
|
||||
forward ? "forward" : "reverse",
|
||||
runningPersistent ? "recovering partial data, " : "");
|
||||
|
||||
bool error = ataReader.ReadBlock(out cmdBuf, badSector, out duration);
|
||||
|
||||
@@ -325,8 +330,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
dumpFile.WriteAt(cmdBuf, badSector, blockSize);
|
||||
dumpLog.WriteLine("Correctly retried block {0} in pass {1}.", badSector, pass);
|
||||
}
|
||||
else if(runningPersistent)
|
||||
dumpFile.WriteAt(cmdBuf, badSector, blockSize);
|
||||
else if(runningPersistent) dumpFile.WriteAt(cmdBuf, badSector, blockSize);
|
||||
}
|
||||
|
||||
if(pass < retryPasses && !aborted && resume.BadBlocks.Count > 0)
|
||||
@@ -367,13 +371,12 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
|
||||
#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;
|
||||
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);
|
||||
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);
|
||||
|
||||
@@ -390,10 +393,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
else
|
||||
{
|
||||
resume.BadBlocks.Add(currentBlock);
|
||||
if(duration < 500)
|
||||
mhddLog.Write(currentBlock, 65535);
|
||||
else
|
||||
mhddLog.Write(currentBlock, duration);
|
||||
if(duration < 500) mhddLog.Write(currentBlock, 65535);
|
||||
else mhddLog.Write(currentBlock, duration);
|
||||
|
||||
ibgLog.Write(currentBlock, 0);
|
||||
dumpFile.Write(new byte[blockSize]);
|
||||
@@ -408,15 +409,20 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
end = DateTime.Now;
|
||||
DicConsole.WriteLine();
|
||||
mhddLog.Close();
|
||||
#pragma warning disable IDE0004 // Cast is necessary, otherwise incorrect value is created
|
||||
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024, (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000), devicePath);
|
||||
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
|
||||
(((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000),
|
||||
devicePath);
|
||||
#pragma warning disable IDE0004 // Cast is necessary, otherwise incorrect value is created
|
||||
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));
|
||||
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;
|
||||
@@ -430,8 +436,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
break;
|
||||
}
|
||||
|
||||
if((blocks - i) < blocksToRead)
|
||||
blocksToRead = (byte)(blocks - i);
|
||||
if((blocks - i) < blocksToRead) blocksToRead = (byte)(blocks - i);
|
||||
|
||||
DicConsole.Write("\rChecksumming sector {0} of {1} ({2:F3} MiB/sec.)", i, blocks, currentSpeed);
|
||||
|
||||
@@ -446,11 +451,13 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
currentSpeed = ((double)blockSize * blocksToRead / (double)1048576) / (chkDuration / (double)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));
|
||||
dumpLog.WriteLine("Average checksum speed {0:F3} KiB/sec.",
|
||||
(((double)blockSize * (double)(blocks + 1)) / 1024) / (totalChkDuration / 1000));
|
||||
|
||||
PluginBase plugins = new PluginBase();
|
||||
plugins.RegisterAllPlugins(encoding);
|
||||
@@ -468,15 +475,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
_imageFormat = ImageFormat.Detect(inputFilter);
|
||||
PartitionType[] xmlFileSysInfo = null;
|
||||
|
||||
try
|
||||
{
|
||||
if(!_imageFormat.OpenImage(inputFilter))
|
||||
_imageFormat = null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
_imageFormat = null;
|
||||
}
|
||||
try { if(!_imageFormat.OpenImage(inputFilter)) _imageFormat = null; }
|
||||
catch { _imageFormat = null; }
|
||||
|
||||
if(_imageFormat != null)
|
||||
{
|
||||
@@ -500,8 +500,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
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);
|
||||
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)
|
||||
{
|
||||
@@ -523,8 +525,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
}
|
||||
|
||||
if(lstFs.Count > 0)
|
||||
xmlFileSysInfo[i].FileSystems = lstFs.ToArray();
|
||||
if(lstFs.Count > 0) xmlFileSysInfo[i].FileSystems = lstFs.ToArray();
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -532,11 +533,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
dumpLog.WriteLine("Getting filesystem for whole device.");
|
||||
|
||||
xmlFileSysInfo = new PartitionType[1];
|
||||
xmlFileSysInfo[0] = new PartitionType
|
||||
{
|
||||
EndSector = (int)(blocks - 1),
|
||||
StartSector = 0
|
||||
};
|
||||
xmlFileSysInfo[0] = new PartitionType {EndSector = (int)(blocks - 1), StartSector = 0};
|
||||
List<FileSystemType> lstFs = new List<FileSystemType>();
|
||||
|
||||
Partition wholePart = new Partition
|
||||
@@ -566,8 +563,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
}
|
||||
|
||||
if(lstFs.Count > 0)
|
||||
xmlFileSysInfo[0].FileSystems = lstFs.ToArray();
|
||||
if(lstFs.Count > 0) xmlFileSysInfo[0].FileSystems = lstFs.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -577,8 +573,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
Metadata.MediaType.MediaTypeToString(MediaType.CompactFlash, out xmlDskTyp, out xmlDskSubTyp);
|
||||
else if(dev.IsPCMCIA)
|
||||
Metadata.MediaType.MediaTypeToString(MediaType.PCCardTypeI, out xmlDskTyp, out xmlDskSubTyp);
|
||||
else
|
||||
Metadata.MediaType.MediaTypeToString(MediaType.GENERIC_HDD, out xmlDskTyp, out xmlDskSubTyp);
|
||||
else Metadata.MediaType.MediaTypeToString(MediaType.GENERIC_HDD, out xmlDskTyp, out xmlDskSubTyp);
|
||||
sidecar.BlockMedia[0].DiskType = xmlDskTyp;
|
||||
sidecar.BlockMedia[0].DiskSubType = xmlDskSubTyp;
|
||||
// TODO: Implement device firmware revision
|
||||
@@ -595,8 +590,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
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(xmlFileSysInfo != null) sidecar.BlockMedia[0].FileSystemInformation = xmlFileSysInfo;
|
||||
if(cylinders > 0 && heads > 0 && sectors > 0)
|
||||
{
|
||||
sidecar.BlockMedia[0].Cylinders = cylinders;
|
||||
@@ -609,31 +603,31 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
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("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();
|
||||
if(resume.BadBlocks.Count > 0) resume.BadBlocks.Sort();
|
||||
DicConsole.WriteLine();
|
||||
|
||||
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);
|
||||
|
||||
System.Xml.Serialization.XmlSerializer xmlSer = new System.Xml.Serialization.XmlSerializer(typeof(CICMMetadataType));
|
||||
System.Xml.Serialization.XmlSerializer xmlSer =
|
||||
new System.Xml.Serialization.XmlSerializer(typeof(CICMMetadataType));
|
||||
xmlSer.Serialize(xmlFs, sidecar);
|
||||
xmlFs.Close();
|
||||
}
|
||||
|
||||
Statistics.AddMedia(MediaType.GENERIC_HDD, true);
|
||||
}
|
||||
else
|
||||
DicConsole.ErrorWriteLine("Unable to communicate with ATA device.");
|
||||
else DicConsole.ErrorWriteLine("Unable to communicate with ATA device.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -47,23 +47,17 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
struct AlcoholHeader
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
|
||||
public string signature;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
|
||||
public byte[] version;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)] public string signature;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public byte[] version;
|
||||
public AlcoholMediumType type;
|
||||
public ushort sessions;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
|
||||
public ushort[] unknown1;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public ushort[] unknown1;
|
||||
public ushort bcaLength;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
|
||||
public uint[] unknown2;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public uint[] unknown2;
|
||||
public uint bcaOffset;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
|
||||
public uint[] unknown3;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] public uint[] unknown3;
|
||||
public uint structuresOffset;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
|
||||
public uint[] unknown4;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public uint[] unknown4;
|
||||
public uint sessionOffset;
|
||||
public uint dpmOffset;
|
||||
}
|
||||
@@ -99,14 +93,12 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
public byte pframe;
|
||||
public uint extraOffset;
|
||||
public ushort sectorSize;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 18)]
|
||||
public byte[] unknown;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 18)] public byte[] unknown;
|
||||
public uint startLba;
|
||||
public ulong startOffset;
|
||||
public uint files;
|
||||
public uint footerOffset;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 24)]
|
||||
public byte[] unknown2;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 24)] public byte[] unknown2;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
@@ -172,24 +164,23 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
header = new AlcoholHeader
|
||||
{
|
||||
signature = "MEDIA DESCRIPTOR",
|
||||
unknown1 = new ushort[] { 0x0002, 0x0000 },
|
||||
unknown1 = new ushort[] {0x0002, 0x0000},
|
||||
unknown2 = new uint[2],
|
||||
unknown3 = new uint[6],
|
||||
unknown4 = new uint[3],
|
||||
version = new byte[] { 1, 5 }
|
||||
version = new byte[] {1, 5}
|
||||
};
|
||||
header.version[0] = 1;
|
||||
header.version[1] = 5;
|
||||
tracks = new List<AlcoholTrack>();
|
||||
sessions = new List<AlcoholSession>();
|
||||
trackLengths = new Dictionary<byte, uint>();
|
||||
footer = new AlcoholFooter { widechar = 1 };
|
||||
footer = new AlcoholFooter {widechar = 1};
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
if(sessions.Count == 0 || tracks.Count == 0)
|
||||
return;
|
||||
if(sessions.Count == 0 || tracks.Count == 0) return;
|
||||
|
||||
// Calculate first offsets
|
||||
header.sessions = (ushort)sessions.Count;
|
||||
@@ -201,7 +192,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
for(int i = 0; i < sessionsArray.Length; i++)
|
||||
{
|
||||
sessionsArray[i].allBlocks = (byte)(((sessionsArray[i].lastTrack - sessionsArray[i].firstTrack) + 1) +
|
||||
sessionsArray[i].nonTrackBlocks);
|
||||
sessionsArray[i].nonTrackBlocks);
|
||||
sessionsArray[i].trackOffset = (uint)nextOffset;
|
||||
nextOffset += sessionsArray[i].allBlocks * 80;
|
||||
}
|
||||
@@ -214,10 +205,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(tracksArray[i].point >= 0xA0) continue;
|
||||
if(!trackLengths.TryGetValue(tracksArray[i].point, out uint trkLen)) continue;
|
||||
|
||||
if(tracksArray[i].mode == AlcoholTrackMode.DVD)
|
||||
{
|
||||
tracksArray[i].extraOffset = trkLen;
|
||||
}
|
||||
if(tracksArray[i].mode == AlcoholTrackMode.DVD) { tracksArray[i].extraOffset = trkLen; }
|
||||
else
|
||||
{
|
||||
AlcoholTrackExtra extra = new AlcoholTrackExtra();
|
||||
@@ -247,15 +235,15 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
nextOffset += 4100;
|
||||
}
|
||||
|
||||
for(int i = 0; i < tracksArray.Length; i++)
|
||||
tracksArray[i].footerOffset = (uint)nextOffset;
|
||||
for(int i = 0; i < tracksArray.Length; i++) tracksArray[i].footerOffset = (uint)nextOffset;
|
||||
|
||||
footer.filenameOffset = (uint)(nextOffset + 16);
|
||||
|
||||
byte[] filename = Encoding.Unicode.GetBytes(outputPrefix + extension);
|
||||
|
||||
// Open descriptor file here
|
||||
FileStream descriptorFile = new FileStream(outputPrefix + ".mds", FileMode.Create, FileAccess.ReadWrite, FileShare.None);
|
||||
FileStream descriptorFile =
|
||||
new FileStream(outputPrefix + ".mds", FileMode.Create, FileAccess.ReadWrite, FileShare.None);
|
||||
|
||||
byte[] tmp = new byte[88];
|
||||
IntPtr hdrPtr = Marshal.AllocHGlobal(88);
|
||||
@@ -284,7 +272,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
Marshal.FreeHGlobal(trkPtr);
|
||||
}
|
||||
|
||||
if(header.type == AlcoholMediumType.CD || header.type == AlcoholMediumType.CDR || header.type == AlcoholMediumType.CDRW)
|
||||
if(header.type == AlcoholMediumType.CD || header.type == AlcoholMediumType.CDR ||
|
||||
header.type == AlcoholMediumType.CDRW)
|
||||
{
|
||||
foreach(AlcoholTrackExtra extra in extrasArray)
|
||||
{
|
||||
@@ -429,8 +418,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
case TrackType.CDMode2Form2:
|
||||
trkArray[i].mode = AlcoholTrackMode.Mode2F2;
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(mode), mode, null);
|
||||
default: throw new ArgumentOutOfRangeException(nameof(mode), mode, null);
|
||||
}
|
||||
|
||||
switch(subMode)
|
||||
@@ -447,8 +435,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
case TrackSubchannelType.Q16:
|
||||
case TrackSubchannelType.Q16Interleaved:
|
||||
throw new FeatureUnsupportedImageException("Specified subchannel type is not supported.");
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(subMode), subMode, null);
|
||||
default: throw new ArgumentOutOfRangeException(nameof(subMode), subMode, null);
|
||||
}
|
||||
|
||||
tracks = new List<AlcoholTrack>(trkArray);
|
||||
@@ -472,8 +459,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
break;
|
||||
}
|
||||
|
||||
if(trackLengths.ContainsKey(point))
|
||||
trackLengths.Remove(point);
|
||||
if(trackLengths.ContainsKey(point)) trackLengths.Remove(point);
|
||||
|
||||
trackLengths.Add(point, (uint)length);
|
||||
|
||||
@@ -481,18 +467,15 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
for(int i = 0; i < sess.Length; i++)
|
||||
{
|
||||
if(sess[i].firstTrack == point)
|
||||
sess[i].sessionStart = (int)startLba;
|
||||
if(sess[i].lastTrack == point)
|
||||
sess[i].sessionEnd = (int)(startLba + length);
|
||||
if(sess[i].firstTrack == point) sess[i].sessionStart = (int)startLba;
|
||||
if(sess[i].lastTrack == point) sess[i].sessionEnd = (int)(startLba + length);
|
||||
}
|
||||
|
||||
sessions = new List<AlcoholSession>(sess);
|
||||
|
||||
}
|
||||
|
||||
public void AddTrack(byte adrCtl, byte tno, byte point, byte min, byte sec, byte frame, byte zero, byte pmin,
|
||||
byte psec, byte pframe, byte session)
|
||||
byte psec, byte pframe, byte session)
|
||||
{
|
||||
AlcoholTrack trk = new AlcoholTrack
|
||||
{
|
||||
@@ -519,11 +502,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
AlcoholSession[] sess = sessions.ToArray();
|
||||
|
||||
for(int i = 0; i < sess.Length; i++)
|
||||
{
|
||||
if(sess[i].sessionSequence == session)
|
||||
sess[i].nonTrackBlocks++;
|
||||
}
|
||||
for(int i = 0; i < sess.Length; i++) { if(sess[i].sessionSequence == session) sess[i].nonTrackBlocks++; }
|
||||
|
||||
sessions = new List<AlcoholSession>(sess);
|
||||
}
|
||||
@@ -540,8 +519,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
this.pfi = new byte[2048];
|
||||
Array.Copy(pfi, 4, this.pfi, 0, 2048);
|
||||
}
|
||||
else
|
||||
this.pfi = pfi;
|
||||
else this.pfi = pfi;
|
||||
}
|
||||
|
||||
public void AddDMI(byte[] dmi)
|
||||
@@ -551,8 +529,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
this.dmi = new byte[2048];
|
||||
Array.Copy(dmi, 4, this.dmi, 0, 2048);
|
||||
}
|
||||
else
|
||||
this.dmi = dmi;
|
||||
else this.dmi = dmi;
|
||||
}
|
||||
|
||||
public void SetExtension(string extension)
|
||||
@@ -560,4 +537,4 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
this.extension = extension;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -51,7 +51,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
internal class CompactDisc
|
||||
{
|
||||
internal static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, ref CICMMetadataType sidecar, ref MediaType dskType, bool separateSubchannel, ref Resume resume, ref DumpLog dumpLog, Alcohol120 alcohol, bool dumpLeadIn)
|
||||
internal static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force,
|
||||
bool dumpRaw, bool persistent, bool stopOnError, ref CICMMetadataType sidecar,
|
||||
ref MediaType dskType, bool separateSubchannel, ref Resume resume,
|
||||
ref DumpLog dumpLog, Alcohol120 alcohol, bool dumpLeadIn)
|
||||
{
|
||||
MHDDLog mhddLog;
|
||||
IBGLog ibgLog;
|
||||
@@ -76,10 +79,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
ulong errored = 0;
|
||||
DataFile dumpFile = null;
|
||||
bool aborted = false;
|
||||
System.Console.CancelKeyPress += (sender, e) =>
|
||||
{
|
||||
e.Cancel = aborted = true;
|
||||
};
|
||||
System.Console.CancelKeyPress += (sender, e) => { e.Cancel = aborted = true; };
|
||||
|
||||
// We discarded all discs that falsify a TOC before requesting a real TOC
|
||||
// No TOC, no CD (or an empty one)
|
||||
@@ -124,10 +124,13 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
|
||||
dumpLog.WriteLine("Reading Disc Information");
|
||||
sense = dev.ReadDiscInformation(out cmdBuf, out senseBuf, MmcDiscInformationDataTypes.DiscInformation, dev.Timeout, out duration);
|
||||
sense = dev.ReadDiscInformation(out cmdBuf, out senseBuf,
|
||||
MmcDiscInformationDataTypes.DiscInformation, dev.Timeout,
|
||||
out duration);
|
||||
if(!sense)
|
||||
{
|
||||
Decoders.SCSI.MMC.DiscInformation.StandardDiscInformation? discInfo = Decoders.SCSI.MMC.DiscInformation.Decode000b(cmdBuf);
|
||||
Decoders.SCSI.MMC.DiscInformation.StandardDiscInformation? discInfo =
|
||||
Decoders.SCSI.MMC.DiscInformation.Decode000b(cmdBuf);
|
||||
if(discInfo.HasValue)
|
||||
{
|
||||
// If it is a read-only CD, check CD type if available
|
||||
@@ -172,21 +175,20 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
foreach(FullTOC.TrackDataDescriptor track in toc.Value.TrackDescriptors)
|
||||
{
|
||||
if(track.TNO == 1 &&
|
||||
((TOC_CONTROL)(track.CONTROL & 0x0D) == TOC_CONTROL.DataTrack ||
|
||||
(TOC_CONTROL)(track.CONTROL & 0x0D) == TOC_CONTROL.DataTrackIncremental))
|
||||
if(track.TNO == 1 && ((TOC_CONTROL)(track.CONTROL & 0x0D) == TOC_CONTROL.DataTrack ||
|
||||
(TOC_CONTROL)(track.CONTROL & 0x0D) ==
|
||||
TOC_CONTROL.DataTrackIncremental))
|
||||
{
|
||||
allFirstSessionTracksAreAudio &= firstTrackLastSession != 1;
|
||||
}
|
||||
|
||||
if((TOC_CONTROL)(track.CONTROL & 0x0D) == TOC_CONTROL.DataTrack ||
|
||||
(TOC_CONTROL)(track.CONTROL & 0x0D) == TOC_CONTROL.DataTrackIncremental)
|
||||
(TOC_CONTROL)(track.CONTROL & 0x0D) == TOC_CONTROL.DataTrackIncremental)
|
||||
{
|
||||
hasDataTrack = true;
|
||||
allFirstSessionTracksAreAudio &= track.TNO >= firstTrackLastSession;
|
||||
}
|
||||
else
|
||||
hasAudioTrack = true;
|
||||
else hasAudioTrack = true;
|
||||
|
||||
hasVideoTrack |= track.ADR == 4;
|
||||
}
|
||||
@@ -194,12 +196,9 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
if(hasDataTrack && hasAudioTrack && allFirstSessionTracksAreAudio && sessions == 2)
|
||||
dskType = MediaType.CDPLUS;
|
||||
if(!hasDataTrack && hasAudioTrack && sessions == 1)
|
||||
dskType = MediaType.CDDA;
|
||||
if(hasDataTrack && !hasAudioTrack && sessions == 1)
|
||||
dskType = MediaType.CDROM;
|
||||
if(hasVideoTrack && !hasDataTrack && sessions == 1)
|
||||
dskType = MediaType.CDV;
|
||||
if(!hasDataTrack && hasAudioTrack && sessions == 1) dskType = MediaType.CDDA;
|
||||
if(hasDataTrack && !hasAudioTrack && sessions == 1) dskType = MediaType.CDROM;
|
||||
if(hasVideoTrack && !hasDataTrack && sessions == 1) dskType = MediaType.CDV;
|
||||
}
|
||||
|
||||
dumpLog.WriteLine("Reading PMA");
|
||||
@@ -244,10 +243,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
blockSize = 2448;
|
||||
subSize = 96;
|
||||
int sectorSize;
|
||||
if(separateSubchannel)
|
||||
sectorSize = (int)(blockSize - subSize);
|
||||
else
|
||||
sectorSize = (int)blockSize;
|
||||
if(separateSubchannel) sectorSize = (int)(blockSize - subSize);
|
||||
else sectorSize = (int)blockSize;
|
||||
|
||||
if(toc == null)
|
||||
{
|
||||
@@ -271,15 +268,17 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
sessionsForAlcohol[trk.SessionNumber - 1].EndTrack = trk.POINT;
|
||||
}
|
||||
}
|
||||
|
||||
alcohol.AddSessions(sessionsForAlcohol);
|
||||
|
||||
foreach(FullTOC.TrackDataDescriptor trk in toc.Value.TrackDescriptors)
|
||||
{
|
||||
alcohol.AddTrack((byte)((trk.ADR << 4) & trk.CONTROL), trk.TNO, trk.POINT, trk.Min, trk.Sec, trk.Frame,
|
||||
trk.Zero, trk.PMIN, trk.PSEC, trk.PFRAME, trk.SessionNumber);
|
||||
trk.Zero, trk.PMIN, trk.PSEC, trk.PFRAME, trk.SessionNumber);
|
||||
}
|
||||
|
||||
FullTOC.TrackDataDescriptor[] sortedTracks = toc.Value.TrackDescriptors.OrderBy(track => track.POINT).ToArray();
|
||||
FullTOC.TrackDataDescriptor[] sortedTracks =
|
||||
toc.Value.TrackDescriptors.OrderBy(track => track.POINT).ToArray();
|
||||
List<TrackType> trackList = new List<TrackType>();
|
||||
long lastSector = 0;
|
||||
string lastMSF = null;
|
||||
@@ -291,22 +290,18 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
TrackType track = new TrackType
|
||||
{
|
||||
Sequence = new TrackSequenceType
|
||||
{
|
||||
Session = trk.SessionNumber,
|
||||
TrackNumber = trk.POINT
|
||||
}
|
||||
Sequence = new TrackSequenceType {Session = trk.SessionNumber, TrackNumber = trk.POINT}
|
||||
};
|
||||
if((TOC_CONTROL)(trk.CONTROL & 0x0D) == TOC_CONTROL.DataTrack ||
|
||||
(TOC_CONTROL)(trk.CONTROL & 0x0D) == TOC_CONTROL.DataTrackIncremental)
|
||||
(TOC_CONTROL)(trk.CONTROL & 0x0D) == TOC_CONTROL.DataTrackIncremental)
|
||||
track.TrackType1 = TrackTypeTrackType.mode1;
|
||||
else
|
||||
track.TrackType1 = TrackTypeTrackType.audio;
|
||||
else track.TrackType1 = TrackTypeTrackType.audio;
|
||||
if(trk.PHOUR > 0)
|
||||
track.StartMSF = string.Format("{3:D2}:{0:D2}:{1:D2}:{2:D2}", trk.PMIN, trk.PSEC, trk.PFRAME, trk.PHOUR);
|
||||
else
|
||||
track.StartMSF = string.Format("{0:D2}:{1:D2}:{2:D2}", trk.PMIN, trk.PSEC, trk.PFRAME);
|
||||
track.StartSector = trk.PHOUR * 3600 * 75 + trk.PMIN * 60 * 75 + trk.PSEC * 75 + trk.PFRAME - 150;
|
||||
track.StartMSF = string.Format("{3:D2}:{0:D2}:{1:D2}:{2:D2}", trk.PMIN, trk.PSEC,
|
||||
trk.PFRAME, trk.PHOUR);
|
||||
else track.StartMSF = string.Format("{0:D2}:{1:D2}:{2:D2}", trk.PMIN, trk.PSEC, trk.PFRAME);
|
||||
track.StartSector = trk.PHOUR * 3600 * 75 + trk.PMIN * 60 * 75 + trk.PSEC * 75 + trk.PFRAME -
|
||||
150;
|
||||
trackList.Add(track);
|
||||
}
|
||||
else if(trk.POINT == 0xA2)
|
||||
@@ -346,17 +341,15 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
phour = trk.PHOUR;
|
||||
}
|
||||
|
||||
if(phour > 0)
|
||||
lastMSF = string.Format("{3:D2}:{0:D2}:{1:D2}:{2:D2}", pmin, psec, pframe, phour);
|
||||
else
|
||||
lastMSF = string.Format("{0:D2}:{1:D2}:{2:D2}", pmin, psec, pframe);
|
||||
if(phour > 0) lastMSF = string.Format("{3:D2}:{0:D2}:{1:D2}:{2:D2}", pmin, psec, pframe, phour);
|
||||
else lastMSF = string.Format("{0:D2}:{1:D2}:{2:D2}", pmin, psec, pframe);
|
||||
lastSector = phour * 3600 * 75 + pmin * 60 * 75 + psec * 75 + pframe - 150;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TrackType[] tracks = trackList.ToArray();
|
||||
for(int t = 1; t < tracks.Length;t++)
|
||||
for(int t = 1; t < tracks.Length; t++)
|
||||
{
|
||||
tracks[t - 1].EndSector = tracks[t].StartSector - 1;
|
||||
int phour = 0, pmin = 0, psec = 0;
|
||||
@@ -380,9 +373,9 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
if(phour > 0)
|
||||
tracks[t - 1].EndMSF = string.Format("{3:D2}:{0:D2}:{1:D2}:{2:D2}", pmin, psec, pframe, phour);
|
||||
else
|
||||
tracks[t - 1].EndMSF = string.Format("{0:D2}:{1:D2}:{2:D2}", pmin, psec, pframe);
|
||||
else tracks[t - 1].EndMSF = string.Format("{0:D2}:{1:D2}:{2:D2}", pmin, psec, pframe);
|
||||
}
|
||||
|
||||
tracks[tracks.Length - 1].EndMSF = lastMSF;
|
||||
tracks[tracks.Length - 1].EndSector = lastSector;
|
||||
blocks = (ulong)(lastSector + 1);
|
||||
@@ -393,23 +386,21 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
return;
|
||||
}
|
||||
|
||||
if(dumpRaw)
|
||||
{
|
||||
throw new NotImplementedException("Raw CD dumping not yet implemented");
|
||||
}
|
||||
if(dumpRaw) { throw new NotImplementedException("Raw CD dumping not yet implemented"); }
|
||||
else
|
||||
{
|
||||
// TODO: Check subchannel capabilities
|
||||
readcd = !dev.ReadCd(out readBuffer, out senseBuf, 0, blockSize, 1, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders,
|
||||
true, true, MmcErrorField.None, MmcSubchannel.Raw, dev.Timeout, out duration);
|
||||
readcd = !dev.ReadCd(out readBuffer, out senseBuf, 0, blockSize, 1, MmcSectorTypes.AllTypes, false,
|
||||
false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None,
|
||||
MmcSubchannel.Raw, dev.Timeout, out duration);
|
||||
|
||||
if(readcd)
|
||||
DicConsole.WriteLine("Using MMC READ CD command.");
|
||||
if(readcd) DicConsole.WriteLine("Using MMC READ CD command.");
|
||||
}
|
||||
|
||||
DumpHardwareType currentTry = null;
|
||||
ExtentsULong extents = null;
|
||||
ResumeSupport.Process(true, true, blocks, dev.Manufacturer, dev.Model, dev.Serial, dev.PlatformID, ref resume, ref currentTry, ref extents);
|
||||
ResumeSupport.Process(true, true, 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...");
|
||||
|
||||
@@ -503,14 +494,13 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
if(readcd)
|
||||
{
|
||||
sense = dev.ReadCd(out readBuffer, out senseBuf, 0, blockSize, blocksToRead, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders,
|
||||
true, true, MmcErrorField.None, MmcSubchannel.Raw, dev.Timeout, out duration);
|
||||
if(dev.Error || sense)
|
||||
blocksToRead /= 2;
|
||||
sense = dev.ReadCd(out readBuffer, out senseBuf, 0, blockSize, blocksToRead,
|
||||
MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true,
|
||||
true, MmcErrorField.None, MmcSubchannel.Raw, dev.Timeout, out duration);
|
||||
if(dev.Error || sense) blocksToRead /= 2;
|
||||
}
|
||||
|
||||
if(!dev.Error || blocksToRead == 1)
|
||||
break;
|
||||
if(!dev.Error || blocksToRead == 1) break;
|
||||
}
|
||||
|
||||
if(dev.Error || sense)
|
||||
@@ -532,17 +522,14 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
dumpFile = new DataFile(outputPrefix + ".bin");
|
||||
alcohol.SetExtension(".bin");
|
||||
DataFile subFile = null;
|
||||
if(separateSubchannel)
|
||||
subFile = new DataFile(outputPrefix + ".sub");
|
||||
if(separateSubchannel) subFile = new DataFile(outputPrefix + ".sub");
|
||||
mhddLog = new MHDDLog(outputPrefix + ".mhddlog.bin", dev, blocks, blockSize, blocksToRead);
|
||||
ibgLog = new IBGLog(outputPrefix + ".ibg", 0x0008);
|
||||
|
||||
dumpFile.Seek(resume.NextBlock, (ulong)sectorSize);
|
||||
if(separateSubchannel)
|
||||
subFile.Seek(resume.NextBlock, subSize);
|
||||
if(separateSubchannel) subFile.Seek(resume.NextBlock, subSize);
|
||||
|
||||
if(resume.NextBlock > 0)
|
||||
dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
|
||||
if(resume.NextBlock > 0) dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
|
||||
|
||||
start = DateTime.UtcNow;
|
||||
for(int t = 0; t < tracks.Count(); t++)
|
||||
@@ -560,11 +547,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
tracks[t].Size = (tracks[t].EndSector - tracks[t].StartSector + 1) * sectorSize;
|
||||
tracks[t].SubChannel = new SubChannelType
|
||||
{
|
||||
Image = new ImageType
|
||||
{
|
||||
format = "rw_raw",
|
||||
offsetSpecified = true
|
||||
},
|
||||
Image = new ImageType {format = "rw_raw", offsetSpecified = true},
|
||||
Size = (tracks[t].EndSector - tracks[t].StartSector + 1) * subSize
|
||||
};
|
||||
if(separateSubchannel)
|
||||
@@ -578,8 +561,9 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
tracks[t].SubChannel.Image.Value = tracks[t].Image.Value;
|
||||
}
|
||||
|
||||
alcohol.SetTrackSizes((byte)(t + 1), sectorSize, tracks[t].StartSector, dumpFile.Position, (tracks[t].EndSector - tracks[t].StartSector + 1));
|
||||
|
||||
alcohol.SetTrackSizes((byte)(t + 1), sectorSize, tracks[t].StartSector, dumpFile.Position,
|
||||
(tracks[t].EndSector - tracks[t].StartSector + 1));
|
||||
|
||||
bool checkedDataFormat = false;
|
||||
|
||||
for(ulong i = resume.NextBlock; i <= (ulong)tracks[t].EndSector; i += blocksToRead)
|
||||
@@ -597,18 +581,18 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
blocksToRead = (uint)((ulong)tracks[t].EndSector + 1 - 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;
|
||||
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} at track {3} ({2:F3} MiB/sec.)", i, blocks, currentSpeed, t + 1);
|
||||
DicConsole.Write("\rReading sector {0} of {1} at track {3} ({2:F3} MiB/sec.)", i, blocks,
|
||||
currentSpeed, t + 1);
|
||||
|
||||
if(readcd)
|
||||
{
|
||||
sense = dev.ReadCd(out readBuffer, out senseBuf, (uint)i, blockSize, blocksToRead, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders,
|
||||
true, true, MmcErrorField.None, MmcSubchannel.Raw, dev.Timeout, out cmdDuration);
|
||||
sense = dev.ReadCd(out readBuffer, out senseBuf, (uint)i, blockSize, blocksToRead,
|
||||
MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true,
|
||||
true, MmcErrorField.None, MmcSubchannel.Raw, dev.Timeout, out cmdDuration);
|
||||
totalDuration += cmdDuration;
|
||||
}
|
||||
|
||||
@@ -625,14 +609,12 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
subFile.Write(readBuffer, (int)(sectorSize + b * blockSize), (int)subSize);
|
||||
}
|
||||
}
|
||||
else
|
||||
dumpFile.Write(readBuffer);
|
||||
else dumpFile.Write(readBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Reset device after X errors
|
||||
if(stopOnError)
|
||||
return; // TODO: Return more cleanly
|
||||
if(stopOnError) return; // TODO: Return more cleanly
|
||||
|
||||
// Write empty data
|
||||
if(separateSubchannel)
|
||||
@@ -640,17 +622,15 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
dumpFile.Write(new byte[sectorSize * blocksToRead]);
|
||||
subFile.Write(new byte[subSize * blocksToRead]);
|
||||
}
|
||||
else
|
||||
dumpFile.Write(new byte[blockSize * blocksToRead]);
|
||||
else dumpFile.Write(new byte[blockSize * blocksToRead]);
|
||||
|
||||
errored += blocksToRead;
|
||||
for(ulong b = i; b < i + blocksToRead; b++)
|
||||
resume.BadBlocks.Add(b);
|
||||
DicConsole.DebugWriteLine("Dump-Media", "READ error:\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf));
|
||||
if(cmdDuration < 500)
|
||||
mhddLog.Write(i, 65535);
|
||||
else
|
||||
mhddLog.Write(i, cmdDuration);
|
||||
for(ulong b = i; b < i + blocksToRead; b++) resume.BadBlocks.Add(b);
|
||||
|
||||
DicConsole.DebugWriteLine("Dump-Media", "READ error:\n{0}",
|
||||
Decoders.SCSI.Sense.PrettifySense(senseBuf));
|
||||
if(cmdDuration < 500) mhddLog.Write(i, 65535);
|
||||
else mhddLog.Write(i, cmdDuration);
|
||||
|
||||
ibgLog.Write(i, 0);
|
||||
dumpLog.WriteLine("Error reading {0} sectors from sector {1}.", blocksToRead, i);
|
||||
@@ -660,7 +640,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
byte[] sync = new byte[12];
|
||||
Array.Copy(readBuffer, 0, sync, 0, 12);
|
||||
if(sync.SequenceEqual(new byte[] { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00 }))
|
||||
if(sync.SequenceEqual(new byte[]
|
||||
{
|
||||
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00
|
||||
}))
|
||||
{
|
||||
switch(readBuffer[15])
|
||||
{
|
||||
@@ -711,21 +694,25 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
case TrackTypeTrackType.mode0:
|
||||
trkType = ImagePlugins.TrackType.Data;
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
default: throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
alcohol.SetTrackTypes((byte)(t + 1), trkType,
|
||||
separateSubchannel ? TrackSubchannelType.None : TrackSubchannelType.RawInterleaved);
|
||||
separateSubchannel
|
||||
? TrackSubchannelType.None
|
||||
: TrackSubchannelType.RawInterleaved);
|
||||
}
|
||||
|
||||
DicConsole.WriteLine();
|
||||
end = DateTime.UtcNow;
|
||||
mhddLog.Close();
|
||||
#pragma warning disable IDE0004 // Remove Unnecessary Cast
|
||||
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024, (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000), devicePath);
|
||||
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
|
||||
(((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000), devicePath);
|
||||
#pragma warning restore IDE0004 // Remove Unnecessary Cast
|
||||
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));
|
||||
dumpLog.WriteLine("Average dump speed {0:F3} KiB/sec.",
|
||||
(((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000));
|
||||
|
||||
#region Compact Disc Error handling
|
||||
if(resume.BadBlocks.Count > 0 && !aborted)
|
||||
@@ -734,7 +721,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
bool forward = true;
|
||||
bool runningPersistent = false;
|
||||
|
||||
cdRepeatRetry:
|
||||
cdRepeatRetry:
|
||||
ulong[] tmpArray = resume.BadBlocks.ToArray();
|
||||
foreach(ulong badSector in tmpArray)
|
||||
{
|
||||
@@ -747,12 +734,15 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
double cmdDuration = 0;
|
||||
|
||||
DicConsole.Write("\rRetrying sector {0}, pass {1}, {3}{2}", badSector, pass + 1, forward ? "forward" : "reverse", runningPersistent ? "recovering partial data, " : "");
|
||||
DicConsole.Write("\rRetrying sector {0}, pass {1}, {3}{2}", badSector, pass + 1,
|
||||
forward ? "forward" : "reverse",
|
||||
runningPersistent ? "recovering partial data, " : "");
|
||||
|
||||
if(readcd)
|
||||
{
|
||||
sense = dev.ReadCd(out readBuffer, out senseBuf, (uint)badSector, blockSize, blocksToRead, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders,
|
||||
true, true, MmcErrorField.None, MmcSubchannel.Raw, dev.Timeout, out cmdDuration);
|
||||
sense = dev.ReadCd(out readBuffer, out senseBuf, (uint)badSector, blockSize, blocksToRead,
|
||||
MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true,
|
||||
true, MmcErrorField.None, MmcSubchannel.Raw, dev.Timeout, out cmdDuration);
|
||||
totalDuration += cmdDuration;
|
||||
}
|
||||
|
||||
@@ -764,14 +754,13 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
extents.Add(badSector);
|
||||
dumpLog.WriteLine("Correctly retried sector {0} in pass {1}.", badSector, pass);
|
||||
}
|
||||
|
||||
|
||||
if(separateSubchannel)
|
||||
{
|
||||
dumpFile.WriteAt(readBuffer, badSector, (uint)sectorSize, 0, sectorSize);
|
||||
subFile.WriteAt(readBuffer, badSector, subSize, sectorSize, (int)subSize);
|
||||
}
|
||||
else
|
||||
dumpFile.WriteAt(readBuffer, badSector, blockSize);
|
||||
else dumpFile.WriteAt(readBuffer, badSector, blockSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -791,47 +780,39 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
if(!runningPersistent && persistent)
|
||||
{
|
||||
sense = dev.ModeSense6(out readBuffer, out senseBuf, false, ScsiModeSensePageControl.Current, 0x01, dev.Timeout, out duration);
|
||||
sense = dev.ModeSense6(out readBuffer, out senseBuf, false, ScsiModeSensePageControl.Current, 0x01,
|
||||
dev.Timeout, out duration);
|
||||
if(sense)
|
||||
{
|
||||
sense = dev.ModeSense10(out readBuffer, out senseBuf, false, ScsiModeSensePageControl.Current, 0x01, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
currentMode = Decoders.SCSI.Modes.DecodeMode10(readBuffer, dev.SCSIType);
|
||||
sense = dev.ModeSense10(out readBuffer, out senseBuf, false, ScsiModeSensePageControl.Current,
|
||||
0x01, dev.Timeout, out duration);
|
||||
if(!sense) currentMode = Decoders.SCSI.Modes.DecodeMode10(readBuffer, dev.SCSIType);
|
||||
}
|
||||
else
|
||||
currentMode = Decoders.SCSI.Modes.DecodeMode6(readBuffer, dev.SCSIType);
|
||||
else currentMode = Decoders.SCSI.Modes.DecodeMode6(readBuffer, dev.SCSIType);
|
||||
|
||||
if(currentMode.HasValue)
|
||||
currentModePage = currentMode.Value.Pages[0];
|
||||
if(currentMode.HasValue) currentModePage = currentMode.Value.Pages[0];
|
||||
|
||||
Decoders.SCSI.Modes.ModePage_01_MMC pgMMC = new Decoders.SCSI.Modes.ModePage_01_MMC
|
||||
{
|
||||
PS = false,
|
||||
ReadRetryCount = 255,
|
||||
Parameter = 0x20
|
||||
};
|
||||
Decoders.SCSI.Modes.ModePage_01_MMC pgMMC =
|
||||
new Decoders.SCSI.Modes.ModePage_01_MMC {PS = false, ReadRetryCount = 255, Parameter = 0x20};
|
||||
Decoders.SCSI.Modes.DecodedMode md = new Decoders.SCSI.Modes.DecodedMode
|
||||
{
|
||||
Header = new Decoders.SCSI.Modes.ModeHeader(),
|
||||
Pages = new Decoders.SCSI.Modes.ModePage[]
|
||||
{
|
||||
new Decoders.SCSI.Modes.ModePage
|
||||
{
|
||||
Page = 0x01,
|
||||
Subpage = 0x00,
|
||||
PageResponse = Decoders.SCSI.Modes.EncodeModePage_01_MMC(pgMMC)
|
||||
}
|
||||
}
|
||||
{
|
||||
new Decoders.SCSI.Modes.ModePage
|
||||
{
|
||||
Page = 0x01,
|
||||
Subpage = 0x00,
|
||||
PageResponse = Decoders.SCSI.Modes.EncodeModePage_01_MMC(pgMMC)
|
||||
}
|
||||
}
|
||||
};
|
||||
md6 = Decoders.SCSI.Modes.EncodeMode6(md, dev.SCSIType);
|
||||
md10 = Decoders.SCSI.Modes.EncodeMode10(md, dev.SCSIType);
|
||||
|
||||
dumpLog.WriteLine("Sending MODE SELECT to drive.");
|
||||
sense = dev.ModeSelect(md6, out senseBuf, true, false, dev.Timeout, out duration);
|
||||
if(sense)
|
||||
{
|
||||
sense = dev.ModeSelect10(md10, out senseBuf, true, false, dev.Timeout, out duration);
|
||||
}
|
||||
if(sense) { sense = dev.ModeSelect10(md10, out senseBuf, true, false, dev.Timeout, out duration); }
|
||||
|
||||
runningPersistent = true;
|
||||
if(!sense && !dev.Error)
|
||||
@@ -845,32 +826,26 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
Decoders.SCSI.Modes.DecodedMode md = new Decoders.SCSI.Modes.DecodedMode
|
||||
{
|
||||
Header = new Decoders.SCSI.Modes.ModeHeader(),
|
||||
Pages = new Decoders.SCSI.Modes.ModePage[]
|
||||
{
|
||||
currentModePage.Value
|
||||
}
|
||||
Pages = new Decoders.SCSI.Modes.ModePage[] {currentModePage.Value}
|
||||
};
|
||||
md6 = Decoders.SCSI.Modes.EncodeMode6(md, dev.SCSIType);
|
||||
md10 = Decoders.SCSI.Modes.EncodeMode10(md, dev.SCSIType);
|
||||
|
||||
dumpLog.WriteLine("Sending MODE SELECT to drive.");
|
||||
sense = dev.ModeSelect(md6, out senseBuf, true, false, dev.Timeout, out duration);
|
||||
if(sense)
|
||||
{
|
||||
sense = dev.ModeSelect10(md10, out senseBuf, true, false, dev.Timeout, out duration);
|
||||
}
|
||||
if(sense) { sense = dev.ModeSelect10(md10, out senseBuf, true, false, dev.Timeout, out duration); }
|
||||
}
|
||||
|
||||
DicConsole.WriteLine();
|
||||
}
|
||||
#endregion Compact Disc Error handling
|
||||
|
||||
resume.BadBlocks.Sort();
|
||||
currentTry.Extents = Metadata.ExtentsConverter.ToMetadata(extents);
|
||||
|
||||
dataChk = new Checksum();
|
||||
dumpFile.Seek(0, SeekOrigin.Begin);
|
||||
if(separateSubchannel)
|
||||
subFile.Seek(0, SeekOrigin.Begin);
|
||||
if(separateSubchannel) subFile.Seek(0, SeekOrigin.Begin);
|
||||
blocksToRead = 500;
|
||||
|
||||
dumpLog.WriteLine("Checksum starts.");
|
||||
@@ -890,7 +865,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(((ulong)tracks[t].EndSector + 1 - i) < blocksToRead)
|
||||
blocksToRead = (uint)((ulong)tracks[t].EndSector + 1 - i);
|
||||
|
||||
DicConsole.Write("\rChecksumming sector {0} of {1} at track {3} ({2:F3} MiB/sec.)", i, blocks, currentSpeed, t + 1);
|
||||
DicConsole.Write("\rChecksumming sector {0} of {1} at track {3} ({2:F3} MiB/sec.)", i, blocks,
|
||||
currentSpeed, t + 1);
|
||||
|
||||
DateTime chkStart = DateTime.UtcNow;
|
||||
byte[] dataToCheck = new byte[blockSize * blocksToRead];
|
||||
@@ -913,6 +889,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
dataChk.Update(dataToCheck);
|
||||
trkChk.Update(dataToCheck);
|
||||
}
|
||||
|
||||
DateTime chkEnd = DateTime.UtcNow;
|
||||
|
||||
double chkDuration = (chkEnd - chkStart).TotalMilliseconds;
|
||||
@@ -924,16 +901,16 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
|
||||
tracks[t].Checksums = trkChk.End().ToArray();
|
||||
if(separateSubchannel)
|
||||
tracks[t].SubChannel.Checksums = subChk.End().ToArray();
|
||||
else
|
||||
tracks[t].SubChannel.Checksums = tracks[t].Checksums;
|
||||
if(separateSubchannel) tracks[t].SubChannel.Checksums = subChk.End().ToArray();
|
||||
else tracks[t].SubChannel.Checksums = tracks[t].Checksums;
|
||||
}
|
||||
|
||||
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));
|
||||
dumpLog.WriteLine("Average checksum speed {0:F3} KiB/sec.",
|
||||
(((double)blockSize * (double)(blocks + 1)) / 1024) / (totalChkDuration / 1000));
|
||||
|
||||
// TODO: Correct this
|
||||
sidecar.OpticalDisc[0].Checksums = dataChk.End().ToArray();
|
||||
@@ -944,7 +921,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
Value = outputPrefix + ".bin"
|
||||
};
|
||||
sidecar.OpticalDisc[0].Sessions = toc.Value.LastCompleteSession;
|
||||
sidecar.OpticalDisc[0].Tracks = new[] { tracks.Count() };
|
||||
sidecar.OpticalDisc[0].Tracks = new[] {tracks.Count()};
|
||||
sidecar.OpticalDisc[0].Track = tracks;
|
||||
sidecar.OpticalDisc[0].Dimensions = Metadata.Dimensions.DimensionsFromMediaType(dskType);
|
||||
Metadata.MediaType.MediaTypeToString(dskType, out string xmlDskTyp, out string xmlDskSubTyp);
|
||||
@@ -955,10 +932,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
DicConsole.WriteLine("Writing metadata sidecar");
|
||||
|
||||
FileStream xmlFs = new FileStream(outputPrefix + ".cicm.xml",
|
||||
FileMode.Create);
|
||||
FileStream xmlFs = new FileStream(outputPrefix + ".cicm.xml", FileMode.Create);
|
||||
|
||||
System.Xml.Serialization.XmlSerializer xmlSer = new System.Xml.Serialization.XmlSerializer(typeof(CICMMetadataType));
|
||||
System.Xml.Serialization.XmlSerializer xmlSer =
|
||||
new System.Xml.Serialization.XmlSerializer(typeof(CICMMetadataType));
|
||||
xmlSer.Serialize(xmlFs, sidecar);
|
||||
xmlFs.Close();
|
||||
alcohol.Close();
|
||||
@@ -967,4 +944,4 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
Statistics.AddMedia(dskType, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
internal static class MMC
|
||||
{
|
||||
internal static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, ref CICMMetadataType sidecar, ref MediaType dskType, bool separateSubchannel, ref Metadata.Resume resume, ref DumpLog dumpLog, bool dumpLeadIn, Encoding encoding)
|
||||
internal static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force,
|
||||
bool dumpRaw, bool persistent, bool stopOnError, ref CICMMetadataType sidecar,
|
||||
ref MediaType dskType, bool separateSubchannel, ref Metadata.Resume resume,
|
||||
ref DumpLog dumpLog, bool dumpLeadIn, Encoding encoding)
|
||||
{
|
||||
byte[] cmdBuf = null;
|
||||
byte[] senseBuf = null;
|
||||
@@ -60,7 +63,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
// TODO: Log not only what is it reading, but if it was read correctly or not.
|
||||
|
||||
sense = dev.GetConfiguration(out cmdBuf, out senseBuf, 0, MmcGetConfigurationRt.Current, dev.Timeout, out duration);
|
||||
sense = dev.GetConfiguration(out cmdBuf, out senseBuf, 0, MmcGetConfigurationRt.Current, dev.Timeout,
|
||||
out duration);
|
||||
if(!sense)
|
||||
{
|
||||
Decoders.SCSI.MMC.Features.SeparatedFeatures ftr = Decoders.SCSI.MMC.Features.Separate(cmdBuf);
|
||||
@@ -164,7 +168,9 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
if(compactDisc)
|
||||
{
|
||||
CompactDisc.Dump(dev, devicePath, outputPrefix, retryPasses, force, dumpRaw, persistent, stopOnError, ref sidecar, ref dskType, separateSubchannel, ref resume, ref dumpLog, alcohol, dumpLeadIn);
|
||||
CompactDisc.Dump(dev, devicePath, outputPrefix, retryPasses, force, dumpRaw, persistent, stopOnError,
|
||||
ref sidecar, ref dskType, separateSubchannel, ref resume, ref dumpLog, alcohol,
|
||||
dumpLeadIn);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -176,17 +182,19 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(dskType == MediaType.Unknown && blocks > 0)
|
||||
{
|
||||
dumpLog.WriteLine("Reading Physical Format Information");
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.PhysicalInformation, 0, dev.Timeout, out duration);
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0,
|
||||
MmcDiscStructureFormat.PhysicalInformation, 0, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
Decoders.DVD.PFI.PhysicalFormatInformation? nintendoPfi = Decoders.DVD.PFI.Decode(cmdBuf);
|
||||
if(nintendoPfi != null)
|
||||
{
|
||||
if(nintendoPfi.Value.DiskCategory == Decoders.DVD.DiskCategory.Nintendo &&
|
||||
nintendoPfi.Value.PartVersion == 15)
|
||||
nintendoPfi.Value.PartVersion == 15)
|
||||
{
|
||||
dumpLog.WriteLine("Dumping Nintendo GameCube or Wii discs is not yet implemented.");
|
||||
throw new NotImplementedException("Dumping Nintendo GameCube or Wii discs is not yet implemented.");
|
||||
throw new
|
||||
NotImplementedException("Dumping Nintendo GameCube or Wii discs is not yet implemented.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -194,18 +202,16 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
#endregion Nintendo
|
||||
|
||||
#region All DVD and HD DVD types
|
||||
if(dskType == MediaType.DVDDownload || dskType == MediaType.DVDPR ||
|
||||
dskType == MediaType.DVDPRDL || dskType == MediaType.DVDPRW ||
|
||||
dskType == MediaType.DVDPRWDL || dskType == MediaType.DVDR ||
|
||||
dskType == MediaType.DVDRAM || dskType == MediaType.DVDRDL ||
|
||||
dskType == MediaType.DVDROM || dskType == MediaType.DVDRW ||
|
||||
dskType == MediaType.DVDRWDL || dskType == MediaType.HDDVDR ||
|
||||
dskType == MediaType.HDDVDRAM || dskType == MediaType.HDDVDRDL ||
|
||||
dskType == MediaType.HDDVDROM || dskType == MediaType.HDDVDRW ||
|
||||
dskType == MediaType.HDDVDRWDL)
|
||||
if(dskType == MediaType.DVDDownload || dskType == MediaType.DVDPR || dskType == MediaType.DVDPRDL ||
|
||||
dskType == MediaType.DVDPRW || dskType == MediaType.DVDPRWDL || dskType == MediaType.DVDR ||
|
||||
dskType == MediaType.DVDRAM || dskType == MediaType.DVDRDL || dskType == MediaType.DVDROM ||
|
||||
dskType == MediaType.DVDRW || dskType == MediaType.DVDRWDL || dskType == MediaType.HDDVDR ||
|
||||
dskType == MediaType.HDDVDRAM || dskType == MediaType.HDDVDRDL || dskType == MediaType.HDDVDROM ||
|
||||
dskType == MediaType.HDDVDRW || dskType == MediaType.HDDVDRWDL)
|
||||
{
|
||||
dumpLog.WriteLine("Reading Physical Format Information");
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.PhysicalInformation, 0, dev.Timeout, out duration);
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0,
|
||||
MmcDiscStructureFormat.PhysicalInformation, 0, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
alcohol.AddPFI(cmdBuf);
|
||||
@@ -242,10 +248,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
dskType = MediaType.DVDPRWDL;
|
||||
break;
|
||||
case Decoders.DVD.DiskCategory.DVDR:
|
||||
if(decPfi.PartVersion == 6)
|
||||
dskType = MediaType.DVDRDL;
|
||||
else
|
||||
dskType = MediaType.DVDR;
|
||||
if(decPfi.PartVersion == 6) dskType = MediaType.DVDRDL;
|
||||
else dskType = MediaType.DVDR;
|
||||
break;
|
||||
case Decoders.DVD.DiskCategory.DVDRAM:
|
||||
dskType = MediaType.DVDRAM;
|
||||
@@ -254,10 +258,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
dskType = MediaType.DVDROM;
|
||||
break;
|
||||
case Decoders.DVD.DiskCategory.DVDRW:
|
||||
if(decPfi.PartVersion == 3)
|
||||
dskType = MediaType.DVDRWDL;
|
||||
else
|
||||
dskType = MediaType.DVDRW;
|
||||
if(decPfi.PartVersion == 3) dskType = MediaType.DVDRWDL;
|
||||
else dskType = MediaType.DVDRW;
|
||||
break;
|
||||
case Decoders.DVD.DiskCategory.HDDVDR:
|
||||
dskType = MediaType.HDDVDR;
|
||||
@@ -272,10 +274,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
dskType = MediaType.HDDVDRW;
|
||||
break;
|
||||
case Decoders.DVD.DiskCategory.Nintendo:
|
||||
if(decPfi.DiscSize == Decoders.DVD.DVDSize.Eighty)
|
||||
dskType = MediaType.GOD;
|
||||
else
|
||||
dskType = MediaType.WOD;
|
||||
if(decPfi.DiscSize == Decoders.DVD.DVDSize.Eighty) dskType = MediaType.GOD;
|
||||
else dskType = MediaType.WOD;
|
||||
break;
|
||||
case Decoders.DVD.DiskCategory.UMD:
|
||||
dskType = MediaType.UMD;
|
||||
@@ -286,13 +286,14 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
|
||||
dumpLog.WriteLine("Reading Disc Manufacturing Information");
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DiscManufacturingInformation, 0, dev.Timeout, out duration);
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0,
|
||||
MmcDiscStructureFormat.DiscManufacturingInformation, 0, dev.Timeout,
|
||||
out duration);
|
||||
if(!sense)
|
||||
{
|
||||
if(Decoders.Xbox.DMI.IsXbox(cmdBuf) || Decoders.Xbox.DMI.IsXbox360(cmdBuf))
|
||||
{
|
||||
if(Decoders.Xbox.DMI.IsXbox(cmdBuf))
|
||||
dskType = MediaType.XGD;
|
||||
if(Decoders.Xbox.DMI.IsXbox(cmdBuf)) dskType = MediaType.XGD;
|
||||
else if(Decoders.Xbox.DMI.IsXbox360(cmdBuf))
|
||||
{
|
||||
dskType = MediaType.XGD2;
|
||||
@@ -307,15 +308,18 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
sense = dev.ScsiInquiry(out byte[] inqBuf, out senseBuf);
|
||||
|
||||
if(sense || !Decoders.SCSI.Inquiry.Decode(inqBuf).HasValue ||
|
||||
(Decoders.SCSI.Inquiry.Decode(inqBuf).HasValue && !Decoders.SCSI.Inquiry.Decode(inqBuf).Value.KreonPresent))
|
||||
(Decoders.SCSI.Inquiry.Decode(inqBuf).HasValue &&
|
||||
!Decoders.SCSI.Inquiry.Decode(inqBuf).Value.KreonPresent))
|
||||
{
|
||||
dumpLog.WriteLine("Dumping Xbox Game Discs requires a drive with Kreon firmware.");
|
||||
throw new NotImplementedException("Dumping Xbox Game Discs requires a drive with Kreon firmware.");
|
||||
throw new
|
||||
NotImplementedException("Dumping Xbox Game Discs requires a drive with Kreon firmware.");
|
||||
}
|
||||
|
||||
if(dumpRaw && !force)
|
||||
{
|
||||
DicConsole.ErrorWriteLine("Not continuing. If you want to continue reading cooked data when raw is not available use the force option.");
|
||||
DicConsole
|
||||
.ErrorWriteLine("Not continuing. If you want to continue reading cooked data when raw is not available use the force option.");
|
||||
// TODO: Exit more gracefully
|
||||
return;
|
||||
}
|
||||
@@ -324,7 +328,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
|
||||
alcohol.AddDMI(cmdBuf);
|
||||
|
||||
|
||||
if(cmdBuf.Length == 2052)
|
||||
{
|
||||
tmpBuf = new byte[cmdBuf.Length - 4];
|
||||
@@ -345,7 +349,9 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(dskType == MediaType.DVDDownload || dskType == MediaType.DVDROM)
|
||||
{
|
||||
dumpLog.WriteLine("Reading Lead-in Copyright Information.");
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.CopyrightInformation, 0, dev.Timeout, out duration);
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0,
|
||||
MmcDiscStructureFormat.CopyrightInformation, 0, dev.Timeout,
|
||||
out duration);
|
||||
if(!sense)
|
||||
{
|
||||
if(Decoders.DVD.CSS_CPRM.DecodeLeadInCopyright(cmdBuf).HasValue)
|
||||
@@ -360,7 +366,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
};
|
||||
DataFile.WriteTo("SCSI Dump", sidecar.OpticalDisc[0].CMI.Image, tmpBuf);
|
||||
|
||||
Decoders.DVD.CSS_CPRM.LeadInCopyright cpy = Decoders.DVD.CSS_CPRM.DecodeLeadInCopyright(cmdBuf).Value;
|
||||
Decoders.DVD.CSS_CPRM.LeadInCopyright cpy =
|
||||
Decoders.DVD.CSS_CPRM.DecodeLeadInCopyright(cmdBuf).Value;
|
||||
if(cpy.CopyrightType != Decoders.DVD.CopyrightType.NoProtection)
|
||||
sidecar.OpticalDisc[0].CopyProtection = cpy.CopyrightType.ToString();
|
||||
}
|
||||
@@ -369,11 +376,11 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
#endregion DVD-ROM
|
||||
|
||||
#region DVD-ROM and HD DVD-ROM
|
||||
if(dskType == MediaType.DVDDownload || dskType == MediaType.DVDROM ||
|
||||
dskType == MediaType.HDDVDROM)
|
||||
if(dskType == MediaType.DVDDownload || dskType == MediaType.DVDROM || dskType == MediaType.HDDVDROM)
|
||||
{
|
||||
dumpLog.WriteLine("Reading Burst Cutting Area.");
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.BurstCuttingArea, 0, dev.Timeout, out duration);
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0,
|
||||
MmcDiscStructureFormat.BurstCuttingArea, 0, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
tmpBuf = new byte[cmdBuf.Length - 4];
|
||||
@@ -394,7 +401,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(dskType == MediaType.DVDRAM || dskType == MediaType.HDDVDRAM)
|
||||
{
|
||||
dumpLog.WriteLine("Reading Disc Description Structure.");
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DVDRAM_DDS, 0, dev.Timeout, out duration);
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0,
|
||||
MmcDiscStructureFormat.DVDRAM_DDS, 0, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
if(Decoders.DVD.DDS.Decode(cmdBuf).HasValue)
|
||||
@@ -412,7 +420,9 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
|
||||
dumpLog.WriteLine("Reading Spare Area Information.");
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DVDRAM_SpareAreaInformation, 0, dev.Timeout, out duration);
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0,
|
||||
MmcDiscStructureFormat.DVDRAM_SpareAreaInformation, 0, dev.Timeout,
|
||||
out duration);
|
||||
if(!sense)
|
||||
{
|
||||
if(Decoders.DVD.Spare.Decode(cmdBuf).HasValue)
|
||||
@@ -435,7 +445,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(dskType == MediaType.DVDR || dskType == MediaType.DVDRW)
|
||||
{
|
||||
dumpLog.WriteLine("Reading Pre-Recorded Information.");
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.PreRecordedInfo, 0, dev.Timeout, out duration);
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0,
|
||||
MmcDiscStructureFormat.PreRecordedInfo, 0, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
tmpBuf = new byte[cmdBuf.Length - 4];
|
||||
@@ -455,7 +466,9 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(dskType == MediaType.DVDR || dskType == MediaType.DVDRW || dskType == MediaType.HDDVDR)
|
||||
{
|
||||
dumpLog.WriteLine("Reading Media Identifier.");
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DVDR_MediaIdentifier, 0, dev.Timeout, out duration);
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0,
|
||||
MmcDiscStructureFormat.DVDR_MediaIdentifier, 0, dev.Timeout,
|
||||
out duration);
|
||||
if(!sense)
|
||||
{
|
||||
tmpBuf = new byte[cmdBuf.Length - 4];
|
||||
@@ -470,7 +483,9 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
|
||||
dumpLog.WriteLine("Reading Recordable Physical Information.");
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DVDR_PhysicalInformation, 0, dev.Timeout, out duration);
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0,
|
||||
MmcDiscStructureFormat.DVDR_PhysicalInformation, 0, dev.Timeout,
|
||||
out duration);
|
||||
if(!sense)
|
||||
{
|
||||
tmpBuf = new byte[cmdBuf.Length - 4];
|
||||
@@ -487,11 +502,12 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
#endregion DVD-R, DVD-RW and HD DVD-R
|
||||
|
||||
#region All DVD+
|
||||
if(dskType == MediaType.DVDPR || dskType == MediaType.DVDPRDL ||
|
||||
dskType == MediaType.DVDPRW || dskType == MediaType.DVDPRWDL)
|
||||
if(dskType == MediaType.DVDPR || dskType == MediaType.DVDPRDL || dskType == MediaType.DVDPRW ||
|
||||
dskType == MediaType.DVDPRWDL)
|
||||
{
|
||||
dumpLog.WriteLine("Reading ADdress In Pregroove.");
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.ADIP, 0, dev.Timeout, out duration);
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0,
|
||||
MmcDiscStructureFormat.ADIP, 0, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
tmpBuf = new byte[cmdBuf.Length - 4];
|
||||
@@ -506,7 +522,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
|
||||
dumpLog.WriteLine("Reading Disc Control Blocks.");
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DCB, 0, dev.Timeout, out duration);
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0,
|
||||
MmcDiscStructureFormat.DCB, 0, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
tmpBuf = new byte[cmdBuf.Length - 4];
|
||||
@@ -526,7 +543,9 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(dskType == MediaType.HDDVDROM)
|
||||
{
|
||||
dumpLog.WriteLine("Reading Lead-in Copyright Information.");
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.HDDVD_CopyrightInformation, 0, dev.Timeout, out duration);
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0,
|
||||
MmcDiscStructureFormat.HDDVD_CopyrightInformation, 0, dev.Timeout,
|
||||
out duration);
|
||||
if(!sense)
|
||||
{
|
||||
tmpBuf = new byte[cmdBuf.Length - 4];
|
||||
@@ -544,10 +563,11 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
#region All Blu-ray
|
||||
if(dskType == MediaType.BDR || dskType == MediaType.BDRE || dskType == MediaType.BDROM ||
|
||||
dskType == MediaType.BDRXL || dskType == MediaType.BDREXL)
|
||||
dskType == MediaType.BDRXL || dskType == MediaType.BDREXL)
|
||||
{
|
||||
dumpLog.WriteLine("Reading Disc Information.");
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.BD, 0, 0, MmcDiscStructureFormat.DiscInformation, 0, dev.Timeout, out duration);
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.BD, 0, 0,
|
||||
MmcDiscStructureFormat.DiscInformation, 0, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
if(Decoders.Bluray.DI.Decode(cmdBuf).HasValue)
|
||||
@@ -565,7 +585,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
|
||||
dumpLog.WriteLine("Reading PAC.");
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.BD, 0, 0, MmcDiscStructureFormat.PAC, 0, dev.Timeout, out duration);
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.BD, 0, 0,
|
||||
MmcDiscStructureFormat.PAC, 0, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
tmpBuf = new byte[cmdBuf.Length - 4];
|
||||
@@ -581,12 +602,12 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
#endregion All Blu-ray
|
||||
|
||||
|
||||
#region BD-ROM only
|
||||
if(dskType == MediaType.BDROM)
|
||||
{
|
||||
dumpLog.WriteLine("Reading Burst Cutting Area.");
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.BD, 0, 0, MmcDiscStructureFormat.BD_BurstCuttingArea, 0, dev.Timeout, out duration);
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.BD, 0, 0,
|
||||
MmcDiscStructureFormat.BD_BurstCuttingArea, 0, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
tmpBuf = new byte[cmdBuf.Length - 4];
|
||||
@@ -604,11 +625,12 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
#endregion BD-ROM only
|
||||
|
||||
#region Writable Blu-ray only
|
||||
if(dskType == MediaType.BDR || dskType == MediaType.BDRE ||
|
||||
dskType == MediaType.BDRXL || dskType == MediaType.BDREXL)
|
||||
if(dskType == MediaType.BDR || dskType == MediaType.BDRE || dskType == MediaType.BDRXL ||
|
||||
dskType == MediaType.BDREXL)
|
||||
{
|
||||
dumpLog.WriteLine("Reading Disc Definition Structure.");
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.BD, 0, 0, MmcDiscStructureFormat.BD_DDS, 0, dev.Timeout, out duration);
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.BD, 0, 0,
|
||||
MmcDiscStructureFormat.BD_DDS, 0, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
tmpBuf = new byte[cmdBuf.Length - 4];
|
||||
@@ -623,7 +645,9 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
|
||||
dumpLog.WriteLine("Reading Spare Area Information.");
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.BD, 0, 0, MmcDiscStructureFormat.BD_SpareAreaInformation, 0, dev.Timeout, out duration);
|
||||
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.BD, 0, 0,
|
||||
MmcDiscStructureFormat.BD_SpareAreaInformation, 0, dev.Timeout,
|
||||
out duration);
|
||||
if(!sense)
|
||||
{
|
||||
tmpBuf = new byte[cmdBuf.Length - 4];
|
||||
@@ -641,11 +665,13 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
if(isXbox)
|
||||
{
|
||||
XGD.Dump(dev, devicePath, outputPrefix, retryPasses, force, dumpRaw, persistent, stopOnError, ref sidecar, ref dskType, ref resume, ref dumpLog, encoding);
|
||||
XGD.Dump(dev, devicePath, outputPrefix, retryPasses, force, dumpRaw, persistent, stopOnError,
|
||||
ref sidecar, ref dskType, ref resume, ref dumpLog, encoding);
|
||||
return;
|
||||
}
|
||||
|
||||
SBC.Dump(dev, devicePath, outputPrefix, retryPasses, force, dumpRaw, persistent, stopOnError, ref sidecar, ref dskType, true, ref resume, ref dumpLog, encoding, alcohol);
|
||||
SBC.Dump(dev, devicePath, outputPrefix, retryPasses, force, dumpRaw, persistent, stopOnError, ref sidecar,
|
||||
ref dskType, true, ref resume, ref dumpLog, encoding, alcohol);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -39,9 +39,11 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
public static class NVMe
|
||||
{
|
||||
public static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, ref Metadata.Resume resume, ref DumpLog dumpLog, Encoding encoding)
|
||||
public static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force,
|
||||
bool dumpRaw, bool persistent, bool stopOnError, ref Metadata.Resume resume,
|
||||
ref DumpLog dumpLog, Encoding encoding)
|
||||
{
|
||||
throw new NotImplementedException("NVMe devices not yet supported.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -40,45 +40,51 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
public static class ResumeSupport
|
||||
{
|
||||
public static void Process(bool isLba, bool removable, ulong blocks, string Manufacturer, string Model, string Serial, Interop.PlatformID platform, ref Resume resume, ref DumpHardwareType currentTry, ref ExtentsULong extents)
|
||||
public static void Process(bool isLba, bool removable, ulong blocks, string Manufacturer, string Model,
|
||||
string Serial, Interop.PlatformID platform, ref Resume resume,
|
||||
ref DumpHardwareType currentTry, ref ExtentsULong extents)
|
||||
{
|
||||
if(resume != null)
|
||||
{
|
||||
if(!isLba)
|
||||
throw new NotImplementedException("Resuming CHS devices is currently not supported.");
|
||||
if(!isLba) throw new NotImplementedException("Resuming CHS devices is currently not supported.");
|
||||
|
||||
if(resume.Removable != removable)
|
||||
throw new Exception(string.Format("Resume file specifies a {0} device but you're requesting to dump a {1} device, not continuing...",
|
||||
resume.Removable ? "removable" : "non removable",
|
||||
removable ? "removable" : "non removable"));
|
||||
throw new
|
||||
Exception(string.Format("Resume file specifies a {0} device but you're requesting to dump a {1} device, not continuing...",
|
||||
resume.Removable ? "removable" : "non removable",
|
||||
removable ? "removable" : "non removable"));
|
||||
|
||||
if(resume.LastBlock != blocks - 1)
|
||||
throw new Exception(string.Format("Resume file specifies a device with {0} blocks but you're requesting to dump one with {1} blocks, not continuing...",
|
||||
resume.LastBlock + 1, blocks));
|
||||
|
||||
throw new
|
||||
Exception(string.Format("Resume file specifies a device with {0} blocks but you're requesting to dump one with {1} blocks, not continuing...",
|
||||
resume.LastBlock + 1, blocks));
|
||||
|
||||
foreach(DumpHardwareType oldtry in resume.Tries)
|
||||
{
|
||||
if(oldtry.Manufacturer != Manufacturer && !removable)
|
||||
throw new Exception(string.Format("Resume file specifies a device manufactured by {0} but you're requesting to dump one by {1}, not continuing...",
|
||||
oldtry.Manufacturer, Manufacturer));
|
||||
throw new
|
||||
Exception(string.Format("Resume file specifies a device manufactured by {0} but you're requesting to dump one by {1}, not continuing...",
|
||||
oldtry.Manufacturer, Manufacturer));
|
||||
|
||||
if(oldtry.Model != Model && !removable)
|
||||
throw new Exception(string.Format("Resume file specifies a device model {0} but you're requesting to dump model {1}, not continuing...",
|
||||
oldtry.Model, Model));
|
||||
throw new
|
||||
Exception(string.Format("Resume file specifies a device model {0} but you're requesting to dump model {1}, not continuing...",
|
||||
oldtry.Model, Model));
|
||||
|
||||
if(oldtry.Serial != Serial && !removable)
|
||||
throw new Exception(string.Format("Resume file specifies a device with serial {0} but you're requesting to dump one with serial {1}, not continuing...",
|
||||
oldtry.Serial, Serial));
|
||||
throw new
|
||||
Exception(string.Format("Resume file specifies a device with serial {0} but you're requesting to dump one with serial {1}, not continuing...",
|
||||
oldtry.Serial, Serial));
|
||||
|
||||
if(oldtry.Software == null)
|
||||
throw new Exception("Found corrupt resume file, cannot continue...");
|
||||
if(oldtry.Software == null) throw new Exception("Found corrupt resume file, cannot continue...");
|
||||
|
||||
if(oldtry.Software.Name == "DiscImageChef" && oldtry.Software.OperatingSystem == platform.ToString() && oldtry.Software.Version == Version.GetVersion())
|
||||
if(oldtry.Software.Name == "DiscImageChef" &&
|
||||
oldtry.Software.OperatingSystem == platform.ToString() &&
|
||||
oldtry.Software.Version == Version.GetVersion())
|
||||
{
|
||||
if(removable && (oldtry.Manufacturer != Manufacturer || oldtry.Model != Model || oldtry.Serial != Serial))
|
||||
continue;
|
||||
|
||||
if(removable && (oldtry.Manufacturer != Manufacturer || oldtry.Model != Model ||
|
||||
oldtry.Serial != Serial)) continue;
|
||||
|
||||
currentTry = oldtry;
|
||||
extents = ExtentsConverter.FromMetadata(currentTry.Extents);
|
||||
break;
|
||||
@@ -120,4 +126,4 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -51,7 +51,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
internal static class SBC
|
||||
{
|
||||
internal static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, ref CICMMetadataType sidecar, ref MediaType dskType, bool opticalDisc, ref Metadata.Resume resume, ref DumpLog dumpLog, Encoding encoding, Alcohol120 alcohol = null)
|
||||
internal static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force,
|
||||
bool dumpRaw, bool persistent, bool stopOnError, ref CICMMetadataType sidecar,
|
||||
ref MediaType dskType, bool opticalDisc, ref Metadata.Resume resume,
|
||||
ref DumpLog dumpLog, Encoding encoding, Alcohol120 alcohol = null)
|
||||
{
|
||||
MHDDLog mhddLog;
|
||||
IBGLog ibgLog;
|
||||
@@ -80,10 +83,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
ulong errored = 0;
|
||||
DataFile dumpFile = null;
|
||||
bool aborted = false;
|
||||
System.Console.CancelKeyPress += (sender, e) =>
|
||||
{
|
||||
e.Cancel = aborted = true;
|
||||
};
|
||||
System.Console.CancelKeyPress += (sender, e) => { e.Cancel = aborted = true; };
|
||||
|
||||
dumpLog.WriteLine("Initializing reader.");
|
||||
Reader scsiReader = new Reader(dev, dev.Timeout, null, dumpRaw);
|
||||
@@ -99,8 +99,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(blocks != 0 && blockSize != 0)
|
||||
{
|
||||
blocks++;
|
||||
DicConsole.WriteLine("Media has {0} blocks of {1} bytes/each. (for a total of {2} bytes)",
|
||||
blocks, blockSize, blocks * (ulong)blockSize);
|
||||
DicConsole.WriteLine("Media has {0} blocks of {1} bytes/each. (for a total of {2} bytes)", blocks,
|
||||
blockSize, blocks * (ulong)blockSize);
|
||||
}
|
||||
// Check how many blocks to read, if error show and return
|
||||
if(scsiReader.GetBlocksToRead())
|
||||
@@ -109,6 +109,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DicConsole.ErrorWriteLine(scsiReader.ErrorMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
blocksToRead = scsiReader.BlocksToRead;
|
||||
logicalBlockSize = blockSize;
|
||||
physicalBlockSize = scsiReader.PhysicalBlockSize;
|
||||
@@ -121,10 +122,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
|
||||
if(dskType == MediaType.Unknown)
|
||||
dskType = MediaTypeFromSCSI.Get((byte)dev.SCSIType, dev.Manufacturer, dev.Model, scsiMediumType, scsiDensityCode, blocks, blockSize);
|
||||
dskType = MediaTypeFromSCSI.Get((byte)dev.SCSIType, dev.Manufacturer, dev.Model, scsiMediumType,
|
||||
scsiDensityCode, blocks, blockSize);
|
||||
|
||||
if(dskType == MediaType.Unknown && dev.IsUSB && containsFloppyPage)
|
||||
dskType = MediaType.FlashDrive;
|
||||
if(dskType == MediaType.Unknown && dev.IsUSB && containsFloppyPage) dskType = MediaType.FlashDrive;
|
||||
|
||||
DicConsole.WriteLine("Media identified as {0}", dskType);
|
||||
|
||||
@@ -224,16 +225,17 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
}
|
||||
|
||||
if(evpds.Count > 0)
|
||||
sidecar.BlockMedia[0].SCSI.EVPD = evpds.ToArray();
|
||||
if(evpds.Count > 0) sidecar.BlockMedia[0].SCSI.EVPD = evpds.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
dumpLog.WriteLine("Requesting MODE SENSE (10).");
|
||||
sense = dev.ModeSense10(out cmdBuf, out senseBuf, false, true, ScsiModeSensePageControl.Current, 0x3F, 0xFF, 5, out duration);
|
||||
sense = dev.ModeSense10(out cmdBuf, out senseBuf, false, true, ScsiModeSensePageControl.Current,
|
||||
0x3F, 0xFF, 5, out duration);
|
||||
if(!sense || dev.Error)
|
||||
{
|
||||
sense = dev.ModeSense10(out cmdBuf, out senseBuf, false, true, ScsiModeSensePageControl.Current, 0x3F, 0x00, 5, out duration);
|
||||
sense = dev.ModeSense10(out cmdBuf, out senseBuf, false, true,
|
||||
ScsiModeSensePageControl.Current, 0x3F, 0x00, 5, out duration);
|
||||
}
|
||||
|
||||
Decoders.SCSI.Modes.DecodedMode? decMode = null;
|
||||
@@ -254,11 +256,12 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
|
||||
dumpLog.WriteLine("Requesting MODE SENSE (6).");
|
||||
sense = dev.ModeSense6(out cmdBuf, out senseBuf, false, ScsiModeSensePageControl.Current, 0x3F, 0x00, 5, out duration);
|
||||
sense = dev.ModeSense6(out cmdBuf, out senseBuf, false, ScsiModeSensePageControl.Current, 0x3F,
|
||||
0x00, 5, out duration);
|
||||
if(sense || dev.Error)
|
||||
sense = dev.ModeSense6(out cmdBuf, out senseBuf, false, ScsiModeSensePageControl.Current, 0x3F, 0x00, 5, out duration);
|
||||
if(sense || dev.Error)
|
||||
sense = dev.ModeSense(out cmdBuf, out senseBuf, 5, out duration);
|
||||
sense = dev.ModeSense6(out cmdBuf, out senseBuf, false, ScsiModeSensePageControl.Current,
|
||||
0x3F, 0x00, 5, out duration);
|
||||
if(sense || dev.Error) sense = dev.ModeSense(out cmdBuf, out senseBuf, 5, out duration);
|
||||
|
||||
if(!sense && !dev.Error)
|
||||
{
|
||||
@@ -278,7 +281,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(decMode.HasValue)
|
||||
{
|
||||
scsiMediumType = (byte)decMode.Value.Header.MediumType;
|
||||
if(decMode.Value.Header.BlockDescriptors != null && decMode.Value.Header.BlockDescriptors.Length >= 1)
|
||||
if(decMode.Value.Header.BlockDescriptors != null &&
|
||||
decMode.Value.Header.BlockDescriptors.Length >= 1)
|
||||
scsiDensityCode = (byte)decMode.Value.Header.BlockDescriptors[0].Density;
|
||||
|
||||
foreach(Decoders.SCSI.Modes.ModePage modePage in decMode.Value.Pages)
|
||||
@@ -300,12 +304,14 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
else
|
||||
{
|
||||
DicConsole.ErrorWriteLine("Device is capable of reading raw data but I've been unable to guess correct sector size.");
|
||||
DicConsole
|
||||
.ErrorWriteLine("Device is capable of reading raw data but I've been unable to guess correct sector size.");
|
||||
}
|
||||
|
||||
if(!force)
|
||||
{
|
||||
DicConsole.ErrorWriteLine("Not continuing. If you want to continue reading cooked data when raw is not available use the force option.");
|
||||
DicConsole
|
||||
.ErrorWriteLine("Not continuing. If you want to continue reading cooked data when raw is not available use the force option.");
|
||||
// TODO: Exit more gracefully
|
||||
return;
|
||||
}
|
||||
@@ -315,23 +321,21 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if(longBlockSize == 37856) // Only a block will be read, but it contains 16 sectors and command expect sector number not block number
|
||||
if(longBlockSize == 37856
|
||||
) // Only a block will be read, but it contains 16 sectors and command expect sector number not block number
|
||||
blocksToRead = 16;
|
||||
else
|
||||
blocksToRead = 1;
|
||||
DicConsole.WriteLine("Reading {0} raw bytes ({1} cooked bytes) per sector.",
|
||||
longBlockSize, blockSize * blocksToRead);
|
||||
else blocksToRead = 1;
|
||||
DicConsole.WriteLine("Reading {0} raw bytes ({1} cooked bytes) per sector.", longBlockSize,
|
||||
blockSize * blocksToRead);
|
||||
physicalBlockSize = longBlockSize;
|
||||
blockSize = longBlockSize;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DicConsole.WriteLine("Reading {0} sectors at a time.", blocksToRead);
|
||||
|
||||
string outputExtension = ".bin";
|
||||
if(opticalDisc && blockSize == 2048)
|
||||
outputExtension = ".iso";
|
||||
if(opticalDisc && blockSize == 2048) outputExtension = ".iso";
|
||||
mhddLog = new MHDDLog(outputPrefix + ".mhddlog.bin", dev, blocks, blockSize, blocksToRead);
|
||||
ibgLog = new IBGLog(outputPrefix + ".ibg", currentProfile);
|
||||
dumpFile = new DataFile(outputPrefix + outputExtension);
|
||||
@@ -342,21 +346,22 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
if(alcohol != null && !dumpRaw)
|
||||
{
|
||||
alcohol.AddSessions(new [] { new Session() { StartTrack = 1, EndTrack = 1, SessionSequence = 1}});
|
||||
alcohol.AddSessions(new[] {new Session() {StartTrack = 1, EndTrack = 1, SessionSequence = 1}});
|
||||
alcohol.AddTrack(20, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1);
|
||||
alcohol.SetExtension(outputExtension);
|
||||
alcohol.SetTrackSizes(1, (int)blockSize, 0, 0, (long)blocks);
|
||||
alcohol.SetTrackTypes(1, TrackType.Data, TrackSubchannelType.None);
|
||||
}
|
||||
|
||||
|
||||
DumpHardwareType currentTry = null;
|
||||
ExtentsULong extents = null;
|
||||
ResumeSupport.Process(true, dev.IsRemovable, blocks, dev.Manufacturer, dev.Model, dev.Serial, dev.PlatformID, ref resume, ref currentTry, ref extents);
|
||||
ResumeSupport.Process(true, dev.IsRemovable, 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...");
|
||||
|
||||
dumpFile.Seek(resume.NextBlock, blockSize);
|
||||
if(resume.NextBlock > 0)
|
||||
dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
|
||||
if(resume.NextBlock > 0) dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
|
||||
|
||||
for(ulong i = resume.NextBlock; i < blocks; i += blocksToRead)
|
||||
{
|
||||
@@ -367,14 +372,11 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
break;
|
||||
}
|
||||
|
||||
if((blocks - i) < blocksToRead)
|
||||
blocksToRead = (uint)(blocks - i);
|
||||
if((blocks - i) < blocksToRead) blocksToRead = (uint)(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;
|
||||
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);
|
||||
@@ -392,19 +394,16 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
else
|
||||
{
|
||||
// TODO: Reset device after X errors
|
||||
if(stopOnError)
|
||||
return; // TODO: Return more cleanly
|
||||
if(stopOnError) return; // TODO: Return more cleanly
|
||||
|
||||
// Write empty data
|
||||
dumpFile.Write(new byte[blockSize * blocksToRead]);
|
||||
|
||||
errored += blocksToRead;
|
||||
for(ulong b = i; b < i + blocksToRead; b++)
|
||||
resume.BadBlocks.Add(b);
|
||||
if(cmdDuration < 500)
|
||||
mhddLog.Write(i, 65535);
|
||||
else
|
||||
mhddLog.Write(i, cmdDuration);
|
||||
for(ulong b = i; b < i + blocksToRead; b++) resume.BadBlocks.Add(b);
|
||||
|
||||
if(cmdDuration < 500) mhddLog.Write(i, 65535);
|
||||
else mhddLog.Write(i, cmdDuration);
|
||||
|
||||
ibgLog.Write(i, 0);
|
||||
dumpLog.WriteLine("Error reading {0} blocks from block {1}.", blocksToRead, i);
|
||||
@@ -415,14 +414,17 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
#pragma warning restore IDE0004 // Remove Unnecessary Cast
|
||||
resume.NextBlock = i + blocksToRead;
|
||||
}
|
||||
|
||||
end = DateTime.UtcNow;
|
||||
DicConsole.WriteLine();
|
||||
mhddLog.Close();
|
||||
#pragma warning disable IDE0004 // Remove Unnecessary Cast
|
||||
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024, (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000), devicePath);
|
||||
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
|
||||
(((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000), devicePath);
|
||||
#pragma warning restore IDE0004 // Remove Unnecessary Cast
|
||||
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));
|
||||
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)
|
||||
@@ -431,7 +433,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
bool forward = true;
|
||||
bool runningPersistent = false;
|
||||
|
||||
repeatRetry:
|
||||
repeatRetry:
|
||||
ulong[] tmpArray = resume.BadBlocks.ToArray();
|
||||
foreach(ulong badSector in tmpArray)
|
||||
{
|
||||
@@ -442,7 +444,9 @@ 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, " : "");
|
||||
DicConsole.Write("\rRetrying sector {0}, pass {1}, {3}{2}", badSector, pass + 1,
|
||||
forward ? "forward" : "reverse",
|
||||
runningPersistent ? "recovering partial data, " : "");
|
||||
|
||||
sense = scsiReader.ReadBlock(out readBuffer, badSector, out double cmdDuration);
|
||||
totalDuration += cmdDuration;
|
||||
@@ -454,8 +458,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
dumpFile.WriteAt(readBuffer, badSector, blockSize);
|
||||
dumpLog.WriteLine("Correctly retried block {0} in pass {1}.", badSector, pass);
|
||||
}
|
||||
else if(runningPersistent)
|
||||
dumpFile.WriteAt(readBuffer, badSector, blockSize);
|
||||
else if(runningPersistent) dumpFile.WriteAt(readBuffer, badSector, blockSize);
|
||||
}
|
||||
|
||||
if(pass < retryPasses && !aborted && resume.BadBlocks.Count > 0)
|
||||
@@ -474,27 +477,27 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
if(!runningPersistent && persistent)
|
||||
{
|
||||
sense = dev.ModeSense6(out readBuffer, out senseBuf, false, ScsiModeSensePageControl.Current, 0x01, dev.Timeout, out duration);
|
||||
sense = dev.ModeSense6(out readBuffer, out senseBuf, false, ScsiModeSensePageControl.Current, 0x01,
|
||||
dev.Timeout, out duration);
|
||||
if(sense)
|
||||
{
|
||||
sense = dev.ModeSense10(out readBuffer, out senseBuf, false, ScsiModeSensePageControl.Current, 0x01, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
currentMode = Decoders.SCSI.Modes.DecodeMode10(readBuffer, dev.SCSIType);
|
||||
sense = dev.ModeSense10(out readBuffer, out senseBuf, false, ScsiModeSensePageControl.Current,
|
||||
0x01, dev.Timeout, out duration);
|
||||
if(!sense) currentMode = Decoders.SCSI.Modes.DecodeMode10(readBuffer, dev.SCSIType);
|
||||
}
|
||||
else
|
||||
currentMode = Decoders.SCSI.Modes.DecodeMode6(readBuffer, dev.SCSIType);
|
||||
else currentMode = Decoders.SCSI.Modes.DecodeMode6(readBuffer, dev.SCSIType);
|
||||
|
||||
if(currentMode.HasValue)
|
||||
currentModePage = currentMode.Value.Pages[0];
|
||||
if(currentMode.HasValue) currentModePage = currentMode.Value.Pages[0];
|
||||
|
||||
if(dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.MultiMediaDevice)
|
||||
{
|
||||
Decoders.SCSI.Modes.ModePage_01_MMC pgMMC = new Decoders.SCSI.Modes.ModePage_01_MMC
|
||||
{
|
||||
PS = false,
|
||||
ReadRetryCount = 255,
|
||||
Parameter = 0x20
|
||||
};
|
||||
Decoders.SCSI.Modes.ModePage_01_MMC pgMMC =
|
||||
new Decoders.SCSI.Modes.ModePage_01_MMC
|
||||
{
|
||||
PS = false,
|
||||
ReadRetryCount = 255,
|
||||
Parameter = 0x20
|
||||
};
|
||||
Decoders.SCSI.Modes.DecodedMode md = new Decoders.SCSI.Modes.DecodedMode
|
||||
{
|
||||
Header = new Decoders.SCSI.Modes.ModeHeader(),
|
||||
@@ -545,10 +548,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
dumpLog.WriteLine("Sending MODE SELECT to drive.");
|
||||
sense = dev.ModeSelect(md6, out senseBuf, true, false, dev.Timeout, out duration);
|
||||
if(sense)
|
||||
{
|
||||
sense = dev.ModeSelect10(md10, out senseBuf, true, false, dev.Timeout, out duration);
|
||||
}
|
||||
if(sense) { sense = dev.ModeSelect10(md10, out senseBuf, true, false, dev.Timeout, out duration); }
|
||||
|
||||
runningPersistent = true;
|
||||
if(!sense && !dev.Error)
|
||||
@@ -562,25 +562,20 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
Decoders.SCSI.Modes.DecodedMode md = new Decoders.SCSI.Modes.DecodedMode
|
||||
{
|
||||
Header = new Decoders.SCSI.Modes.ModeHeader(),
|
||||
Pages = new Decoders.SCSI.Modes.ModePage[]
|
||||
{
|
||||
currentModePage.Value
|
||||
}
|
||||
Pages = new Decoders.SCSI.Modes.ModePage[] {currentModePage.Value}
|
||||
};
|
||||
md6 = Decoders.SCSI.Modes.EncodeMode6(md, dev.SCSIType);
|
||||
md10 = Decoders.SCSI.Modes.EncodeMode10(md, dev.SCSIType);
|
||||
|
||||
dumpLog.WriteLine("Sending MODE SELECT to drive.");
|
||||
sense = dev.ModeSelect(md6, out senseBuf, true, false, dev.Timeout, out duration);
|
||||
if(sense)
|
||||
{
|
||||
sense = dev.ModeSelect10(md10, out senseBuf, true, false, dev.Timeout, out duration);
|
||||
}
|
||||
if(sense) { sense = dev.ModeSelect10(md10, out senseBuf, true, false, dev.Timeout, out duration); }
|
||||
}
|
||||
|
||||
DicConsole.WriteLine();
|
||||
}
|
||||
#endregion Error handling
|
||||
|
||||
resume.BadBlocks.Sort();
|
||||
currentTry.Extents = Metadata.ExtentsConverter.ToMetadata(extents);
|
||||
|
||||
@@ -597,8 +592,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
break;
|
||||
}
|
||||
|
||||
if((blocks - i) < blocksToRead)
|
||||
blocksToRead = (uint)(blocks - i);
|
||||
if((blocks - i) < blocksToRead) blocksToRead = (uint)(blocks - i);
|
||||
|
||||
DicConsole.Write("\rChecksumming sector {0} of {1} ({2:F3} MiB/sec.)", i, blocks, currentSpeed);
|
||||
|
||||
@@ -615,11 +609,13 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
currentSpeed = ((double)blockSize * blocksToRead / (double)1048576) / (chkDuration / (double)1000);
|
||||
#pragma warning restore IDE0004 // Cast is necessary, otherwise incorrect value is created
|
||||
}
|
||||
|
||||
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));
|
||||
dumpLog.WriteLine("Average checksum speed {0:F3} KiB/sec.",
|
||||
(((double)blockSize * (double)(blocks + 1)) / 1024) / (totalChkDuration / 1000));
|
||||
|
||||
PluginBase plugins = new PluginBase();
|
||||
plugins.RegisterAllPlugins(encoding);
|
||||
@@ -636,15 +632,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
_imageFormat = ImageFormat.Detect(inputFilter);
|
||||
PartitionType[] xmlFileSysInfo = null;
|
||||
|
||||
try
|
||||
{
|
||||
if(!_imageFormat.OpenImage(inputFilter))
|
||||
_imageFormat = null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
_imageFormat = null;
|
||||
}
|
||||
try { if(!_imageFormat.OpenImage(inputFilter)) _imageFormat = null; }
|
||||
catch { _imageFormat = null; }
|
||||
|
||||
if(_imageFormat != null)
|
||||
{
|
||||
@@ -669,7 +658,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
};
|
||||
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);
|
||||
i, partitions[i].Start, partitions[i].End, partitions[i].Type,
|
||||
partitions[i].Scheme);
|
||||
|
||||
foreach(Filesystem _plugin in plugins.PluginsList.Values)
|
||||
{
|
||||
@@ -682,12 +672,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
Statistics.AddFilesystem(_plugin.XmlFSType.Type);
|
||||
dumpLog.WriteLine("Filesystem {0} found.", _plugin.XmlFSType.Type);
|
||||
|
||||
if(_plugin.XmlFSType.Type == "Opera")
|
||||
dskType = MediaType.ThreeDO;
|
||||
if(_plugin.XmlFSType.Type == "Opera") dskType = MediaType.ThreeDO;
|
||||
if(_plugin.XmlFSType.Type == "PC Engine filesystem")
|
||||
dskType = MediaType.SuperCDROM2;
|
||||
if(_plugin.XmlFSType.Type == "Nintendo Wii filesystem")
|
||||
dskType = MediaType.WOD;
|
||||
if(_plugin.XmlFSType.Type == "Nintendo Wii filesystem") dskType = MediaType.WOD;
|
||||
if(_plugin.XmlFSType.Type == "Nintendo Gamecube filesystem")
|
||||
dskType = MediaType.GOD;
|
||||
}
|
||||
@@ -700,27 +688,18 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
}
|
||||
|
||||
if(lstFs.Count > 0)
|
||||
xmlFileSysInfo[i].FileSystems = lstFs.ToArray();
|
||||
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
|
||||
};
|
||||
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
|
||||
};
|
||||
Partition wholePart =
|
||||
new Partition {Name = "Whole device", Length = blocks, Size = blocks * blockSize};
|
||||
|
||||
foreach(Filesystem _plugin in plugins.PluginsList.Values)
|
||||
{
|
||||
@@ -733,14 +712,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
Statistics.AddFilesystem(_plugin.XmlFSType.Type);
|
||||
dumpLog.WriteLine("Filesystem {0} found.", _plugin.XmlFSType.Type);
|
||||
|
||||
if(_plugin.XmlFSType.Type == "Opera")
|
||||
dskType = MediaType.ThreeDO;
|
||||
if(_plugin.XmlFSType.Type == "PC Engine filesystem")
|
||||
dskType = MediaType.SuperCDROM2;
|
||||
if(_plugin.XmlFSType.Type == "Nintendo Wii filesystem")
|
||||
dskType = MediaType.WOD;
|
||||
if(_plugin.XmlFSType.Type == "Nintendo Gamecube filesystem")
|
||||
dskType = MediaType.GOD;
|
||||
if(_plugin.XmlFSType.Type == "Opera") dskType = MediaType.ThreeDO;
|
||||
if(_plugin.XmlFSType.Type == "PC Engine filesystem") dskType = MediaType.SuperCDROM2;
|
||||
if(_plugin.XmlFSType.Type == "Nintendo Wii filesystem") dskType = MediaType.WOD;
|
||||
if(_plugin.XmlFSType.Type == "Nintendo Gamecube filesystem") dskType = MediaType.GOD;
|
||||
}
|
||||
}
|
||||
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
|
||||
@@ -751,14 +726,12 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
}
|
||||
|
||||
if(lstFs.Count > 0)
|
||||
xmlFileSysInfo[0].FileSystems = lstFs.ToArray();
|
||||
if(lstFs.Count > 0) xmlFileSysInfo[0].FileSystems = lstFs.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
if(alcohol != null && !dumpRaw)
|
||||
alcohol.SetMediaType(dskType);
|
||||
|
||||
if(alcohol != null && !dumpRaw) alcohol.SetMediaType(dskType);
|
||||
|
||||
if(opticalDisc)
|
||||
{
|
||||
sidecar.OpticalDisc[0].Checksums = dataChk.End().ToArray();
|
||||
@@ -771,30 +744,26 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
// TODO: Implement layers
|
||||
//sidecar.OpticalDisc[0].Layers = new LayersType();
|
||||
sidecar.OpticalDisc[0].Sessions = 1;
|
||||
sidecar.OpticalDisc[0].Tracks = new[] { 1 };
|
||||
sidecar.OpticalDisc[0].Tracks = new[] {1};
|
||||
sidecar.OpticalDisc[0].Track = new Schemas.TrackType[1];
|
||||
sidecar.OpticalDisc[0].Track[0] = new Schemas.TrackType
|
||||
{
|
||||
BytesPerSector = (int)blockSize,
|
||||
Checksums = sidecar.OpticalDisc[0].Checksums,
|
||||
EndSector = (long)(blocks - 1),
|
||||
Image = new ImageType
|
||||
{
|
||||
format = "BINARY",
|
||||
offset = 0,
|
||||
offsetSpecified = true,
|
||||
Value = sidecar.OpticalDisc[0].Image.Value
|
||||
},
|
||||
Sequence = new TrackSequenceType
|
||||
{
|
||||
Session = 1,
|
||||
TrackNumber = 1
|
||||
},
|
||||
Image =
|
||||
new ImageType
|
||||
{
|
||||
format = "BINARY",
|
||||
offset = 0,
|
||||
offsetSpecified = true,
|
||||
Value = sidecar.OpticalDisc[0].Image.Value
|
||||
},
|
||||
Sequence = new TrackSequenceType {Session = 1, TrackNumber = 1},
|
||||
Size = (long)(blocks * blockSize),
|
||||
StartSector = 0
|
||||
};
|
||||
if(xmlFileSysInfo != null)
|
||||
sidecar.OpticalDisc[0].Track[0].FileSystemInformation = xmlFileSysInfo;
|
||||
if(xmlFileSysInfo != null) sidecar.OpticalDisc[0].Track[0].FileSystemInformation = xmlFileSysInfo;
|
||||
switch(dskType)
|
||||
{
|
||||
case MediaType.DDCD:
|
||||
@@ -831,6 +800,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
sidecar.OpticalDisc[0].Track[0].TrackType1 = TrackTypeTrackType.bluray;
|
||||
break;
|
||||
}
|
||||
|
||||
sidecar.OpticalDisc[0].Dimensions = Metadata.Dimensions.DimensionsFromMediaType(dskType);
|
||||
Metadata.MediaType.MediaTypeToString(dskType, out string xmlDskTyp, out string xmlDskSubTyp);
|
||||
sidecar.OpticalDisc[0].DiscType = xmlDskTyp;
|
||||
@@ -851,14 +821,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
};
|
||||
if(!dev.IsRemovable || dev.IsUSB)
|
||||
{
|
||||
if(dev.Type == DeviceType.ATAPI)
|
||||
sidecar.BlockMedia[0].Interface = "ATAPI";
|
||||
else if(dev.IsUSB)
|
||||
sidecar.BlockMedia[0].Interface = "USB";
|
||||
else if(dev.IsFireWire)
|
||||
sidecar.BlockMedia[0].Interface = "FireWire";
|
||||
else
|
||||
sidecar.BlockMedia[0].Interface = "SCSI";
|
||||
if(dev.Type == DeviceType.ATAPI) sidecar.BlockMedia[0].Interface = "ATAPI";
|
||||
else if(dev.IsUSB) sidecar.BlockMedia[0].Interface = "USB";
|
||||
else if(dev.IsFireWire) sidecar.BlockMedia[0].Interface = "FireWire";
|
||||
else sidecar.BlockMedia[0].Interface = "SCSI";
|
||||
}
|
||||
sidecar.BlockMedia[0].LogicalBlocks = (long)blocks;
|
||||
sidecar.BlockMedia[0].PhysicalBlockSize = (int)physicalBlockSize;
|
||||
@@ -867,18 +833,18 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
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(xmlFileSysInfo != null) sidecar.BlockMedia[0].FileSystemInformation = xmlFileSysInfo;
|
||||
|
||||
if(dev.IsRemovable)
|
||||
sidecar.BlockMedia[0].DumpHardwareArray = resume.Tries.ToArray();
|
||||
if(dev.IsRemovable) sidecar.BlockMedia[0].DumpHardwareArray = resume.Tries.ToArray();
|
||||
}
|
||||
|
||||
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("Took a total of {0:F3} seconds ({1:F3} processing commands, {2:F3} checksumming).",
|
||||
(end - start).TotalSeconds, totalDuration / 1000, totalChkDuration / 1000);
|
||||
#pragma warning disable IDE0004 // Cast is necessary, otherwise incorrect value is created
|
||||
DicConsole.WriteLine("Avegare speed: {0:F3} MiB/sec.", (((double)blockSize * (double)(blocks + 1)) / 1048576) / (totalDuration / 1000));
|
||||
DicConsole.WriteLine("Avegare speed: {0:F3} MiB/sec.",
|
||||
(((double)blockSize * (double)(blocks + 1)) / 1048576) / (totalDuration / 1000));
|
||||
#pragma warning restore IDE0004 // Cast is necessary, otherwise incorrect value is created
|
||||
DicConsole.WriteLine("Fastest speed burst: {0:F3} MiB/sec.", maxSpeed);
|
||||
DicConsole.WriteLine("Slowest speed burst: {0:F3} MiB/sec.", minSpeed);
|
||||
@@ -889,17 +855,16 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
DicConsole.WriteLine("Writing metadata sidecar");
|
||||
|
||||
FileStream xmlFs = new FileStream(outputPrefix + ".cicm.xml",
|
||||
FileMode.Create);
|
||||
FileStream xmlFs = new FileStream(outputPrefix + ".cicm.xml", FileMode.Create);
|
||||
|
||||
System.Xml.Serialization.XmlSerializer xmlSer = new System.Xml.Serialization.XmlSerializer(typeof(CICMMetadataType));
|
||||
System.Xml.Serialization.XmlSerializer xmlSer =
|
||||
new System.Xml.Serialization.XmlSerializer(typeof(CICMMetadataType));
|
||||
xmlSer.Serialize(xmlFs, sidecar);
|
||||
xmlFs.Close();
|
||||
if(alcohol != null && !dumpRaw)
|
||||
alcohol.Close();
|
||||
if(alcohol != null && !dumpRaw) alcohol.Close();
|
||||
}
|
||||
|
||||
Statistics.AddMedia(dskType, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -44,7 +44,9 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
public class SCSI
|
||||
{
|
||||
// TODO: Get cartridge serial number from Certance vendor EVPD
|
||||
public static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, bool separateSubchannel, ref Metadata.Resume resume, ref DumpLog dumpLog, bool dumpLeadIn, Encoding encoding)
|
||||
public static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force,
|
||||
bool dumpRaw, bool persistent, bool stopOnError, bool separateSubchannel,
|
||||
ref Metadata.Resume resume, ref DumpLog dumpLog, bool dumpLeadIn, Encoding encoding)
|
||||
{
|
||||
byte[] senseBuf = null;
|
||||
bool sense = false;
|
||||
@@ -60,14 +62,14 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
Decoders.SCSI.FixedSense? decSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf);
|
||||
if(decSense.HasValue)
|
||||
{
|
||||
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", decSense.Value.SenseKey, decSense.Value.ASC, decSense.Value.ASCQ);
|
||||
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h",
|
||||
decSense.Value.SenseKey, decSense.Value.ASC, decSense.Value.ASCQ);
|
||||
|
||||
// Just retry, for 5 times
|
||||
if(decSense.Value.ASC == 0x29)
|
||||
{
|
||||
resets++;
|
||||
if(resets < 5)
|
||||
goto deviceGotReset;
|
||||
if(resets < 5) goto deviceGotReset;
|
||||
}
|
||||
|
||||
if(decSense.Value.ASC == 0x3A)
|
||||
@@ -78,12 +80,12 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DicConsole.WriteLine("\rWaiting for drive to become ready");
|
||||
System.Threading.Thread.Sleep(2000);
|
||||
sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
break;
|
||||
if(!sense) break;
|
||||
|
||||
decSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf);
|
||||
if(decSense.HasValue)
|
||||
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", decSense.Value.SenseKey, decSense.Value.ASC, decSense.Value.ASCQ);
|
||||
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h",
|
||||
decSense.Value.SenseKey, decSense.Value.ASC, decSense.Value.ASCQ);
|
||||
leftRetries--;
|
||||
}
|
||||
|
||||
@@ -101,18 +103,19 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DicConsole.WriteLine("\rWaiting for drive to become ready");
|
||||
System.Threading.Thread.Sleep(2000);
|
||||
sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
break;
|
||||
if(!sense) break;
|
||||
|
||||
decSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf);
|
||||
if(decSense.HasValue)
|
||||
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", decSense.Value.SenseKey, decSense.Value.ASC, decSense.Value.ASCQ);
|
||||
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h",
|
||||
decSense.Value.SenseKey, decSense.Value.ASC, decSense.Value.ASCQ);
|
||||
leftRetries--;
|
||||
}
|
||||
|
||||
if(sense)
|
||||
{
|
||||
DicConsole.ErrorWriteLine("Error testing unit was ready:\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf));
|
||||
DicConsole.ErrorWriteLine("Error testing unit was ready:\n{0}",
|
||||
Decoders.SCSI.Sense.PrettifySense(senseBuf));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -137,24 +140,26 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DicConsole.WriteLine("\rWaiting for drive to become ready");
|
||||
System.Threading.Thread.Sleep(2000);
|
||||
sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
break;
|
||||
if(!sense) break;
|
||||
|
||||
decSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf);
|
||||
if(decSense.HasValue)
|
||||
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", decSense.Value.SenseKey, decSense.Value.ASC, decSense.Value.ASCQ);
|
||||
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h",
|
||||
decSense.Value.SenseKey, decSense.Value.ASC, decSense.Value.ASCQ);
|
||||
leftRetries--;
|
||||
}
|
||||
|
||||
if(sense)
|
||||
{
|
||||
DicConsole.ErrorWriteLine("Error testing unit was ready:\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf));
|
||||
DicConsole.ErrorWriteLine("Error testing unit was ready:\n{0}",
|
||||
Decoders.SCSI.Sense.PrettifySense(senseBuf));
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DicConsole.ErrorWriteLine("Error testing unit was ready:\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf));
|
||||
DicConsole.ErrorWriteLine("Error testing unit was ready:\n{0}",
|
||||
Decoders.SCSI.Sense.PrettifySense(senseBuf));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -170,8 +175,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
if(dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.SequentialAccess)
|
||||
{
|
||||
if(dumpRaw)
|
||||
throw new ArgumentException("Tapes cannot be dumped raw.");
|
||||
if(dumpRaw) throw new ArgumentException("Tapes cannot be dumped raw.");
|
||||
|
||||
SSC.Dump(dev, outputPrefix, devicePath, ref sidecar, ref resume, ref dumpLog);
|
||||
return;
|
||||
@@ -179,11 +183,13 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
if(dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.MultiMediaDevice)
|
||||
{
|
||||
MMC.Dump(dev, devicePath, outputPrefix, retryPasses, force, dumpRaw, persistent, stopOnError, ref sidecar, ref dskType, separateSubchannel, ref resume, ref dumpLog, dumpLeadIn, encoding);
|
||||
MMC.Dump(dev, devicePath, outputPrefix, retryPasses, force, dumpRaw, persistent, stopOnError,
|
||||
ref sidecar, ref dskType, separateSubchannel, ref resume, ref dumpLog, dumpLeadIn, encoding);
|
||||
return;
|
||||
}
|
||||
|
||||
SBC.Dump(dev, devicePath, outputPrefix, retryPasses, force, dumpRaw, persistent, stopOnError, ref sidecar, ref dskType, false, ref resume, ref dumpLog, encoding);
|
||||
SBC.Dump(dev, devicePath, outputPrefix, retryPasses, force, dumpRaw, persistent, stopOnError, ref sidecar,
|
||||
ref dskType, false, ref resume, ref dumpLog, encoding);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -44,7 +44,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
internal static class SSC
|
||||
{
|
||||
internal static void Dump(Device dev, string outputPrefix, string devicePath, ref CICMMetadataType sidecar, ref Metadata.Resume resume, ref DumpLog dumpLog)
|
||||
internal static void Dump(Device dev, string outputPrefix, string devicePath, ref CICMMetadataType sidecar,
|
||||
ref Metadata.Resume resume, ref DumpLog dumpLog)
|
||||
{
|
||||
Decoders.SCSI.FixedSense? fxSense;
|
||||
bool aborted;
|
||||
@@ -69,14 +70,16 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
if(fxSense.HasValue && fxSense.Value.SenseKey != Decoders.SCSI.SenseKeys.NoSense)
|
||||
{
|
||||
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ);
|
||||
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey,
|
||||
fxSense.Value.ASC, fxSense.Value.ASCQ);
|
||||
DicConsole.ErrorWriteLine("Drive has status error, please correct. Sense follows...");
|
||||
DicConsole.ErrorWriteLine("{0}", strSense);
|
||||
return;
|
||||
}
|
||||
|
||||
// Not in BOM/P
|
||||
if(fxSense.HasValue && fxSense.Value.ASC == 0x00 && fxSense.Value.ASCQ != 0x00 && fxSense.Value.ASCQ != 0x04 && fxSense.Value.SenseKey != Decoders.SCSI.SenseKeys.IllegalRequest)
|
||||
if(fxSense.HasValue && fxSense.Value.ASC == 0x00 && fxSense.Value.ASCQ != 0x00 &&
|
||||
fxSense.Value.ASCQ != 0x04 && fxSense.Value.SenseKey != Decoders.SCSI.SenseKeys.IllegalRequest)
|
||||
{
|
||||
dumpLog.WriteLine("Rewinding, please wait...");
|
||||
DicConsole.Write("Rewinding, please wait...");
|
||||
@@ -91,19 +94,22 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
dev.RequestSense(out senseBuf, dev.Timeout, out duration);
|
||||
fxSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf, out strSense);
|
||||
}
|
||||
while(fxSense.HasValue && fxSense.Value.ASC == 0x00 && (fxSense.Value.ASCQ == 0x1A || fxSense.Value.ASCQ != 0x04));
|
||||
while(fxSense.HasValue && fxSense.Value.ASC == 0x00 &&
|
||||
(fxSense.Value.ASCQ == 0x1A || fxSense.Value.ASCQ != 0x04));
|
||||
|
||||
dev.RequestSense(out senseBuf, dev.Timeout, out duration);
|
||||
fxSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf, out strSense);
|
||||
|
||||
// And yet, did not rewind!
|
||||
if(fxSense.HasValue && ((fxSense.Value.ASC == 0x00 && fxSense.Value.ASCQ != 0x04) || fxSense.Value.ASC != 0x00))
|
||||
if(fxSense.HasValue && ((fxSense.Value.ASC == 0x00 && fxSense.Value.ASCQ != 0x04) ||
|
||||
fxSense.Value.ASC != 0x00))
|
||||
{
|
||||
DicConsole.WriteLine();
|
||||
DicConsole.ErrorWriteLine("Drive could not rewind, please correct. Sense follows...");
|
||||
DicConsole.ErrorWriteLine("{0}", strSense);
|
||||
dumpLog.WriteLine("Drive could not rewind, please correct. Sense follows...");
|
||||
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ);
|
||||
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey,
|
||||
fxSense.Value.ASC, fxSense.Value.ASCQ);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -111,7 +117,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
|
||||
// Check position
|
||||
sense = dev.ReadPosition(out byte[] cmdBuf, out senseBuf, SscPositionForms.Short, dev.Timeout, out duration);
|
||||
sense = dev.ReadPosition(out byte[] cmdBuf, out senseBuf, SscPositionForms.Short, dev.Timeout,
|
||||
out duration);
|
||||
|
||||
if(sense)
|
||||
{
|
||||
@@ -119,12 +126,15 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
// Anyway, <=SCSI-1 tapes do not support partitions
|
||||
fxSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf, out strSense);
|
||||
|
||||
if(fxSense.HasValue && ((fxSense.Value.ASC == 0x20 && fxSense.Value.ASCQ != 0x00) || fxSense.Value.ASC != 0x20 && fxSense.Value.SenseKey != Decoders.SCSI.SenseKeys.IllegalRequest))
|
||||
if(fxSense.HasValue && ((fxSense.Value.ASC == 0x20 && fxSense.Value.ASCQ != 0x00) ||
|
||||
fxSense.Value.ASC != 0x20 && fxSense.Value.SenseKey !=
|
||||
Decoders.SCSI.SenseKeys.IllegalRequest))
|
||||
{
|
||||
DicConsole.ErrorWriteLine("Could not get position. Sense follows...");
|
||||
DicConsole.ErrorWriteLine("{0}", strSense);
|
||||
dumpLog.WriteLine("Could not get position. Sense follows...");
|
||||
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ);
|
||||
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey,
|
||||
fxSense.Value.ASC, fxSense.Value.ASCQ);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -143,7 +153,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DicConsole.ErrorWriteLine("Drive could not rewind, please correct. Sense follows...");
|
||||
DicConsole.ErrorWriteLine("{0}", strSense);
|
||||
dumpLog.WriteLine("Drive could not rewind, please correct. Sense follows...");
|
||||
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ);
|
||||
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h",
|
||||
fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -156,27 +167,32 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
dev.RequestSense(out senseBuf, dev.Timeout, out duration);
|
||||
fxSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf, out strSense);
|
||||
}
|
||||
while(fxSense.HasValue && fxSense.Value.ASC == 0x00 && (fxSense.Value.ASCQ == 0x1A || fxSense.Value.ASCQ == 0x19));
|
||||
while(fxSense.HasValue && fxSense.Value.ASC == 0x00 &&
|
||||
(fxSense.Value.ASCQ == 0x1A || fxSense.Value.ASCQ == 0x19));
|
||||
|
||||
// And yet, did not rewind!
|
||||
if(fxSense.HasValue && ((fxSense.Value.ASC == 0x00 && fxSense.Value.ASCQ != 0x04) || fxSense.Value.ASC != 0x00))
|
||||
if(fxSense.HasValue && ((fxSense.Value.ASC == 0x00 && fxSense.Value.ASCQ != 0x04) ||
|
||||
fxSense.Value.ASC != 0x00))
|
||||
{
|
||||
DicConsole.WriteLine();
|
||||
DicConsole.ErrorWriteLine("Drive could not rewind, please correct. Sense follows...");
|
||||
DicConsole.ErrorWriteLine("{0}", strSense);
|
||||
dumpLog.WriteLine("Drive could not rewind, please correct. Sense follows...");
|
||||
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ);
|
||||
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h",
|
||||
fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ);
|
||||
return;
|
||||
}
|
||||
|
||||
sense = dev.ReadPosition(out cmdBuf, out senseBuf, SscPositionForms.Short, dev.Timeout, out duration);
|
||||
sense = dev.ReadPosition(out cmdBuf, out senseBuf, SscPositionForms.Short, dev.Timeout,
|
||||
out duration);
|
||||
if(sense)
|
||||
{
|
||||
fxSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf, out strSense);
|
||||
DicConsole.ErrorWriteLine("Drive could not rewind, please correct. Sense follows...");
|
||||
DicConsole.ErrorWriteLine("{0}", strSense);
|
||||
dumpLog.WriteLine("Drive could not rewind, please correct. Sense follows...");
|
||||
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ);
|
||||
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h",
|
||||
fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -193,18 +209,17 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
|
||||
sidecar.BlockMedia = new BlockMediaType[1];
|
||||
sidecar.BlockMedia[0] = new BlockMediaType
|
||||
{
|
||||
SCSI = new SCSIType()
|
||||
};
|
||||
sidecar.BlockMedia[0] = new BlockMediaType {SCSI = new SCSIType()};
|
||||
byte scsiMediumTypeTape = 0;
|
||||
byte scsiDensityCodeTape = 0;
|
||||
|
||||
dumpLog.WriteLine("Requesting MODE SENSE (10).");
|
||||
sense = dev.ModeSense10(out cmdBuf, out senseBuf, false, true, ScsiModeSensePageControl.Current, 0x3F, 0xFF, 5, out duration);
|
||||
sense = dev.ModeSense10(out cmdBuf, out senseBuf, false, true, ScsiModeSensePageControl.Current, 0x3F, 0xFF,
|
||||
5, out duration);
|
||||
if(!sense || dev.Error)
|
||||
{
|
||||
sense = dev.ModeSense10(out cmdBuf, out senseBuf, false, true, ScsiModeSensePageControl.Current, 0x3F, 0x00, 5, out duration);
|
||||
sense = dev.ModeSense10(out cmdBuf, out senseBuf, false, true, ScsiModeSensePageControl.Current, 0x3F,
|
||||
0x00, 5, out duration);
|
||||
}
|
||||
|
||||
Decoders.SCSI.Modes.DecodedMode? decMode = null;
|
||||
@@ -225,11 +240,12 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
|
||||
dumpLog.WriteLine("Requesting MODE SENSE (6).");
|
||||
sense = dev.ModeSense6(out cmdBuf, out senseBuf, false, ScsiModeSensePageControl.Current, 0x3F, 0x00, 5, out duration);
|
||||
sense = dev.ModeSense6(out cmdBuf, out senseBuf, false, ScsiModeSensePageControl.Current, 0x3F, 0x00, 5,
|
||||
out duration);
|
||||
if(sense || dev.Error)
|
||||
sense = dev.ModeSense6(out cmdBuf, out senseBuf, false, ScsiModeSensePageControl.Current, 0x3F, 0x00, 5, out duration);
|
||||
if(sense || dev.Error)
|
||||
sense = dev.ModeSense(out cmdBuf, out senseBuf, 5, out duration);
|
||||
sense = dev.ModeSense6(out cmdBuf, out senseBuf, false, ScsiModeSensePageControl.Current, 0x3F, 0x00, 5,
|
||||
out duration);
|
||||
if(sense || dev.Error) sense = dev.ModeSense(out cmdBuf, out senseBuf, 5, out duration);
|
||||
|
||||
if(!sense && !dev.Error)
|
||||
{
|
||||
@@ -255,11 +271,11 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
blockSize = decMode.Value.Header.BlockDescriptors[0].BlockLength;
|
||||
dumpLog.WriteLine("Device reports {0} blocks ({1} bytes).", blocks, blocks * blockSize);
|
||||
}
|
||||
else
|
||||
blockSize = 1;
|
||||
else blockSize = 1;
|
||||
|
||||
if(dskType == MediaType.Unknown)
|
||||
dskType = MediaTypeFromSCSI.Get((byte)dev.SCSIType, dev.Manufacturer, dev.Model, scsiMediumTypeTape, scsiDensityCodeTape, blocks, blockSize);
|
||||
dskType = MediaTypeFromSCSI.Get((byte)dev.SCSIType, dev.Manufacturer, dev.Model, scsiMediumTypeTape,
|
||||
scsiDensityCodeTape, blocks, blockSize);
|
||||
|
||||
DicConsole.WriteLine("Media identified as {0}", dskType);
|
||||
|
||||
@@ -280,7 +296,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
bool fixedLen = false;
|
||||
uint transferLen = blockSize;
|
||||
|
||||
sense = dev.Read6(out cmdBuf, out senseBuf, false, fixedLen, transferLen, blockSize, dev.Timeout, out duration);
|
||||
sense = dev.Read6(out cmdBuf, out senseBuf, false, fixedLen, transferLen, blockSize, dev.Timeout,
|
||||
out duration);
|
||||
if(sense)
|
||||
{
|
||||
fxSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf, out strSense);
|
||||
@@ -298,21 +315,24 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DicConsole.ErrorWriteLine("Drive could not return back. Sense follows...");
|
||||
DicConsole.ErrorWriteLine("{0}", strSense);
|
||||
dumpLog.WriteLine("Drive could not return back. Sense follows...");
|
||||
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ);
|
||||
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h",
|
||||
fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fixedLen = true;
|
||||
transferLen = 1;
|
||||
sense = dev.Read6(out cmdBuf, out senseBuf, false, fixedLen, transferLen, blockSize, dev.Timeout, out duration);
|
||||
sense = dev.Read6(out cmdBuf, out senseBuf, false, fixedLen, transferLen, blockSize,
|
||||
dev.Timeout, out duration);
|
||||
if(sense)
|
||||
{
|
||||
DicConsole.WriteLine();
|
||||
DicConsole.ErrorWriteLine("Drive could not read. Sense follows...");
|
||||
DicConsole.ErrorWriteLine("{0}", strSense);
|
||||
dumpLog.WriteLine("Drive could not read. Sense follows...");
|
||||
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ);
|
||||
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h",
|
||||
fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -322,7 +342,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DicConsole.ErrorWriteLine("Drive could not read. Sense follows...");
|
||||
DicConsole.ErrorWriteLine("{0}", strSense);
|
||||
dumpLog.WriteLine("Drive could not read. Sense follows...");
|
||||
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ);
|
||||
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h",
|
||||
fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -345,7 +366,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DicConsole.ErrorWriteLine("Drive could not return back. Sense follows...");
|
||||
DicConsole.ErrorWriteLine("{0}", strSense);
|
||||
dumpLog.WriteLine("Drive could not return back. Sense follows...");
|
||||
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ);
|
||||
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey,
|
||||
fxSense.Value.ASC, fxSense.Value.ASCQ);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -393,10 +415,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
partitionChk = new Checksum();
|
||||
|
||||
aborted = false;
|
||||
System.Console.CancelKeyPress += (sender, e) =>
|
||||
{
|
||||
e.Cancel = aborted = true;
|
||||
};
|
||||
System.Console.CancelKeyPress += (sender, e) => { e.Cancel = aborted = true; };
|
||||
|
||||
while(currentPartition < totalPartitions)
|
||||
{
|
||||
@@ -461,23 +480,24 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
|
||||
#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;
|
||||
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 block {0} ({1:F3} MiB/sec.)", currentBlock, currentSpeed);
|
||||
|
||||
sense = dev.Read6(out cmdBuf, out senseBuf, false, fixedLen, transferLen, blockSize, dev.Timeout, out duration);
|
||||
sense = dev.Read6(out cmdBuf, out senseBuf, false, fixedLen, transferLen, blockSize, dev.Timeout,
|
||||
out duration);
|
||||
totalDuration += duration;
|
||||
|
||||
if(sense)
|
||||
{
|
||||
fxSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf, out strSense);
|
||||
if(fxSense.Value.ASC == 0x00 && fxSense.Value.ASCQ == 0x00 && fxSense.Value.ILI && fxSense.Value.InformationValid)
|
||||
if(fxSense.Value.ASC == 0x00 && fxSense.Value.ASCQ == 0x00 && fxSense.Value.ILI &&
|
||||
fxSense.Value.InformationValid)
|
||||
{
|
||||
blockSize = (uint)((int)blockSize - BitConverter.ToInt32(BitConverter.GetBytes(fxSense.Value.Information), 0));
|
||||
blockSize = (uint)((int)blockSize -
|
||||
BitConverter.ToInt32(BitConverter.GetBytes(fxSense.Value.Information), 0));
|
||||
currentTapeFile.BlockSize = blockSize;
|
||||
|
||||
DicConsole.WriteLine();
|
||||
@@ -495,7 +515,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DicConsole.ErrorWriteLine("{0}", strSense);
|
||||
dumpFile.Close();
|
||||
dumpLog.WriteLine("Drive could not go back one block. Sense follows...");
|
||||
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ);
|
||||
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h",
|
||||
fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -514,7 +535,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
|
||||
// For sure this is an end-of-tape/partition
|
||||
if(fxSense.Value.ASC == 0x00 && (fxSense.Value.ASCQ == 0x02 || fxSense.Value.ASCQ == 0x05 || fxSense.Value.EOM))
|
||||
if(fxSense.Value.ASC == 0x00 &&
|
||||
(fxSense.Value.ASCQ == 0x02 || fxSense.Value.ASCQ == 0x05 || fxSense.Value.EOM))
|
||||
{
|
||||
// TODO: Detect end of partition
|
||||
endOfMedia = true;
|
||||
@@ -529,7 +551,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
continue;
|
||||
}
|
||||
|
||||
if((fxSense.Value.SenseKey == Decoders.SCSI.SenseKeys.NoSense || fxSense.Value.SenseKey == Decoders.SCSI.SenseKeys.RecoveredError) &&
|
||||
if((fxSense.Value.SenseKey == Decoders.SCSI.SenseKeys.NoSense ||
|
||||
fxSense.Value.SenseKey == Decoders.SCSI.SenseKeys.RecoveredError) &&
|
||||
(fxSense.Value.ASCQ == 0x02 || fxSense.Value.ASCQ == 0x05 || fxSense.Value.EOM))
|
||||
{
|
||||
// TODO: Detect end of partition
|
||||
@@ -538,7 +561,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
continue;
|
||||
}
|
||||
|
||||
if((fxSense.Value.SenseKey == Decoders.SCSI.SenseKeys.NoSense || fxSense.Value.SenseKey == Decoders.SCSI.SenseKeys.RecoveredError) &&
|
||||
if((fxSense.Value.SenseKey == Decoders.SCSI.SenseKeys.NoSense ||
|
||||
fxSense.Value.SenseKey == Decoders.SCSI.SenseKeys.RecoveredError) &&
|
||||
(fxSense.Value.ASCQ == 0x01 || fxSense.Value.Filemark))
|
||||
{
|
||||
currentTapeFile.Checksums = fileChk.End().ToArray();
|
||||
@@ -574,7 +598,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DicConsole.ErrorWriteLine("Drive could not read block. Sense follows...");
|
||||
DicConsole.ErrorWriteLine("{0} {1}", fxSense.Value.SenseKey, strSense);
|
||||
dumpLog.WriteLine("Drive could not read block. Sense follows...");
|
||||
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ);
|
||||
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey,
|
||||
fxSense.Value.ASC, fxSense.Value.ASCQ);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -602,14 +627,19 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DicConsole.WriteLine();
|
||||
end = DateTime.UtcNow;
|
||||
mhddLog.Close();
|
||||
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024, (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000), devicePath);
|
||||
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
|
||||
(((double)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));
|
||||
dumpLog.WriteLine("Average checksum speed {0:F3} KiB/sec.", (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalChkDuration / 1000));
|
||||
dumpLog.WriteLine("Average dump speed {0:F3} KiB/sec.",
|
||||
(((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000));
|
||||
dumpLog.WriteLine("Average checksum speed {0:F3} KiB/sec.",
|
||||
(((double)blockSize * (double)(blocks + 1)) / 1024) / (totalChkDuration / 1000));
|
||||
|
||||
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("Took a total of {0:F3} seconds ({1:F3} processing commands, {2:F3} checksumming).",
|
||||
(end - start).TotalSeconds, totalDuration / 1000, totalChkDuration / 1000);
|
||||
#pragma warning disable IDE0004 // Cast is necessary, otherwise incorrect value is created
|
||||
DicConsole.WriteLine("Avegare speed: {0:F3} MiB/sec.", (((double)blockSize * (double)(blocks + 1)) / 1048576) / (totalDuration / 1000));
|
||||
DicConsole.WriteLine("Avegare speed: {0:F3} MiB/sec.",
|
||||
(((double)blockSize * (double)(blocks + 1)) / 1048576) / (totalDuration / 1000));
|
||||
#pragma warning restore IDE0004 // Cast is necessary, otherwise incorrect value is created
|
||||
DicConsole.WriteLine("Fastest speed burst: {0:F3} MiB/sec.", maxSpeed);
|
||||
DicConsole.WriteLine("Slowest speed burst: {0:F3} MiB/sec.", minSpeed);
|
||||
@@ -628,15 +658,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
sidecar.BlockMedia[0].LogicalBlocks = (long)blocks;
|
||||
sidecar.BlockMedia[0].Size = (long)(currentSize);
|
||||
sidecar.BlockMedia[0].DumpHardwareArray = new DumpHardwareType[1];
|
||||
sidecar.BlockMedia[0].DumpHardwareArray[0] = new DumpHardwareType
|
||||
{
|
||||
Extents = new ExtentType[1]
|
||||
};
|
||||
sidecar.BlockMedia[0].DumpHardwareArray[0].Extents[0] = new ExtentType
|
||||
{
|
||||
Start = 0,
|
||||
End = blocks - 1
|
||||
};
|
||||
sidecar.BlockMedia[0].DumpHardwareArray[0] = new DumpHardwareType {Extents = new ExtentType[1]};
|
||||
sidecar.BlockMedia[0].DumpHardwareArray[0].Extents[0] = new ExtentType {Start = 0, End = blocks - 1};
|
||||
sidecar.BlockMedia[0].DumpHardwareArray[0].Manufacturer = dev.Manufacturer;
|
||||
sidecar.BlockMedia[0].DumpHardwareArray[0].Model = dev.Model;
|
||||
sidecar.BlockMedia[0].DumpHardwareArray[0].Revision = dev.Revision;
|
||||
@@ -648,10 +671,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
DicConsole.WriteLine("Writing metadata sidecar");
|
||||
|
||||
FileStream xmlFs = new FileStream(outputPrefix + ".cicm.xml",
|
||||
FileMode.Create);
|
||||
FileStream xmlFs = new FileStream(outputPrefix + ".cicm.xml", FileMode.Create);
|
||||
|
||||
System.Xml.Serialization.XmlSerializer xmlSer = new System.Xml.Serialization.XmlSerializer(typeof(CICMMetadataType));
|
||||
System.Xml.Serialization.XmlSerializer xmlSer =
|
||||
new System.Xml.Serialization.XmlSerializer(typeof(CICMMetadataType));
|
||||
xmlSer.Serialize(xmlFs, sidecar);
|
||||
xmlFs.Close();
|
||||
}
|
||||
@@ -661,4 +684,4 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -49,7 +49,9 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
public class SecureDigital
|
||||
{
|
||||
public static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, ref Metadata.Resume resume, ref DumpLog dumpLog, Encoding encoding)
|
||||
public static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force,
|
||||
bool dumpRaw, bool persistent, bool stopOnError, ref Metadata.Resume resume,
|
||||
ref DumpLog dumpLog, Encoding encoding)
|
||||
{
|
||||
bool aborted;
|
||||
MHDDLog mhddLog;
|
||||
@@ -59,8 +61,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
DicConsole.ErrorWriteLine("Raw dumping is not supported in MultiMediaCard or SecureDigital devices.");
|
||||
|
||||
if(force)
|
||||
DicConsole.ErrorWriteLine("Continuing...");
|
||||
if(force) DicConsole.ErrorWriteLine("Continuing...");
|
||||
else
|
||||
{
|
||||
DicConsole.ErrorWriteLine("Aborting...");
|
||||
@@ -73,10 +74,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
uint timeout = 5;
|
||||
double duration;
|
||||
|
||||
CICMMetadataType sidecar = new CICMMetadataType()
|
||||
{
|
||||
BlockMedia = new BlockMediaType[] { new BlockMediaType() }
|
||||
};
|
||||
CICMMetadataType sidecar =
|
||||
new CICMMetadataType() {BlockMedia = new BlockMediaType[] {new BlockMediaType()}};
|
||||
|
||||
uint blocksToRead = 128;
|
||||
uint blockSize = 512;
|
||||
@@ -103,15 +102,12 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
blocksToRead = ecsdDecoded.OptimalReadSize;
|
||||
blocks = ecsdDecoded.SectorCount;
|
||||
blockSize = (uint)(ecsdDecoded.SectorSize == 1 ? 4096 : 512);
|
||||
if(ecsdDecoded.NativeSectorSize == 0)
|
||||
physicalBlockSize = 512;
|
||||
else if(ecsdDecoded.NativeSectorSize == 1)
|
||||
physicalBlockSize = 4096;
|
||||
if(ecsdDecoded.NativeSectorSize == 0) physicalBlockSize = 512;
|
||||
else if(ecsdDecoded.NativeSectorSize == 1) physicalBlockSize = 4096;
|
||||
// Supposing it's high-capacity MMC if it has Extended CSD...
|
||||
byteAddressed = false;
|
||||
}
|
||||
else
|
||||
ecsd = null;
|
||||
else ecsd = null;
|
||||
|
||||
dumpLog.WriteLine("Reading CSD");
|
||||
sense = dev.ReadCSD(out csd, out response, timeout, out duration);
|
||||
@@ -124,13 +120,11 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
blockSize = (uint)Math.Pow(2, csdDecoded.ReadBlockLength);
|
||||
}
|
||||
}
|
||||
else
|
||||
csd = null;
|
||||
else csd = null;
|
||||
|
||||
dumpLog.WriteLine("Reading OCR");
|
||||
sense = dev.ReadOCR(out ocr, out response, timeout, out duration);
|
||||
if(sense)
|
||||
ocr = null;
|
||||
if(sense) ocr = null;
|
||||
|
||||
sidecar.BlockMedia[0].MultiMediaCard = new MultiMediaCardType();
|
||||
}
|
||||
@@ -143,31 +137,29 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(!sense)
|
||||
{
|
||||
csdDecoded = Decoders.SecureDigital.Decoders.DecodeCSD(csd);
|
||||
blocks = (ulong)(csdDecoded.Structure == 0 ? (csdDecoded.Size + 1) * Math.Pow(2, csdDecoded.SizeMultiplier + 2) : (csdDecoded.Size + 1) * 1024);
|
||||
blocks = (ulong)(csdDecoded.Structure == 0
|
||||
? (csdDecoded.Size + 1) * Math.Pow(2, csdDecoded.SizeMultiplier + 2)
|
||||
: (csdDecoded.Size + 1) * 1024);
|
||||
blockSize = (uint)Math.Pow(2, csdDecoded.ReadBlockLength);
|
||||
// Structure >=1 for SDHC/SDXC, so that's block addressed
|
||||
byteAddressed = csdDecoded.Structure == 0;
|
||||
}
|
||||
else
|
||||
csd = null;
|
||||
else csd = null;
|
||||
|
||||
dumpLog.WriteLine("Reading OCR");
|
||||
sense = dev.ReadSDOCR(out ocr, out response, timeout, out duration);
|
||||
if(sense)
|
||||
ocr = null;
|
||||
if(sense) ocr = null;
|
||||
|
||||
dumpLog.WriteLine("Reading SCR");
|
||||
sense = dev.ReadSCR(out scr, out response, timeout, out duration);
|
||||
if(sense)
|
||||
scr = null;
|
||||
if(sense) scr = null;
|
||||
|
||||
sidecar.BlockMedia[0].SecureDigital = new SecureDigitalType();
|
||||
}
|
||||
|
||||
dumpLog.WriteLine("Reading CID");
|
||||
sense = dev.ReadCID(out cid, out response, timeout, out duration);
|
||||
if(sense)
|
||||
cid = null;
|
||||
if(sense) cid = null;
|
||||
|
||||
DumpType cidDump = null;
|
||||
DumpType csdDump = null;
|
||||
@@ -182,7 +174,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
Checksums = Checksum.GetChecksums(cid).ToArray()
|
||||
};
|
||||
DataFile.WriteTo("MMC/SecureDigital Dump", cidDump.Image, cid);
|
||||
};
|
||||
}
|
||||
;
|
||||
if(csd != null)
|
||||
{
|
||||
csdDump = new DumpType
|
||||
@@ -192,7 +185,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
Checksums = Checksum.GetChecksums(csd).ToArray()
|
||||
};
|
||||
DataFile.WriteTo("MMC/SecureDigital Dump", csdDump.Image, csd);
|
||||
};
|
||||
}
|
||||
;
|
||||
if(ecsd != null)
|
||||
{
|
||||
sidecar.BlockMedia[0].MultiMediaCard.ExtendedCSD = new DumpType
|
||||
@@ -201,8 +195,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
Size = ecsd.Length,
|
||||
Checksums = Checksum.GetChecksums(ecsd).ToArray()
|
||||
};
|
||||
DataFile.WriteTo("MMC/SecureDigital Dump", sidecar.BlockMedia[0].MultiMediaCard.ExtendedCSD.Image, ecsd);
|
||||
};
|
||||
DataFile.WriteTo("MMC/SecureDigital Dump", sidecar.BlockMedia[0].MultiMediaCard.ExtendedCSD.Image,
|
||||
ecsd);
|
||||
}
|
||||
;
|
||||
if(ocr != null)
|
||||
{
|
||||
ocrDump = new DumpType
|
||||
@@ -212,7 +208,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
Checksums = Checksum.GetChecksums(ocr).ToArray()
|
||||
};
|
||||
DataFile.WriteTo("MMC/SecureDigital Dump", ocrDump.Image, ocr);
|
||||
};
|
||||
}
|
||||
;
|
||||
if(scr != null)
|
||||
{
|
||||
sidecar.BlockMedia[0].SecureDigital.SCR = new DumpType
|
||||
@@ -222,7 +219,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
Checksums = Checksum.GetChecksums(scr).ToArray()
|
||||
};
|
||||
DataFile.WriteTo("MMC/SecureDigital Dump", sidecar.BlockMedia[0].SecureDigital.SCR.Image, scr);
|
||||
};
|
||||
}
|
||||
;
|
||||
|
||||
if(dev.Type == DeviceType.MMC)
|
||||
{
|
||||
@@ -247,10 +245,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
Checksum dataChk;
|
||||
|
||||
aborted = false;
|
||||
System.Console.CancelKeyPress += (sender, e) =>
|
||||
{
|
||||
e.Cancel = aborted = true;
|
||||
};
|
||||
System.Console.CancelKeyPress += (sender, e) => { e.Cancel = aborted = true; };
|
||||
|
||||
DataFile dumpFile;
|
||||
|
||||
@@ -260,6 +255,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DicConsole.ErrorWriteLine("Unable to get device size.");
|
||||
return;
|
||||
}
|
||||
|
||||
dumpLog.WriteLine("Device reports {0} blocks.", blocks);
|
||||
|
||||
byte[] cmdBuf;
|
||||
@@ -267,13 +263,12 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
while(true)
|
||||
{
|
||||
error = dev.Read(out cmdBuf, out response, 0, blockSize, blocksToRead, byteAddressed, timeout, out duration);
|
||||
error = dev.Read(out cmdBuf, out response, 0, blockSize, blocksToRead, byteAddressed, timeout,
|
||||
out duration);
|
||||
|
||||
if(error)
|
||||
blocksToRead /= 2;
|
||||
if(error) blocksToRead /= 2;
|
||||
|
||||
if(!error || blocksToRead == 1)
|
||||
break;
|
||||
if(!error || blocksToRead == 1) break;
|
||||
}
|
||||
|
||||
if(error)
|
||||
@@ -288,7 +283,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
DumpHardwareType currentTry = null;
|
||||
ExtentsULong extents = null;
|
||||
ResumeSupport.Process(true, false, blocks, dev.Manufacturer, dev.Model, dev.Serial, dev.PlatformID, ref resume, ref currentTry, ref extents);
|
||||
ResumeSupport.Process(true, false, 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...");
|
||||
|
||||
@@ -298,8 +294,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
ibgLog = new IBGLog(outputPrefix + ".ibg", currentProfile);
|
||||
dumpFile = new DataFile(outputPrefix + ".bin");
|
||||
dumpFile.Seek(resume.NextBlock, blockSize);
|
||||
if(resume.NextBlock > 0)
|
||||
dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
|
||||
if(resume.NextBlock > 0) dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
|
||||
|
||||
start = DateTime.UtcNow;
|
||||
for(ulong i = resume.NextBlock; i < blocks; i += blocksToRead)
|
||||
@@ -311,19 +306,17 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
break;
|
||||
}
|
||||
|
||||
if((blocks - i) < blocksToRead)
|
||||
blocksToRead = (byte)(blocks - i);
|
||||
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;
|
||||
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);
|
||||
|
||||
error = dev.Read(out cmdBuf, out response, (uint)i, blockSize, blocksToRead, byteAddressed, timeout, out duration);
|
||||
error = dev.Read(out cmdBuf, out response, (uint)i, blockSize, blocksToRead, byteAddressed, timeout,
|
||||
out duration);
|
||||
|
||||
if(!error)
|
||||
{
|
||||
@@ -334,12 +327,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
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);
|
||||
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]);
|
||||
@@ -352,24 +343,26 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
GC.Collect();
|
||||
resume.NextBlock = i + blocksToRead;
|
||||
}
|
||||
|
||||
end = DateTime.Now;
|
||||
DicConsole.WriteLine();
|
||||
mhddLog.Close();
|
||||
#pragma warning disable IDE0004 // Cast is necessary, otherwise incorrect value is created
|
||||
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024, (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000), devicePath);
|
||||
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
|
||||
(((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000), devicePath);
|
||||
#pragma warning restore IDE0004 // Cast is necessary, otherwise incorrect value is created
|
||||
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));
|
||||
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;
|
||||
bool forward = true;
|
||||
bool runningPersistent = false;
|
||||
|
||||
repeatRetryLba:
|
||||
repeatRetryLba:
|
||||
ulong[] tmpArray = resume.BadBlocks.ToArray();
|
||||
foreach(ulong badSector in tmpArray)
|
||||
{
|
||||
@@ -380,9 +373,12 @@ 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, " : "");
|
||||
DicConsole.Write("\rRetrying sector {0}, pass {1}, {3}{2}", badSector, pass + 1,
|
||||
forward ? "forward" : "reverse",
|
||||
runningPersistent ? "recovering partial data, " : "");
|
||||
|
||||
error = dev.Read(out cmdBuf, out response, (uint)badSector, blockSize, 1, byteAddressed, timeout, out duration);
|
||||
error = dev.Read(out cmdBuf, out response, (uint)badSector, blockSize, 1, byteAddressed, timeout,
|
||||
out duration);
|
||||
|
||||
totalDuration += duration;
|
||||
|
||||
@@ -393,8 +389,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
dumpFile.WriteAt(cmdBuf, badSector, blockSize);
|
||||
dumpLog.WriteLine("Correctly retried block {0} in pass {1}.", badSector, pass);
|
||||
}
|
||||
else if(runningPersistent)
|
||||
dumpFile.WriteAt(cmdBuf, badSector, blockSize);
|
||||
else if(runningPersistent) dumpFile.WriteAt(cmdBuf, badSector, blockSize);
|
||||
}
|
||||
|
||||
if(pass < retryPasses && !aborted && resume.BadBlocks.Count > 0)
|
||||
@@ -425,8 +420,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
break;
|
||||
}
|
||||
|
||||
if((blocks - i) < blocksToRead)
|
||||
blocksToRead = (byte)(blocks - i);
|
||||
if((blocks - i) < blocksToRead) blocksToRead = (byte)(blocks - i);
|
||||
|
||||
DicConsole.Write("\rChecksumming sector {0} of {1} ({2:F3} MiB/sec.)", i, blocks, currentSpeed);
|
||||
|
||||
@@ -441,11 +435,13 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
currentSpeed = ((double)blockSize * blocksToRead / (double)1048576) / (chkDuration / (double)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));
|
||||
dumpLog.WriteLine("Average checksum speed {0:F3} KiB/sec.",
|
||||
(((double)blockSize * (double)(blocks + 1)) / 1024) / (totalChkDuration / 1000));
|
||||
|
||||
PluginBase plugins = new PluginBase();
|
||||
plugins.RegisterAllPlugins(encoding);
|
||||
@@ -463,15 +459,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
_imageFormat = ImageFormat.Detect(inputFilter);
|
||||
PartitionType[] xmlFileSysInfo = null;
|
||||
|
||||
try
|
||||
{
|
||||
if(!_imageFormat.OpenImage(inputFilter))
|
||||
_imageFormat = null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
_imageFormat = null;
|
||||
}
|
||||
try { if(!_imageFormat.OpenImage(inputFilter)) _imageFormat = null; }
|
||||
catch { _imageFormat = null; }
|
||||
|
||||
if(_imageFormat != null)
|
||||
{
|
||||
@@ -496,7 +485,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
};
|
||||
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);
|
||||
i, partitions[i].Start, partitions[i].End, partitions[i].Type,
|
||||
partitions[i].Scheme);
|
||||
|
||||
foreach(Filesystem _plugin in plugins.PluginsList.Values)
|
||||
{
|
||||
@@ -518,8 +508,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
}
|
||||
|
||||
if(lstFs.Count > 0)
|
||||
xmlFileSysInfo[i].FileSystems = lstFs.ToArray();
|
||||
if(lstFs.Count > 0) xmlFileSysInfo[i].FileSystems = lstFs.ToArray();
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -527,19 +516,11 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
dumpLog.WriteLine("Getting filesystem for whole device.");
|
||||
|
||||
xmlFileSysInfo = new PartitionType[1];
|
||||
xmlFileSysInfo[0] = new PartitionType
|
||||
{
|
||||
EndSector = (int)(blocks - 1),
|
||||
StartSector = 0
|
||||
};
|
||||
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
|
||||
};
|
||||
Partition wholePart =
|
||||
new Partition {Name = "Whole device", Length = blocks, Size = blocks * blockSize};
|
||||
|
||||
foreach(Filesystem _plugin in plugins.PluginsList.Values)
|
||||
{
|
||||
@@ -561,8 +542,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
}
|
||||
|
||||
if(lstFs.Count > 0)
|
||||
xmlFileSysInfo[0].FileSystems = lstFs.ToArray();
|
||||
if(lstFs.Count > 0) xmlFileSysInfo[0].FileSystems = lstFs.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -586,10 +566,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
format = "Raw disk image (sector by sector copy)",
|
||||
Value = outputPrefix + ".bin"
|
||||
};
|
||||
if(dev.Type == DeviceType.MMC)
|
||||
sidecar.BlockMedia[0].Interface = "MultiMediaCard";
|
||||
else if(dev.Type == DeviceType.SecureDigital)
|
||||
sidecar.BlockMedia[0].Interface = "SecureDigital";
|
||||
if(dev.Type == DeviceType.MMC) sidecar.BlockMedia[0].Interface = "MultiMediaCard";
|
||||
else if(dev.Type == DeviceType.SecureDigital) sidecar.BlockMedia[0].Interface = "SecureDigital";
|
||||
sidecar.BlockMedia[0].LogicalBlocks = (long)blocks;
|
||||
sidecar.BlockMedia[0].PhysicalBlockSize = physicalBlockSize > 0 ? physicalBlockSize : (int)blockSize;
|
||||
sidecar.BlockMedia[0].LogicalBlockSize = (int)blockSize;
|
||||
@@ -597,36 +575,34 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
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(xmlFileSysInfo != null) sidecar.BlockMedia[0].FileSystemInformation = xmlFileSysInfo;
|
||||
|
||||
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("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();
|
||||
if(resume.BadBlocks.Count > 0) resume.BadBlocks.Sort();
|
||||
DicConsole.WriteLine();
|
||||
|
||||
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);
|
||||
|
||||
System.Xml.Serialization.XmlSerializer xmlSer = new System.Xml.Serialization.XmlSerializer(typeof(CICMMetadataType));
|
||||
System.Xml.Serialization.XmlSerializer xmlSer =
|
||||
new System.Xml.Serialization.XmlSerializer(typeof(CICMMetadataType));
|
||||
xmlSer.Serialize(xmlFs, sidecar);
|
||||
xmlFs.Close();
|
||||
}
|
||||
|
||||
if(dev.Type == DeviceType.MMC)
|
||||
Statistics.AddMedia(MediaType.MMC, true);
|
||||
else if(dev.Type == DeviceType.SecureDigital)
|
||||
Statistics.AddMedia(MediaType.SecureDigital, true);
|
||||
if(dev.Type == DeviceType.MMC) Statistics.AddMedia(MediaType.MMC, true);
|
||||
else if(dev.Type == DeviceType.SecureDigital) Statistics.AddMedia(MediaType.SecureDigital, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -49,7 +49,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
internal static class XGD
|
||||
{
|
||||
internal static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, ref CICMMetadataType sidecar, ref MediaType dskType, ref Metadata.Resume resume, ref DumpLog dumpLog, Encoding encoding)
|
||||
internal static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force,
|
||||
bool dumpRaw, bool persistent, bool stopOnError, ref CICMMetadataType sidecar,
|
||||
ref MediaType dskType, ref Metadata.Resume resume, ref DumpLog dumpLog,
|
||||
Encoding encoding)
|
||||
{
|
||||
MHDDLog mhddLog;
|
||||
IBGLog ibgLog;
|
||||
@@ -68,10 +71,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
Checksum dataChk;
|
||||
DataFile dumpFile = null;
|
||||
bool aborted = false;
|
||||
System.Console.CancelKeyPress += (sender, e) =>
|
||||
{
|
||||
e.Cancel = aborted = true;
|
||||
};
|
||||
System.Console.CancelKeyPress += (sender, e) => { e.Cancel = aborted = true; };
|
||||
|
||||
dumpLog.WriteLine("Reading Xbox Security Sector.");
|
||||
sense = dev.KreonExtractSS(out byte[] ssBuf, out byte[] senseBuf, dev.Timeout, out double duration);
|
||||
@@ -96,19 +96,19 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
sidecar.OpticalDisc[0].Xbox = new XboxType()
|
||||
{
|
||||
SecuritySectors = new XboxSecuritySectorsType[]
|
||||
{
|
||||
new XboxSecuritySectorsType()
|
||||
{
|
||||
RequestNumber = 0,
|
||||
RequestVersion = 1,
|
||||
SecuritySectors = new DumpType()
|
||||
{
|
||||
Image = outputPrefix + ".ss.bin",
|
||||
Size = tmpBuf.Length,
|
||||
Checksums = Checksum.GetChecksums(tmpBuf).ToArray()
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
new XboxSecuritySectorsType()
|
||||
{
|
||||
RequestNumber = 0,
|
||||
RequestVersion = 1,
|
||||
SecuritySectors = new DumpType()
|
||||
{
|
||||
Image = outputPrefix + ".ss.bin",
|
||||
Size = tmpBuf.Length,
|
||||
Checksums = Checksum.GetChecksums(tmpBuf).ToArray()
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
DataFile.WriteTo("SCSI Dump", outputPrefix + ".ss.bin", ssBuf);
|
||||
|
||||
@@ -124,6 +124,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DicConsole.ErrorWriteLine("Cannot lock drive, not continuing.");
|
||||
return;
|
||||
}
|
||||
|
||||
dumpLog.WriteLine("Getting video partition size.");
|
||||
sense = dev.ReadCapacity(out byte[] readBuffer, out senseBuf, dev.Timeout, out duration);
|
||||
if(sense)
|
||||
@@ -132,15 +133,18 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DicConsole.ErrorWriteLine("Cannot get disc capacity.");
|
||||
return;
|
||||
}
|
||||
|
||||
totalSize = (ulong)((readBuffer[0] << 24) + (readBuffer[1] << 16) + (readBuffer[2] << 8) + (readBuffer[3]));
|
||||
dumpLog.WriteLine("Reading Physical Format Information.");
|
||||
sense = dev.ReadDiscStructure(out readBuffer, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.PhysicalInformation, 0, 0, out duration);
|
||||
sense = dev.ReadDiscStructure(out readBuffer, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0,
|
||||
MmcDiscStructureFormat.PhysicalInformation, 0, 0, out duration);
|
||||
if(sense)
|
||||
{
|
||||
dumpLog.WriteLine("Cannot get PFI.");
|
||||
DicConsole.ErrorWriteLine("Cannot get PFI.");
|
||||
return;
|
||||
}
|
||||
|
||||
tmpBuf = new byte[readBuffer.Length - 4];
|
||||
Array.Copy(readBuffer, 4, tmpBuf, 0, readBuffer.Length - 4);
|
||||
sidecar.OpticalDisc[0].PFI = new DumpType
|
||||
@@ -151,16 +155,19 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
};
|
||||
DataFile.WriteTo("SCSI Dump", sidecar.OpticalDisc[0].PFI.Image, tmpBuf, "Locked PFI", true);
|
||||
DicConsole.DebugWriteLine("Dump-media command", "Video partition total size: {0} sectors", totalSize);
|
||||
l0Video = Decoders.DVD.PFI.Decode(readBuffer).Value.Layer0EndPSN - Decoders.DVD.PFI.Decode(readBuffer).Value.DataAreaStartPSN + 1;
|
||||
l0Video = Decoders.DVD.PFI.Decode(readBuffer).Value.Layer0EndPSN -
|
||||
Decoders.DVD.PFI.Decode(readBuffer).Value.DataAreaStartPSN + 1;
|
||||
l1Video = totalSize - l0Video + 1;
|
||||
dumpLog.WriteLine("Reading Disc Manufacturing Information.");
|
||||
sense = dev.ReadDiscStructure(out readBuffer, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DiscManufacturingInformation, 0, 0, out duration);
|
||||
sense = dev.ReadDiscStructure(out readBuffer, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0,
|
||||
MmcDiscStructureFormat.DiscManufacturingInformation, 0, 0, out duration);
|
||||
if(sense)
|
||||
{
|
||||
dumpLog.WriteLine("Cannot get DMI.");
|
||||
DicConsole.ErrorWriteLine("Cannot get DMI.");
|
||||
return;
|
||||
}
|
||||
|
||||
tmpBuf = new byte[readBuffer.Length - 4];
|
||||
Array.Copy(readBuffer, 4, tmpBuf, 0, readBuffer.Length - 4);
|
||||
sidecar.OpticalDisc[0].DMI = new DumpType
|
||||
@@ -181,6 +188,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DicConsole.ErrorWriteLine("Cannot unlock drive, not continuing.");
|
||||
return;
|
||||
}
|
||||
|
||||
dumpLog.WriteLine("Getting game partition size.");
|
||||
sense = dev.ReadCapacity(out readBuffer, out senseBuf, dev.Timeout, out duration);
|
||||
if(sense)
|
||||
@@ -189,7 +197,9 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DicConsole.ErrorWriteLine("Cannot get disc capacity.");
|
||||
return;
|
||||
}
|
||||
gameSize = (ulong)((readBuffer[0] << 24) + (readBuffer[1] << 16) + (readBuffer[2] << 8) + (readBuffer[3])) + 1;
|
||||
|
||||
gameSize = (ulong)((readBuffer[0] << 24) + (readBuffer[1] << 16) + (readBuffer[2] << 8) + (readBuffer[3])) +
|
||||
1;
|
||||
DicConsole.DebugWriteLine("Dump-media command", "Game partition total size: {0} sectors", gameSize);
|
||||
|
||||
// Get middle zone size
|
||||
@@ -202,6 +212,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DicConsole.ErrorWriteLine("Cannot unlock drive, not continuing.");
|
||||
return;
|
||||
}
|
||||
|
||||
dumpLog.WriteLine("Getting disc size.");
|
||||
sense = dev.ReadCapacity(out readBuffer, out senseBuf, dev.Timeout, out duration);
|
||||
if(sense)
|
||||
@@ -210,18 +221,22 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DicConsole.ErrorWriteLine("Cannot get disc capacity.");
|
||||
return;
|
||||
}
|
||||
|
||||
totalSize = (ulong)((readBuffer[0] << 24) + (readBuffer[1] << 16) + (readBuffer[2] << 8) + (readBuffer[3]));
|
||||
dumpLog.WriteLine("Reading Physical Format Information.");
|
||||
sense = dev.ReadDiscStructure(out readBuffer, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.PhysicalInformation, 0, 0, out duration);
|
||||
sense = dev.ReadDiscStructure(out readBuffer, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0,
|
||||
MmcDiscStructureFormat.PhysicalInformation, 0, 0, out duration);
|
||||
if(sense)
|
||||
{
|
||||
dumpLog.WriteLine("Cannot get PFI.");
|
||||
DicConsole.ErrorWriteLine("Cannot get PFI.");
|
||||
return;
|
||||
}
|
||||
|
||||
DicConsole.DebugWriteLine("Dump-media command", "Unlocked total size: {0} sectors", totalSize);
|
||||
blocks = totalSize + 1;
|
||||
middleZone = totalSize - (Decoders.DVD.PFI.Decode(readBuffer).Value.Layer0EndPSN - Decoders.DVD.PFI.Decode(readBuffer).Value.DataAreaStartPSN + 1) - gameSize + 1;
|
||||
middleZone = totalSize - (Decoders.DVD.PFI.Decode(readBuffer).Value.Layer0EndPSN -
|
||||
Decoders.DVD.PFI.Decode(readBuffer).Value.DataAreaStartPSN + 1) - gameSize + 1;
|
||||
|
||||
tmpBuf = new byte[readBuffer.Length - 4];
|
||||
Array.Copy(readBuffer, 4, tmpBuf, 0, readBuffer.Length - 4);
|
||||
@@ -234,13 +249,15 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DataFile.WriteTo("SCSI Dump", sidecar.OpticalDisc[0].Xbox.PFI.Image, tmpBuf, "Unlocked PFI", true);
|
||||
|
||||
dumpLog.WriteLine("Reading Disc Manufacturing Information.");
|
||||
sense = dev.ReadDiscStructure(out readBuffer, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DiscManufacturingInformation, 0, 0, out duration);
|
||||
sense = dev.ReadDiscStructure(out readBuffer, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0,
|
||||
MmcDiscStructureFormat.DiscManufacturingInformation, 0, 0, out duration);
|
||||
if(sense)
|
||||
{
|
||||
dumpLog.WriteLine("Cannot get DMI.");
|
||||
DicConsole.ErrorWriteLine("Cannot get DMI.");
|
||||
return;
|
||||
}
|
||||
|
||||
tmpBuf = new byte[readBuffer.Length - 4];
|
||||
Array.Copy(readBuffer, 4, tmpBuf, 0, readBuffer.Length - 4);
|
||||
sidecar.OpticalDisc[0].Xbox.DMI = new DumpType
|
||||
@@ -251,7 +268,6 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
};
|
||||
DataFile.WriteTo("SCSI Dump", sidecar.OpticalDisc[0].Xbox.DMI.Image, tmpBuf, "Unlocked DMI", true);
|
||||
|
||||
|
||||
totalSize = l0Video + l1Video + middleZone * 2 + gameSize;
|
||||
layerBreak = l0Video + middleZone + gameSize / 2;
|
||||
|
||||
@@ -270,7 +286,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
dumpLog.WriteLine("Total 0 size: {0} sectors", totalSize);
|
||||
dumpLog.WriteLine("Real layer break: {0}", layerBreak);
|
||||
|
||||
bool read12 = !dev.Read12(out readBuffer, out senseBuf, 0, false, true, false, false, 0, blockSize, 0, 1, false, dev.Timeout, out duration);
|
||||
bool read12 = !dev.Read12(out readBuffer, out senseBuf, 0, false, true, false, false, 0, blockSize, 0, 1,
|
||||
false, dev.Timeout, out duration);
|
||||
if(!read12)
|
||||
{
|
||||
dumpLog.WriteLine("Cannot read medium, aborting scan...");
|
||||
@@ -285,13 +302,12 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
if(read12)
|
||||
{
|
||||
sense = dev.Read12(out readBuffer, out senseBuf, 0, false, false, false, false, 0, blockSize, 0, blocksToRead, false, dev.Timeout, out duration);
|
||||
if(sense || dev.Error)
|
||||
blocksToRead /= 2;
|
||||
sense = dev.Read12(out readBuffer, out senseBuf, 0, false, false, false, false, 0, blockSize, 0,
|
||||
blocksToRead, false, dev.Timeout, out duration);
|
||||
if(sense || dev.Error) blocksToRead /= 2;
|
||||
}
|
||||
|
||||
if(!dev.Error || blocksToRead == 1)
|
||||
break;
|
||||
if(!dev.Error || blocksToRead == 1) break;
|
||||
}
|
||||
|
||||
if(dev.Error)
|
||||
@@ -316,13 +332,14 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
uint saveBlocksToRead = blocksToRead;
|
||||
DumpHardwareType currentTry = null;
|
||||
ExtentsULong extents = null;
|
||||
ResumeSupport.Process(true, true, totalSize, dev.Manufacturer, dev.Model, dev.Serial, dev.PlatformID, ref resume, ref currentTry, ref extents);
|
||||
ResumeSupport.Process(true, true, totalSize, 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...");
|
||||
|
||||
ulong currentSector = resume.NextBlock;
|
||||
dumpFile.Seek(resume.NextBlock, blockSize);
|
||||
if(resume.NextBlock > 0)
|
||||
dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
|
||||
if(resume.NextBlock > 0) dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
|
||||
|
||||
dumpLog.WriteLine("Reading game partition.");
|
||||
for(int e = 0; e <= 16; e++)
|
||||
@@ -335,8 +352,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
break;
|
||||
}
|
||||
|
||||
if(currentSector >= blocks)
|
||||
break;
|
||||
if(currentSector >= blocks) break;
|
||||
|
||||
ulong extentStart, extentEnd;
|
||||
// Extents
|
||||
@@ -345,11 +361,13 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
if(xboxSS.Value.Extents[e].StartPSN <= xboxSS.Value.Layer0EndPSN)
|
||||
extentStart = xboxSS.Value.Extents[e].StartPSN - 0x30000;
|
||||
else
|
||||
extentStart = (xboxSS.Value.Layer0EndPSN + 1) * 2 - ((xboxSS.Value.Extents[e].StartPSN ^ 0xFFFFFF) + 1) - 0x30000;
|
||||
extentStart = (xboxSS.Value.Layer0EndPSN + 1) * 2 -
|
||||
((xboxSS.Value.Extents[e].StartPSN ^ 0xFFFFFF) + 1) - 0x30000;
|
||||
if(xboxSS.Value.Extents[e].EndPSN <= xboxSS.Value.Layer0EndPSN)
|
||||
extentEnd = xboxSS.Value.Extents[e].EndPSN - 0x30000;
|
||||
else
|
||||
extentEnd = (xboxSS.Value.Layer0EndPSN + 1) * 2 - ((xboxSS.Value.Extents[e].EndPSN ^ 0xFFFFFF) + 1) - 0x30000;
|
||||
extentEnd = (xboxSS.Value.Layer0EndPSN + 1) * 2 -
|
||||
((xboxSS.Value.Extents[e].EndPSN ^ 0xFFFFFF) + 1) - 0x30000;
|
||||
}
|
||||
// After last extent
|
||||
else
|
||||
@@ -358,8 +376,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
extentEnd = blocks;
|
||||
}
|
||||
|
||||
if(currentSector > extentEnd)
|
||||
continue;
|
||||
if(currentSector > extentEnd) continue;
|
||||
|
||||
for(ulong i = currentSector; i < extentStart; i += blocksToRead)
|
||||
{
|
||||
@@ -372,19 +389,17 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
break;
|
||||
}
|
||||
|
||||
if((extentStart - i) < blocksToRead)
|
||||
blocksToRead = (uint)(extentStart - i);
|
||||
if((extentStart - i) < blocksToRead) blocksToRead = (uint)(extentStart - 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;
|
||||
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, totalSize, currentSpeed);
|
||||
|
||||
sense = dev.Read12(out readBuffer, out senseBuf, 0, false, false, false, false, (uint)i, blockSize, 0, blocksToRead, false, dev.Timeout, out cmdDuration);
|
||||
sense = dev.Read12(out readBuffer, out senseBuf, 0, false, false, false, false, (uint)i, blockSize,
|
||||
0, blocksToRead, false, dev.Timeout, out cmdDuration);
|
||||
totalDuration += cmdDuration;
|
||||
|
||||
if(!sense && !dev.Error)
|
||||
@@ -397,27 +412,26 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
else
|
||||
{
|
||||
// TODO: Reset device after X errors
|
||||
if(stopOnError)
|
||||
return; // TODO: Return more cleanly
|
||||
if(stopOnError) return; // TODO: Return more cleanly
|
||||
|
||||
// Write empty data
|
||||
dumpFile.Write(new byte[blockSize * blocksToRead]);
|
||||
|
||||
errored += blocksToRead;
|
||||
for(ulong b = i; b < i + blocksToRead; b++)
|
||||
resume.BadBlocks.Add(b);
|
||||
DicConsole.DebugWriteLine("Dump-Media", "READ error:\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf));
|
||||
if(cmdDuration < 500)
|
||||
mhddLog.Write(i, 65535);
|
||||
else
|
||||
mhddLog.Write(i, cmdDuration);
|
||||
for(ulong b = i; b < i + blocksToRead; b++) resume.BadBlocks.Add(b);
|
||||
|
||||
DicConsole.DebugWriteLine("Dump-Media", "READ error:\n{0}",
|
||||
Decoders.SCSI.Sense.PrettifySense(senseBuf));
|
||||
if(cmdDuration < 500) mhddLog.Write(i, 65535);
|
||||
else mhddLog.Write(i, cmdDuration);
|
||||
|
||||
ibgLog.Write(i, 0);
|
||||
|
||||
dumpLog.WriteLine("Error reading {0} blocks from block {1}.", blocksToRead, i);
|
||||
string[] senseLines = Decoders.SCSI.Sense.PrettifySense(senseBuf).Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
|
||||
foreach(string senseLine in senseLines)
|
||||
dumpLog.WriteLine(senseLine);
|
||||
string[] senseLines = Decoders
|
||||
.SCSI.Sense.PrettifySense(senseBuf).Split(new[] {Environment.NewLine},
|
||||
StringSplitOptions.RemoveEmptyEntries);
|
||||
foreach(string senseLine in senseLines) dumpLog.WriteLine(senseLine);
|
||||
}
|
||||
|
||||
#pragma warning disable IDE0004 // Remove Unnecessary Cast
|
||||
@@ -438,8 +452,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
break;
|
||||
}
|
||||
|
||||
if((extentEnd - i) < blocksToRead)
|
||||
blocksToRead = (uint)(extentEnd - i) + 1;
|
||||
if((extentEnd - i) < blocksToRead) blocksToRead = (uint)(extentEnd - i) + 1;
|
||||
|
||||
mhddLog.Write(i, cmdDuration);
|
||||
ibgLog.Write(i, currentSpeed * 1024);
|
||||
@@ -450,8 +463,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
resume.NextBlock = currentSector;
|
||||
}
|
||||
|
||||
if(!aborted)
|
||||
currentSector = extentEnd + 1;
|
||||
if(!aborted) currentSector = extentEnd + 1;
|
||||
}
|
||||
|
||||
// Middle Zone D
|
||||
@@ -465,10 +477,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
break;
|
||||
}
|
||||
|
||||
if(((middleZone - 1) - middle) < blocksToRead)
|
||||
blocksToRead = (uint)((middleZone - 1) - middle);
|
||||
if(((middleZone - 1) - middle) < blocksToRead) blocksToRead = (uint)((middleZone - 1) - middle);
|
||||
|
||||
DicConsole.Write("\rReading sector {0} of {1} ({2:F3} MiB/sec.)", middle + currentSector, totalSize, currentSpeed);
|
||||
DicConsole.Write("\rReading sector {0} of {1} ({2:F3} MiB/sec.)", middle + currentSector, totalSize,
|
||||
currentSpeed);
|
||||
|
||||
mhddLog.Write(middle + currentSector, cmdDuration);
|
||||
ibgLog.Write(middle + currentSector, currentSpeed * 1024);
|
||||
@@ -489,6 +501,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DicConsole.ErrorWriteLine("Cannot lock drive, not continuing.");
|
||||
return;
|
||||
}
|
||||
|
||||
sense = dev.ReadCapacity(out readBuffer, out senseBuf, dev.Timeout, out duration);
|
||||
if(sense)
|
||||
{
|
||||
@@ -507,19 +520,18 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
break;
|
||||
}
|
||||
|
||||
if(((l0Video + l1Video) - l1) < blocksToRead)
|
||||
blocksToRead = (uint)((l0Video + l1Video) - l1);
|
||||
if(((l0Video + l1Video) - l1) < blocksToRead) blocksToRead = (uint)((l0Video + l1Video) - l1);
|
||||
|
||||
#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;
|
||||
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.)", currentSector, totalSize, currentSpeed);
|
||||
DicConsole.Write("\rReading sector {0} of {1} ({2:F3} MiB/sec.)", currentSector, totalSize,
|
||||
currentSpeed);
|
||||
|
||||
sense = dev.Read12(out readBuffer, out senseBuf, 0, false, false, false, false, (uint)l1, blockSize, 0, blocksToRead, false, dev.Timeout, out cmdDuration);
|
||||
sense = dev.Read12(out readBuffer, out senseBuf, 0, false, false, false, false, (uint)l1, blockSize, 0,
|
||||
blocksToRead, false, dev.Timeout, out cmdDuration);
|
||||
totalDuration += cmdDuration;
|
||||
|
||||
if(!sense && !dev.Error)
|
||||
@@ -532,8 +544,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
else
|
||||
{
|
||||
// TODO: Reset device after X errors
|
||||
if(stopOnError)
|
||||
return; // TODO: Return more cleanly
|
||||
if(stopOnError) return; // TODO: Return more cleanly
|
||||
|
||||
// Write empty data
|
||||
dumpFile.Write(new byte[blockSize * blocksToRead]);
|
||||
@@ -541,17 +552,17 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
// TODO: Handle errors in video partition
|
||||
//errored += blocksToRead;
|
||||
//resume.BadBlocks.Add(l1);
|
||||
DicConsole.DebugWriteLine("Dump-Media", "READ error:\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf));
|
||||
if(cmdDuration < 500)
|
||||
mhddLog.Write(l1, 65535);
|
||||
else
|
||||
mhddLog.Write(l1, cmdDuration);
|
||||
DicConsole.DebugWriteLine("Dump-Media", "READ error:\n{0}",
|
||||
Decoders.SCSI.Sense.PrettifySense(senseBuf));
|
||||
if(cmdDuration < 500) mhddLog.Write(l1, 65535);
|
||||
else mhddLog.Write(l1, cmdDuration);
|
||||
|
||||
ibgLog.Write(l1, 0);
|
||||
dumpLog.WriteLine("Error reading {0} blocks from block {1}.", blocksToRead, l1);
|
||||
string[] senseLines = Decoders.SCSI.Sense.PrettifySense(senseBuf).Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
|
||||
foreach(string senseLine in senseLines)
|
||||
dumpLog.WriteLine(senseLine);
|
||||
string[] senseLines = Decoders.SCSI.Sense.PrettifySense(senseBuf).Split(new[] {Environment.NewLine},
|
||||
StringSplitOptions
|
||||
.RemoveEmptyEntries);
|
||||
foreach(string senseLine in senseLines) dumpLog.WriteLine(senseLine);
|
||||
}
|
||||
|
||||
#pragma warning disable IDE0004 // Remove Unnecessary Cast
|
||||
@@ -569,6 +580,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DicConsole.ErrorWriteLine("Cannot unlock drive, not continuing.");
|
||||
return;
|
||||
}
|
||||
|
||||
sense = dev.ReadCapacity(out readBuffer, out senseBuf, dev.Timeout, out duration);
|
||||
if(sense)
|
||||
{
|
||||
@@ -580,21 +592,19 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
DicConsole.WriteLine();
|
||||
mhddLog.Close();
|
||||
#pragma warning disable IDE0004 // Remove Unnecessary Cast
|
||||
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024, (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000), devicePath);
|
||||
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
|
||||
(((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000), devicePath);
|
||||
#pragma warning restore IDE0004 // Remove Unnecessary Cast
|
||||
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));
|
||||
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)
|
||||
{
|
||||
List<ulong> tmpList = new List<ulong>();
|
||||
|
||||
foreach(ulong ur in resume.BadBlocks)
|
||||
{
|
||||
for(ulong i = ur; i < ur + blocksToRead; i++)
|
||||
tmpList.Add(i);
|
||||
}
|
||||
foreach(ulong ur in resume.BadBlocks) { for(ulong i = ur; i < ur + blocksToRead; i++) tmpList.Add(i); }
|
||||
|
||||
tmpList.Sort();
|
||||
|
||||
@@ -604,7 +614,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
resume.BadBlocks = tmpList;
|
||||
|
||||
repeatRetry:
|
||||
repeatRetry:
|
||||
ulong[] tmpArray = resume.BadBlocks.ToArray();
|
||||
foreach(ulong badSector in tmpArray)
|
||||
{
|
||||
@@ -617,9 +627,12 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
cmdDuration = 0;
|
||||
|
||||
DicConsole.Write("\rRetrying sector {0}, pass {1}, {3}{2}", badSector, pass + 1, forward ? "forward" : "reverse", runningPersistent ? "recovering partial data, " : "");
|
||||
DicConsole.Write("\rRetrying sector {0}, pass {1}, {3}{2}", badSector, pass + 1,
|
||||
forward ? "forward" : "reverse",
|
||||
runningPersistent ? "recovering partial data, " : "");
|
||||
|
||||
sense = dev.Read12(out readBuffer, out senseBuf, 0, false, false, false, false, (uint)badSector, blockSize, 0, 1, false, dev.Timeout, out cmdDuration);
|
||||
sense = dev.Read12(out readBuffer, out senseBuf, 0, false, false, false, false, (uint)badSector,
|
||||
blockSize, 0, 1, false, dev.Timeout, out cmdDuration);
|
||||
totalDuration += cmdDuration;
|
||||
|
||||
if(!sense && !dev.Error)
|
||||
@@ -629,8 +642,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
dumpFile.WriteAt(readBuffer, badSector, blockSize);
|
||||
dumpLog.WriteLine("Correctly retried block {0} in pass {1}.", badSector, pass);
|
||||
}
|
||||
else if(runningPersistent)
|
||||
dumpFile.WriteAt(readBuffer, badSector, blockSize);
|
||||
else if(runningPersistent) dumpFile.WriteAt(readBuffer, badSector, blockSize);
|
||||
}
|
||||
|
||||
if(pass < retryPasses && !aborted && resume.BadBlocks.Count > 0)
|
||||
@@ -649,27 +661,27 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
if(!runningPersistent && persistent)
|
||||
{
|
||||
sense = dev.ModeSense6(out readBuffer, out senseBuf, false, ScsiModeSensePageControl.Current, 0x01, dev.Timeout, out duration);
|
||||
sense = dev.ModeSense6(out readBuffer, out senseBuf, false, ScsiModeSensePageControl.Current, 0x01,
|
||||
dev.Timeout, out duration);
|
||||
if(sense)
|
||||
{
|
||||
sense = dev.ModeSense10(out readBuffer, out senseBuf, false, ScsiModeSensePageControl.Current, 0x01, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
currentMode = Decoders.SCSI.Modes.DecodeMode10(readBuffer, dev.SCSIType);
|
||||
sense = dev.ModeSense10(out readBuffer, out senseBuf, false, ScsiModeSensePageControl.Current,
|
||||
0x01, dev.Timeout, out duration);
|
||||
if(!sense) currentMode = Decoders.SCSI.Modes.DecodeMode10(readBuffer, dev.SCSIType);
|
||||
}
|
||||
else
|
||||
currentMode = Decoders.SCSI.Modes.DecodeMode6(readBuffer, dev.SCSIType);
|
||||
else currentMode = Decoders.SCSI.Modes.DecodeMode6(readBuffer, dev.SCSIType);
|
||||
|
||||
if(currentMode.HasValue)
|
||||
currentModePage = currentMode.Value.Pages[0];
|
||||
if(currentMode.HasValue) currentModePage = currentMode.Value.Pages[0];
|
||||
|
||||
if(dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.MultiMediaDevice)
|
||||
{
|
||||
Decoders.SCSI.Modes.ModePage_01_MMC pgMMC = new Decoders.SCSI.Modes.ModePage_01_MMC
|
||||
{
|
||||
PS = false,
|
||||
ReadRetryCount = 255,
|
||||
Parameter = 0x20
|
||||
};
|
||||
Decoders.SCSI.Modes.ModePage_01_MMC pgMMC =
|
||||
new Decoders.SCSI.Modes.ModePage_01_MMC
|
||||
{
|
||||
PS = false,
|
||||
ReadRetryCount = 255,
|
||||
Parameter = 0x20
|
||||
};
|
||||
Decoders.SCSI.Modes.DecodedMode md = new Decoders.SCSI.Modes.DecodedMode
|
||||
{
|
||||
Header = new Decoders.SCSI.Modes.ModeHeader(),
|
||||
@@ -677,10 +689,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
new Decoders.SCSI.Modes.ModePage
|
||||
{
|
||||
Page = 0x01,
|
||||
Subpage = 0x00,
|
||||
PageResponse = Decoders.SCSI.Modes.EncodeModePage_01_MMC(pgMMC)
|
||||
}
|
||||
Page = 0x01,
|
||||
Subpage = 0x00,
|
||||
PageResponse = Decoders.SCSI.Modes.EncodeModePage_01_MMC(pgMMC)
|
||||
}
|
||||
}
|
||||
};
|
||||
md6 = Decoders.SCSI.Modes.EncodeMode6(md, dev.SCSIType);
|
||||
@@ -707,11 +719,11 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
Pages = new Decoders.SCSI.Modes.ModePage[]
|
||||
{
|
||||
new Decoders.SCSI.Modes.ModePage
|
||||
{
|
||||
Page = 0x01,
|
||||
Subpage = 0x00,
|
||||
PageResponse = Decoders.SCSI.Modes.EncodeModePage_01(pg)
|
||||
}
|
||||
{
|
||||
Page = 0x01,
|
||||
Subpage = 0x00,
|
||||
PageResponse = Decoders.SCSI.Modes.EncodeModePage_01(pg)
|
||||
}
|
||||
}
|
||||
};
|
||||
md6 = Decoders.SCSI.Modes.EncodeMode6(md, dev.SCSIType);
|
||||
@@ -720,10 +732,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
|
||||
dumpLog.WriteLine("Sending MODE SELECT to drive.");
|
||||
sense = dev.ModeSelect(md6, out senseBuf, true, false, dev.Timeout, out duration);
|
||||
if(sense)
|
||||
{
|
||||
sense = dev.ModeSelect10(md10, out senseBuf, true, false, dev.Timeout, out duration);
|
||||
}
|
||||
if(sense) { sense = dev.ModeSelect10(md10, out senseBuf, true, false, dev.Timeout, out duration); }
|
||||
|
||||
runningPersistent = true;
|
||||
if(!sense && !dev.Error)
|
||||
@@ -737,25 +746,20 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
Decoders.SCSI.Modes.DecodedMode md = new Decoders.SCSI.Modes.DecodedMode
|
||||
{
|
||||
Header = new Decoders.SCSI.Modes.ModeHeader(),
|
||||
Pages = new Decoders.SCSI.Modes.ModePage[]
|
||||
{
|
||||
currentModePage.Value
|
||||
}
|
||||
Pages = new Decoders.SCSI.Modes.ModePage[] {currentModePage.Value}
|
||||
};
|
||||
md6 = Decoders.SCSI.Modes.EncodeMode6(md, dev.SCSIType);
|
||||
md10 = Decoders.SCSI.Modes.EncodeMode10(md, dev.SCSIType);
|
||||
|
||||
dumpLog.WriteLine("Sending MODE SELECT to drive.");
|
||||
sense = dev.ModeSelect(md6, out senseBuf, true, false, dev.Timeout, out duration);
|
||||
if(sense)
|
||||
{
|
||||
sense = dev.ModeSelect10(md10, out senseBuf, true, false, dev.Timeout, out duration);
|
||||
}
|
||||
if(sense) { sense = dev.ModeSelect10(md10, out senseBuf, true, false, dev.Timeout, out duration); }
|
||||
}
|
||||
|
||||
DicConsole.WriteLine();
|
||||
}
|
||||
#endregion Error handling
|
||||
|
||||
resume.BadBlocks.Sort();
|
||||
currentTry.Extents = Metadata.ExtentsConverter.ToMetadata(extents);
|
||||
|
||||
@@ -774,8 +778,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
break;
|
||||
}
|
||||
|
||||
if((blocks - i) < blocksToRead)
|
||||
blocksToRead = (uint)(blocks - i);
|
||||
if((blocks - i) < blocksToRead) blocksToRead = (uint)(blocks - i);
|
||||
|
||||
DicConsole.Write("\rChecksumming sector {0} of {1} ({2:F3} MiB/sec.)", i, blocks, currentSpeed);
|
||||
|
||||
@@ -792,11 +795,13 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
currentSpeed = ((double)blockSize * blocksToRead / (double)1048576) / (chkDuration / (double)1000);
|
||||
#pragma warning restore IDE0004 // Cast is necessary, otherwise incorrect value is created
|
||||
}
|
||||
|
||||
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));
|
||||
dumpLog.WriteLine("Average checksum speed {0:F3} KiB/sec.",
|
||||
(((double)blockSize * (double)(blocks + 1)) / 1024) / (totalChkDuration / 1000));
|
||||
|
||||
PluginBase plugins = new PluginBase();
|
||||
plugins.RegisterAllPlugins(encoding);
|
||||
@@ -813,15 +818,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
_imageFormat = ImageFormat.Detect(inputFilter);
|
||||
PartitionType[] xmlFileSysInfo = null;
|
||||
|
||||
try
|
||||
{
|
||||
if(!_imageFormat.OpenImage(inputFilter))
|
||||
_imageFormat = null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
_imageFormat = null;
|
||||
}
|
||||
try { if(!_imageFormat.OpenImage(inputFilter)) _imageFormat = null; }
|
||||
catch { _imageFormat = null; }
|
||||
|
||||
if(_imageFormat != null)
|
||||
{
|
||||
@@ -846,7 +844,8 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
};
|
||||
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);
|
||||
i, partitions[i].Start, partitions[i].End, partitions[i].Type,
|
||||
partitions[i].Scheme);
|
||||
|
||||
foreach(Filesystem _plugin in plugins.PluginsList.Values)
|
||||
{
|
||||
@@ -859,12 +858,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
Statistics.AddFilesystem(_plugin.XmlFSType.Type);
|
||||
dumpLog.WriteLine("Filesystem {0} found.", _plugin.XmlFSType.Type);
|
||||
|
||||
if(_plugin.XmlFSType.Type == "Opera")
|
||||
dskType = MediaType.ThreeDO;
|
||||
if(_plugin.XmlFSType.Type == "Opera") dskType = MediaType.ThreeDO;
|
||||
if(_plugin.XmlFSType.Type == "PC Engine filesystem")
|
||||
dskType = MediaType.SuperCDROM2;
|
||||
if(_plugin.XmlFSType.Type == "Nintendo Wii filesystem")
|
||||
dskType = MediaType.WOD;
|
||||
if(_plugin.XmlFSType.Type == "Nintendo Wii filesystem") dskType = MediaType.WOD;
|
||||
if(_plugin.XmlFSType.Type == "Nintendo Gamecube filesystem")
|
||||
dskType = MediaType.GOD;
|
||||
}
|
||||
@@ -877,27 +874,18 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
}
|
||||
|
||||
if(lstFs.Count > 0)
|
||||
xmlFileSysInfo[i].FileSystems = lstFs.ToArray();
|
||||
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
|
||||
};
|
||||
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
|
||||
};
|
||||
Partition wholePart =
|
||||
new Partition {Name = "Whole device", Length = blocks, Size = blocks * blockSize};
|
||||
|
||||
foreach(Filesystem _plugin in plugins.PluginsList.Values)
|
||||
{
|
||||
@@ -910,14 +898,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
Statistics.AddFilesystem(_plugin.XmlFSType.Type);
|
||||
dumpLog.WriteLine("Filesystem {0} found.", _plugin.XmlFSType.Type);
|
||||
|
||||
if(_plugin.XmlFSType.Type == "Opera")
|
||||
dskType = MediaType.ThreeDO;
|
||||
if(_plugin.XmlFSType.Type == "PC Engine filesystem")
|
||||
dskType = MediaType.SuperCDROM2;
|
||||
if(_plugin.XmlFSType.Type == "Nintendo Wii filesystem")
|
||||
dskType = MediaType.WOD;
|
||||
if(_plugin.XmlFSType.Type == "Nintendo Gamecube filesystem")
|
||||
dskType = MediaType.GOD;
|
||||
if(_plugin.XmlFSType.Type == "Opera") dskType = MediaType.ThreeDO;
|
||||
if(_plugin.XmlFSType.Type == "PC Engine filesystem") dskType = MediaType.SuperCDROM2;
|
||||
if(_plugin.XmlFSType.Type == "Nintendo Wii filesystem") dskType = MediaType.WOD;
|
||||
if(_plugin.XmlFSType.Type == "Nintendo Gamecube filesystem") dskType = MediaType.GOD;
|
||||
}
|
||||
}
|
||||
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
|
||||
@@ -928,8 +912,7 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
}
|
||||
}
|
||||
|
||||
if(lstFs.Count > 0)
|
||||
xmlFileSysInfo[0].FileSystems = lstFs.ToArray();
|
||||
if(lstFs.Count > 0) xmlFileSysInfo[0].FileSystems = lstFs.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -946,35 +929,28 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
typeSpecified = true,
|
||||
Sectors = new SectorsType[1]
|
||||
};
|
||||
sidecar.OpticalDisc[0].Layers.Sectors[0] = new SectorsType
|
||||
{
|
||||
Value = (long)layerBreak
|
||||
};
|
||||
sidecar.OpticalDisc[0].Layers.Sectors[0] = new SectorsType {Value = (long)layerBreak};
|
||||
sidecar.OpticalDisc[0].Sessions = 1;
|
||||
sidecar.OpticalDisc[0].Tracks = new[] { 1 };
|
||||
sidecar.OpticalDisc[0].Tracks = new[] {1};
|
||||
sidecar.OpticalDisc[0].Track = new Schemas.TrackType[1];
|
||||
sidecar.OpticalDisc[0].Track[0] = new Schemas.TrackType
|
||||
{
|
||||
BytesPerSector = (int)blockSize,
|
||||
Checksums = sidecar.OpticalDisc[0].Checksums,
|
||||
EndSector = (long)(blocks - 1),
|
||||
Image = new ImageType()
|
||||
{
|
||||
format = "BINARY",
|
||||
offset = 0,
|
||||
offsetSpecified = true,
|
||||
Value = sidecar.OpticalDisc[0].Image.Value
|
||||
},
|
||||
Sequence = new TrackSequenceType()
|
||||
{
|
||||
Session = 1,
|
||||
TrackNumber = 1
|
||||
},
|
||||
Image =
|
||||
new ImageType()
|
||||
{
|
||||
format = "BINARY",
|
||||
offset = 0,
|
||||
offsetSpecified = true,
|
||||
Value = sidecar.OpticalDisc[0].Image.Value
|
||||
},
|
||||
Sequence = new TrackSequenceType() {Session = 1, TrackNumber = 1},
|
||||
Size = (long)(totalSize * blockSize),
|
||||
StartSector = 0
|
||||
};
|
||||
if(xmlFileSysInfo != null)
|
||||
sidecar.OpticalDisc[0].Track[0].FileSystemInformation = xmlFileSysInfo;
|
||||
if(xmlFileSysInfo != null) sidecar.OpticalDisc[0].Track[0].FileSystemInformation = xmlFileSysInfo;
|
||||
sidecar.OpticalDisc[0].Track[0].TrackType1 = TrackTypeTrackType.dvd;
|
||||
sidecar.OpticalDisc[0].Dimensions = Metadata.Dimensions.DimensionsFromMediaType(dskType);
|
||||
Metadata.MediaType.MediaTypeToString(dskType, out string xmlDskTyp, out string xmlDskSubTyp);
|
||||
@@ -985,10 +961,10 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
{
|
||||
DicConsole.WriteLine("Writing metadata sidecar");
|
||||
|
||||
FileStream xmlFs = new FileStream(outputPrefix + ".cicm.xml",
|
||||
FileMode.Create);
|
||||
FileStream xmlFs = new FileStream(outputPrefix + ".cicm.xml", FileMode.Create);
|
||||
|
||||
System.Xml.Serialization.XmlSerializer xmlSer = new System.Xml.Serialization.XmlSerializer(typeof(CICMMetadataType));
|
||||
System.Xml.Serialization.XmlSerializer xmlSer =
|
||||
new System.Xml.Serialization.XmlSerializer(typeof(CICMMetadataType));
|
||||
xmlSer.Serialize(xmlFs, sidecar);
|
||||
xmlFs.Close();
|
||||
}
|
||||
@@ -996,4 +972,4 @@ namespace DiscImageChef.Core.Devices.Dumping
|
||||
Statistics.AddMedia(dskType, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -48,15 +48,42 @@ namespace DiscImageChef.Core.Devices
|
||||
uint physicalsectorsize;
|
||||
uint longBlockSize;
|
||||
|
||||
public string ErrorMessage { get { return errorMessage; } }
|
||||
public ulong Blocks { get { return blocks; } }
|
||||
public uint BlocksToRead { get { return blocksToRead; } }
|
||||
public uint LogicalBlockSize { get { return blockSize; } }
|
||||
public uint PhysicalBlockSize { get { return physicalsectorsize; } }
|
||||
public uint LongBlockSize { get { return longBlockSize; } }
|
||||
public bool CanReadRaw { get { return readRaw; } }
|
||||
public bool CanSeek { get { return ataSeek || seek6 || seek10; } }
|
||||
public bool CanSeekLBA { get { return ataSeekLba || seek6 || seek10; } }
|
||||
public string ErrorMessage
|
||||
{
|
||||
get { return errorMessage; }
|
||||
}
|
||||
public ulong Blocks
|
||||
{
|
||||
get { return blocks; }
|
||||
}
|
||||
public uint BlocksToRead
|
||||
{
|
||||
get { return blocksToRead; }
|
||||
}
|
||||
public uint LogicalBlockSize
|
||||
{
|
||||
get { return blockSize; }
|
||||
}
|
||||
public uint PhysicalBlockSize
|
||||
{
|
||||
get { return physicalsectorsize; }
|
||||
}
|
||||
public uint LongBlockSize
|
||||
{
|
||||
get { return longBlockSize; }
|
||||
}
|
||||
public bool CanReadRaw
|
||||
{
|
||||
get { return readRaw; }
|
||||
}
|
||||
public bool CanSeek
|
||||
{
|
||||
get { return ataSeek || seek6 || seek10; }
|
||||
}
|
||||
public bool CanSeekLBA
|
||||
{
|
||||
get { return ataSeekLba || seek6 || seek10; }
|
||||
}
|
||||
|
||||
public Reader(Device dev, uint timeout, byte[] identification, bool raw = false)
|
||||
{
|
||||
@@ -68,11 +95,9 @@ namespace DiscImageChef.Core.Devices
|
||||
switch(dev.Type)
|
||||
{
|
||||
case DeviceType.ATA:
|
||||
if(Identify.Decode(identification).HasValue)
|
||||
ataId = Identify.Decode(identification).Value;
|
||||
if(Identify.Decode(identification).HasValue) ataId = Identify.Decode(identification).Value;
|
||||
break;
|
||||
case DeviceType.NVMe:
|
||||
throw new NotImplementedException("NVMe devices not yet supported.");
|
||||
case DeviceType.NVMe: throw new NotImplementedException("NVMe devices not yet supported.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,11 +105,9 @@ namespace DiscImageChef.Core.Devices
|
||||
{
|
||||
switch(dev.Type)
|
||||
{
|
||||
case DeviceType.ATA:
|
||||
return AtaGetBlocks();
|
||||
case DeviceType.ATA: return AtaGetBlocks();
|
||||
case DeviceType.ATAPI:
|
||||
case DeviceType.SCSI:
|
||||
return ScsiGetBlocks();
|
||||
case DeviceType.SCSI: return ScsiGetBlocks();
|
||||
default:
|
||||
errorMessage = string.Format("Unknown device type {0}.", dev.Type);
|
||||
return 0;
|
||||
@@ -95,11 +118,9 @@ namespace DiscImageChef.Core.Devices
|
||||
{
|
||||
switch(dev.Type)
|
||||
{
|
||||
case DeviceType.ATA:
|
||||
return AtaFindReadCommand();
|
||||
case DeviceType.ATA: return AtaFindReadCommand();
|
||||
case DeviceType.ATAPI:
|
||||
case DeviceType.SCSI:
|
||||
return ScsiFindReadCommand();
|
||||
case DeviceType.SCSI: return ScsiFindReadCommand();
|
||||
default:
|
||||
errorMessage = string.Format("Unknown device type {0}.", dev.Type);
|
||||
return true;
|
||||
@@ -110,11 +131,9 @@ namespace DiscImageChef.Core.Devices
|
||||
{
|
||||
switch(dev.Type)
|
||||
{
|
||||
case DeviceType.ATA:
|
||||
return AtaGetBlockSize();
|
||||
case DeviceType.ATA: return AtaGetBlockSize();
|
||||
case DeviceType.ATAPI:
|
||||
case DeviceType.SCSI:
|
||||
return ScsiGetBlockSize();
|
||||
case DeviceType.SCSI: return ScsiGetBlockSize();
|
||||
default:
|
||||
errorMessage = string.Format("Unknown device type {0}.", dev.Type);
|
||||
return true;
|
||||
@@ -125,11 +144,9 @@ namespace DiscImageChef.Core.Devices
|
||||
{
|
||||
switch(dev.Type)
|
||||
{
|
||||
case DeviceType.ATA:
|
||||
return AtaGetBlocksToRead(startWithBlocks);
|
||||
case DeviceType.ATA: return AtaGetBlocksToRead(startWithBlocks);
|
||||
case DeviceType.ATAPI:
|
||||
case DeviceType.SCSI:
|
||||
return ScsiGetBlocksToRead(startWithBlocks);
|
||||
case DeviceType.SCSI: return ScsiGetBlocksToRead(startWithBlocks);
|
||||
default:
|
||||
errorMessage = string.Format("Unknown device type {0}.", dev.Type);
|
||||
return true;
|
||||
@@ -150,11 +167,9 @@ namespace DiscImageChef.Core.Devices
|
||||
{
|
||||
switch(dev.Type)
|
||||
{
|
||||
case DeviceType.ATA:
|
||||
return AtaReadBlocks(out buffer, block, count, out duration);
|
||||
case DeviceType.ATA: return AtaReadBlocks(out buffer, block, count, out duration);
|
||||
case DeviceType.ATAPI:
|
||||
case DeviceType.SCSI:
|
||||
return ScsiReadBlocks(out buffer, block, count, out duration);
|
||||
case DeviceType.SCSI: return ScsiReadBlocks(out buffer, block, count, out duration);
|
||||
default:
|
||||
buffer = null;
|
||||
duration = 0d;
|
||||
@@ -166,8 +181,7 @@ namespace DiscImageChef.Core.Devices
|
||||
{
|
||||
switch(dev.Type)
|
||||
{
|
||||
case DeviceType.ATA:
|
||||
return AtaReadCHS(out buffer, cylinder, head, sector, out duration);
|
||||
case DeviceType.ATA: return AtaReadCHS(out buffer, cylinder, head, sector, out duration);
|
||||
default:
|
||||
buffer = null;
|
||||
duration = 0d;
|
||||
@@ -179,11 +193,9 @@ namespace DiscImageChef.Core.Devices
|
||||
{
|
||||
switch(dev.Type)
|
||||
{
|
||||
case DeviceType.ATA:
|
||||
return AtaSeek(block, out duration);
|
||||
case DeviceType.ATA: return AtaSeek(block, out duration);
|
||||
case DeviceType.ATAPI:
|
||||
case DeviceType.SCSI:
|
||||
return ScsiSeek(block, out duration);
|
||||
case DeviceType.SCSI: return ScsiSeek(block, out duration);
|
||||
default:
|
||||
duration = 0d;
|
||||
return true;
|
||||
@@ -194,12 +206,11 @@ namespace DiscImageChef.Core.Devices
|
||||
{
|
||||
switch(dev.Type)
|
||||
{
|
||||
case DeviceType.ATA:
|
||||
return AtaSeekCHS(cylinder, head, sector, out duration);
|
||||
case DeviceType.ATA: return AtaSeekCHS(cylinder, head, sector, out duration);
|
||||
default:
|
||||
duration = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -57,15 +57,26 @@ namespace DiscImageChef.Core.Devices
|
||||
|
||||
Identify.IdentifyDevice ataId;
|
||||
|
||||
public bool IsLBA { get { return lbaMode; } }
|
||||
public ushort Cylinders { get { return cylinders; } }
|
||||
public byte Heads { get { return heads; } }
|
||||
public byte Sectors { get { return sectors; } }
|
||||
public bool IsLBA
|
||||
{
|
||||
get { return lbaMode; }
|
||||
}
|
||||
public ushort Cylinders
|
||||
{
|
||||
get { return cylinders; }
|
||||
}
|
||||
public byte Heads
|
||||
{
|
||||
get { return heads; }
|
||||
}
|
||||
public byte Sectors
|
||||
{
|
||||
get { return sectors; }
|
||||
}
|
||||
|
||||
public (uint, byte, byte) GetDeviceCHS()
|
||||
{
|
||||
if(dev.Type != DeviceType.ATA)
|
||||
return (0, 0, 0);
|
||||
if(dev.Type != DeviceType.ATA) return (0, 0, 0);
|
||||
|
||||
if(ataId.CurrentCylinders > 0 && ataId.CurrentHeads > 0 && ataId.CurrentSectorsPerTrack > 0)
|
||||
{
|
||||
@@ -76,7 +87,7 @@ namespace DiscImageChef.Core.Devices
|
||||
}
|
||||
|
||||
if((ataId.CurrentCylinders == 0 || ataId.CurrentHeads == 0 || ataId.CurrentSectorsPerTrack == 0) &&
|
||||
(ataId.Cylinders > 0 && ataId.Heads > 0 && ataId.SectorsPerTrack > 0))
|
||||
(ataId.Cylinders > 0 && ataId.Heads > 0 && ataId.SectorsPerTrack > 0))
|
||||
{
|
||||
cylinders = ataId.Cylinders;
|
||||
heads = (byte)ataId.Heads;
|
||||
@@ -166,26 +177,16 @@ namespace DiscImageChef.Core.Devices
|
||||
}
|
||||
}
|
||||
|
||||
if(ataReadDmaLba48)
|
||||
DicConsole.WriteLine("Using ATA READ DMA EXT command.");
|
||||
else if(ataReadLba48)
|
||||
DicConsole.WriteLine("Using ATA READ EXT command.");
|
||||
else if(ataReadDmaRetryLba)
|
||||
DicConsole.WriteLine("Using ATA READ DMA command with retries (LBA).");
|
||||
else if(ataReadDmaLba)
|
||||
DicConsole.WriteLine("Using ATA READ DMA command (LBA).");
|
||||
else if(ataReadRetryLba)
|
||||
DicConsole.WriteLine("Using ATA READ command with retries (LBA).");
|
||||
else if(ataReadLba)
|
||||
DicConsole.WriteLine("Using ATA READ command (LBA).");
|
||||
else if(ataReadDmaRetry)
|
||||
DicConsole.WriteLine("Using ATA READ DMA command with retries (CHS).");
|
||||
else if(ataReadDma)
|
||||
DicConsole.WriteLine("Using ATA READ DMA command (CHS).");
|
||||
else if(ataReadRetry)
|
||||
DicConsole.WriteLine("Using ATA READ command with retries (CHS).");
|
||||
else if(ataRead)
|
||||
DicConsole.WriteLine("Using ATA READ command (CHS).");
|
||||
if(ataReadDmaLba48) DicConsole.WriteLine("Using ATA READ DMA EXT command.");
|
||||
else if(ataReadLba48) DicConsole.WriteLine("Using ATA READ EXT command.");
|
||||
else if(ataReadDmaRetryLba) DicConsole.WriteLine("Using ATA READ DMA command with retries (LBA).");
|
||||
else if(ataReadDmaLba) DicConsole.WriteLine("Using ATA READ DMA command (LBA).");
|
||||
else if(ataReadRetryLba) DicConsole.WriteLine("Using ATA READ command with retries (LBA).");
|
||||
else if(ataReadLba) DicConsole.WriteLine("Using ATA READ command (LBA).");
|
||||
else if(ataReadDmaRetry) DicConsole.WriteLine("Using ATA READ DMA command with retries (CHS).");
|
||||
else if(ataReadDma) DicConsole.WriteLine("Using ATA READ DMA command (CHS).");
|
||||
else if(ataReadRetry) DicConsole.WriteLine("Using ATA READ command with retries (CHS).");
|
||||
else if(ataRead) DicConsole.WriteLine("Using ATA READ command (CHS).");
|
||||
else
|
||||
{
|
||||
errorMessage = "Could not get a working read command!";
|
||||
@@ -197,18 +198,14 @@ namespace DiscImageChef.Core.Devices
|
||||
|
||||
bool AtaGetBlockSize()
|
||||
{
|
||||
if((ataId.PhysLogSectorSize & 0x8000) == 0x0000 &&
|
||||
(ataId.PhysLogSectorSize & 0x4000) == 0x4000)
|
||||
if((ataId.PhysLogSectorSize & 0x8000) == 0x0000 && (ataId.PhysLogSectorSize & 0x4000) == 0x4000)
|
||||
{
|
||||
if((ataId.PhysLogSectorSize & 0x1000) == 0x1000)
|
||||
{
|
||||
if(ataId.LogicalSectorWords <= 255 || ataId.LogicalAlignment == 0xFFFF)
|
||||
blockSize = 512;
|
||||
else
|
||||
blockSize = ataId.LogicalSectorWords * 2;
|
||||
if(ataId.LogicalSectorWords <= 255 || ataId.LogicalAlignment == 0xFFFF) blockSize = 512;
|
||||
else blockSize = ataId.LogicalSectorWords * 2;
|
||||
}
|
||||
else
|
||||
blockSize = 512;
|
||||
else blockSize = 512;
|
||||
|
||||
if((ataId.PhysLogSectorSize & 0x2000) == 0x2000)
|
||||
{
|
||||
@@ -216,8 +213,7 @@ namespace DiscImageChef.Core.Devices
|
||||
physicalsectorsize = blockSize * (uint)Math.Pow(2, (double)(ataId.PhysLogSectorSize & 0xF));
|
||||
#pragma warning restore IDE0004 // Cast is necessary, otherwise incorrect value is created
|
||||
}
|
||||
else
|
||||
physicalsectorsize = blockSize;
|
||||
else physicalsectorsize = blockSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -281,17 +277,15 @@ namespace DiscImageChef.Core.Devices
|
||||
error = !(!sense && (errorLba.status & 0x27) == 0 && errorLba.error == 0 && cmdBuf.Length > 0);
|
||||
}
|
||||
|
||||
if(error)
|
||||
blocksToRead /= 2;
|
||||
if(error) blocksToRead /= 2;
|
||||
|
||||
if(!error || blocksToRead == 1)
|
||||
break;
|
||||
if(!error || blocksToRead == 1) break;
|
||||
}
|
||||
|
||||
if(error && lbaMode)
|
||||
{
|
||||
blocksToRead = 1;
|
||||
errorMessage=string.Format("Device error {0} trying to guess ideal transfer length.", dev.LastError);
|
||||
errorMessage = string.Format("Device error {0} trying to guess ideal transfer length.", dev.LastError);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -351,8 +345,7 @@ namespace DiscImageChef.Core.Devices
|
||||
errorByte = errorLba.error;
|
||||
}
|
||||
|
||||
if(error)
|
||||
DicConsole.DebugWriteLine("ATA Reader", "ATA ERROR: {0} STATUS: {1}", errorByte, status);
|
||||
if(error) DicConsole.DebugWriteLine("ATA Reader", "ATA ERROR: {0} STATUS: {1}", errorByte, status);
|
||||
|
||||
return error;
|
||||
}
|
||||
@@ -395,8 +388,7 @@ namespace DiscImageChef.Core.Devices
|
||||
errorByte = errorChs.error;
|
||||
}
|
||||
|
||||
if(error)
|
||||
DicConsole.DebugWriteLine("ATA Reader", "ATA ERROR: {0} STATUS: {1}", errorByte, status);
|
||||
if(error) DicConsole.DebugWriteLine("ATA Reader", "ATA ERROR: {0} STATUS: {1}", errorByte, status);
|
||||
|
||||
return error;
|
||||
}
|
||||
@@ -417,4 +409,4 @@ namespace DiscImageChef.Core.Devices
|
||||
return !(!sense && (errorChs.status & 0x27) == 0 && errorChs.error == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -65,11 +65,14 @@ namespace DiscImageChef.Core.Devices
|
||||
|
||||
read6 = !dev.Read6(out readBuffer, out senseBuf, 0, blockSize, timeout, out duration);
|
||||
|
||||
read10 = !dev.Read10(out readBuffer, out senseBuf, 0, false, true, false, false, 0, blockSize, 0, 1, timeout, out duration);
|
||||
read10 = !dev.Read10(out readBuffer, out senseBuf, 0, false, true, false, false, 0, blockSize, 0, 1,
|
||||
timeout, out duration);
|
||||
|
||||
read12 = !dev.Read12(out readBuffer, out senseBuf, 0, false, true, false, false, 0, blockSize, 0, 1, false, timeout, out duration);
|
||||
read12 = !dev.Read12(out readBuffer, out senseBuf, 0, false, true, false, false, 0, blockSize, 0, 1, false,
|
||||
timeout, out duration);
|
||||
|
||||
read16 = !dev.Read16(out readBuffer, out senseBuf, 0, false, true, false, 0, blockSize, 0, 1, false, timeout, out duration);
|
||||
read16 = !dev.Read16(out readBuffer, out senseBuf, 0, false, true, false, 0, blockSize, 0, 1, false,
|
||||
timeout, out duration);
|
||||
|
||||
seek6 = !dev.Seek6(out senseBuf, 0, timeout, out duration);
|
||||
|
||||
@@ -83,7 +86,9 @@ namespace DiscImageChef.Core.Devices
|
||||
|
||||
if(read6 && !read10 && !read12 && !read16 && blocks > (0x001FFFFF + 1))
|
||||
{
|
||||
errorMessage = string.Format("Device only supports SCSI READ (6) but has more than {0} blocks ({1} blocks total)", 0x001FFFFF + 1, blocks);
|
||||
errorMessage =
|
||||
string.Format("Device only supports SCSI READ (6) but has more than {0} blocks ({1} blocks total)",
|
||||
0x001FFFFF + 1, blocks);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -92,7 +97,9 @@ namespace DiscImageChef.Core.Devices
|
||||
#pragma warning restore IDE0004 // Remove Unnecessary Cast
|
||||
{
|
||||
#pragma warning disable IDE0004 // Remove Unnecessary Cast
|
||||
errorMessage = string.Format("Device only supports SCSI READ (10) but has more than {0} blocks ({1} blocks total)", (long)0xFFFFFFFF + (long)1, blocks);
|
||||
errorMessage =
|
||||
string.Format("Device only supports SCSI READ (10) but has more than {0} blocks ({1} blocks total)",
|
||||
(long)0xFFFFFFFF + (long)1, blocks);
|
||||
#pragma warning restore IDE0004 // Remove Unnecessary Cast
|
||||
return true;
|
||||
}
|
||||
@@ -124,20 +131,22 @@ namespace DiscImageChef.Core.Devices
|
||||
}
|
||||
}*/
|
||||
|
||||
testSense = dev.ReadLong10(out readBuffer, out senseBuf, false, false, 0, 0xFFFF, timeout, out duration);
|
||||
testSense = dev.ReadLong10(out readBuffer, out senseBuf, false, false, 0, 0xFFFF, timeout,
|
||||
out duration);
|
||||
if(testSense && !dev.Error)
|
||||
{
|
||||
decSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf);
|
||||
if(decSense.HasValue)
|
||||
{
|
||||
if(decSense.Value.SenseKey == Decoders.SCSI.SenseKeys.IllegalRequest &&
|
||||
decSense.Value.ASC == 0x24 && decSense.Value.ASCQ == 0x00)
|
||||
decSense.Value.ASC == 0x24 && decSense.Value.ASCQ == 0x00)
|
||||
{
|
||||
readRaw = true;
|
||||
if(decSense.Value.InformationValid && decSense.Value.ILI)
|
||||
{
|
||||
longBlockSize = 0xFFFF - (decSense.Value.Information & 0xFFFF);
|
||||
readLong10 = !dev.ReadLong10(out readBuffer, out senseBuf, false, false, 0, (ushort)longBlockSize, timeout, out duration);
|
||||
readLong10 = !dev.ReadLong10(out readBuffer, out senseBuf, false, false, 0,
|
||||
(ushort)longBlockSize, timeout, out duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -147,15 +156,18 @@ namespace DiscImageChef.Core.Devices
|
||||
{
|
||||
if(blockSize == 512)
|
||||
{
|
||||
foreach(ushort testSize in new[] {
|
||||
// Long sector sizes for floppies
|
||||
514,
|
||||
// Long sector sizes for SuperDisk
|
||||
536, 558,
|
||||
// Long sector sizes for 512-byte magneto-opticals
|
||||
600, 610, 630 })
|
||||
foreach(ushort testSize in new[]
|
||||
{
|
||||
testSense = dev.ReadLong16(out readBuffer, out senseBuf, false, 0, testSize, timeout, out duration);
|
||||
// Long sector sizes for floppies
|
||||
514,
|
||||
// Long sector sizes for SuperDisk
|
||||
536, 558,
|
||||
// Long sector sizes for 512-byte magneto-opticals
|
||||
600, 610, 630
|
||||
})
|
||||
{
|
||||
testSense = dev.ReadLong16(out readBuffer, out senseBuf, false, 0, testSize, timeout,
|
||||
out duration);
|
||||
if(!testSense && !dev.Error)
|
||||
{
|
||||
readLong16 = true;
|
||||
@@ -164,7 +176,8 @@ namespace DiscImageChef.Core.Devices
|
||||
break;
|
||||
}
|
||||
|
||||
testSense = dev.ReadLong10(out readBuffer, out senseBuf, false, false, 0, testSize, timeout, out duration);
|
||||
testSense = dev.ReadLong10(out readBuffer, out senseBuf, false, false, 0, testSize,
|
||||
timeout, out duration);
|
||||
if(!testSense && !dev.Error)
|
||||
{
|
||||
readLong10 = true;
|
||||
@@ -176,13 +189,16 @@ namespace DiscImageChef.Core.Devices
|
||||
}
|
||||
else if(blockSize == 1024)
|
||||
{
|
||||
foreach(ushort testSize in new[] {
|
||||
// Long sector sizes for floppies
|
||||
1026,
|
||||
// Long sector sizes for 1024-byte magneto-opticals
|
||||
1200 })
|
||||
foreach(ushort testSize in new[]
|
||||
{
|
||||
testSense = dev.ReadLong16(out readBuffer, out senseBuf, false, 0, testSize, timeout, out duration);
|
||||
// Long sector sizes for floppies
|
||||
1026,
|
||||
// Long sector sizes for 1024-byte magneto-opticals
|
||||
1200
|
||||
})
|
||||
{
|
||||
testSense = dev.ReadLong16(out readBuffer, out senseBuf, false, 0, testSize, timeout,
|
||||
out duration);
|
||||
if(!testSense && !dev.Error)
|
||||
{
|
||||
readLong16 = true;
|
||||
@@ -191,7 +207,8 @@ namespace DiscImageChef.Core.Devices
|
||||
break;
|
||||
}
|
||||
|
||||
testSense = dev.ReadLong10(out readBuffer, out senseBuf, false, false, 0, testSize, timeout, out duration);
|
||||
testSense = dev.ReadLong10(out readBuffer, out senseBuf, false, false, 0, testSize,
|
||||
timeout, out duration);
|
||||
if(!testSense && !dev.Error)
|
||||
{
|
||||
readLong10 = true;
|
||||
@@ -203,7 +220,8 @@ namespace DiscImageChef.Core.Devices
|
||||
}
|
||||
else if(blockSize == 2048)
|
||||
{
|
||||
testSense = dev.ReadLong16(out readBuffer, out senseBuf, false, 0, 2380, timeout, out duration);
|
||||
testSense = dev.ReadLong16(out readBuffer, out senseBuf, false, 0, 2380, timeout,
|
||||
out duration);
|
||||
if(!testSense && !dev.Error)
|
||||
{
|
||||
readLong16 = true;
|
||||
@@ -212,7 +230,8 @@ namespace DiscImageChef.Core.Devices
|
||||
}
|
||||
else
|
||||
{
|
||||
testSense = dev.ReadLong10(out readBuffer, out senseBuf, false, false, 0, 2380, timeout, out duration);
|
||||
testSense = dev.ReadLong10(out readBuffer, out senseBuf, false, false, 0, 2380, timeout,
|
||||
out duration);
|
||||
if(!testSense && !dev.Error)
|
||||
{
|
||||
readLong10 = true;
|
||||
@@ -223,7 +242,8 @@ namespace DiscImageChef.Core.Devices
|
||||
}
|
||||
else if(blockSize == 4096)
|
||||
{
|
||||
testSense = dev.ReadLong16(out readBuffer, out senseBuf, false, 0, 4760, timeout, out duration);
|
||||
testSense = dev.ReadLong16(out readBuffer, out senseBuf, false, 0, 4760, timeout,
|
||||
out duration);
|
||||
if(!testSense && !dev.Error)
|
||||
{
|
||||
readLong16 = true;
|
||||
@@ -232,7 +252,8 @@ namespace DiscImageChef.Core.Devices
|
||||
}
|
||||
else
|
||||
{
|
||||
testSense = dev.ReadLong10(out readBuffer, out senseBuf, false, false, 0, 4760, timeout, out duration);
|
||||
testSense = dev.ReadLong10(out readBuffer, out senseBuf, false, false, 0, 4760, timeout,
|
||||
out duration);
|
||||
if(!testSense && !dev.Error)
|
||||
{
|
||||
readLong10 = true;
|
||||
@@ -243,7 +264,8 @@ namespace DiscImageChef.Core.Devices
|
||||
}
|
||||
else if(blockSize == 8192)
|
||||
{
|
||||
testSense = dev.ReadLong16(out readBuffer, out senseBuf, false, 0, 9424, timeout, out duration);
|
||||
testSense = dev.ReadLong16(out readBuffer, out senseBuf, false, 0, 9424, timeout,
|
||||
out duration);
|
||||
if(!testSense && !dev.Error)
|
||||
{
|
||||
readLong16 = true;
|
||||
@@ -252,7 +274,8 @@ namespace DiscImageChef.Core.Devices
|
||||
}
|
||||
else
|
||||
{
|
||||
testSense = dev.ReadLong10(out readBuffer, out senseBuf, false, false, 0, 9424, timeout, out duration);
|
||||
testSense = dev.ReadLong10(out readBuffer, out senseBuf, false, false, 0, 9424, timeout,
|
||||
out duration);
|
||||
if(!testSense && !dev.Error)
|
||||
{
|
||||
readLong10 = true;
|
||||
@@ -265,38 +288,44 @@ namespace DiscImageChef.Core.Devices
|
||||
|
||||
if(!readRaw && dev.Manufacturer == "SYQUEST")
|
||||
{
|
||||
testSense = dev.SyQuestReadLong10(out readBuffer, out senseBuf, 0, 0xFFFF, timeout, out duration);
|
||||
testSense = dev.SyQuestReadLong10(out readBuffer, out senseBuf, 0, 0xFFFF, timeout,
|
||||
out duration);
|
||||
if(testSense)
|
||||
{
|
||||
decSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf);
|
||||
if(decSense.HasValue)
|
||||
{
|
||||
if(decSense.Value.SenseKey == Decoders.SCSI.SenseKeys.IllegalRequest &&
|
||||
decSense.Value.ASC == 0x24 && decSense.Value.ASCQ == 0x00)
|
||||
decSense.Value.ASC == 0x24 && decSense.Value.ASCQ == 0x00)
|
||||
{
|
||||
readRaw = true;
|
||||
if(decSense.Value.InformationValid && decSense.Value.ILI)
|
||||
{
|
||||
longBlockSize = 0xFFFF - (decSense.Value.Information & 0xFFFF);
|
||||
syqReadLong10 = !dev.SyQuestReadLong10(out readBuffer, out senseBuf, 0, longBlockSize, timeout, out duration);
|
||||
syqReadLong10 =
|
||||
!dev.SyQuestReadLong10(out readBuffer, out senseBuf, 0, longBlockSize,
|
||||
timeout, out duration);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
testSense = dev.SyQuestReadLong6(out readBuffer, out senseBuf, 0, 0xFFFF, timeout, out duration);
|
||||
testSense = dev.SyQuestReadLong6(out readBuffer, out senseBuf, 0, 0xFFFF, timeout,
|
||||
out duration);
|
||||
if(testSense)
|
||||
{
|
||||
decSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf);
|
||||
if(decSense.HasValue)
|
||||
{
|
||||
if(decSense.Value.SenseKey == Decoders.SCSI.SenseKeys.IllegalRequest &&
|
||||
decSense.Value.ASC == 0x24 && decSense.Value.ASCQ == 0x00)
|
||||
decSense.Value.ASC == 0x24 && decSense.Value.ASCQ == 0x00)
|
||||
{
|
||||
readRaw = true;
|
||||
if(decSense.Value.InformationValid && decSense.Value.ILI)
|
||||
{
|
||||
longBlockSize = 0xFFFF - (decSense.Value.Information & 0xFFFF);
|
||||
syqReadLong6 = !dev.SyQuestReadLong6(out readBuffer, out senseBuf, 0, longBlockSize, timeout, out duration);
|
||||
syqReadLong6 =
|
||||
!dev.SyQuestReadLong6(out readBuffer, out senseBuf, 0,
|
||||
longBlockSize, timeout, out duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -307,7 +336,8 @@ namespace DiscImageChef.Core.Devices
|
||||
|
||||
if(!readRaw && blockSize == 256)
|
||||
{
|
||||
testSense = dev.SyQuestReadLong6(out readBuffer, out senseBuf, 0, 262, timeout, out duration);
|
||||
testSense = dev.SyQuestReadLong6(out readBuffer, out senseBuf, 0, 262, timeout,
|
||||
out duration);
|
||||
if(!testSense && !dev.Error)
|
||||
{
|
||||
syqReadLong6 = true;
|
||||
@@ -320,10 +350,12 @@ namespace DiscImageChef.Core.Devices
|
||||
else
|
||||
{
|
||||
if(dev.Manufacturer == "HL-DT-ST")
|
||||
hldtstReadRaw = !dev.HlDtStReadRawDvd(out readBuffer, out senseBuf, 0, 1, timeout, out duration);
|
||||
hldtstReadRaw =
|
||||
!dev.HlDtStReadRawDvd(out readBuffer, out senseBuf, 0, 1, timeout, out duration);
|
||||
|
||||
if(dev.Manufacturer == "PLEXTOR")
|
||||
plextorReadRaw = !dev.PlextorReadRawDvd(out readBuffer, out senseBuf, 0, 1, timeout, out duration);
|
||||
plextorReadRaw =
|
||||
!dev.PlextorReadRawDvd(out readBuffer, out senseBuf, 0, 1, timeout, out duration);
|
||||
|
||||
if(hldtstReadRaw || plextorReadRaw)
|
||||
{
|
||||
@@ -334,7 +366,8 @@ namespace DiscImageChef.Core.Devices
|
||||
// READ LONG (10) for some DVD drives
|
||||
if(!readRaw && dev.Manufacturer == "MATSHITA")
|
||||
{
|
||||
testSense = dev.ReadLong10(out readBuffer, out senseBuf, false, false, 0, 37856, timeout, out duration);
|
||||
testSense = dev.ReadLong10(out readBuffer, out senseBuf, false, false, 0, 37856, timeout,
|
||||
out duration);
|
||||
if(!testSense && !dev.Error)
|
||||
{
|
||||
readLongDvd = true;
|
||||
@@ -347,27 +380,17 @@ namespace DiscImageChef.Core.Devices
|
||||
|
||||
if(readRaw)
|
||||
{
|
||||
if(readLong16)
|
||||
DicConsole.WriteLine("Using SCSI READ LONG (16) command.");
|
||||
else if(readLong10 || readLongDvd)
|
||||
DicConsole.WriteLine("Using SCSI READ LONG (10) command.");
|
||||
else if(syqReadLong10)
|
||||
DicConsole.WriteLine("Using SyQuest READ LONG (10) command.");
|
||||
else if(syqReadLong6)
|
||||
DicConsole.WriteLine("Using SyQuest READ LONG (6) command.");
|
||||
else if(hldtstReadRaw)
|
||||
DicConsole.WriteLine("Using HL-DT-ST raw DVD reading.");
|
||||
else if(plextorReadRaw)
|
||||
DicConsole.WriteLine("Using Plextor raw DVD reading.");
|
||||
if(readLong16) DicConsole.WriteLine("Using SCSI READ LONG (16) command.");
|
||||
else if(readLong10 || readLongDvd) DicConsole.WriteLine("Using SCSI READ LONG (10) command.");
|
||||
else if(syqReadLong10) DicConsole.WriteLine("Using SyQuest READ LONG (10) command.");
|
||||
else if(syqReadLong6) DicConsole.WriteLine("Using SyQuest READ LONG (6) command.");
|
||||
else if(hldtstReadRaw) DicConsole.WriteLine("Using HL-DT-ST raw DVD reading.");
|
||||
else if(plextorReadRaw) DicConsole.WriteLine("Using Plextor raw DVD reading.");
|
||||
}
|
||||
else if(read16)
|
||||
DicConsole.WriteLine("Using SCSI READ (16) command.");
|
||||
else if(read12)
|
||||
DicConsole.WriteLine("Using SCSI READ (12) command.");
|
||||
else if(read10)
|
||||
DicConsole.WriteLine("Using SCSI READ (10) command.");
|
||||
else if(read6)
|
||||
DicConsole.WriteLine("Using SCSI READ (6) command.");
|
||||
else if(read16) DicConsole.WriteLine("Using SCSI READ (16) command.");
|
||||
else if(read12) DicConsole.WriteLine("Using SCSI READ (12) command.");
|
||||
else if(read10) DicConsole.WriteLine("Using SCSI READ (10) command.");
|
||||
else if(read6) DicConsole.WriteLine("Using SCSI READ (6) command.");
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -396,8 +419,8 @@ namespace DiscImageChef.Core.Devices
|
||||
// Not all MMC devices support READ CAPACITY, as they have READ TOC
|
||||
if(dev.SCSIType != Decoders.SCSI.PeripheralDeviceTypes.MultiMediaDevice)
|
||||
{
|
||||
errorMessage = string.Format("Unable to get media capacity\n" +
|
||||
"{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf));
|
||||
errorMessage = string.Format("Unable to get media capacity\n" + "{0}",
|
||||
Decoders.SCSI.Sense.PrettifySense(senseBuf));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -431,31 +454,30 @@ namespace DiscImageChef.Core.Devices
|
||||
{
|
||||
if(read16)
|
||||
{
|
||||
sense = dev.Read16(out readBuffer, out senseBuf, 0, false, true, false, 0, blockSize, 0, blocksToRead, false, timeout, out duration);
|
||||
if(dev.Error)
|
||||
blocksToRead /= 2;
|
||||
sense = dev.Read16(out readBuffer, out senseBuf, 0, false, true, false, 0, blockSize, 0,
|
||||
blocksToRead, false, timeout, out duration);
|
||||
if(dev.Error) blocksToRead /= 2;
|
||||
}
|
||||
else if(read12)
|
||||
{
|
||||
sense = dev.Read12(out readBuffer, out senseBuf, 0, false, false, false, false, 0, blockSize, 0, blocksToRead, false, timeout, out duration);
|
||||
if(dev.Error)
|
||||
blocksToRead /= 2;
|
||||
sense = dev.Read12(out readBuffer, out senseBuf, 0, false, false, false, false, 0, blockSize, 0,
|
||||
blocksToRead, false, timeout, out duration);
|
||||
if(dev.Error) blocksToRead /= 2;
|
||||
}
|
||||
else if(read10)
|
||||
{
|
||||
sense = dev.Read10(out readBuffer, out senseBuf, 0, false, true, false, false, 0, blockSize, 0, (ushort)blocksToRead, timeout, out duration);
|
||||
if(dev.Error)
|
||||
blocksToRead /= 2;
|
||||
sense = dev.Read10(out readBuffer, out senseBuf, 0, false, true, false, false, 0, blockSize, 0,
|
||||
(ushort)blocksToRead, timeout, out duration);
|
||||
if(dev.Error) blocksToRead /= 2;
|
||||
}
|
||||
else if(read6)
|
||||
{
|
||||
sense = dev.Read6(out readBuffer, out senseBuf, 0, blockSize, (byte)blocksToRead, timeout, out duration);
|
||||
if(dev.Error)
|
||||
blocksToRead /= 2;
|
||||
sense = dev.Read6(out readBuffer, out senseBuf, 0, blockSize, (byte)blocksToRead, timeout,
|
||||
out duration);
|
||||
if(dev.Error) blocksToRead /= 2;
|
||||
}
|
||||
|
||||
if(!dev.Error || blocksToRead == 1)
|
||||
break;
|
||||
if(!dev.Error || blocksToRead == 1) break;
|
||||
}
|
||||
|
||||
if(dev.Error)
|
||||
@@ -478,37 +500,46 @@ namespace DiscImageChef.Core.Devices
|
||||
if(readRaw)
|
||||
{
|
||||
if(readLong16)
|
||||
sense = dev.ReadLong16(out buffer, out senseBuf, false, block, longBlockSize, timeout, out duration);
|
||||
sense = dev.ReadLong16(out buffer, out senseBuf, false, block, longBlockSize, timeout,
|
||||
out duration);
|
||||
else if(readLong10)
|
||||
sense = dev.ReadLong10(out buffer, out senseBuf, false, false, (uint)block, (ushort)longBlockSize, timeout, out duration);
|
||||
sense = dev.ReadLong10(out buffer, out senseBuf, false, false, (uint)block, (ushort)longBlockSize,
|
||||
timeout, out duration);
|
||||
else if(syqReadLong10)
|
||||
sense = dev.SyQuestReadLong10(out buffer, out senseBuf, (uint)block, longBlockSize, timeout, out duration);
|
||||
sense = dev.SyQuestReadLong10(out buffer, out senseBuf, (uint)block, longBlockSize, timeout,
|
||||
out duration);
|
||||
else if(syqReadLong6)
|
||||
sense = dev.SyQuestReadLong6(out buffer, out senseBuf, (uint)block, longBlockSize, timeout, out duration);
|
||||
sense = dev.SyQuestReadLong6(out buffer, out senseBuf, (uint)block, longBlockSize, timeout,
|
||||
out duration);
|
||||
else if(hldtstReadRaw)
|
||||
sense = dev.HlDtStReadRawDvd(out buffer, out senseBuf, (uint)block, longBlockSize, timeout, out duration);
|
||||
sense = dev.HlDtStReadRawDvd(out buffer, out senseBuf, (uint)block, longBlockSize, timeout,
|
||||
out duration);
|
||||
else if(plextorReadRaw)
|
||||
sense = dev.PlextorReadRawDvd(out buffer, out senseBuf, (uint)block, longBlockSize, timeout, out duration);
|
||||
else
|
||||
return true;
|
||||
sense = dev.PlextorReadRawDvd(out buffer, out senseBuf, (uint)block, longBlockSize, timeout,
|
||||
out duration);
|
||||
else return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(read16)
|
||||
sense = dev.Read16(out buffer, out senseBuf, 0, false, true, false, block, blockSize, 0, count, false, timeout, out duration);
|
||||
sense = dev.Read16(out buffer, out senseBuf, 0, false, true, false, block, blockSize, 0, count,
|
||||
false, timeout, out duration);
|
||||
else if(read12)
|
||||
sense = dev.Read12(out buffer, out senseBuf, 0, false, false, false, false, (uint)block, blockSize, 0, count, false, timeout, out duration);
|
||||
sense = dev.Read12(out buffer, out senseBuf, 0, false, false, false, false, (uint)block, blockSize,
|
||||
0, count, false, timeout, out duration);
|
||||
else if(read10)
|
||||
sense = dev.Read10(out buffer, out senseBuf, 0, false, true, false, false, (uint)block, blockSize, 0, (ushort)count, timeout, out duration);
|
||||
sense = dev.Read10(out buffer, out senseBuf, 0, false, true, false, false, (uint)block, blockSize,
|
||||
0, (ushort)count, timeout, out duration);
|
||||
else if(read6)
|
||||
sense = dev.Read6(out buffer, out senseBuf, (uint)block, blockSize, (byte)count, timeout, out duration);
|
||||
else
|
||||
return true;
|
||||
sense = dev.Read6(out buffer, out senseBuf, (uint)block, blockSize, (byte)count, timeout,
|
||||
out duration);
|
||||
else return true;
|
||||
}
|
||||
|
||||
if(sense || dev.Error)
|
||||
{
|
||||
DicConsole.DebugWriteLine("SCSI Reader", "READ error:\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf));
|
||||
DicConsole.DebugWriteLine("SCSI Reader", "READ error:\n{0}",
|
||||
Decoders.SCSI.Sense.PrettifySense(senseBuf));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -521,12 +552,10 @@ namespace DiscImageChef.Core.Devices
|
||||
bool sense = true;
|
||||
duration = 0;
|
||||
|
||||
if(seek6)
|
||||
sense = dev.Seek6(out senseBuf, (uint)block, timeout, out duration);
|
||||
else if(seek10)
|
||||
sense = dev.Seek10(out senseBuf, (uint)block, timeout, out duration);
|
||||
if(seek6) sense = dev.Seek6(out senseBuf, (uint)block, timeout, out duration);
|
||||
else if(seek10) sense = dev.Seek10(out senseBuf, (uint)block, timeout, out duration);
|
||||
|
||||
return sense;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,8 +42,7 @@ namespace DiscImageChef.Core.Devices.Report
|
||||
{
|
||||
public static void Report(Device dev, ref DeviceReport report, bool debug, ref bool removable)
|
||||
{
|
||||
if(report == null)
|
||||
return;
|
||||
if(report == null) return;
|
||||
|
||||
Decoders.ATA.AtaErrorRegistersCHS errorRegs;
|
||||
byte[] buffer;
|
||||
@@ -51,14 +50,11 @@ namespace DiscImageChef.Core.Devices.Report
|
||||
uint timeout = 5;
|
||||
ConsoleKeyInfo pressedKey;
|
||||
|
||||
if(dev.IsUSB)
|
||||
USB.Report(dev, ref report, debug, ref removable);
|
||||
if(dev.IsUSB) USB.Report(dev, ref report, debug, ref removable);
|
||||
|
||||
if(dev.IsFireWire)
|
||||
FireWire.Report(dev, ref report, debug, ref removable);
|
||||
if(dev.IsFireWire) FireWire.Report(dev, ref report, debug, ref removable);
|
||||
|
||||
if(dev.IsPCMCIA)
|
||||
PCMCIA.Report(dev, ref report, debug, ref removable);
|
||||
if(dev.IsPCMCIA) PCMCIA.Report(dev, ref report, debug, ref removable);
|
||||
|
||||
DicConsole.WriteLine("Querying ATA IDENTIFY...");
|
||||
|
||||
@@ -74,7 +70,8 @@ namespace DiscImageChef.Core.Devices.Report
|
||||
report.CompactFlashSpecified = true;
|
||||
removable = false;
|
||||
}
|
||||
else if(!removable && ataId.GeneralConfiguration.HasFlag(Decoders.ATA.Identify.GeneralConfigurationBit.Removable))
|
||||
else if(!removable &&
|
||||
ataId.GeneralConfiguration.HasFlag(Decoders.ATA.Identify.GeneralConfigurationBit.Removable))
|
||||
{
|
||||
pressedKey = new ConsoleKeyInfo();
|
||||
while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N)
|
||||
@@ -488,9 +485,8 @@ namespace DiscImageChef.Core.Devices.Report
|
||||
report.ATA.WRVSectorCountMode2 = ataId.WRVSectorCountMode2;
|
||||
report.ATA.WRVSectorCountMode2Specified = true;
|
||||
}
|
||||
if(debug)
|
||||
report.ATA.Identify = buffer;
|
||||
|
||||
if(debug) report.ATA.Identify = buffer;
|
||||
|
||||
if(removable)
|
||||
{
|
||||
List<testedMediaType> mediaTests = new List<testedMediaType>();
|
||||
@@ -549,14 +545,17 @@ namespace DiscImageChef.Core.Devices.Report
|
||||
mediaTest.BlocksSpecified = true;
|
||||
}
|
||||
|
||||
if(ataId.CurrentCylinders > 0 && ataId.CurrentHeads > 0 && ataId.CurrentSectorsPerTrack > 0)
|
||||
if(ataId.CurrentCylinders > 0 && ataId.CurrentHeads > 0 &&
|
||||
ataId.CurrentSectorsPerTrack > 0)
|
||||
{
|
||||
mediaTest.CurrentCHS = new chsType();
|
||||
mediaTest.CurrentCHS.Cylinders = ataId.CurrentCylinders;
|
||||
mediaTest.CurrentCHS.Heads = ataId.CurrentHeads;
|
||||
mediaTest.CurrentCHS.Sectors = ataId.CurrentSectorsPerTrack;
|
||||
if(mediaTest.Blocks == 0)
|
||||
mediaTest.Blocks = (ulong)(ataId.CurrentCylinders * ataId.CurrentHeads * ataId.CurrentSectorsPerTrack);
|
||||
mediaTest.Blocks =
|
||||
(ulong)(ataId.CurrentCylinders * ataId.CurrentHeads *
|
||||
ataId.CurrentSectorsPerTrack);
|
||||
mediaTest.BlocksSpecified = true;
|
||||
}
|
||||
|
||||
@@ -576,8 +575,7 @@ namespace DiscImageChef.Core.Devices.Report
|
||||
mediaTest.BlocksSpecified = true;
|
||||
}
|
||||
|
||||
if(ataId.NominalRotationRate != 0x0000 &&
|
||||
ataId.NominalRotationRate != 0xFFFF)
|
||||
if(ataId.NominalRotationRate != 0x0000 && ataId.NominalRotationRate != 0xFFFF)
|
||||
{
|
||||
if(ataId.NominalRotationRate == 0x0001)
|
||||
{
|
||||
@@ -596,26 +594,24 @@ namespace DiscImageChef.Core.Devices.Report
|
||||
uint logicalsectorsize = 0;
|
||||
uint physicalsectorsize;
|
||||
if((ataId.PhysLogSectorSize & 0x8000) == 0x0000 &&
|
||||
(ataId.PhysLogSectorSize & 0x4000) == 0x4000)
|
||||
(ataId.PhysLogSectorSize & 0x4000) == 0x4000)
|
||||
{
|
||||
if((ataId.PhysLogSectorSize & 0x1000) == 0x1000)
|
||||
{
|
||||
if(ataId.LogicalSectorWords <= 255 || ataId.LogicalAlignment == 0xFFFF)
|
||||
logicalsectorsize = 512;
|
||||
else
|
||||
logicalsectorsize = ataId.LogicalSectorWords * 2;
|
||||
else logicalsectorsize = ataId.LogicalSectorWords * 2;
|
||||
}
|
||||
else
|
||||
logicalsectorsize = 512;
|
||||
else logicalsectorsize = 512;
|
||||
|
||||
if((ataId.PhysLogSectorSize & 0x2000) == 0x2000)
|
||||
{
|
||||
#pragma warning disable IDE0004 // Cast is necessary, otherwise incorrect value is created
|
||||
physicalsectorsize = (uint)(logicalsectorsize * (1 << ataId.PhysLogSectorSize & 0xF));
|
||||
physicalsectorsize =
|
||||
(uint)(logicalsectorsize * (1 << ataId.PhysLogSectorSize & 0xF));
|
||||
#pragma warning restore IDE0004 // Cast is necessary, otherwise incorrect value is created
|
||||
}
|
||||
else
|
||||
physicalsectorsize = logicalsectorsize;
|
||||
else physicalsectorsize = logicalsectorsize;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -631,7 +627,7 @@ namespace DiscImageChef.Core.Devices.Report
|
||||
mediaTest.PhysicalBlockSizeSpecified = true;
|
||||
|
||||
if((ataId.LogicalAlignment & 0x8000) == 0x0000 &&
|
||||
(ataId.LogicalAlignment & 0x4000) == 0x4000)
|
||||
(ataId.LogicalAlignment & 0x4000) == 0x4000)
|
||||
{
|
||||
mediaTest.LogicalAlignment = (ushort)(ataId.LogicalAlignment & 0x3FFF);
|
||||
mediaTest.LogicalAlignmentSpecified = true;
|
||||
@@ -644,15 +640,16 @@ namespace DiscImageChef.Core.Devices.Report
|
||||
mediaTest.LongBlockSizeSpecified = true;
|
||||
}
|
||||
|
||||
if(ataId.UnformattedBPS > logicalsectorsize && (!mediaTest.LongBlockSizeSpecified || mediaTest.LongBlockSize == 516))
|
||||
if(ataId.UnformattedBPS > logicalsectorsize &&
|
||||
(!mediaTest.LongBlockSizeSpecified || mediaTest.LongBlockSize == 516))
|
||||
{
|
||||
mediaTest.LongBlockSize = ataId.UnformattedBPS;
|
||||
mediaTest.LongBlockSizeSpecified = true;
|
||||
}
|
||||
|
||||
if(ataId.CommandSet3.HasFlag(Decoders.ATA.Identify.CommandSetBit3.MustBeSet) &&
|
||||
!ataId.CommandSet3.HasFlag(Decoders.ATA.Identify.CommandSetBit3.MustBeClear) &&
|
||||
ataId.EnabledCommandSet3.HasFlag(Decoders.ATA.Identify.CommandSetBit3.MediaSerial))
|
||||
!ataId.CommandSet3.HasFlag(Decoders.ATA.Identify.CommandSetBit3.MustBeClear) &&
|
||||
ataId.EnabledCommandSet3.HasFlag(Decoders.ATA.Identify.CommandSetBit3.MediaSerial))
|
||||
{
|
||||
mediaTest.CanReadMediaSerial = true;
|
||||
mediaTest.CanReadMediaSerialSpecified = true;
|
||||
@@ -692,137 +689,213 @@ namespace DiscImageChef.Core.Devices.Report
|
||||
|
||||
DicConsole.WriteLine("Trying READ SECTOR(S) in CHS mode...");
|
||||
sense = dev.Read(out readBuf, out errorChs, false, 0, 0, 1, 1, timeout, out duration);
|
||||
mediaTest.SupportsRead = (!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 && readBuf.Length > 0);
|
||||
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
mediaTest.SupportsRead =
|
||||
(!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 &&
|
||||
readBuf.Length > 0);
|
||||
DicConsole.DebugWriteLine("ATA Report",
|
||||
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
sense, errorChs.status, errorChs.error, readBuf.Length);
|
||||
if(debug)
|
||||
DataFile.WriteTo("ATA Report", "readsectorschs", "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", readBuf);
|
||||
DataFile.WriteTo("ATA Report", "readsectorschs",
|
||||
"_debug_" + mediaTest.MediumTypeName + ".bin", "read results",
|
||||
readBuf);
|
||||
|
||||
DicConsole.WriteLine("Trying READ SECTOR(S) RETRY in CHS mode...");
|
||||
sense = dev.Read(out readBuf, out errorChs, true, 0, 0, 1, 1, timeout, out duration);
|
||||
mediaTest.SupportsReadRetry = (!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 && readBuf.Length > 0);
|
||||
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
mediaTest.SupportsReadRetry =
|
||||
(!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 &&
|
||||
readBuf.Length > 0);
|
||||
DicConsole.DebugWriteLine("ATA Report",
|
||||
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
sense, errorChs.status, errorChs.error, readBuf.Length);
|
||||
if(debug)
|
||||
DataFile.WriteTo("ATA Report", "readsectorsretrychs", "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", readBuf);
|
||||
DataFile.WriteTo("ATA Report", "readsectorsretrychs",
|
||||
"_debug_" + mediaTest.MediumTypeName + ".bin", "read results",
|
||||
readBuf);
|
||||
|
||||
DicConsole.WriteLine("Trying READ DMA in CHS mode...");
|
||||
sense = dev.ReadDma(out readBuf, out errorChs, false, 0, 0, 1, 1, timeout, out duration);
|
||||
mediaTest.SupportsReadDma = (!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 && readBuf.Length > 0);
|
||||
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
sense = dev.ReadDma(out readBuf, out errorChs, false, 0, 0, 1, 1, timeout,
|
||||
out duration);
|
||||
mediaTest.SupportsReadDma =
|
||||
(!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 &&
|
||||
readBuf.Length > 0);
|
||||
DicConsole.DebugWriteLine("ATA Report",
|
||||
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
sense, errorChs.status, errorChs.error, readBuf.Length);
|
||||
if(debug)
|
||||
DataFile.WriteTo("ATA Report", "readdmachs", "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", readBuf);
|
||||
DataFile.WriteTo("ATA Report", "readdmachs",
|
||||
"_debug_" + mediaTest.MediumTypeName + ".bin", "read results",
|
||||
readBuf);
|
||||
|
||||
DicConsole.WriteLine("Trying READ DMA RETRY in CHS mode...");
|
||||
sense = dev.ReadDma(out readBuf, out errorChs, true, 0, 0, 1, 1, timeout, out duration);
|
||||
mediaTest.SupportsReadDmaRetry = (!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 && readBuf.Length > 0);
|
||||
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
mediaTest.SupportsReadDmaRetry =
|
||||
(!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 &&
|
||||
readBuf.Length > 0);
|
||||
DicConsole.DebugWriteLine("ATA Report",
|
||||
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
sense, errorChs.status, errorChs.error, readBuf.Length);
|
||||
if(debug)
|
||||
DataFile.WriteTo("ATA Report", "readdmaretrychs", "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", readBuf);
|
||||
DataFile.WriteTo("ATA Report", "readdmaretrychs",
|
||||
"_debug_" + mediaTest.MediumTypeName + ".bin", "read results",
|
||||
readBuf);
|
||||
|
||||
DicConsole.WriteLine("Trying SEEK in CHS mode...");
|
||||
sense = dev.Seek(out errorChs, 0, 0, 1, timeout, out duration);
|
||||
mediaTest.SupportsSeek = (!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0);
|
||||
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}",
|
||||
sense, errorChs.status, errorChs.error);
|
||||
|
||||
mediaTest.SupportsSeek =
|
||||
(!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0);
|
||||
DicConsole.DebugWriteLine("ATA Report",
|
||||
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}", sense,
|
||||
errorChs.status, errorChs.error);
|
||||
|
||||
DicConsole.WriteLine("Trying READ SECTOR(S) in LBA mode...");
|
||||
sense = dev.Read(out readBuf, out errorLba, false, 0, 1, timeout, out duration);
|
||||
mediaTest.SupportsReadLba = (!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 && readBuf.Length > 0);
|
||||
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
mediaTest.SupportsReadLba =
|
||||
(!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 &&
|
||||
readBuf.Length > 0);
|
||||
DicConsole.DebugWriteLine("ATA Report",
|
||||
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
sense, errorChs.status, errorChs.error, readBuf.Length);
|
||||
if(debug)
|
||||
DataFile.WriteTo("ATA Report", "readsectors", "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", readBuf);
|
||||
DataFile.WriteTo("ATA Report", "readsectors",
|
||||
"_debug_" + mediaTest.MediumTypeName + ".bin", "read results",
|
||||
readBuf);
|
||||
|
||||
DicConsole.WriteLine("Trying READ SECTOR(S) RETRY in LBA mode...");
|
||||
sense = dev.Read(out readBuf, out errorLba, true, 0, 1, timeout, out duration);
|
||||
mediaTest.SupportsReadRetryLba = (!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 && readBuf.Length > 0);
|
||||
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
mediaTest.SupportsReadRetryLba =
|
||||
(!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 &&
|
||||
readBuf.Length > 0);
|
||||
DicConsole.DebugWriteLine("ATA Report",
|
||||
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
sense, errorChs.status, errorChs.error, readBuf.Length);
|
||||
if(debug)
|
||||
DataFile.WriteTo("ATA Report", "readsectorsretry", "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", readBuf);
|
||||
DataFile.WriteTo("ATA Report", "readsectorsretry",
|
||||
"_debug_" + mediaTest.MediumTypeName + ".bin", "read results",
|
||||
readBuf);
|
||||
|
||||
DicConsole.WriteLine("Trying READ DMA in LBA mode...");
|
||||
sense = dev.ReadDma(out readBuf, out errorLba, false, 0, 1, timeout, out duration);
|
||||
mediaTest.SupportsReadDmaLba = (!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 && readBuf.Length > 0);
|
||||
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
mediaTest.SupportsReadDmaLba =
|
||||
(!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 &&
|
||||
readBuf.Length > 0);
|
||||
DicConsole.DebugWriteLine("ATA Report",
|
||||
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
sense, errorChs.status, errorChs.error, readBuf.Length);
|
||||
if(debug)
|
||||
DataFile.WriteTo("ATA Report", "readdma", "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", readBuf);
|
||||
DataFile.WriteTo("ATA Report", "readdma",
|
||||
"_debug_" + mediaTest.MediumTypeName + ".bin", "read results",
|
||||
readBuf);
|
||||
|
||||
DicConsole.WriteLine("Trying READ DMA RETRY in LBA mode...");
|
||||
sense = dev.ReadDma(out readBuf, out errorLba, true, 0, 1, timeout, out duration);
|
||||
mediaTest.SupportsReadDmaRetryLba = (!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 && readBuf.Length > 0);
|
||||
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
mediaTest.SupportsReadDmaRetryLba =
|
||||
(!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 &&
|
||||
readBuf.Length > 0);
|
||||
DicConsole.DebugWriteLine("ATA Report",
|
||||
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
sense, errorChs.status, errorChs.error, readBuf.Length);
|
||||
if(debug)
|
||||
DataFile.WriteTo("ATA Report", "readdmaretry", "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", readBuf);
|
||||
DataFile.WriteTo("ATA Report", "readdmaretry",
|
||||
"_debug_" + mediaTest.MediumTypeName + ".bin", "read results",
|
||||
readBuf);
|
||||
|
||||
DicConsole.WriteLine("Trying SEEK in LBA mode...");
|
||||
sense = dev.Seek(out errorLba, 0, timeout, out duration);
|
||||
mediaTest.SupportsSeekLba = (!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0);
|
||||
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}",
|
||||
sense, errorChs.status, errorChs.error);
|
||||
|
||||
mediaTest.SupportsSeekLba =
|
||||
(!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0);
|
||||
DicConsole.DebugWriteLine("ATA Report",
|
||||
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}", sense,
|
||||
errorChs.status, errorChs.error);
|
||||
|
||||
DicConsole.WriteLine("Trying READ SECTOR(S) in LBA48 mode...");
|
||||
sense = dev.Read(out readBuf, out errorLba48, 0, 1, timeout, out duration);
|
||||
mediaTest.SupportsReadLba48 = (!sense && (errorLba48.status & 0x01) != 0x01 && errorLba48.error == 0 && readBuf.Length > 0);
|
||||
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
mediaTest.SupportsReadLba48 =
|
||||
(!sense && (errorLba48.status & 0x01) != 0x01 && errorLba48.error == 0 &&
|
||||
readBuf.Length > 0);
|
||||
DicConsole.DebugWriteLine("ATA Report",
|
||||
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
sense, errorChs.status, errorChs.error, readBuf.Length);
|
||||
if(debug)
|
||||
DataFile.WriteTo("ATA Report", "readsectors48", "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", readBuf);
|
||||
DataFile.WriteTo("ATA Report", "readsectors48",
|
||||
"_debug_" + mediaTest.MediumTypeName + ".bin", "read results",
|
||||
readBuf);
|
||||
|
||||
DicConsole.WriteLine("Trying READ DMA in LBA48 mode...");
|
||||
sense = dev.ReadDma(out readBuf, out errorLba48, 0, 1, timeout, out duration);
|
||||
mediaTest.SupportsReadDmaLba48 = (!sense && (errorLba48.status & 0x01) != 0x01 && errorLba48.error == 0 && readBuf.Length > 0);
|
||||
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
mediaTest.SupportsReadDmaLba48 =
|
||||
(!sense && (errorLba48.status & 0x01) != 0x01 && errorLba48.error == 0 &&
|
||||
readBuf.Length > 0);
|
||||
DicConsole.DebugWriteLine("ATA Report",
|
||||
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
sense, errorChs.status, errorChs.error, readBuf.Length);
|
||||
if(debug)
|
||||
DataFile.WriteTo("ATA Report", "readdma48", "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", readBuf);
|
||||
|
||||
DataFile.WriteTo("ATA Report", "readdma48",
|
||||
"_debug_" + mediaTest.MediumTypeName + ".bin", "read results",
|
||||
readBuf);
|
||||
|
||||
DicConsole.WriteLine("Trying READ LONG in CHS mode...");
|
||||
sense = dev.ReadLong(out readBuf, out errorChs, false, 0, 0, 1, mediaTest.LongBlockSize, timeout, out duration);
|
||||
mediaTest.SupportsReadLong = (!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 && readBuf.Length > 0 && BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead);
|
||||
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
sense = dev.ReadLong(out readBuf, out errorChs, false, 0, 0, 1, mediaTest.LongBlockSize,
|
||||
timeout, out duration);
|
||||
mediaTest.SupportsReadLong =
|
||||
(!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 &&
|
||||
readBuf.Length > 0 && BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead);
|
||||
DicConsole.DebugWriteLine("ATA Report",
|
||||
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
sense, errorChs.status, errorChs.error, readBuf.Length);
|
||||
if(debug)
|
||||
DataFile.WriteTo("ATA Report", "readlongchs", "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", readBuf);
|
||||
DataFile.WriteTo("ATA Report", "readlongchs",
|
||||
"_debug_" + mediaTest.MediumTypeName + ".bin", "read results",
|
||||
readBuf);
|
||||
|
||||
DicConsole.WriteLine("Trying READ LONG RETRY in CHS mode...");
|
||||
sense = dev.ReadLong(out readBuf, out errorChs, true, 0, 0, 1, mediaTest.LongBlockSize, timeout, out duration);
|
||||
mediaTest.SupportsReadLongRetry = (!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 && readBuf.Length > 0 && BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead);
|
||||
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
sense = dev.ReadLong(out readBuf, out errorChs, true, 0, 0, 1, mediaTest.LongBlockSize,
|
||||
timeout, out duration);
|
||||
mediaTest.SupportsReadLongRetry =
|
||||
(!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 &&
|
||||
readBuf.Length > 0 && BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead);
|
||||
DicConsole.DebugWriteLine("ATA Report",
|
||||
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
sense, errorChs.status, errorChs.error, readBuf.Length);
|
||||
if(debug)
|
||||
DataFile.WriteTo("ATA Report", "readlongretrychs", "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", readBuf);
|
||||
DataFile.WriteTo("ATA Report", "readlongretrychs",
|
||||
"_debug_" + mediaTest.MediumTypeName + ".bin", "read results",
|
||||
readBuf);
|
||||
|
||||
DicConsole.WriteLine("Trying READ LONG in LBA mode...");
|
||||
sense = dev.ReadLong(out readBuf, out errorLba, false, 0, mediaTest.LongBlockSize, timeout, out duration);
|
||||
mediaTest.SupportsReadLongLba = (!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 && readBuf.Length > 0 && BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead);
|
||||
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
sense = dev.ReadLong(out readBuf, out errorLba, false, 0, mediaTest.LongBlockSize,
|
||||
timeout, out duration);
|
||||
mediaTest.SupportsReadLongLba =
|
||||
(!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 &&
|
||||
readBuf.Length > 0 && BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead);
|
||||
DicConsole.DebugWriteLine("ATA Report",
|
||||
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
sense, errorChs.status, errorChs.error, readBuf.Length);
|
||||
if(debug)
|
||||
DataFile.WriteTo("ATA Report", "readlong", "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", readBuf);
|
||||
DataFile.WriteTo("ATA Report", "readlong",
|
||||
"_debug_" + mediaTest.MediumTypeName + ".bin", "read results",
|
||||
readBuf);
|
||||
|
||||
DicConsole.WriteLine("Trying READ LONG RETRY in LBA mode...");
|
||||
sense = dev.ReadLong(out readBuf, out errorLba, true, 0, mediaTest.LongBlockSize, timeout, out duration);
|
||||
mediaTest.SupportsReadLongRetryLba = (!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 && readBuf.Length > 0 && BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead);
|
||||
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
sense = dev.ReadLong(out readBuf, out errorLba, true, 0, mediaTest.LongBlockSize,
|
||||
timeout, out duration);
|
||||
mediaTest.SupportsReadLongRetryLba =
|
||||
(!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 &&
|
||||
readBuf.Length > 0 && BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead);
|
||||
DicConsole.DebugWriteLine("ATA Report",
|
||||
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
sense, errorChs.status, errorChs.error, readBuf.Length);
|
||||
if(debug)
|
||||
DataFile.WriteTo("ATA Report", "readlongretry", "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", readBuf);
|
||||
DataFile.WriteTo("ATA Report", "readlongretry",
|
||||
"_debug_" + mediaTest.MediumTypeName + ".bin", "read results",
|
||||
readBuf);
|
||||
}
|
||||
else
|
||||
mediaTest.MediaIsRecognized = false;
|
||||
else mediaTest.MediaIsRecognized = false;
|
||||
|
||||
mediaTests.Add(mediaTest);
|
||||
}
|
||||
}
|
||||
|
||||
report.ATA.RemovableMedias = mediaTests.ToArray();
|
||||
}
|
||||
else
|
||||
@@ -846,7 +919,8 @@ namespace DiscImageChef.Core.Devices.Report
|
||||
report.ATA.ReadCapabilities.CHS.Cylinders = ataId.Cylinders;
|
||||
report.ATA.ReadCapabilities.CHS.Heads = ataId.Heads;
|
||||
report.ATA.ReadCapabilities.CHS.Sectors = ataId.SectorsPerTrack;
|
||||
report.ATA.ReadCapabilities.Blocks = (ulong)(ataId.Cylinders * ataId.Heads * ataId.SectorsPerTrack);
|
||||
report.ATA.ReadCapabilities.Blocks =
|
||||
(ulong)(ataId.Cylinders * ataId.Heads * ataId.SectorsPerTrack);
|
||||
report.ATA.ReadCapabilities.BlocksSpecified = true;
|
||||
}
|
||||
|
||||
@@ -856,7 +930,8 @@ namespace DiscImageChef.Core.Devices.Report
|
||||
report.ATA.ReadCapabilities.CurrentCHS.Cylinders = ataId.CurrentCylinders;
|
||||
report.ATA.ReadCapabilities.CurrentCHS.Heads = ataId.CurrentHeads;
|
||||
report.ATA.ReadCapabilities.CurrentCHS.Sectors = ataId.CurrentSectorsPerTrack;
|
||||
report.ATA.ReadCapabilities.Blocks = (ulong)(ataId.CurrentCylinders * ataId.CurrentHeads * ataId.CurrentSectorsPerTrack);
|
||||
report.ATA.ReadCapabilities.Blocks =
|
||||
(ulong)(ataId.CurrentCylinders * ataId.CurrentHeads * ataId.CurrentSectorsPerTrack);
|
||||
report.ATA.ReadCapabilities.BlocksSpecified = true;
|
||||
}
|
||||
|
||||
@@ -876,8 +951,7 @@ namespace DiscImageChef.Core.Devices.Report
|
||||
report.ATA.ReadCapabilities.BlocksSpecified = true;
|
||||
}
|
||||
|
||||
if(ataId.NominalRotationRate != 0x0000 &&
|
||||
ataId.NominalRotationRate != 0xFFFF)
|
||||
if(ataId.NominalRotationRate != 0x0000 && ataId.NominalRotationRate != 0xFFFF)
|
||||
{
|
||||
if(ataId.NominalRotationRate == 0x0001)
|
||||
{
|
||||
@@ -895,27 +969,24 @@ namespace DiscImageChef.Core.Devices.Report
|
||||
|
||||
uint logicalsectorsize = 0;
|
||||
uint physicalsectorsize;
|
||||
if((ataId.PhysLogSectorSize & 0x8000) == 0x0000 &&
|
||||
(ataId.PhysLogSectorSize & 0x4000) == 0x4000)
|
||||
if((ataId.PhysLogSectorSize & 0x8000) == 0x0000 && (ataId.PhysLogSectorSize & 0x4000) == 0x4000)
|
||||
{
|
||||
if((ataId.PhysLogSectorSize & 0x1000) == 0x1000)
|
||||
{
|
||||
if(ataId.LogicalSectorWords <= 255 || ataId.LogicalAlignment == 0xFFFF)
|
||||
logicalsectorsize = 512;
|
||||
else
|
||||
logicalsectorsize = ataId.LogicalSectorWords * 2;
|
||||
else logicalsectorsize = ataId.LogicalSectorWords * 2;
|
||||
}
|
||||
else
|
||||
logicalsectorsize = 512;
|
||||
else logicalsectorsize = 512;
|
||||
|
||||
if((ataId.PhysLogSectorSize & 0x2000) == 0x2000)
|
||||
{
|
||||
#pragma warning disable IDE0004 // Cast is necessary, otherwise incorrect value is created
|
||||
physicalsectorsize = logicalsectorsize * (uint)Math.Pow(2, (double)(ataId.PhysLogSectorSize & 0xF));
|
||||
physicalsectorsize = logicalsectorsize *
|
||||
(uint)Math.Pow(2, (double)(ataId.PhysLogSectorSize & 0xF));
|
||||
#pragma warning restore IDE0004 // Cast is necessary, otherwise incorrect value is created
|
||||
}
|
||||
else
|
||||
physicalsectorsize = logicalsectorsize;
|
||||
else physicalsectorsize = logicalsectorsize;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -930,8 +1001,7 @@ namespace DiscImageChef.Core.Devices.Report
|
||||
report.ATA.ReadCapabilities.PhysicalBlockSize = physicalsectorsize;
|
||||
report.ATA.ReadCapabilities.PhysicalBlockSizeSpecified = true;
|
||||
|
||||
if((ataId.LogicalAlignment & 0x8000) == 0x0000 &&
|
||||
(ataId.LogicalAlignment & 0x4000) == 0x4000)
|
||||
if((ataId.LogicalAlignment & 0x8000) == 0x0000 && (ataId.LogicalAlignment & 0x4000) == 0x4000)
|
||||
{
|
||||
report.ATA.ReadCapabilities.LogicalAlignment = (ushort)(ataId.LogicalAlignment & 0x3FFF);
|
||||
report.ATA.ReadCapabilities.LogicalAlignmentSpecified = true;
|
||||
@@ -944,15 +1014,17 @@ namespace DiscImageChef.Core.Devices.Report
|
||||
report.ATA.ReadCapabilities.LongBlockSizeSpecified = true;
|
||||
}
|
||||
|
||||
if(ataId.UnformattedBPS > logicalsectorsize && (!report.ATA.ReadCapabilities.LongBlockSizeSpecified || report.ATA.ReadCapabilities.LongBlockSize == 516))
|
||||
if(ataId.UnformattedBPS > logicalsectorsize &&
|
||||
(!report.ATA.ReadCapabilities.LongBlockSizeSpecified ||
|
||||
report.ATA.ReadCapabilities.LongBlockSize == 516))
|
||||
{
|
||||
report.ATA.ReadCapabilities.LongBlockSize = ataId.UnformattedBPS;
|
||||
report.ATA.ReadCapabilities.LongBlockSizeSpecified = true;
|
||||
}
|
||||
|
||||
if(ataId.CommandSet3.HasFlag(Decoders.ATA.Identify.CommandSetBit3.MustBeSet) &&
|
||||
!ataId.CommandSet3.HasFlag(Decoders.ATA.Identify.CommandSetBit3.MustBeClear) &&
|
||||
ataId.EnabledCommandSet3.HasFlag(Decoders.ATA.Identify.CommandSetBit3.MediaSerial))
|
||||
!ataId.CommandSet3.HasFlag(Decoders.ATA.Identify.CommandSetBit3.MustBeClear) &&
|
||||
ataId.EnabledCommandSet3.HasFlag(Decoders.ATA.Identify.CommandSetBit3.MediaSerial))
|
||||
{
|
||||
report.ATA.ReadCapabilities.CanReadMediaSerial = true;
|
||||
report.ATA.ReadCapabilities.CanReadMediaSerialSpecified = true;
|
||||
@@ -992,129 +1064,181 @@ namespace DiscImageChef.Core.Devices.Report
|
||||
|
||||
DicConsole.WriteLine("Trying READ SECTOR(S) in CHS mode...");
|
||||
sense = dev.Read(out readBuf, out errorChs, false, 0, 0, 1, 1, timeout, out duration);
|
||||
report.ATA.ReadCapabilities.SupportsRead = (!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 && readBuf.Length > 0);
|
||||
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
sense, errorChs.status, errorChs.error, readBuf.Length);
|
||||
report.ATA.ReadCapabilities.SupportsRead =
|
||||
(!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 && readBuf.Length > 0);
|
||||
DicConsole.DebugWriteLine("ATA Report",
|
||||
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense,
|
||||
errorChs.status, errorChs.error, readBuf.Length);
|
||||
if(debug)
|
||||
DataFile.WriteTo("ATA Report", "readsectorschs", "_debug_" + report.ATA.Model + ".bin", "read results", readBuf);
|
||||
DataFile.WriteTo("ATA Report", "readsectorschs", "_debug_" + report.ATA.Model + ".bin",
|
||||
"read results", readBuf);
|
||||
|
||||
DicConsole.WriteLine("Trying READ SECTOR(S) RETRY in CHS mode...");
|
||||
sense = dev.Read(out readBuf, out errorChs, true, 0, 0, 1, 1, timeout, out duration);
|
||||
report.ATA.ReadCapabilities.SupportsReadRetry = (!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 && readBuf.Length > 0);
|
||||
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
sense, errorChs.status, errorChs.error, readBuf.Length);
|
||||
report.ATA.ReadCapabilities.SupportsReadRetry =
|
||||
(!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 && readBuf.Length > 0);
|
||||
DicConsole.DebugWriteLine("ATA Report",
|
||||
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense,
|
||||
errorChs.status, errorChs.error, readBuf.Length);
|
||||
if(debug)
|
||||
DataFile.WriteTo("ATA Report", "readsectorsretrychs", "_debug_" + report.ATA.Model + ".bin", "read results", readBuf);
|
||||
|
||||
DataFile.WriteTo("ATA Report", "readsectorsretrychs", "_debug_" + report.ATA.Model + ".bin",
|
||||
"read results", readBuf);
|
||||
|
||||
DicConsole.WriteLine("Trying READ DMA in CHS mode...");
|
||||
sense = dev.ReadDma(out readBuf, out errorChs, false, 0, 0, 1, 1, timeout, out duration);
|
||||
report.ATA.ReadCapabilities.SupportsReadDma = (!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 && readBuf.Length > 0);
|
||||
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
sense, errorChs.status, errorChs.error, readBuf.Length);
|
||||
report.ATA.ReadCapabilities.SupportsReadDma =
|
||||
(!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 && readBuf.Length > 0);
|
||||
DicConsole.DebugWriteLine("ATA Report",
|
||||
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense,
|
||||
errorChs.status, errorChs.error, readBuf.Length);
|
||||
if(debug)
|
||||
DataFile.WriteTo("ATA Report", "readdmachs", "_debug_" + report.ATA.Model + ".bin", "read results", readBuf);
|
||||
|
||||
DataFile.WriteTo("ATA Report", "readdmachs", "_debug_" + report.ATA.Model + ".bin",
|
||||
"read results", readBuf);
|
||||
|
||||
DicConsole.WriteLine("Trying READ DMA RETRY in CHS mode...");
|
||||
sense = dev.ReadDma(out readBuf, out errorChs, true, 0, 0, 1, 1, timeout, out duration);
|
||||
report.ATA.ReadCapabilities.SupportsReadDmaRetry = (!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 && readBuf.Length > 0);
|
||||
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
sense, errorChs.status, errorChs.error, readBuf.Length);
|
||||
report.ATA.ReadCapabilities.SupportsReadDmaRetry =
|
||||
(!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 && readBuf.Length > 0);
|
||||
DicConsole.DebugWriteLine("ATA Report",
|
||||
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense,
|
||||
errorChs.status, errorChs.error, readBuf.Length);
|
||||
if(debug)
|
||||
DataFile.WriteTo("ATA Report", "readdmaretrychs", "_debug_" + report.ATA.Model + ".bin", "read results", readBuf);
|
||||
|
||||
DataFile.WriteTo("ATA Report", "readdmaretrychs", "_debug_" + report.ATA.Model + ".bin",
|
||||
"read results", readBuf);
|
||||
|
||||
DicConsole.WriteLine("Trying SEEK in CHS mode...");
|
||||
sense = dev.Seek(out errorChs, 0, 0, 1, timeout, out duration);
|
||||
report.ATA.ReadCapabilities.SupportsSeek = (!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0);
|
||||
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}",
|
||||
sense, errorChs.status, errorChs.error);
|
||||
report.ATA.ReadCapabilities.SupportsSeek =
|
||||
(!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0);
|
||||
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}", sense,
|
||||
errorChs.status, errorChs.error);
|
||||
|
||||
DicConsole.WriteLine("Trying READ SECTOR(S) in LBA mode...");
|
||||
sense = dev.Read(out readBuf, out errorLba, false, 0, 1, timeout, out duration);
|
||||
report.ATA.ReadCapabilities.SupportsReadLba = (!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 && readBuf.Length > 0);
|
||||
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
sense, errorLba.status, errorLba.error, readBuf.Length);
|
||||
report.ATA.ReadCapabilities.SupportsReadLba =
|
||||
(!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 && readBuf.Length > 0);
|
||||
DicConsole.DebugWriteLine("ATA Report",
|
||||
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense,
|
||||
errorLba.status, errorLba.error, readBuf.Length);
|
||||
if(debug)
|
||||
DataFile.WriteTo("ATA Report", "readsectors", "_debug_" + report.ATA.Model + ".bin", "read results", readBuf);
|
||||
|
||||
DataFile.WriteTo("ATA Report", "readsectors", "_debug_" + report.ATA.Model + ".bin",
|
||||
"read results", readBuf);
|
||||
|
||||
DicConsole.WriteLine("Trying READ SECTOR(S) RETRY in LBA mode...");
|
||||
sense = dev.Read(out readBuf, out errorLba, true, 0, 1, timeout, out duration);
|
||||
report.ATA.ReadCapabilities.SupportsReadRetryLba = (!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 && readBuf.Length > 0);
|
||||
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
sense, errorLba.status, errorLba.error, readBuf.Length);
|
||||
report.ATA.ReadCapabilities.SupportsReadRetryLba =
|
||||
(!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 && readBuf.Length > 0);
|
||||
DicConsole.DebugWriteLine("ATA Report",
|
||||
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense,
|
||||
errorLba.status, errorLba.error, readBuf.Length);
|
||||
if(debug)
|
||||
DataFile.WriteTo("ATA Report", "readsectorsretry", "_debug_" + report.ATA.Model + ".bin", "read results", readBuf);
|
||||
|
||||
DataFile.WriteTo("ATA Report", "readsectorsretry", "_debug_" + report.ATA.Model + ".bin",
|
||||
"read results", readBuf);
|
||||
|
||||
DicConsole.WriteLine("Trying READ DMA in LBA mode...");
|
||||
sense = dev.ReadDma(out readBuf, out errorLba, false, 0, 1, timeout, out duration);
|
||||
report.ATA.ReadCapabilities.SupportsReadDmaLba = (!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 && readBuf.Length > 0);
|
||||
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
sense, errorLba.status, errorLba.error, readBuf.Length);
|
||||
report.ATA.ReadCapabilities.SupportsReadDmaLba =
|
||||
(!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 && readBuf.Length > 0);
|
||||
DicConsole.DebugWriteLine("ATA Report",
|
||||
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense,
|
||||
errorLba.status, errorLba.error, readBuf.Length);
|
||||
if(debug)
|
||||
DataFile.WriteTo("ATA Report", "readdma", "_debug_" + report.ATA.Model + ".bin", "read results", readBuf);
|
||||
|
||||
DataFile.WriteTo("ATA Report", "readdma", "_debug_" + report.ATA.Model + ".bin", "read results",
|
||||
readBuf);
|
||||
|
||||
DicConsole.WriteLine("Trying READ DMA RETRY in LBA mode...");
|
||||
sense = dev.ReadDma(out readBuf, out errorLba, true, 0, 1, timeout, out duration);
|
||||
report.ATA.ReadCapabilities.SupportsReadDmaRetryLba = (!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 && readBuf.Length > 0);
|
||||
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
sense, errorLba.status, errorLba.error, readBuf.Length);
|
||||
report.ATA.ReadCapabilities.SupportsReadDmaRetryLba =
|
||||
(!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 && readBuf.Length > 0);
|
||||
DicConsole.DebugWriteLine("ATA Report",
|
||||
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense,
|
||||
errorLba.status, errorLba.error, readBuf.Length);
|
||||
if(debug)
|
||||
DataFile.WriteTo("ATA Report", "readdmaretry", "_debug_" + report.ATA.Model + ".bin", "read results", readBuf);
|
||||
|
||||
DataFile.WriteTo("ATA Report", "readdmaretry", "_debug_" + report.ATA.Model + ".bin",
|
||||
"read results", readBuf);
|
||||
|
||||
DicConsole.WriteLine("Trying SEEK in LBA mode...");
|
||||
sense = dev.Seek(out errorLba, 0, timeout, out duration);
|
||||
report.ATA.ReadCapabilities.SupportsSeekLba = (!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0);
|
||||
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}",
|
||||
sense, errorLba.status, errorLba.error);
|
||||
report.ATA.ReadCapabilities.SupportsSeekLba =
|
||||
(!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0);
|
||||
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}", sense,
|
||||
errorLba.status, errorLba.error);
|
||||
|
||||
DicConsole.WriteLine("Trying READ SECTOR(S) in LBA48 mode...");
|
||||
sense = dev.Read(out readBuf, out errorLba48, 0, 1, timeout, out duration);
|
||||
report.ATA.ReadCapabilities.SupportsReadLba48 = (!sense && (errorLba48.status & 0x01) != 0x01 && errorLba48.error == 0 && readBuf.Length > 0);
|
||||
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
sense, errorLba48.status, errorLba48.error, readBuf.Length);
|
||||
report.ATA.ReadCapabilities.SupportsReadLba48 =
|
||||
(!sense && (errorLba48.status & 0x01) != 0x01 && errorLba48.error == 0 && readBuf.Length > 0);
|
||||
DicConsole.DebugWriteLine("ATA Report",
|
||||
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense,
|
||||
errorLba48.status, errorLba48.error, readBuf.Length);
|
||||
if(debug)
|
||||
DataFile.WriteTo("ATA Report", "readsectors48", "_debug_" + report.ATA.Model + ".bin", "read results", readBuf);
|
||||
|
||||
DataFile.WriteTo("ATA Report", "readsectors48", "_debug_" + report.ATA.Model + ".bin",
|
||||
"read results", readBuf);
|
||||
|
||||
DicConsole.WriteLine("Trying READ DMA in LBA48 mode...");
|
||||
sense = dev.ReadDma(out readBuf, out errorLba48, 0, 1, timeout, out duration);
|
||||
report.ATA.ReadCapabilities.SupportsReadDmaLba48 = (!sense && (errorLba48.status & 0x01) != 0x01 && errorLba48.error == 0 && readBuf.Length > 0);
|
||||
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
sense, errorLba48.status, errorLba48.error, readBuf.Length);
|
||||
report.ATA.ReadCapabilities.SupportsReadDmaLba48 =
|
||||
(!sense && (errorLba48.status & 0x01) != 0x01 && errorLba48.error == 0 && readBuf.Length > 0);
|
||||
DicConsole.DebugWriteLine("ATA Report",
|
||||
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense,
|
||||
errorLba48.status, errorLba48.error, readBuf.Length);
|
||||
if(debug)
|
||||
DataFile.WriteTo("ATA Report", "readdma48", "_debug_" + report.ATA.Model + ".bin", "read results", readBuf);
|
||||
DataFile.WriteTo("ATA Report", "readdma48", "_debug_" + report.ATA.Model + ".bin",
|
||||
"read results", readBuf);
|
||||
|
||||
DicConsole.WriteLine("Trying READ LONG in CHS mode...");
|
||||
sense = dev.ReadLong(out readBuf, out errorChs, false, 0, 0, 1, report.ATA.ReadCapabilities.LongBlockSize, timeout, out duration);
|
||||
report.ATA.ReadCapabilities.SupportsReadLong = (!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 && readBuf.Length > 0 && BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead);
|
||||
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
sense, errorChs.status, errorChs.error, readBuf.Length);
|
||||
sense = dev.ReadLong(out readBuf, out errorChs, false, 0, 0, 1,
|
||||
report.ATA.ReadCapabilities.LongBlockSize, timeout, out duration);
|
||||
report.ATA.ReadCapabilities.SupportsReadLong =
|
||||
(!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 && readBuf.Length > 0 &&
|
||||
BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead);
|
||||
DicConsole.DebugWriteLine("ATA Report",
|
||||
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense,
|
||||
errorChs.status, errorChs.error, readBuf.Length);
|
||||
if(debug)
|
||||
DataFile.WriteTo("ATA Report", "readlongchs", "_debug_" + report.ATA.Model + ".bin", "read results", readBuf);
|
||||
|
||||
DataFile.WriteTo("ATA Report", "readlongchs", "_debug_" + report.ATA.Model + ".bin",
|
||||
"read results", readBuf);
|
||||
|
||||
DicConsole.WriteLine("Trying READ LONG RETRY in CHS mode...");
|
||||
sense = dev.ReadLong(out readBuf, out errorChs, true, 0, 0, 1, report.ATA.ReadCapabilities.LongBlockSize, timeout, out duration);
|
||||
report.ATA.ReadCapabilities.SupportsReadLongRetry = (!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 && readBuf.Length > 0 && BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead);
|
||||
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
sense, errorChs.status, errorChs.error, readBuf.Length);
|
||||
sense = dev.ReadLong(out readBuf, out errorChs, true, 0, 0, 1,
|
||||
report.ATA.ReadCapabilities.LongBlockSize, timeout, out duration);
|
||||
report.ATA.ReadCapabilities.SupportsReadLongRetry =
|
||||
(!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 && readBuf.Length > 0 &&
|
||||
BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead);
|
||||
DicConsole.DebugWriteLine("ATA Report",
|
||||
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense,
|
||||
errorChs.status, errorChs.error, readBuf.Length);
|
||||
if(debug)
|
||||
DataFile.WriteTo("ATA Report", "readlongretrychs", "_debug_" + report.ATA.Model + ".bin", "read results", readBuf);
|
||||
|
||||
DataFile.WriteTo("ATA Report", "readlongretrychs", "_debug_" + report.ATA.Model + ".bin",
|
||||
"read results", readBuf);
|
||||
|
||||
DicConsole.WriteLine("Trying READ LONG in LBA mode...");
|
||||
sense = dev.ReadLong(out readBuf, out errorLba, false, 0, report.ATA.ReadCapabilities.LongBlockSize, timeout, out duration);
|
||||
report.ATA.ReadCapabilities.SupportsReadLongLba = (!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 && readBuf.Length > 0 && BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead);
|
||||
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
sense, errorLba.status, errorLba.error, readBuf.Length);
|
||||
sense = dev.ReadLong(out readBuf, out errorLba, false, 0, report.ATA.ReadCapabilities.LongBlockSize,
|
||||
timeout, out duration);
|
||||
report.ATA.ReadCapabilities.SupportsReadLongLba =
|
||||
(!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 && readBuf.Length > 0 &&
|
||||
BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead);
|
||||
DicConsole.DebugWriteLine("ATA Report",
|
||||
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense,
|
||||
errorLba.status, errorLba.error, readBuf.Length);
|
||||
if(debug)
|
||||
DataFile.WriteTo("ATA Report", "readlong", "_debug_" + report.ATA.Model + ".bin", "read results", readBuf);
|
||||
|
||||
DataFile.WriteTo("ATA Report", "readlong", "_debug_" + report.ATA.Model + ".bin",
|
||||
"read results", readBuf);
|
||||
|
||||
DicConsole.WriteLine("Trying READ LONG RETRY in LBA mode...");
|
||||
sense = dev.ReadLong(out readBuf, out errorLba, true, 0, report.ATA.ReadCapabilities.LongBlockSize, timeout, out duration);
|
||||
report.ATA.ReadCapabilities.SupportsReadLongRetryLba = (!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 && readBuf.Length > 0 && BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead);
|
||||
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
|
||||
sense, errorLba.status, errorLba.error, readBuf.Length);
|
||||
sense = dev.ReadLong(out readBuf, out errorLba, true, 0, report.ATA.ReadCapabilities.LongBlockSize,
|
||||
timeout, out duration);
|
||||
report.ATA.ReadCapabilities.SupportsReadLongRetryLba =
|
||||
(!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 && readBuf.Length > 0 &&
|
||||
BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead);
|
||||
DicConsole.DebugWriteLine("ATA Report",
|
||||
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense,
|
||||
errorLba.status, errorLba.error, readBuf.Length);
|
||||
if(debug)
|
||||
DataFile.WriteTo("ATA Report", "readlongretry", "_debug_" + report.ATA.Model + ".bin", "read results", readBuf);
|
||||
DataFile.WriteTo("ATA Report", "readlongretry", "_debug_" + report.ATA.Model + ".bin",
|
||||
"read results", readBuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -40,8 +40,7 @@ namespace DiscImageChef.Core.Devices.Report
|
||||
{
|
||||
public static void Report(Device dev, ref DeviceReport report, bool debug, ref bool removable)
|
||||
{
|
||||
if(report == null)
|
||||
return;
|
||||
if(report == null) return;
|
||||
|
||||
byte[] buffer;
|
||||
double duration;
|
||||
@@ -453,9 +452,8 @@ namespace DiscImageChef.Core.Devices.Report
|
||||
report.ATAPI.WRVSectorCountMode2 = atapiId.WRVSectorCountMode2;
|
||||
report.ATAPI.WRVSectorCountMode2Specified = true;
|
||||
}
|
||||
if(debug)
|
||||
report.ATAPI.Identify = buffer;
|
||||
if(debug) report.ATAPI.Identify = buffer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -41,8 +41,7 @@ namespace DiscImageChef.Core.Devices.Report
|
||||
{
|
||||
public static void Report(Device dev, ref DeviceReport report, bool debug, ref bool removable)
|
||||
{
|
||||
if(report == null)
|
||||
return;
|
||||
if(report == null) return;
|
||||
|
||||
ConsoleKeyInfo pressedKey = new ConsoleKeyInfo();
|
||||
while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N)
|
||||
@@ -73,4 +72,4 @@ namespace DiscImageChef.Core.Devices.Report
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -40,10 +40,9 @@ namespace DiscImageChef.Core.Devices.Report
|
||||
{
|
||||
public static void Report(Device dev, ref DeviceReport report, bool debug, ref bool removable)
|
||||
{
|
||||
if(report == null)
|
||||
return;
|
||||
if(report == null) return;
|
||||
|
||||
throw new NotImplementedException("NVMe devices not yet supported.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -75,4 +75,4 @@ namespace DiscImageChef.Core.Devices.Report
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -43,8 +43,7 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
{
|
||||
public static void Report(Device dev, ref DeviceReport report, bool debug, ref bool removable)
|
||||
{
|
||||
if(report == null)
|
||||
return;
|
||||
if(report == null) return;
|
||||
|
||||
byte[] senseBuffer;
|
||||
byte[] buffer;
|
||||
@@ -53,14 +52,11 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
uint timeout = 5;
|
||||
ConsoleKeyInfo pressedKey;
|
||||
|
||||
if(dev.IsUSB)
|
||||
USB.Report(dev, ref report, debug, ref removable);
|
||||
if(dev.IsUSB) USB.Report(dev, ref report, debug, ref removable);
|
||||
|
||||
if(dev.IsFireWire)
|
||||
FireWire.Report(dev, ref report, debug, ref removable);
|
||||
if(dev.IsFireWire) FireWire.Report(dev, ref report, debug, ref removable);
|
||||
|
||||
if(dev.IsPCMCIA)
|
||||
PCMCIA.Report(dev, ref report, debug, ref removable);
|
||||
if(dev.IsPCMCIA) PCMCIA.Report(dev, ref report, debug, ref removable);
|
||||
|
||||
if(!dev.IsUSB && !dev.IsFireWire && dev.IsRemovable)
|
||||
{
|
||||
@@ -75,8 +71,7 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
removable = pressedKey.Key == ConsoleKey.Y;
|
||||
}
|
||||
|
||||
if(dev.Type == DeviceType.ATAPI)
|
||||
ATAPI.Report(dev, ref report, debug, ref removable);
|
||||
if(dev.Type == DeviceType.ATAPI) ATAPI.Report(dev, ref report, debug, ref removable);
|
||||
|
||||
DicConsole.WriteLine("Querying SCSI INQUIRY...");
|
||||
sense = dev.ScsiInquiry(out buffer, out senseBuffer);
|
||||
@@ -117,19 +112,22 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
}
|
||||
if(!string.IsNullOrWhiteSpace(StringHandlers.CToString(inq.VendorIdentification)))
|
||||
{
|
||||
report.SCSI.Inquiry.VendorIdentification = StringHandlers.CToString(inq.VendorIdentification).Trim();
|
||||
report.SCSI.Inquiry.VendorIdentification =
|
||||
StringHandlers.CToString(inq.VendorIdentification).Trim();
|
||||
if(!string.IsNullOrWhiteSpace(report.SCSI.Inquiry.VendorIdentification))
|
||||
report.SCSI.Inquiry.VendorIdentificationSpecified = true;
|
||||
}
|
||||
if(!string.IsNullOrWhiteSpace(StringHandlers.CToString(inq.ProductIdentification)))
|
||||
{
|
||||
report.SCSI.Inquiry.ProductIdentification = StringHandlers.CToString(inq.ProductIdentification).Trim();
|
||||
report.SCSI.Inquiry.ProductIdentification =
|
||||
StringHandlers.CToString(inq.ProductIdentification).Trim();
|
||||
if(!string.IsNullOrWhiteSpace(report.SCSI.Inquiry.ProductIdentification))
|
||||
report.SCSI.Inquiry.ProductIdentificationSpecified = true;
|
||||
}
|
||||
if(!string.IsNullOrWhiteSpace(StringHandlers.CToString(inq.ProductRevisionLevel)))
|
||||
{
|
||||
report.SCSI.Inquiry.ProductRevisionLevel = StringHandlers.CToString(inq.ProductRevisionLevel).Trim();
|
||||
report.SCSI.Inquiry.ProductRevisionLevel =
|
||||
StringHandlers.CToString(inq.ProductRevisionLevel).Trim();
|
||||
if(!string.IsNullOrWhiteSpace(report.SCSI.Inquiry.ProductRevisionLevel))
|
||||
report.SCSI.Inquiry.ProductRevisionLevelSpecified = true;
|
||||
}
|
||||
@@ -137,8 +135,7 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
{
|
||||
foreach(ushort descriptor in inq.VersionDescriptors)
|
||||
{
|
||||
if(descriptor != 0)
|
||||
versionDescriptors.Add(descriptor);
|
||||
if(descriptor != 0) versionDescriptors.Add(descriptor);
|
||||
}
|
||||
|
||||
if(versionDescriptors.Count > 0)
|
||||
@@ -146,7 +143,8 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
}
|
||||
|
||||
report.SCSI.Inquiry.PeripheralQualifier = (Decoders.SCSI.PeripheralQualifiers)inq.PeripheralQualifier;
|
||||
report.SCSI.Inquiry.PeripheralDeviceType = (Decoders.SCSI.PeripheralDeviceTypes)inq.PeripheralDeviceType;
|
||||
report.SCSI.Inquiry.PeripheralDeviceType =
|
||||
(Decoders.SCSI.PeripheralDeviceTypes)inq.PeripheralDeviceType;
|
||||
report.SCSI.Inquiry.AsymmetricalLUNAccess = (Decoders.SCSI.TGPSValues)inq.TPGS;
|
||||
report.SCSI.Inquiry.SPIClocking = (Decoders.SCSI.SPIClocking)inq.Clocking;
|
||||
|
||||
@@ -177,8 +175,7 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
report.SCSI.Inquiry.WideBus16 = inq.WBus16;
|
||||
report.SCSI.Inquiry.WideBus32 = inq.WBus32;
|
||||
|
||||
if(debug)
|
||||
report.SCSI.Inquiry.Data = buffer;
|
||||
if(debug) report.SCSI.Inquiry.Data = buffer;
|
||||
}
|
||||
|
||||
DicConsole.WriteLine("Querying list of SCSI EVPDs...");
|
||||
@@ -205,8 +202,8 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
}
|
||||
}
|
||||
}
|
||||
if(evpds.Count > 0)
|
||||
report.SCSI.EVPDPages = evpds.ToArray();
|
||||
|
||||
if(evpds.Count > 0) report.SCSI.EVPDPages = evpds.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,11 +228,13 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
Decoders.SCSI.PeripheralDeviceTypes devType = dev.SCSIType;
|
||||
|
||||
DicConsole.WriteLine("Querying all mode pages and subpages using SCSI MODE SENSE (10)...");
|
||||
sense = dev.ModeSense10(out byte[] mode10Buffer, out senseBuffer, false, true, ScsiModeSensePageControl.Default, 0x3F, 0xFF, timeout, out duration);
|
||||
sense = dev.ModeSense10(out byte[] mode10Buffer, out senseBuffer, false, true,
|
||||
ScsiModeSensePageControl.Default, 0x3F, 0xFF, timeout, out duration);
|
||||
if(sense || dev.Error)
|
||||
{
|
||||
DicConsole.WriteLine("Querying all mode pages using SCSI MODE SENSE (10)...");
|
||||
sense = dev.ModeSense10(out mode10Buffer, out senseBuffer, false, true, ScsiModeSensePageControl.Default, 0x3F, 0x00, timeout, out duration);
|
||||
sense = dev.ModeSense10(out mode10Buffer, out senseBuffer, false, true,
|
||||
ScsiModeSensePageControl.Default, 0x3F, 0x00, timeout, out duration);
|
||||
if(!sense && !dev.Error)
|
||||
{
|
||||
report.SCSI.SupportsModeSense10 = true;
|
||||
@@ -251,19 +250,20 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
}
|
||||
|
||||
DicConsole.WriteLine("Querying all mode pages and subpages using SCSI MODE SENSE (6)...");
|
||||
sense = dev.ModeSense6(out byte[] mode6Buffer, out senseBuffer, false, ScsiModeSensePageControl.Default, 0x3F, 0xFF, timeout, out duration);
|
||||
sense = dev.ModeSense6(out byte[] mode6Buffer, out senseBuffer, false, ScsiModeSensePageControl.Default,
|
||||
0x3F, 0xFF, timeout, out duration);
|
||||
if(sense || dev.Error)
|
||||
{
|
||||
DicConsole.WriteLine("Querying all mode pages using SCSI MODE SENSE (6)...");
|
||||
sense = dev.ModeSense6(out mode6Buffer, out senseBuffer, false, ScsiModeSensePageControl.Default, 0x3F, 0x00, timeout, out duration);
|
||||
sense = dev.ModeSense6(out mode6Buffer, out senseBuffer, false, ScsiModeSensePageControl.Default, 0x3F,
|
||||
0x00, timeout, out duration);
|
||||
if(sense || dev.Error)
|
||||
{
|
||||
DicConsole.WriteLine("Querying SCSI MODE SENSE (6)...");
|
||||
sense = dev.ModeSense(out mode6Buffer, out senseBuffer, timeout, out duration);
|
||||
}
|
||||
}
|
||||
else
|
||||
report.SCSI.SupportsModeSubpages = true;
|
||||
else report.SCSI.SupportsModeSubpages = true;
|
||||
|
||||
if(!sense && !dev.Error && !decMode.HasValue)
|
||||
decMode = Decoders.SCSI.Modes.DecodeMode6(mode6Buffer, devType);
|
||||
@@ -272,10 +272,8 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
|
||||
Decoders.SCSI.Modes.ModePage_2A? cdromMode = null;
|
||||
|
||||
if(debug && report.SCSI.SupportsModeSense6)
|
||||
report.SCSI.ModeSense6Data = mode6Buffer;
|
||||
if(debug && report.SCSI.SupportsModeSense10)
|
||||
report.SCSI.ModeSense10Data = mode10Buffer;
|
||||
if(debug && report.SCSI.SupportsModeSense6) report.SCSI.ModeSense6Data = mode6Buffer;
|
||||
if(debug && report.SCSI.SupportsModeSense10) report.SCSI.ModeSense10Data = mode10Buffer;
|
||||
|
||||
if(decMode.HasValue)
|
||||
{
|
||||
@@ -313,8 +311,7 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
}
|
||||
}
|
||||
|
||||
if(modePages.Count > 0)
|
||||
report.SCSI.ModeSense.ModePages = modePages.ToArray();
|
||||
if(modePages.Count > 0) report.SCSI.ModeSense.ModePages = modePages.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -372,8 +369,7 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
DicConsole.Write("\rWaiting for drive to become ready");
|
||||
System.Threading.Thread.Sleep(2000);
|
||||
sense = dev.ScsiTestUnitReady(out senseBuffer, timeout, out duration);
|
||||
if(!sense)
|
||||
break;
|
||||
if(!sense) break;
|
||||
|
||||
leftRetries--;
|
||||
}
|
||||
@@ -388,19 +384,16 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
DicConsole.Write("\rWaiting for drive to become ready");
|
||||
System.Threading.Thread.Sleep(2000);
|
||||
sense = dev.ScsiTestUnitReady(out senseBuffer, timeout, out duration);
|
||||
if(!sense)
|
||||
break;
|
||||
if(!sense) break;
|
||||
|
||||
leftRetries--;
|
||||
}
|
||||
|
||||
mediaTest.MediaIsRecognized &= !sense;
|
||||
}
|
||||
else
|
||||
mediaTest.MediaIsRecognized = false;
|
||||
else mediaTest.MediaIsRecognized = false;
|
||||
}
|
||||
else
|
||||
mediaTest.MediaIsRecognized = false;
|
||||
else mediaTest.MediaIsRecognized = false;
|
||||
}
|
||||
|
||||
if(mediaTest.MediaIsRecognized)
|
||||
@@ -413,8 +406,11 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
if(!sense && !dev.Error)
|
||||
{
|
||||
mediaTest.SupportsReadCapacity = true;
|
||||
mediaTest.Blocks = (ulong)((buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + (buffer[3])) + 1;
|
||||
mediaTest.BlockSize = (uint)((buffer[4] << 24) + (buffer[5] << 16) + (buffer[6] << 8) + (buffer[7]));
|
||||
mediaTest.Blocks =
|
||||
(ulong)((buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) +
|
||||
(buffer[3])) + 1;
|
||||
mediaTest.BlockSize =
|
||||
(uint)((buffer[4] << 24) + (buffer[5] << 16) + (buffer[6] << 8) + (buffer[7]));
|
||||
mediaTest.BlocksSpecified = true;
|
||||
mediaTest.BlockSizeSpecified = true;
|
||||
}
|
||||
@@ -428,7 +424,9 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
Array.Copy(buffer, 0, temp, 0, 8);
|
||||
Array.Reverse(temp);
|
||||
mediaTest.Blocks = BitConverter.ToUInt64(temp, 0) + 1;
|
||||
mediaTest.BlockSize = (uint)((buffer[8] << 24) + (buffer[9] << 16) + (buffer[10] << 8) + (buffer[11]));
|
||||
mediaTest.BlockSize =
|
||||
(uint)((buffer[8] << 24) + (buffer[9] << 16) + (buffer[10] << 8) +
|
||||
(buffer[11]));
|
||||
mediaTest.BlocksSpecified = true;
|
||||
mediaTest.BlockSizeSpecified = true;
|
||||
}
|
||||
@@ -436,13 +434,14 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
decMode = null;
|
||||
|
||||
DicConsole.WriteLine("Querying SCSI MODE SENSE (10)...");
|
||||
sense = dev.ModeSense10(out buffer, out senseBuffer, false, true, ScsiModeSensePageControl.Current, 0x3F, 0x00, timeout, out duration);
|
||||
sense = dev.ModeSense10(out buffer, out senseBuffer, false, true,
|
||||
ScsiModeSensePageControl.Current, 0x3F, 0x00, timeout,
|
||||
out duration);
|
||||
if(!sense && !dev.Error)
|
||||
{
|
||||
report.SCSI.SupportsModeSense10 = true;
|
||||
decMode = Decoders.SCSI.Modes.DecodeMode10(buffer, dev.SCSIType);
|
||||
if(debug)
|
||||
mediaTest.ModeSense10Data = buffer;
|
||||
if(debug) mediaTest.ModeSense10Data = buffer;
|
||||
}
|
||||
|
||||
DicConsole.WriteLine("Querying SCSI MODE SENSE...");
|
||||
@@ -452,15 +451,15 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
report.SCSI.SupportsModeSense6 = true;
|
||||
if(!decMode.HasValue)
|
||||
decMode = Decoders.SCSI.Modes.DecodeMode6(buffer, dev.SCSIType);
|
||||
if(debug)
|
||||
mediaTest.ModeSense6Data = buffer;
|
||||
if(debug) mediaTest.ModeSense6Data = buffer;
|
||||
}
|
||||
|
||||
if(decMode.HasValue)
|
||||
{
|
||||
mediaTest.MediumType = (byte)decMode.Value.Header.MediumType;
|
||||
mediaTest.MediumTypeSpecified = true;
|
||||
if(decMode.Value.Header.BlockDescriptors != null && decMode.Value.Header.BlockDescriptors.Length > 0)
|
||||
if(decMode.Value.Header.BlockDescriptors != null &&
|
||||
decMode.Value.Header.BlockDescriptors.Length > 0)
|
||||
{
|
||||
mediaTest.Density = (byte)decMode.Value.Header.BlockDescriptors[0].Density;
|
||||
mediaTest.DensitySpecified = true;
|
||||
@@ -474,44 +473,61 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
mediaTest.SupportsReadLongSpecified = true;
|
||||
|
||||
DicConsole.WriteLine("Trying SCSI READ (6)...");
|
||||
mediaTest.SupportsRead = !dev.Read6(out buffer, out senseBuffer, 0, mediaTest.BlockSize, timeout, out duration);
|
||||
mediaTest.SupportsRead = !dev.Read6(out buffer, out senseBuffer, 0, mediaTest.BlockSize,
|
||||
timeout, out duration);
|
||||
DicConsole.DebugWriteLine("SCSI Report", "Sense = {0}", !mediaTest.SupportsRead);
|
||||
if(debug)
|
||||
DataFile.WriteTo("SCSI Report", "read6", "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", buffer);
|
||||
DataFile.WriteTo("SCSI Report", "read6",
|
||||
"_debug_" + mediaTest.MediumTypeName + ".bin", "read results",
|
||||
buffer);
|
||||
|
||||
DicConsole.WriteLine("Trying SCSI READ (10)...");
|
||||
mediaTest.SupportsRead10 = !dev.Read10(out buffer, out senseBuffer, 0, false, true, false, false, 0, mediaTest.BlockSize, 0, 1, timeout, out duration);
|
||||
mediaTest.SupportsRead10 =
|
||||
!dev.Read10(out buffer, out senseBuffer, 0, false, true, false, false, 0,
|
||||
mediaTest.BlockSize, 0, 1, timeout, out duration);
|
||||
DicConsole.DebugWriteLine("SCSI Report", "Sense = {0}", !mediaTest.SupportsRead10);
|
||||
if(debug)
|
||||
DataFile.WriteTo("SCSI Report", "read10", "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", buffer);
|
||||
DataFile.WriteTo("SCSI Report", "read10",
|
||||
"_debug_" + mediaTest.MediumTypeName + ".bin", "read results",
|
||||
buffer);
|
||||
|
||||
DicConsole.WriteLine("Trying SCSI READ (12)...");
|
||||
mediaTest.SupportsRead12 = !dev.Read12(out buffer, out senseBuffer, 0, false, true, false, false, 0, mediaTest.BlockSize, 0, 1, false, timeout, out duration);
|
||||
mediaTest.SupportsRead12 =
|
||||
!dev.Read12(out buffer, out senseBuffer, 0, false, true, false, false, 0,
|
||||
mediaTest.BlockSize, 0, 1, false, timeout, out duration);
|
||||
DicConsole.DebugWriteLine("SCSI Report", "Sense = {0}", !mediaTest.SupportsRead12);
|
||||
if(debug)
|
||||
DataFile.WriteTo("SCSI Report", "read12", "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", buffer);
|
||||
DataFile.WriteTo("SCSI Report", "read12",
|
||||
"_debug_" + mediaTest.MediumTypeName + ".bin", "read results",
|
||||
buffer);
|
||||
|
||||
DicConsole.WriteLine("Trying SCSI READ (16)...");
|
||||
mediaTest.SupportsRead16 = !dev.Read16(out buffer, out senseBuffer, 0, false, true, false, 0, mediaTest.BlockSize, 0, 1, false, timeout, out duration);
|
||||
mediaTest.SupportsRead16 =
|
||||
!dev.Read16(out buffer, out senseBuffer, 0, false, true, false, 0,
|
||||
mediaTest.BlockSize, 0, 1, false, timeout, out duration);
|
||||
DicConsole.DebugWriteLine("SCSI Report", "Sense = {0}", !mediaTest.SupportsRead16);
|
||||
if(debug)
|
||||
DataFile.WriteTo("SCSI Report", "read16", "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", buffer);
|
||||
DataFile.WriteTo("SCSI Report", "read16",
|
||||
"_debug_" + mediaTest.MediumTypeName + ".bin", "read results",
|
||||
buffer);
|
||||
|
||||
mediaTest.LongBlockSize = mediaTest.BlockSize;
|
||||
DicConsole.WriteLine("Trying SCSI READ LONG (10)...");
|
||||
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 0xFFFF, timeout, out duration);
|
||||
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 0xFFFF, timeout,
|
||||
out duration);
|
||||
if(sense && !dev.Error)
|
||||
{
|
||||
Decoders.SCSI.FixedSense? decSense = Decoders.SCSI.Sense.DecodeFixed(senseBuffer);
|
||||
if(decSense.HasValue)
|
||||
{
|
||||
if(decSense.Value.SenseKey == Decoders.SCSI.SenseKeys.IllegalRequest &&
|
||||
decSense.Value.ASC == 0x24 && decSense.Value.ASCQ == 0x00)
|
||||
decSense.Value.ASC == 0x24 && decSense.Value.ASCQ == 0x00)
|
||||
{
|
||||
mediaTest.SupportsReadLong = true;
|
||||
if(decSense.Value.InformationValid && decSense.Value.ILI)
|
||||
{
|
||||
mediaTest.LongBlockSize = 0xFFFF - (decSense.Value.Information & 0xFFFF);
|
||||
mediaTest.LongBlockSize =
|
||||
0xFFFF - (decSense.Value.Information & 0xFFFF);
|
||||
mediaTest.LongBlockSizeSpecified = true;
|
||||
}
|
||||
}
|
||||
@@ -522,15 +538,18 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
{
|
||||
if(mediaTest.BlockSize == 512)
|
||||
{
|
||||
foreach(ushort testSize in new[] {
|
||||
foreach(ushort testSize in new[]
|
||||
{
|
||||
// Long sector sizes for floppies
|
||||
514,
|
||||
// Long sector sizes for SuperDisk
|
||||
536, 558,
|
||||
// Long sector sizes for 512-byte magneto-opticals
|
||||
600, 610, 630 })
|
||||
600, 610, 630
|
||||
})
|
||||
{
|
||||
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, testSize, timeout, out duration);
|
||||
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0,
|
||||
testSize, timeout, out duration);
|
||||
if(!sense && !dev.Error)
|
||||
{
|
||||
mediaTest.SupportsReadLong = true;
|
||||
@@ -542,13 +561,16 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
}
|
||||
else if(mediaTest.BlockSize == 1024)
|
||||
{
|
||||
foreach(ushort testSize in new[] {
|
||||
foreach(ushort testSize in new[]
|
||||
{
|
||||
// Long sector sizes for floppies
|
||||
1026,
|
||||
// Long sector sizes for 1024-byte magneto-opticals
|
||||
1200 })
|
||||
1200
|
||||
})
|
||||
{
|
||||
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, testSize, timeout, out duration);
|
||||
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0,
|
||||
testSize, timeout, out duration);
|
||||
if(!sense && !dev.Error)
|
||||
{
|
||||
mediaTest.SupportsReadLong = true;
|
||||
@@ -560,7 +582,8 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
}
|
||||
else if(mediaTest.BlockSize == 2048)
|
||||
{
|
||||
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 2380, timeout, out duration);
|
||||
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 2380,
|
||||
timeout, out duration);
|
||||
if(!sense && !dev.Error)
|
||||
{
|
||||
mediaTest.SupportsReadLong = true;
|
||||
@@ -570,7 +593,8 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
}
|
||||
else if(mediaTest.BlockSize == 4096)
|
||||
{
|
||||
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 4760, timeout, out duration);
|
||||
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 4760,
|
||||
timeout, out duration);
|
||||
if(!sense && !dev.Error)
|
||||
{
|
||||
mediaTest.SupportsReadLong = true;
|
||||
@@ -580,7 +604,8 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
}
|
||||
else if(mediaTest.BlockSize == 8192)
|
||||
{
|
||||
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 9424, timeout, out duration);
|
||||
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 9424,
|
||||
timeout, out duration);
|
||||
if(!sense && !dev.Error)
|
||||
{
|
||||
mediaTest.SupportsReadLong = true;
|
||||
@@ -595,7 +620,8 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
pressedKey = new ConsoleKeyInfo();
|
||||
while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N)
|
||||
{
|
||||
DicConsole.Write("Drive supports SCSI READ LONG but I cannot find the correct size. Do you want me to try? (This can take hours) (Y/N): ");
|
||||
DicConsole
|
||||
.Write("Drive supports SCSI READ LONG but I cannot find the correct size. Do you want me to try? (This can take hours) (Y/N): ");
|
||||
pressedKey = System.Console.ReadKey();
|
||||
DicConsole.WriteLine();
|
||||
}
|
||||
@@ -605,7 +631,8 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
for(ushort i = (ushort)mediaTest.BlockSize; i <= ushort.MaxValue; i++)
|
||||
{
|
||||
DicConsole.Write("\rTrying to READ LONG with a size of {0} bytes...", i);
|
||||
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, i, timeout, out duration);
|
||||
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, i,
|
||||
timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
mediaTest.LongBlockSize = i;
|
||||
@@ -613,27 +640,34 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
break;
|
||||
}
|
||||
|
||||
if(i == ushort.MaxValue)
|
||||
break;
|
||||
if(i == ushort.MaxValue) break;
|
||||
}
|
||||
|
||||
DicConsole.WriteLine();
|
||||
}
|
||||
}
|
||||
|
||||
if(debug && mediaTest.SupportsReadLong && mediaTest.LongBlockSizeSpecified && mediaTest.LongBlockSize != mediaTest.BlockSize)
|
||||
if(debug && mediaTest.SupportsReadLong && mediaTest.LongBlockSizeSpecified &&
|
||||
mediaTest.LongBlockSize != mediaTest.BlockSize)
|
||||
{
|
||||
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, (ushort)mediaTest.LongBlockSize, timeout, out duration);
|
||||
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0,
|
||||
(ushort)mediaTest.LongBlockSize, timeout, out duration);
|
||||
if(!sense)
|
||||
DataFile.WriteTo("SCSI Report", "readlong10", "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", buffer);
|
||||
DataFile.WriteTo("SCSI Report", "readlong10",
|
||||
"_debug_" + mediaTest.MediumTypeName + ".bin", "read results",
|
||||
buffer);
|
||||
}
|
||||
|
||||
mediaTest.CanReadMediaSerialSpecified = true;
|
||||
DicConsole.WriteLine("Trying SCSI READ MEDIA SERIAL NUMBER...");
|
||||
mediaTest.CanReadMediaSerial = !dev.ReadMediaSerialNumber(out buffer, out senseBuffer, timeout, out duration);
|
||||
mediaTest.CanReadMediaSerial =
|
||||
!dev.ReadMediaSerialNumber(out buffer, out senseBuffer, timeout, out duration);
|
||||
}
|
||||
|
||||
mediaTests.Add(mediaTest);
|
||||
}
|
||||
}
|
||||
|
||||
report.SCSI.RemovableMedias = mediaTests.ToArray();
|
||||
}
|
||||
else
|
||||
@@ -650,8 +684,10 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
if(!sense && !dev.Error)
|
||||
{
|
||||
report.SCSI.ReadCapabilities.SupportsReadCapacity = true;
|
||||
report.SCSI.ReadCapabilities.Blocks = (ulong)((buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + (buffer[3])) + 1;
|
||||
report.SCSI.ReadCapabilities.BlockSize = (uint)((buffer[4] << 24) + (buffer[5] << 16) + (buffer[6] << 8) + (buffer[7]));
|
||||
report.SCSI.ReadCapabilities.Blocks =
|
||||
(ulong)((buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + (buffer[3])) + 1;
|
||||
report.SCSI.ReadCapabilities.BlockSize =
|
||||
(uint)((buffer[4] << 24) + (buffer[5] << 16) + (buffer[6] << 8) + (buffer[7]));
|
||||
report.SCSI.ReadCapabilities.BlocksSpecified = true;
|
||||
report.SCSI.ReadCapabilities.BlockSizeSpecified = true;
|
||||
}
|
||||
@@ -665,7 +701,8 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
Array.Copy(buffer, 0, temp, 0, 8);
|
||||
Array.Reverse(temp);
|
||||
report.SCSI.ReadCapabilities.Blocks = BitConverter.ToUInt64(temp, 0) + 1;
|
||||
report.SCSI.ReadCapabilities.BlockSize = (uint)((buffer[8] << 24) + (buffer[9] << 16) + (buffer[10] << 8) + (buffer[11]));
|
||||
report.SCSI.ReadCapabilities.BlockSize =
|
||||
(uint)((buffer[8] << 24) + (buffer[9] << 16) + (buffer[10] << 8) + (buffer[11]));
|
||||
report.SCSI.ReadCapabilities.BlocksSpecified = true;
|
||||
report.SCSI.ReadCapabilities.BlockSizeSpecified = true;
|
||||
}
|
||||
@@ -673,13 +710,13 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
decMode = null;
|
||||
|
||||
DicConsole.WriteLine("Querying SCSI MODE SENSE (10)...");
|
||||
sense = dev.ModeSense10(out buffer, out senseBuffer, false, true, ScsiModeSensePageControl.Current, 0x3F, 0x00, timeout, out duration);
|
||||
sense = dev.ModeSense10(out buffer, out senseBuffer, false, true, ScsiModeSensePageControl.Current,
|
||||
0x3F, 0x00, timeout, out duration);
|
||||
if(!sense && !dev.Error)
|
||||
{
|
||||
report.SCSI.SupportsModeSense10 = true;
|
||||
decMode = Decoders.SCSI.Modes.DecodeMode10(buffer, dev.SCSIType);
|
||||
if(debug)
|
||||
report.SCSI.ReadCapabilities.ModeSense10Data = buffer;
|
||||
if(debug) report.SCSI.ReadCapabilities.ModeSense10Data = buffer;
|
||||
}
|
||||
|
||||
DicConsole.WriteLine("Querying SCSI MODE SENSE...");
|
||||
@@ -687,19 +724,19 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
if(!sense && !dev.Error)
|
||||
{
|
||||
report.SCSI.SupportsModeSense6 = true;
|
||||
if(!decMode.HasValue)
|
||||
decMode = Decoders.SCSI.Modes.DecodeMode6(buffer, dev.SCSIType);
|
||||
if(debug)
|
||||
report.SCSI.ReadCapabilities.ModeSense6Data = buffer;
|
||||
if(!decMode.HasValue) decMode = Decoders.SCSI.Modes.DecodeMode6(buffer, dev.SCSIType);
|
||||
if(debug) report.SCSI.ReadCapabilities.ModeSense6Data = buffer;
|
||||
}
|
||||
|
||||
if(decMode.HasValue)
|
||||
{
|
||||
report.SCSI.ReadCapabilities.MediumType = (byte)decMode.Value.Header.MediumType;
|
||||
report.SCSI.ReadCapabilities.MediumTypeSpecified = true;
|
||||
if(decMode.Value.Header.BlockDescriptors != null && decMode.Value.Header.BlockDescriptors.Length > 0)
|
||||
if(decMode.Value.Header.BlockDescriptors != null &&
|
||||
decMode.Value.Header.BlockDescriptors.Length > 0)
|
||||
{
|
||||
report.SCSI.ReadCapabilities.Density = (byte)decMode.Value.Header.BlockDescriptors[0].Density;
|
||||
report.SCSI.ReadCapabilities.Density =
|
||||
(byte)decMode.Value.Header.BlockDescriptors[0].Density;
|
||||
report.SCSI.ReadCapabilities.DensitySpecified = true;
|
||||
}
|
||||
}
|
||||
@@ -711,28 +748,47 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
report.SCSI.ReadCapabilities.SupportsReadLongSpecified = true;
|
||||
|
||||
DicConsole.WriteLine("Trying SCSI READ (6)...");
|
||||
report.SCSI.ReadCapabilities.SupportsRead = !dev.Read6(out buffer, out senseBuffer, 0, report.SCSI.ReadCapabilities.BlockSize, timeout, out duration);
|
||||
report.SCSI.ReadCapabilities.SupportsRead = !dev.Read6(out buffer, out senseBuffer, 0,
|
||||
report.SCSI.ReadCapabilities.BlockSize,
|
||||
timeout, out duration);
|
||||
DicConsole.DebugWriteLine("SCSI Report", "Sense = {0}", !report.SCSI.ReadCapabilities.SupportsRead);
|
||||
if(debug)
|
||||
DataFile.WriteTo("SCSI Report", "read6", "_debug_" + report.SCSI.Inquiry.ProductIdentification + ".bin", "read results", buffer);
|
||||
|
||||
DataFile.WriteTo("SCSI Report", "read6",
|
||||
"_debug_" + report.SCSI.Inquiry.ProductIdentification + ".bin", "read results",
|
||||
buffer);
|
||||
|
||||
DicConsole.WriteLine("Trying SCSI READ (10)...");
|
||||
report.SCSI.ReadCapabilities.SupportsRead10 = !dev.Read10(out buffer, out senseBuffer, 0, false, true, false, false, 0, report.SCSI.ReadCapabilities.BlockSize, 0, 1, timeout, out duration);
|
||||
DicConsole.DebugWriteLine("SCSI Report", "Sense = {0}", !report.SCSI.ReadCapabilities.SupportsRead10);
|
||||
report.SCSI.ReadCapabilities.SupportsRead10 =
|
||||
!dev.Read10(out buffer, out senseBuffer, 0, false, true, false, false, 0,
|
||||
report.SCSI.ReadCapabilities.BlockSize, 0, 1, timeout, out duration);
|
||||
DicConsole.DebugWriteLine("SCSI Report", "Sense = {0}",
|
||||
!report.SCSI.ReadCapabilities.SupportsRead10);
|
||||
if(debug)
|
||||
DataFile.WriteTo("SCSI Report", "read10", "_debug_" + report.SCSI.Inquiry.ProductIdentification + ".bin", "read results", buffer);
|
||||
DataFile.WriteTo("SCSI Report", "read10",
|
||||
"_debug_" + report.SCSI.Inquiry.ProductIdentification + ".bin", "read results",
|
||||
buffer);
|
||||
|
||||
DicConsole.WriteLine("Trying SCSI READ (12)...");
|
||||
report.SCSI.ReadCapabilities.SupportsRead12 = !dev.Read12(out buffer, out senseBuffer, 0, false, true, false, false, 0, report.SCSI.ReadCapabilities.BlockSize, 0, 1, false, timeout, out duration);
|
||||
DicConsole.DebugWriteLine("SCSI Report", "Sense = {0}", !report.SCSI.ReadCapabilities.SupportsRead12);
|
||||
report.SCSI.ReadCapabilities.SupportsRead12 =
|
||||
!dev.Read12(out buffer, out senseBuffer, 0, false, true, false, false, 0,
|
||||
report.SCSI.ReadCapabilities.BlockSize, 0, 1, false, timeout, out duration);
|
||||
DicConsole.DebugWriteLine("SCSI Report", "Sense = {0}",
|
||||
!report.SCSI.ReadCapabilities.SupportsRead12);
|
||||
if(debug)
|
||||
DataFile.WriteTo("SCSI Report", "read12", "_debug_" + report.SCSI.Inquiry.ProductIdentification + ".bin", "read results", buffer);
|
||||
DataFile.WriteTo("SCSI Report", "read12",
|
||||
"_debug_" + report.SCSI.Inquiry.ProductIdentification + ".bin", "read results",
|
||||
buffer);
|
||||
|
||||
DicConsole.WriteLine("Trying SCSI READ (16)...");
|
||||
report.SCSI.ReadCapabilities.SupportsRead16 = !dev.Read16(out buffer, out senseBuffer, 0, false, true, false, 0, report.SCSI.ReadCapabilities.BlockSize, 0, 1, false, timeout, out duration);
|
||||
DicConsole.DebugWriteLine("SCSI Report", "Sense = {0}", !report.SCSI.ReadCapabilities.SupportsRead16);
|
||||
report.SCSI.ReadCapabilities.SupportsRead16 =
|
||||
!dev.Read16(out buffer, out senseBuffer, 0, false, true, false, 0,
|
||||
report.SCSI.ReadCapabilities.BlockSize, 0, 1, false, timeout, out duration);
|
||||
DicConsole.DebugWriteLine("SCSI Report", "Sense = {0}",
|
||||
!report.SCSI.ReadCapabilities.SupportsRead16);
|
||||
if(debug)
|
||||
DataFile.WriteTo("SCSI Report", "read16", "_debug_" + report.SCSI.Inquiry.ProductIdentification + ".bin", "read results", buffer);
|
||||
DataFile.WriteTo("SCSI Report", "read16",
|
||||
"_debug_" + report.SCSI.Inquiry.ProductIdentification + ".bin", "read results",
|
||||
buffer);
|
||||
|
||||
report.SCSI.ReadCapabilities.LongBlockSize = report.SCSI.ReadCapabilities.BlockSize;
|
||||
DicConsole.WriteLine("Trying SCSI READ LONG (10)...");
|
||||
@@ -743,19 +799,21 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
if(decSense.HasValue)
|
||||
{
|
||||
if(decSense.Value.SenseKey == Decoders.SCSI.SenseKeys.IllegalRequest &&
|
||||
decSense.Value.ASC == 0x24 && decSense.Value.ASCQ == 0x00)
|
||||
decSense.Value.ASC == 0x24 && decSense.Value.ASCQ == 0x00)
|
||||
{
|
||||
report.SCSI.ReadCapabilities.SupportsReadLong = true;
|
||||
if(decSense.Value.InformationValid && decSense.Value.ILI)
|
||||
{
|
||||
report.SCSI.ReadCapabilities.LongBlockSize = 0xFFFF - (decSense.Value.Information & 0xFFFF);
|
||||
report.SCSI.ReadCapabilities.LongBlockSize =
|
||||
0xFFFF - (decSense.Value.Information & 0xFFFF);
|
||||
report.SCSI.ReadCapabilities.LongBlockSizeSpecified = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(report.SCSI.ReadCapabilities.SupportsReadLong && report.SCSI.ReadCapabilities.LongBlockSize == report.SCSI.ReadCapabilities.BlockSize)
|
||||
if(report.SCSI.ReadCapabilities.SupportsReadLong && report.SCSI.ReadCapabilities.LongBlockSize ==
|
||||
report.SCSI.ReadCapabilities.BlockSize)
|
||||
{
|
||||
if(report.SCSI.ReadCapabilities.BlockSize == 512)
|
||||
{
|
||||
@@ -803,7 +861,8 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
}
|
||||
else if(report.SCSI.ReadCapabilities.BlockSize == 2048)
|
||||
{
|
||||
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 2380, timeout, out duration);
|
||||
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 2380, timeout,
|
||||
out duration);
|
||||
if(!sense && !dev.Error)
|
||||
{
|
||||
report.SCSI.ReadCapabilities.SupportsReadLong = true;
|
||||
@@ -813,7 +872,8 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
}
|
||||
else if(report.SCSI.ReadCapabilities.BlockSize == 4096)
|
||||
{
|
||||
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 4760, timeout, out duration);
|
||||
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 4760, timeout,
|
||||
out duration);
|
||||
if(!sense && !dev.Error)
|
||||
{
|
||||
report.SCSI.ReadCapabilities.SupportsReadLong = true;
|
||||
@@ -823,7 +883,8 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
}
|
||||
else if(report.SCSI.ReadCapabilities.BlockSize == 8192)
|
||||
{
|
||||
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 9424, timeout, out duration);
|
||||
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 9424, timeout,
|
||||
out duration);
|
||||
if(!sense && !dev.Error)
|
||||
{
|
||||
report.SCSI.ReadCapabilities.SupportsReadLong = true;
|
||||
@@ -833,12 +894,14 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
}
|
||||
}
|
||||
|
||||
if(report.SCSI.ReadCapabilities.SupportsReadLong && report.SCSI.ReadCapabilities.LongBlockSize == report.SCSI.ReadCapabilities.BlockSize)
|
||||
if(report.SCSI.ReadCapabilities.SupportsReadLong && report.SCSI.ReadCapabilities.LongBlockSize ==
|
||||
report.SCSI.ReadCapabilities.BlockSize)
|
||||
{
|
||||
pressedKey = new ConsoleKeyInfo();
|
||||
while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N)
|
||||
{
|
||||
DicConsole.Write("Drive supports SCSI READ LONG but I cannot find the correct size. Do you want me to try? (This can take hours) (Y/N): ");
|
||||
DicConsole
|
||||
.Write("Drive supports SCSI READ LONG but I cannot find the correct size. Do you want me to try? (This can take hours) (Y/N): ");
|
||||
pressedKey = System.Console.ReadKey();
|
||||
DicConsole.WriteLine();
|
||||
}
|
||||
@@ -848,12 +911,15 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
for(ushort i = (ushort)report.SCSI.ReadCapabilities.BlockSize; i <= ushort.MaxValue; i++)
|
||||
{
|
||||
DicConsole.Write("\rTrying to READ LONG with a size of {0} bytes...", i);
|
||||
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, i, timeout, out duration);
|
||||
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, i, timeout,
|
||||
out duration);
|
||||
if(!sense)
|
||||
{
|
||||
if(debug)
|
||||
{
|
||||
FileStream bingo = new FileStream(string.Format("{0}_readlong.bin", dev.Model), FileMode.Create);
|
||||
FileStream bingo =
|
||||
new FileStream(string.Format("{0}_readlong.bin", dev.Model),
|
||||
FileMode.Create);
|
||||
bingo.Write(buffer, 0, buffer.Length);
|
||||
bingo.Close();
|
||||
}
|
||||
@@ -862,21 +928,27 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
break;
|
||||
}
|
||||
|
||||
if(i == ushort.MaxValue)
|
||||
break;
|
||||
if(i == ushort.MaxValue) break;
|
||||
}
|
||||
|
||||
DicConsole.WriteLine();
|
||||
}
|
||||
}
|
||||
|
||||
if(debug && report.SCSI.ReadCapabilities.SupportsReadLong && report.SCSI.ReadCapabilities.LongBlockSizeSpecified && report.SCSI.ReadCapabilities.LongBlockSize != report.SCSI.ReadCapabilities.BlockSize)
|
||||
if(debug && report.SCSI.ReadCapabilities.SupportsReadLong &&
|
||||
report.SCSI.ReadCapabilities.LongBlockSizeSpecified &&
|
||||
report.SCSI.ReadCapabilities.LongBlockSize != report.SCSI.ReadCapabilities.BlockSize)
|
||||
{
|
||||
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, (ushort)report.SCSI.ReadCapabilities.LongBlockSize, timeout, out duration);
|
||||
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0,
|
||||
(ushort)report.SCSI.ReadCapabilities.LongBlockSize, timeout,
|
||||
out duration);
|
||||
if(!sense)
|
||||
DataFile.WriteTo("SCSI Report", "readlong10", "_debug_" + report.SCSI.Inquiry.ProductIdentification + ".bin", "read results", buffer);
|
||||
DataFile.WriteTo("SCSI Report", "readlong10",
|
||||
"_debug_" + report.SCSI.Inquiry.ProductIdentification + ".bin",
|
||||
"read results", buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -42,8 +42,7 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
{
|
||||
internal static void Report(Device dev, ref DeviceReport report, bool debug)
|
||||
{
|
||||
if(report == null)
|
||||
return;
|
||||
if(report == null) return;
|
||||
|
||||
byte[] senseBuffer;
|
||||
byte[] buffer;
|
||||
@@ -83,21 +82,29 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
sense = dev.ReportDensitySupport(out buffer, out senseBuffer, false, false, timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
Decoders.SCSI.SSC.DensitySupport.DensitySupportHeader? dsh = Decoders.SCSI.SSC.DensitySupport.DecodeDensity(buffer);
|
||||
Decoders.SCSI.SSC.DensitySupport.DensitySupportHeader? dsh =
|
||||
Decoders.SCSI.SSC.DensitySupport.DecodeDensity(buffer);
|
||||
if(dsh.HasValue)
|
||||
{
|
||||
report.SCSI.SequentialDevice.SupportedDensities = new SupportedDensity[dsh.Value.descriptors.Length];
|
||||
report.SCSI.SequentialDevice.SupportedDensities =
|
||||
new SupportedDensity[dsh.Value.descriptors.Length];
|
||||
for(int i = 0; i < dsh.Value.descriptors.Length; i++)
|
||||
{
|
||||
report.SCSI.SequentialDevice.SupportedDensities[i].BitsPerMm = dsh.Value.descriptors[i].bpmm;
|
||||
report.SCSI.SequentialDevice.SupportedDensities[i].Capacity = dsh.Value.descriptors[i].capacity;
|
||||
report.SCSI.SequentialDevice.SupportedDensities[i].DefaultDensity = dsh.Value.descriptors[i].defaultDensity;
|
||||
report.SCSI.SequentialDevice.SupportedDensities[i].Description = dsh.Value.descriptors[i].description;
|
||||
report.SCSI.SequentialDevice.SupportedDensities[i].Duplicate = dsh.Value.descriptors[i].duplicate;
|
||||
report.SCSI.SequentialDevice.SupportedDensities[i].DefaultDensity =
|
||||
dsh.Value.descriptors[i].defaultDensity;
|
||||
report.SCSI.SequentialDevice.SupportedDensities[i].Description =
|
||||
dsh.Value.descriptors[i].description;
|
||||
report.SCSI.SequentialDevice.SupportedDensities[i].Duplicate =
|
||||
dsh.Value.descriptors[i].duplicate;
|
||||
report.SCSI.SequentialDevice.SupportedDensities[i].Name = dsh.Value.descriptors[i].name;
|
||||
report.SCSI.SequentialDevice.SupportedDensities[i].Organization = dsh.Value.descriptors[i].organization;
|
||||
report.SCSI.SequentialDevice.SupportedDensities[i].PrimaryCode = dsh.Value.descriptors[i].primaryCode;
|
||||
report.SCSI.SequentialDevice.SupportedDensities[i].SecondaryCode = dsh.Value.descriptors[i].secondaryCode;
|
||||
report.SCSI.SequentialDevice.SupportedDensities[i].Organization =
|
||||
dsh.Value.descriptors[i].organization;
|
||||
report.SCSI.SequentialDevice.SupportedDensities[i].PrimaryCode =
|
||||
dsh.Value.descriptors[i].primaryCode;
|
||||
report.SCSI.SequentialDevice.SupportedDensities[i].SecondaryCode =
|
||||
dsh.Value.descriptors[i].secondaryCode;
|
||||
report.SCSI.SequentialDevice.SupportedDensities[i].Tracks = dsh.Value.descriptors[i].tracks;
|
||||
report.SCSI.SequentialDevice.SupportedDensities[i].Width = dsh.Value.descriptors[i].width;
|
||||
report.SCSI.SequentialDevice.SupportedDensities[i].Writable = dsh.Value.descriptors[i].writable;
|
||||
@@ -109,23 +116,30 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
sense = dev.ReportDensitySupport(out buffer, out senseBuffer, true, false, timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
Decoders.SCSI.SSC.DensitySupport.MediaTypeSupportHeader? mtsh = Decoders.SCSI.SSC.DensitySupport.DecodeMediumType(buffer);
|
||||
Decoders.SCSI.SSC.DensitySupport.MediaTypeSupportHeader? mtsh =
|
||||
Decoders.SCSI.SSC.DensitySupport.DecodeMediumType(buffer);
|
||||
if(mtsh.HasValue)
|
||||
{
|
||||
report.SCSI.SequentialDevice.SupportedMediaTypes = new SupportedMedia[mtsh.Value.descriptors.Length];
|
||||
report.SCSI.SequentialDevice.SupportedMediaTypes =
|
||||
new SupportedMedia[mtsh.Value.descriptors.Length];
|
||||
for(int i = 0; i < mtsh.Value.descriptors.Length; i++)
|
||||
{
|
||||
report.SCSI.SequentialDevice.SupportedMediaTypes[i].Description = mtsh.Value.descriptors[i].description;
|
||||
report.SCSI.SequentialDevice.SupportedMediaTypes[i].Description =
|
||||
mtsh.Value.descriptors[i].description;
|
||||
report.SCSI.SequentialDevice.SupportedMediaTypes[i].Length = mtsh.Value.descriptors[i].length;
|
||||
report.SCSI.SequentialDevice.SupportedMediaTypes[i].MediumType = mtsh.Value.descriptors[i].mediumType;
|
||||
report.SCSI.SequentialDevice.SupportedMediaTypes[i].MediumType =
|
||||
mtsh.Value.descriptors[i].mediumType;
|
||||
report.SCSI.SequentialDevice.SupportedMediaTypes[i].Name = mtsh.Value.descriptors[i].name;
|
||||
report.SCSI.SequentialDevice.SupportedMediaTypes[i].Organization = mtsh.Value.descriptors[i].organization;
|
||||
report.SCSI.SequentialDevice.SupportedMediaTypes[i].Organization =
|
||||
mtsh.Value.descriptors[i].organization;
|
||||
report.SCSI.SequentialDevice.SupportedMediaTypes[i].Width = mtsh.Value.descriptors[i].width;
|
||||
if(mtsh.Value.descriptors[i].densityCodes != null)
|
||||
{
|
||||
report.SCSI.SequentialDevice.SupportedMediaTypes[i].DensityCodes = new int[mtsh.Value.descriptors[i].densityCodes.Length];
|
||||
report.SCSI.SequentialDevice.SupportedMediaTypes[i].DensityCodes =
|
||||
new int[mtsh.Value.descriptors[i].densityCodes.Length];
|
||||
for(int j = 0; j < mtsh.Value.descriptors.Length; j++)
|
||||
report.SCSI.SequentialDevice.SupportedMediaTypes[i].DensityCodes[j] = mtsh.Value.descriptors[i].densityCodes[j];
|
||||
report.SCSI.SequentialDevice.SupportedMediaTypes[i].DensityCodes[j] =
|
||||
mtsh.Value.descriptors[i].densityCodes[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -174,8 +188,7 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
DicConsole.Write("\rWaiting for drive to become ready");
|
||||
System.Threading.Thread.Sleep(2000);
|
||||
sense = dev.ScsiTestUnitReady(out senseBuffer, timeout, out duration);
|
||||
if(!sense)
|
||||
break;
|
||||
if(!sense) break;
|
||||
|
||||
leftRetries--;
|
||||
}
|
||||
@@ -190,19 +203,16 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
DicConsole.Write("\rWaiting for drive to become ready");
|
||||
System.Threading.Thread.Sleep(2000);
|
||||
sense = dev.ScsiTestUnitReady(out senseBuffer, timeout, out duration);
|
||||
if(!sense)
|
||||
break;
|
||||
if(!sense) break;
|
||||
|
||||
leftRetries--;
|
||||
}
|
||||
|
||||
seqTest.MediaIsRecognized &= !sense;
|
||||
}
|
||||
else
|
||||
seqTest.MediaIsRecognized = false;
|
||||
else seqTest.MediaIsRecognized = false;
|
||||
}
|
||||
else
|
||||
seqTest.MediaIsRecognized = false;
|
||||
else seqTest.MediaIsRecognized = false;
|
||||
}
|
||||
|
||||
if(seqTest.MediaIsRecognized)
|
||||
@@ -210,13 +220,13 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
decMode = null;
|
||||
|
||||
DicConsole.WriteLine("Querying SCSI MODE SENSE (10)...");
|
||||
sense = dev.ModeSense10(out buffer, out senseBuffer, false, true, ScsiModeSensePageControl.Current, 0x3F, 0x00, timeout, out duration);
|
||||
sense = dev.ModeSense10(out buffer, out senseBuffer, false, true,
|
||||
ScsiModeSensePageControl.Current, 0x3F, 0x00, timeout, out duration);
|
||||
if(!sense && !dev.Error)
|
||||
{
|
||||
report.SCSI.SupportsModeSense10 = true;
|
||||
decMode = Decoders.SCSI.Modes.DecodeMode10(buffer, dev.SCSIType);
|
||||
if(debug)
|
||||
seqTest.ModeSense10Data = buffer;
|
||||
if(debug) seqTest.ModeSense10Data = buffer;
|
||||
}
|
||||
|
||||
DicConsole.WriteLine("Querying SCSI MODE SENSE...");
|
||||
@@ -224,17 +234,16 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
if(!sense && !dev.Error)
|
||||
{
|
||||
report.SCSI.SupportsModeSense6 = true;
|
||||
if(!decMode.HasValue)
|
||||
decMode = Decoders.SCSI.Modes.DecodeMode6(buffer, dev.SCSIType);
|
||||
if(debug)
|
||||
seqTest.ModeSense6Data = buffer;
|
||||
if(!decMode.HasValue) decMode = Decoders.SCSI.Modes.DecodeMode6(buffer, dev.SCSIType);
|
||||
if(debug) seqTest.ModeSense6Data = buffer;
|
||||
}
|
||||
|
||||
if(decMode.HasValue)
|
||||
{
|
||||
seqTest.MediumType = (byte)decMode.Value.Header.MediumType;
|
||||
seqTest.MediumTypeSpecified = true;
|
||||
if(decMode.Value.Header.BlockDescriptors != null && decMode.Value.Header.BlockDescriptors.Length > 0)
|
||||
if(decMode.Value.Header.BlockDescriptors != null &&
|
||||
decMode.Value.Header.BlockDescriptors.Length > 0)
|
||||
{
|
||||
seqTest.Density = (byte)decMode.Value.Header.BlockDescriptors[0].Density;
|
||||
seqTest.DensitySpecified = true;
|
||||
@@ -246,7 +255,8 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
sense = dev.ReportDensitySupport(out buffer, out senseBuffer, false, true, timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
Decoders.SCSI.SSC.DensitySupport.DensitySupportHeader? dsh = Decoders.SCSI.SSC.DensitySupport.DecodeDensity(buffer);
|
||||
Decoders.SCSI.SSC.DensitySupport.DensitySupportHeader? dsh =
|
||||
Decoders.SCSI.SSC.DensitySupport.DecodeDensity(buffer);
|
||||
if(dsh.HasValue)
|
||||
{
|
||||
seqTest.SupportedDensities = new SupportedDensity[dsh.Value.descriptors.Length];
|
||||
@@ -272,7 +282,8 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
sense = dev.ReportDensitySupport(out buffer, out senseBuffer, true, true, timeout, out duration);
|
||||
if(!sense)
|
||||
{
|
||||
Decoders.SCSI.SSC.DensitySupport.MediaTypeSupportHeader? mtsh = Decoders.SCSI.SSC.DensitySupport.DecodeMediumType(buffer);
|
||||
Decoders.SCSI.SSC.DensitySupport.MediaTypeSupportHeader? mtsh =
|
||||
Decoders.SCSI.SSC.DensitySupport.DecodeMediumType(buffer);
|
||||
if(mtsh.HasValue)
|
||||
{
|
||||
seqTest.SupportedMediaTypes = new SupportedMedia[mtsh.Value.descriptors.Length];
|
||||
@@ -286,9 +297,11 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
seqTest.SupportedMediaTypes[i].Width = mtsh.Value.descriptors[i].width;
|
||||
if(mtsh.Value.descriptors[i].densityCodes != null)
|
||||
{
|
||||
seqTest.SupportedMediaTypes[i].DensityCodes = new int[mtsh.Value.descriptors[i].densityCodes.Length];
|
||||
seqTest.SupportedMediaTypes[i].DensityCodes =
|
||||
new int[mtsh.Value.descriptors[i].densityCodes.Length];
|
||||
for(int j = 0; j < mtsh.Value.descriptors.Length; j++)
|
||||
seqTest.SupportedMediaTypes[i].DensityCodes[j] = mtsh.Value.descriptors[i].densityCodes[j];
|
||||
seqTest.SupportedMediaTypes[i].DensityCodes[j] =
|
||||
mtsh.Value.descriptors[i].densityCodes[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -296,11 +309,13 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
|
||||
|
||||
seqTest.CanReadMediaSerialSpecified = true;
|
||||
DicConsole.WriteLine("Trying SCSI READ MEDIA SERIAL NUMBER...");
|
||||
seqTest.CanReadMediaSerial = !dev.ReadMediaSerialNumber(out buffer, out senseBuffer, timeout, out duration);
|
||||
seqTest.CanReadMediaSerial =
|
||||
!dev.ReadMediaSerialNumber(out buffer, out senseBuffer, timeout, out duration);
|
||||
seqTests.Add(seqTest);
|
||||
}
|
||||
}
|
||||
|
||||
report.SCSI.SequentialDevice.TestedMedia = seqTests.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -40,13 +40,10 @@ namespace DiscImageChef.Core.Devices.Report
|
||||
{
|
||||
public static void Report(Device dev, ref DeviceReport report, bool debug, ref bool removable)
|
||||
{
|
||||
if(report == null)
|
||||
return;
|
||||
if(report == null) return;
|
||||
|
||||
if(dev.Type == DeviceType.MMC)
|
||||
report.MultiMediaCard = new mmcsdType();
|
||||
else if(dev.Type == DeviceType.SecureDigital)
|
||||
report.SecureDigital = new mmcsdType();
|
||||
if(dev.Type == DeviceType.MMC) report.MultiMediaCard = new mmcsdType();
|
||||
else if(dev.Type == DeviceType.SecureDigital) report.SecureDigital = new mmcsdType();
|
||||
|
||||
DicConsole.WriteLine("Trying to get CID...");
|
||||
bool sense = dev.ReadCID(out byte[] cid, out uint[] response, dev.Timeout, out double duration);
|
||||
@@ -77,8 +74,7 @@ namespace DiscImageChef.Core.Devices.Report
|
||||
report.MultiMediaCard.CID = cid;
|
||||
}
|
||||
}
|
||||
else
|
||||
DicConsole.WriteLine("Could not read CID...");
|
||||
else DicConsole.WriteLine("Could not read CID...");
|
||||
|
||||
DicConsole.WriteLine("Trying to get CSD...");
|
||||
sense = dev.ReadCSD(out byte[] csd, out response, dev.Timeout, out duration);
|
||||
@@ -87,13 +83,10 @@ namespace DiscImageChef.Core.Devices.Report
|
||||
{
|
||||
DicConsole.WriteLine("CSD obtained correctly...");
|
||||
|
||||
if(dev.Type == DeviceType.MMC)
|
||||
report.MultiMediaCard.CSD = csd;
|
||||
else if(dev.Type == DeviceType.SecureDigital)
|
||||
report.SecureDigital.CSD = csd;
|
||||
if(dev.Type == DeviceType.MMC) report.MultiMediaCard.CSD = csd;
|
||||
else if(dev.Type == DeviceType.SecureDigital) report.SecureDigital.CSD = csd;
|
||||
}
|
||||
else
|
||||
DicConsole.WriteLine("Could not read CSD...");
|
||||
else DicConsole.WriteLine("Could not read CSD...");
|
||||
|
||||
if(dev.Type == DeviceType.MMC)
|
||||
{
|
||||
@@ -105,8 +98,7 @@ namespace DiscImageChef.Core.Devices.Report
|
||||
DicConsole.WriteLine("OCR obtained correctly...");
|
||||
report.MultiMediaCard.OCR = ocr;
|
||||
}
|
||||
else
|
||||
DicConsole.WriteLine("Could not read OCR...");
|
||||
else DicConsole.WriteLine("Could not read OCR...");
|
||||
|
||||
DicConsole.WriteLine("Trying to get Extended CSD...");
|
||||
sense = dev.ReadExtendedCSD(out byte[] ecsd, out response, dev.Timeout, out duration);
|
||||
@@ -116,8 +108,7 @@ namespace DiscImageChef.Core.Devices.Report
|
||||
DicConsole.WriteLine("Extended CSD obtained correctly...");
|
||||
report.MultiMediaCard.ExtendedCSD = ecsd;
|
||||
}
|
||||
else
|
||||
DicConsole.WriteLine("Could not read Extended CSD...");
|
||||
else DicConsole.WriteLine("Could not read Extended CSD...");
|
||||
}
|
||||
else if(dev.Type == DeviceType.SecureDigital)
|
||||
{
|
||||
@@ -129,8 +120,7 @@ namespace DiscImageChef.Core.Devices.Report
|
||||
DicConsole.WriteLine("OCR obtained correctly...");
|
||||
report.SecureDigital.OCR = ocr;
|
||||
}
|
||||
else
|
||||
DicConsole.WriteLine("Could not read OCR...");
|
||||
else DicConsole.WriteLine("Could not read OCR...");
|
||||
|
||||
DicConsole.WriteLine("Trying to get SCR...");
|
||||
sense = dev.ReadSCR(out byte[] scr, out response, dev.Timeout, out duration);
|
||||
@@ -140,10 +130,8 @@ namespace DiscImageChef.Core.Devices.Report
|
||||
DicConsole.WriteLine("SCR obtained correctly...");
|
||||
report.SecureDigital.SCR = scr;
|
||||
}
|
||||
else
|
||||
DicConsole.WriteLine("Could not read SCR...");
|
||||
else DicConsole.WriteLine("Could not read SCR...");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -41,8 +41,7 @@ namespace DiscImageChef.Core.Devices.Report
|
||||
{
|
||||
public static void Report(Device dev, ref DeviceReport report, bool debug, ref bool removable)
|
||||
{
|
||||
if(report == null)
|
||||
return;
|
||||
if(report == null) return;
|
||||
|
||||
ConsoleKeyInfo pressedKey = new ConsoleKeyInfo();
|
||||
while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N)
|
||||
@@ -70,9 +69,8 @@ namespace DiscImageChef.Core.Devices.Report
|
||||
|
||||
report.USB.RemovableMedia = pressedKey.Key == ConsoleKey.Y;
|
||||
removable = report.USB.RemovableMedia;
|
||||
if(debug)
|
||||
report.USB.Descriptors = dev.USBDescriptors;
|
||||
if(debug) report.USB.Descriptors = dev.USBDescriptors;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -74,6 +74,7 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
DicConsole.ErrorWriteLine(ataReader.ErrorMessage);
|
||||
return results;
|
||||
}
|
||||
|
||||
uint blockSize = ataReader.LogicalBlockSize;
|
||||
// Check how many blocks to read, if error show and return
|
||||
if(ataReader.GetBlocksToRead(64))
|
||||
@@ -81,6 +82,7 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
DicConsole.ErrorWriteLine(ataReader.ErrorMessage);
|
||||
return results;
|
||||
}
|
||||
|
||||
uint blocksToRead = ataReader.BlocksToRead;
|
||||
ushort cylinders = ataReader.Cylinders;
|
||||
byte heads = ataReader.Heads;
|
||||
@@ -115,10 +117,7 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
byte seekSc = (byte)rnd.Next(sectors);
|
||||
|
||||
aborted = false;
|
||||
System.Console.CancelKeyPress += (sender, e) =>
|
||||
{
|
||||
e.Cancel = aborted = true;
|
||||
};
|
||||
System.Console.CancelKeyPress += (sender, e) => { e.Cancel = aborted = true; };
|
||||
|
||||
if(ataReader.IsLBA)
|
||||
{
|
||||
@@ -130,49 +129,28 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
start = DateTime.UtcNow;
|
||||
for(ulong i = 0; i < results.blocks; i += blocksToRead)
|
||||
{
|
||||
if(aborted)
|
||||
break;
|
||||
if(aborted) break;
|
||||
|
||||
if((results.blocks - i) < blocksToRead)
|
||||
blocksToRead = (byte)(results.blocks - i);
|
||||
if((results.blocks - i) < blocksToRead) blocksToRead = (byte)(results.blocks - i);
|
||||
|
||||
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
|
||||
if(currentSpeed > results.maxSpeed && currentSpeed != 0)
|
||||
results.maxSpeed = currentSpeed;
|
||||
if(currentSpeed < results.minSpeed && currentSpeed != 0)
|
||||
results.minSpeed = currentSpeed;
|
||||
if(currentSpeed > results.maxSpeed && currentSpeed != 0) results.maxSpeed = currentSpeed;
|
||||
if(currentSpeed < results.minSpeed && currentSpeed != 0) results.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, results.blocks, currentSpeed);
|
||||
DicConsole.Write("\rReading sector {0} of {1} ({2:F3} MiB/sec.)", i, results.blocks,
|
||||
currentSpeed);
|
||||
|
||||
bool error = ataReader.ReadBlocks(out cmdBuf, i, blocksToRead, out duration);
|
||||
|
||||
if(!error)
|
||||
{
|
||||
if(duration >= 500)
|
||||
{
|
||||
results.F += blocksToRead;
|
||||
}
|
||||
else if(duration >= 150)
|
||||
{
|
||||
results.E += blocksToRead;
|
||||
}
|
||||
else if(duration >= 50)
|
||||
{
|
||||
results.D += blocksToRead;
|
||||
}
|
||||
else if(duration >= 10)
|
||||
{
|
||||
results.C += blocksToRead;
|
||||
}
|
||||
else if(duration >= 3)
|
||||
{
|
||||
results.B += blocksToRead;
|
||||
}
|
||||
else
|
||||
{
|
||||
results.A += blocksToRead;
|
||||
}
|
||||
if(duration >= 500) { results.F += blocksToRead; }
|
||||
else if(duration >= 150) { results.E += blocksToRead; }
|
||||
else if(duration >= 50) { results.D += blocksToRead; }
|
||||
else if(duration >= 10) { results.C += blocksToRead; }
|
||||
else if(duration >= 3) { results.B += blocksToRead; }
|
||||
else { results.A += blocksToRead; }
|
||||
|
||||
mhddLog.Write(i, duration);
|
||||
ibgLog.Write(i, currentSpeed * 1024);
|
||||
@@ -180,12 +158,10 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
else
|
||||
{
|
||||
results.errored += blocksToRead;
|
||||
for(ulong b = i; b < i + blocksToRead; b++)
|
||||
results.unreadableSectors.Add(b);
|
||||
if(duration < 500)
|
||||
mhddLog.Write(i, 65535);
|
||||
else
|
||||
mhddLog.Write(i, duration);
|
||||
for(ulong b = i; b < i + blocksToRead; b++) results.unreadableSectors.Add(b);
|
||||
|
||||
if(duration < 500) mhddLog.Write(i, 65535);
|
||||
else mhddLog.Write(i, duration);
|
||||
|
||||
ibgLog.Write(i, 0);
|
||||
}
|
||||
@@ -195,19 +171,21 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
#pragma warning restore IDE0004 // Without this specific cast, it gives incorrect values
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
end = DateTime.UtcNow;
|
||||
DicConsole.WriteLine();
|
||||
mhddLog.Close();
|
||||
#pragma warning disable IDE0004 // Without this specific cast, it gives incorrect values
|
||||
ibgLog.Close(dev, results.blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024, (((double)blockSize * (double)(results.blocks + 1)) / 1024) / (results.processingTime / 1000), devicePath);
|
||||
ibgLog.Close(dev, results.blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
|
||||
(((double)blockSize * (double)(results.blocks + 1)) / 1024) /
|
||||
(results.processingTime / 1000), devicePath);
|
||||
#pragma warning restore IDE0004 // Without this specific cast, it gives incorrect values
|
||||
|
||||
if(ataReader.CanSeekLBA)
|
||||
{
|
||||
for(int i = 0; i < seekTimes; i++)
|
||||
{
|
||||
if(aborted)
|
||||
break;
|
||||
if(aborted) break;
|
||||
|
||||
seekPos = (uint)rnd.Next((int)results.blocks);
|
||||
|
||||
@@ -216,10 +194,8 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
ataReader.Seek(seekPos, out seekCur);
|
||||
|
||||
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
|
||||
if(seekCur > results.seekMax && seekCur != 0)
|
||||
results.seekMax = seekCur;
|
||||
if(seekCur < results.seekMin && seekCur != 0)
|
||||
results.seekMin = seekCur;
|
||||
if(seekCur > results.seekMax && seekCur != 0) results.seekMax = seekCur;
|
||||
if(seekCur < results.seekMin && seekCur != 0) results.seekMin = seekCur;
|
||||
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
|
||||
|
||||
results.seekTotal += seekCur;
|
||||
@@ -241,8 +217,7 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
{
|
||||
for(byte Sc = 1; Sc < sectors; Sc++)
|
||||
{
|
||||
if(aborted)
|
||||
break;
|
||||
if(aborted) break;
|
||||
|
||||
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
|
||||
if(currentSpeed > results.maxSpeed && currentSpeed != 0)
|
||||
@@ -251,36 +226,19 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
results.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);
|
||||
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);
|
||||
|
||||
if(!error)
|
||||
{
|
||||
if(duration >= 500)
|
||||
{
|
||||
results.F += blocksToRead;
|
||||
}
|
||||
else if(duration >= 150)
|
||||
{
|
||||
results.E += blocksToRead;
|
||||
}
|
||||
else if(duration >= 50)
|
||||
{
|
||||
results.D += blocksToRead;
|
||||
}
|
||||
else if(duration >= 10)
|
||||
{
|
||||
results.C += blocksToRead;
|
||||
}
|
||||
else if(duration >= 3)
|
||||
{
|
||||
results.B += blocksToRead;
|
||||
}
|
||||
else
|
||||
{
|
||||
results.A += blocksToRead;
|
||||
}
|
||||
if(duration >= 500) { results.F += blocksToRead; }
|
||||
else if(duration >= 150) { results.E += blocksToRead; }
|
||||
else if(duration >= 50) { results.D += blocksToRead; }
|
||||
else if(duration >= 10) { results.C += blocksToRead; }
|
||||
else if(duration >= 3) { results.B += blocksToRead; }
|
||||
else { results.A += blocksToRead; }
|
||||
|
||||
mhddLog.Write(currentBlock, duration);
|
||||
ibgLog.Write(currentBlock, currentSpeed * 1024);
|
||||
@@ -289,10 +247,8 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
{
|
||||
results.errored += blocksToRead;
|
||||
results.unreadableSectors.Add(currentBlock);
|
||||
if(duration < 500)
|
||||
mhddLog.Write(currentBlock, 65535);
|
||||
else
|
||||
mhddLog.Write(currentBlock, duration);
|
||||
if(duration < 500) mhddLog.Write(currentBlock, 65535);
|
||||
else mhddLog.Write(currentBlock, duration);
|
||||
|
||||
ibgLog.Write(currentBlock, 0);
|
||||
}
|
||||
@@ -306,33 +262,34 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
end = DateTime.UtcNow;
|
||||
DicConsole.WriteLine();
|
||||
mhddLog.Close();
|
||||
#pragma warning disable IDE0004 // Without this specific cast, it gives incorrect values
|
||||
ibgLog.Close(dev, results.blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024, (((double)blockSize * (double)(results.blocks + 1)) / 1024) / (results.processingTime / 1000), devicePath);
|
||||
ibgLog.Close(dev, results.blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
|
||||
(((double)blockSize * (double)(results.blocks + 1)) / 1024) /
|
||||
(results.processingTime / 1000), devicePath);
|
||||
#pragma warning restore IDE0004 // Without this specific cast, it gives incorrect values
|
||||
|
||||
if(ataReader.CanSeek)
|
||||
{
|
||||
for(int i = 0; i < seekTimes; i++)
|
||||
{
|
||||
if(aborted)
|
||||
break;
|
||||
if(aborted) break;
|
||||
|
||||
seekCy = (ushort)rnd.Next(cylinders);
|
||||
seekHd = (byte)rnd.Next(heads);
|
||||
seekSc = (byte)rnd.Next(sectors);
|
||||
|
||||
DicConsole.Write("\rSeeking to cylinder {0}, head {1}, sector {2}...\t\t", seekCy, seekHd, seekSc);
|
||||
DicConsole.Write("\rSeeking to cylinder {0}, head {1}, sector {2}...\t\t", seekCy, seekHd,
|
||||
seekSc);
|
||||
|
||||
ataReader.SeekCHS(seekCy, seekHd, seekSc, out seekCur);
|
||||
|
||||
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
|
||||
if(seekCur > results.seekMax && seekCur != 0)
|
||||
results.seekMax = seekCur;
|
||||
if(seekCur < results.seekMin && seekCur != 0)
|
||||
results.seekMin = seekCur;
|
||||
if(seekCur > results.seekMax && seekCur != 0) results.seekMax = seekCur;
|
||||
if(seekCur < results.seekMin && seekCur != 0) results.seekMin = seekCur;
|
||||
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
|
||||
|
||||
results.seekTotal += seekCur;
|
||||
@@ -346,7 +303,8 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
results.processingTime /= 1000;
|
||||
results.totalTime = (end - start).TotalSeconds;
|
||||
#pragma warning disable IDE0004 // Without this specific cast, it gives incorrect values
|
||||
results.avgSpeed = (((double)blockSize * (double)(results.blocks + 1)) / 1048576) / results.processingTime;
|
||||
results.avgSpeed = (((double)blockSize * (double)(results.blocks + 1)) / 1048576) /
|
||||
results.processingTime;
|
||||
#pragma warning restore IDE0004 // Without this specific cast, it gives incorrect values
|
||||
results.seekTimes = seekTimes;
|
||||
|
||||
@@ -357,4 +315,4 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
return results;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,4 +42,4 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
throw new NotImplementedException("NVMe devices not yet supported.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -70,8 +70,7 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
DicConsole.WriteLine("\rWaiting for drive to become ready");
|
||||
System.Threading.Thread.Sleep(2000);
|
||||
sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
break;
|
||||
if(!sense) break;
|
||||
|
||||
leftRetries--;
|
||||
}
|
||||
@@ -90,15 +89,15 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
DicConsole.WriteLine("\rWaiting for drive to become ready");
|
||||
System.Threading.Thread.Sleep(2000);
|
||||
sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
break;
|
||||
if(!sense) break;
|
||||
|
||||
leftRetries--;
|
||||
}
|
||||
|
||||
if(sense)
|
||||
{
|
||||
DicConsole.ErrorWriteLine("Error testing unit was ready:\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf));
|
||||
DicConsole.ErrorWriteLine("Error testing unit was ready:\n{0}",
|
||||
Decoders.SCSI.Sense.PrettifySense(senseBuf));
|
||||
return results;
|
||||
}
|
||||
}
|
||||
@@ -111,21 +110,22 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
DicConsole.WriteLine("\rWaiting for drive to become ready");
|
||||
System.Threading.Thread.Sleep(2000);
|
||||
sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out duration);
|
||||
if(!sense)
|
||||
break;
|
||||
if(!sense) break;
|
||||
|
||||
leftRetries--;
|
||||
}
|
||||
|
||||
if(sense)
|
||||
{
|
||||
DicConsole.ErrorWriteLine("Error testing unit was ready:\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf));
|
||||
DicConsole.ErrorWriteLine("Error testing unit was ready:\n{0}",
|
||||
Decoders.SCSI.Sense.PrettifySense(senseBuf));
|
||||
return results;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DicConsole.ErrorWriteLine("Error testing unit was ready:\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf));
|
||||
DicConsole.ErrorWriteLine("Error testing unit was ready:\n{0}",
|
||||
Decoders.SCSI.Sense.PrettifySense(senseBuf));
|
||||
return results;
|
||||
}
|
||||
}
|
||||
@@ -140,11 +140,11 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
Reader scsiReader = null;
|
||||
|
||||
if(dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.DirectAccess ||
|
||||
dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.MultiMediaDevice ||
|
||||
dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.OCRWDevice ||
|
||||
dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.OpticalDevice ||
|
||||
dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.SimplifiedDevice ||
|
||||
dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.WriteOnceDevice)
|
||||
dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.MultiMediaDevice ||
|
||||
dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.OCRWDevice ||
|
||||
dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.OpticalDevice ||
|
||||
dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.SimplifiedDevice ||
|
||||
dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.WriteOnceDevice)
|
||||
{
|
||||
scsiReader = new Reader(dev, dev.Timeout, null, false);
|
||||
results.blocks = scsiReader.GetDeviceBlocks();
|
||||
@@ -153,6 +153,7 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
DicConsole.ErrorWriteLine("Unable to read medium.");
|
||||
return results;
|
||||
}
|
||||
|
||||
blockSize = scsiReader.LogicalBlockSize;
|
||||
|
||||
if(results.blocks != 0 && blockSize != 0)
|
||||
@@ -160,7 +161,7 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
results.blocks++;
|
||||
#pragma warning disable IDE0004 // Without this specific cast, it gives incorrect values
|
||||
DicConsole.WriteLine("Media has {0} blocks of {1} bytes/each. (for a total of {2} bytes)",
|
||||
results.blocks, blockSize, results.blocks * (ulong)blockSize);
|
||||
results.blocks, blockSize, results.blocks * (ulong)blockSize);
|
||||
#pragma warning restore IDE0004 // Without this specific cast, it gives incorrect values
|
||||
}
|
||||
}
|
||||
@@ -183,7 +184,8 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
|
||||
if(dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.MultiMediaDevice)
|
||||
{
|
||||
sense = dev.GetConfiguration(out cmdBuf, out senseBuf, 0, MmcGetConfigurationRt.Current, dev.Timeout, out duration);
|
||||
sense = dev.GetConfiguration(out cmdBuf, out senseBuf, 0, MmcGetConfigurationRt.Current, dev.Timeout,
|
||||
out duration);
|
||||
if(!sense)
|
||||
{
|
||||
Decoders.SCSI.MMC.Features.SeparatedFeatures ftr = Decoders.SCSI.MMC.Features.Separate(cmdBuf);
|
||||
@@ -198,8 +200,7 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
case 0x000A:
|
||||
case 0x0020:
|
||||
case 0x0021:
|
||||
case 0x0022:
|
||||
break;
|
||||
case 0x0022: break;
|
||||
default:
|
||||
compactDisc = false;
|
||||
break;
|
||||
@@ -212,12 +213,10 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
// We discarded all discs that falsify a TOC before requesting a real TOC
|
||||
// No TOC, no CD (or an empty one)
|
||||
bool tocSense = dev.ReadRawToc(out cmdBuf, out senseBuf, 1, dev.Timeout, out duration);
|
||||
if(!tocSense)
|
||||
toc = Decoders.CD.FullTOC.Decode(cmdBuf);
|
||||
if(!tocSense) toc = Decoders.CD.FullTOC.Decode(cmdBuf);
|
||||
}
|
||||
}
|
||||
else
|
||||
compactDisc = false;
|
||||
else compactDisc = false;
|
||||
|
||||
byte[] readBuffer;
|
||||
uint blocksToRead = 64;
|
||||
@@ -239,10 +238,7 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
results.unreadableSectors = new List<ulong>();
|
||||
|
||||
aborted = false;
|
||||
System.Console.CancelKeyPress += (sender, e) =>
|
||||
{
|
||||
e.Cancel = aborted = true;
|
||||
};
|
||||
System.Console.CancelKeyPress += (sender, e) => { e.Cancel = aborted = true; };
|
||||
|
||||
bool readcd = false;
|
||||
|
||||
@@ -254,11 +250,11 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
return results;
|
||||
}
|
||||
|
||||
readcd = !dev.ReadCd(out readBuffer, out senseBuf, 0, 2352, 1, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders,
|
||||
true, true, MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out duration);
|
||||
readcd = !dev.ReadCd(out readBuffer, out senseBuf, 0, 2352, 1, MmcSectorTypes.AllTypes, false, false,
|
||||
true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None,
|
||||
MmcSubchannel.None, dev.Timeout, out duration);
|
||||
|
||||
if(readcd)
|
||||
DicConsole.WriteLine("Using MMC READ CD command.");
|
||||
if(readcd) DicConsole.WriteLine("Using MMC READ CD command.");
|
||||
|
||||
start = DateTime.UtcNow;
|
||||
|
||||
@@ -266,14 +262,13 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
{
|
||||
if(readcd)
|
||||
{
|
||||
sense = dev.ReadCd(out readBuffer, out senseBuf, 0, 2352, blocksToRead, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders,
|
||||
true, true, MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out duration);
|
||||
if(dev.Error)
|
||||
blocksToRead /= 2;
|
||||
sense = dev.ReadCd(out readBuffer, out senseBuf, 0, 2352, blocksToRead, MmcSectorTypes.AllTypes,
|
||||
false, false, true, MmcHeaderCodes.AllHeaders, true, true,
|
||||
MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out duration);
|
||||
if(dev.Error) blocksToRead /= 2;
|
||||
}
|
||||
|
||||
if(!dev.Error || blocksToRead == 1)
|
||||
break;
|
||||
if(!dev.Error || blocksToRead == 1) break;
|
||||
}
|
||||
|
||||
if(dev.Error)
|
||||
@@ -289,63 +284,43 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
|
||||
for(ulong i = 0; i < results.blocks; i += blocksToRead)
|
||||
{
|
||||
if(aborted)
|
||||
break;
|
||||
if(aborted) break;
|
||||
|
||||
double cmdDuration = 0;
|
||||
|
||||
if((results.blocks - i) < blocksToRead)
|
||||
blocksToRead = (uint)(results.blocks - i);
|
||||
if((results.blocks - i) < blocksToRead) blocksToRead = (uint)(results.blocks - i);
|
||||
|
||||
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
|
||||
if(currentSpeed > results.maxSpeed && currentSpeed != 0)
|
||||
results.maxSpeed = currentSpeed;
|
||||
if(currentSpeed < results.minSpeed && currentSpeed != 0)
|
||||
results.minSpeed = currentSpeed;
|
||||
if(currentSpeed > results.maxSpeed && currentSpeed != 0) results.maxSpeed = currentSpeed;
|
||||
if(currentSpeed < results.minSpeed && currentSpeed != 0) results.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, results.blocks, currentSpeed);
|
||||
|
||||
if(readcd)
|
||||
{
|
||||
sense = dev.ReadCd(out readBuffer, out senseBuf, (uint)i, 2352, blocksToRead, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders,
|
||||
true, true, MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out cmdDuration);
|
||||
sense = dev.ReadCd(out readBuffer, out senseBuf, (uint)i, 2352, blocksToRead,
|
||||
MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true,
|
||||
true, MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out cmdDuration);
|
||||
results.processingTime += cmdDuration;
|
||||
}
|
||||
|
||||
if(!sense)
|
||||
{
|
||||
if(cmdDuration >= 500)
|
||||
{
|
||||
results.F += blocksToRead;
|
||||
}
|
||||
else if(cmdDuration >= 150)
|
||||
{
|
||||
results.E += blocksToRead;
|
||||
}
|
||||
else if(cmdDuration >= 50)
|
||||
{
|
||||
results.D += blocksToRead;
|
||||
}
|
||||
else if(cmdDuration >= 10)
|
||||
{
|
||||
results.C += blocksToRead;
|
||||
}
|
||||
else if(cmdDuration >= 3)
|
||||
{
|
||||
results.B += blocksToRead;
|
||||
}
|
||||
else
|
||||
{
|
||||
results.A += blocksToRead;
|
||||
}
|
||||
if(cmdDuration >= 500) { results.F += blocksToRead; }
|
||||
else if(cmdDuration >= 150) { results.E += blocksToRead; }
|
||||
else if(cmdDuration >= 50) { results.D += blocksToRead; }
|
||||
else if(cmdDuration >= 10) { results.C += blocksToRead; }
|
||||
else if(cmdDuration >= 3) { results.B += blocksToRead; }
|
||||
else { results.A += blocksToRead; }
|
||||
|
||||
mhddLog.Write(i, cmdDuration);
|
||||
ibgLog.Write(i, currentSpeed * 1024);
|
||||
}
|
||||
else
|
||||
{
|
||||
DicConsole.DebugWriteLine("Media-Scan", "READ CD error:\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf));
|
||||
DicConsole.DebugWriteLine("Media-Scan", "READ CD error:\n{0}",
|
||||
Decoders.SCSI.Sense.PrettifySense(senseBuf));
|
||||
|
||||
Decoders.SCSI.FixedSense? senseDecoded = Decoders.SCSI.Sense.DecodeFixed(senseBuf);
|
||||
if(senseDecoded.HasValue)
|
||||
@@ -353,17 +328,15 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
// TODO: This error happens when changing from track type afaik. Need to solve that more cleanly
|
||||
// LOGICAL BLOCK ADDRESS OUT OF RANGE
|
||||
if((senseDecoded.Value.ASC != 0x21 || senseDecoded.Value.ASCQ != 0x00) &&
|
||||
// ILLEGAL MODE FOR THIS TRACK (requesting sectors as-is, this is a firmware misconception when audio sectors
|
||||
// are in a track where subchannel indicates data)
|
||||
(senseDecoded.Value.ASC != 0x64 || senseDecoded.Value.ASCQ != 0x00))
|
||||
// ILLEGAL MODE FOR THIS TRACK (requesting sectors as-is, this is a firmware misconception when audio sectors
|
||||
// are in a track where subchannel indicates data)
|
||||
(senseDecoded.Value.ASC != 0x64 || senseDecoded.Value.ASCQ != 0x00))
|
||||
{
|
||||
results.errored += blocksToRead;
|
||||
for(ulong b = i; b < i + blocksToRead; b++)
|
||||
results.unreadableSectors.Add(b);
|
||||
if(cmdDuration < 500)
|
||||
mhddLog.Write(i, 65535);
|
||||
else
|
||||
mhddLog.Write(i, cmdDuration);
|
||||
for(ulong b = i; b < i + blocksToRead; b++) results.unreadableSectors.Add(b);
|
||||
|
||||
if(cmdDuration < 500) mhddLog.Write(i, 65535);
|
||||
else mhddLog.Write(i, cmdDuration);
|
||||
|
||||
ibgLog.Write(i, 0);
|
||||
}
|
||||
@@ -371,12 +344,10 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
else
|
||||
{
|
||||
results.errored += blocksToRead;
|
||||
for(ulong b = i; b < i + blocksToRead; b++)
|
||||
results.unreadableSectors.Add(b);
|
||||
if(cmdDuration < 500)
|
||||
mhddLog.Write(i, 65535);
|
||||
else
|
||||
mhddLog.Write(i, cmdDuration);
|
||||
for(ulong b = i; b < i + blocksToRead; b++) results.unreadableSectors.Add(b);
|
||||
|
||||
if(cmdDuration < 500) mhddLog.Write(i, 65535);
|
||||
else mhddLog.Write(i, cmdDuration);
|
||||
|
||||
ibgLog.Write(i, 0);
|
||||
}
|
||||
@@ -387,11 +358,14 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
#pragma warning restore IDE0004 // Without this specific cast, it gives incorrect values
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
end = DateTime.UtcNow;
|
||||
DicConsole.WriteLine();
|
||||
mhddLog.Close();
|
||||
#pragma warning disable IDE0004 // Without this specific cast, it gives incorrect values
|
||||
ibgLog.Close(dev, results.blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024, (((double)blockSize * (double)(results.blocks + 1)) / 1024) / (results.processingTime / 1000), devicePath);
|
||||
ibgLog.Close(dev, results.blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
|
||||
(((double)blockSize * (double)(results.blocks + 1)) / 1024) /
|
||||
(results.processingTime / 1000), devicePath);
|
||||
#pragma warning restore IDE0004 // Without this specific cast, it gives incorrect values
|
||||
}
|
||||
else
|
||||
@@ -405,19 +379,15 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
|
||||
for(ulong i = 0; i < results.blocks; i += blocksToRead)
|
||||
{
|
||||
if(aborted)
|
||||
break;
|
||||
if(aborted) break;
|
||||
|
||||
double cmdDuration = 0;
|
||||
|
||||
if((results.blocks - i) < blocksToRead)
|
||||
blocksToRead = (uint)(results.blocks - i);
|
||||
if((results.blocks - i) < blocksToRead) blocksToRead = (uint)(results.blocks - i);
|
||||
|
||||
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
|
||||
if(currentSpeed > results.maxSpeed && currentSpeed != 0)
|
||||
results.maxSpeed = currentSpeed;
|
||||
if(currentSpeed < results.minSpeed && currentSpeed != 0)
|
||||
results.minSpeed = currentSpeed;
|
||||
if(currentSpeed > results.maxSpeed && currentSpeed != 0) results.maxSpeed = currentSpeed;
|
||||
if(currentSpeed < results.minSpeed && currentSpeed != 0) results.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, results.blocks, currentSpeed);
|
||||
@@ -427,18 +397,12 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
|
||||
if(!sense && !dev.Error)
|
||||
{
|
||||
if(cmdDuration >= 500)
|
||||
results.F += blocksToRead;
|
||||
else if(cmdDuration >= 150)
|
||||
results.E += blocksToRead;
|
||||
else if(cmdDuration >= 50)
|
||||
results.D += blocksToRead;
|
||||
else if(cmdDuration >= 10)
|
||||
results.C += blocksToRead;
|
||||
else if(cmdDuration >= 3)
|
||||
results.B += blocksToRead;
|
||||
else
|
||||
results.A += blocksToRead;
|
||||
if(cmdDuration >= 500) results.F += blocksToRead;
|
||||
else if(cmdDuration >= 150) results.E += blocksToRead;
|
||||
else if(cmdDuration >= 50) results.D += blocksToRead;
|
||||
else if(cmdDuration >= 10) results.C += blocksToRead;
|
||||
else if(cmdDuration >= 3) results.B += blocksToRead;
|
||||
else results.A += blocksToRead;
|
||||
|
||||
mhddLog.Write(i, cmdDuration);
|
||||
ibgLog.Write(i, currentSpeed * 1024);
|
||||
@@ -447,12 +411,10 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
else
|
||||
{
|
||||
results.errored += blocksToRead;
|
||||
for(ulong b = i; b < i + blocksToRead; b++)
|
||||
results.unreadableSectors.Add(b);
|
||||
if(cmdDuration < 500)
|
||||
mhddLog.Write(i, 65535);
|
||||
else
|
||||
mhddLog.Write(i, cmdDuration);
|
||||
for(ulong b = i; b < i + blocksToRead; b++) results.unreadableSectors.Add(b);
|
||||
|
||||
if(cmdDuration < 500) mhddLog.Write(i, 65535);
|
||||
else mhddLog.Write(i, cmdDuration);
|
||||
ibgLog.Write(i, 0);
|
||||
}
|
||||
|
||||
@@ -465,7 +427,9 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
DicConsole.WriteLine();
|
||||
mhddLog.Close();
|
||||
#pragma warning disable IDE0004 // Without this specific cast, it gives incorrect values
|
||||
ibgLog.Close(dev, results.blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024, (((double)blockSize * (double)(results.blocks + 1)) / 1024) / (results.processingTime / 1000), devicePath);
|
||||
ibgLog.Close(dev, results.blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
|
||||
(((double)blockSize * (double)(results.blocks + 1)) / 1024) /
|
||||
(results.processingTime / 1000), devicePath);
|
||||
#pragma warning restore IDE0004 // Without this specific cast, it gives incorrect values
|
||||
}
|
||||
|
||||
@@ -482,23 +446,18 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
|
||||
for(int i = 0; i < seekTimes; i++)
|
||||
{
|
||||
if(aborted)
|
||||
break;
|
||||
if(aborted) break;
|
||||
|
||||
seekPos = (uint)rnd.Next((int)results.blocks);
|
||||
|
||||
DicConsole.Write("\rSeeking to sector {0}...\t\t", seekPos);
|
||||
|
||||
if(scsiReader.CanSeek)
|
||||
scsiReader.Seek(seekPos, out seekCur);
|
||||
else
|
||||
scsiReader.ReadBlock(out readBuffer, seekPos, out seekCur);
|
||||
if(scsiReader.CanSeek) scsiReader.Seek(seekPos, out seekCur);
|
||||
else scsiReader.ReadBlock(out readBuffer, seekPos, out seekCur);
|
||||
|
||||
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
|
||||
if(seekCur > results.seekMax && seekCur != 0)
|
||||
results.seekMax = seekCur;
|
||||
if(seekCur < results.seekMin && seekCur != 0)
|
||||
results.seekMin = seekCur;
|
||||
if(seekCur > results.seekMax && seekCur != 0) results.seekMax = seekCur;
|
||||
if(seekCur < results.seekMin && seekCur != 0) results.seekMin = seekCur;
|
||||
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
|
||||
|
||||
results.seekTotal += seekCur;
|
||||
@@ -517,4 +476,4 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
return results;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -55,4 +55,4 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
public ulong blocks;
|
||||
public ulong errored;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -93,7 +93,9 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
if(!sense)
|
||||
{
|
||||
csd = Decoders.SecureDigital.Decoders.DecodeCSD(cmdBuf);
|
||||
results.blocks = (ulong)(csd.Structure == 0 ? (csd.Size + 1) * Math.Pow(2, csd.SizeMultiplier + 2) : (csd.Size + 1) * 1024);
|
||||
results.blocks = (ulong)(csd.Structure == 0
|
||||
? (csd.Size + 1) * Math.Pow(2, csd.SizeMultiplier + 2)
|
||||
: (csd.Size + 1) * 1024);
|
||||
blockSize = (uint)Math.Pow(2, csd.ReadBlockLength);
|
||||
// Structure >=1 for SDHC/SDXC, so that's block addressed
|
||||
byteAddressed = csd.Structure == 0;
|
||||
@@ -110,13 +112,12 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
|
||||
while(true)
|
||||
{
|
||||
sense = dev.Read(out cmdBuf, out response, 0, blockSize, blocksToRead, byteAddressed, timeout, out duration);
|
||||
sense = dev.Read(out cmdBuf, out response, 0, blockSize, blocksToRead, byteAddressed, timeout,
|
||||
out duration);
|
||||
|
||||
if(sense)
|
||||
blocksToRead /= 2;
|
||||
if(sense) blocksToRead /= 2;
|
||||
|
||||
if(!sense || blocksToRead == 1)
|
||||
break;
|
||||
if(!sense || blocksToRead == 1) break;
|
||||
}
|
||||
|
||||
if(sense)
|
||||
@@ -152,10 +153,7 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
uint seekPos = (uint)rnd.Next((int)results.blocks);
|
||||
|
||||
aborted = false;
|
||||
System.Console.CancelKeyPress += (sender, e) =>
|
||||
{
|
||||
e.Cancel = aborted = true;
|
||||
};
|
||||
System.Console.CancelKeyPress += (sender, e) => { e.Cancel = aborted = true; };
|
||||
|
||||
DicConsole.WriteLine("Reading {0} sectors at a time.", blocksToRead);
|
||||
|
||||
@@ -165,49 +163,28 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
start = DateTime.UtcNow;
|
||||
for(ulong i = 0; i < results.blocks; i += blocksToRead)
|
||||
{
|
||||
if(aborted)
|
||||
break;
|
||||
if(aborted) break;
|
||||
|
||||
if((results.blocks - i) < blocksToRead)
|
||||
blocksToRead = (byte)(results.blocks - i);
|
||||
if((results.blocks - i) < blocksToRead) blocksToRead = (byte)(results.blocks - i);
|
||||
|
||||
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
|
||||
if(currentSpeed > results.maxSpeed && currentSpeed != 0)
|
||||
results.maxSpeed = currentSpeed;
|
||||
if(currentSpeed < results.minSpeed && currentSpeed != 0)
|
||||
results.minSpeed = currentSpeed;
|
||||
if(currentSpeed > results.maxSpeed && currentSpeed != 0) results.maxSpeed = currentSpeed;
|
||||
if(currentSpeed < results.minSpeed && currentSpeed != 0) results.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, results.blocks, currentSpeed);
|
||||
|
||||
bool error = dev.Read(out cmdBuf, out response, (uint)i, blockSize, blocksToRead, byteAddressed, timeout, out duration);
|
||||
bool error = dev.Read(out cmdBuf, out response, (uint)i, blockSize, blocksToRead, byteAddressed,
|
||||
timeout, out duration);
|
||||
|
||||
if(!error)
|
||||
{
|
||||
if(duration >= 500)
|
||||
{
|
||||
results.F += blocksToRead;
|
||||
}
|
||||
else if(duration >= 150)
|
||||
{
|
||||
results.E += blocksToRead;
|
||||
}
|
||||
else if(duration >= 50)
|
||||
{
|
||||
results.D += blocksToRead;
|
||||
}
|
||||
else if(duration >= 10)
|
||||
{
|
||||
results.C += blocksToRead;
|
||||
}
|
||||
else if(duration >= 3)
|
||||
{
|
||||
results.B += blocksToRead;
|
||||
}
|
||||
else
|
||||
{
|
||||
results.A += blocksToRead;
|
||||
}
|
||||
if(duration >= 500) { results.F += blocksToRead; }
|
||||
else if(duration >= 150) { results.E += blocksToRead; }
|
||||
else if(duration >= 50) { results.D += blocksToRead; }
|
||||
else if(duration >= 10) { results.C += blocksToRead; }
|
||||
else if(duration >= 3) { results.B += blocksToRead; }
|
||||
else { results.A += blocksToRead; }
|
||||
|
||||
mhddLog.Write(i, duration);
|
||||
ibgLog.Write(i, currentSpeed * 1024);
|
||||
@@ -215,12 +192,10 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
else
|
||||
{
|
||||
results.errored += blocksToRead;
|
||||
for(ulong b = i; b < i + blocksToRead; b++)
|
||||
results.unreadableSectors.Add(b);
|
||||
if(duration < 500)
|
||||
mhddLog.Write(i, 65535);
|
||||
else
|
||||
mhddLog.Write(i, duration);
|
||||
for(ulong b = i; b < i + blocksToRead; b++) results.unreadableSectors.Add(b);
|
||||
|
||||
if(duration < 500) mhddLog.Write(i, 65535);
|
||||
else mhddLog.Write(i, duration);
|
||||
|
||||
ibgLog.Write(i, 0);
|
||||
}
|
||||
@@ -230,29 +205,30 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
#pragma warning restore IDE0004 // Without this specific cast, it gives incorrect values
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
end = DateTime.UtcNow;
|
||||
DicConsole.WriteLine();
|
||||
mhddLog.Close();
|
||||
#pragma warning disable IDE0004 // Without this specific cast, it gives incorrect values
|
||||
ibgLog.Close(dev, results.blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024, (((double)blockSize * (double)(results.blocks + 1)) / 1024) / (results.processingTime / 1000), devicePath);
|
||||
ibgLog.Close(dev, results.blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
|
||||
(((double)blockSize * (double)(results.blocks + 1)) / 1024) / (results.processingTime / 1000),
|
||||
devicePath);
|
||||
#pragma warning restore IDE0004 // Without this specific cast, it gives incorrect values
|
||||
|
||||
for(int i = 0; i < seekTimes; i++)
|
||||
{
|
||||
if(aborted)
|
||||
break;
|
||||
if(aborted) break;
|
||||
|
||||
seekPos = (uint)rnd.Next((int)results.blocks);
|
||||
|
||||
DicConsole.Write("\rSeeking to sector {0}...\t\t", seekPos);
|
||||
|
||||
dev.Read(out cmdBuf, out response, (uint)seekPos, blockSize, blocksToRead, byteAddressed, timeout, out seekCur);
|
||||
dev.Read(out cmdBuf, out response, (uint)seekPos, blockSize, blocksToRead, byteAddressed, timeout,
|
||||
out seekCur);
|
||||
|
||||
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
|
||||
if(seekCur > results.seekMax && seekCur != 0)
|
||||
results.seekMax = seekCur;
|
||||
if(seekCur < results.seekMin && seekCur != 0)
|
||||
results.seekMin = seekCur;
|
||||
if(seekCur > results.seekMax && seekCur != 0) results.seekMax = seekCur;
|
||||
if(seekCur < results.seekMin && seekCur != 0) results.seekMin = seekCur;
|
||||
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
|
||||
|
||||
results.seekTotal += seekCur;
|
||||
@@ -271,4 +247,4 @@ namespace DiscImageChef.Core.Devices.Scanning
|
||||
return results;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user