mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
Remove DiscImageChef.CommonTypes dependence on DiscImageChef.Decoders.
This commit is contained in:
13
.idea/.idea.DiscImageChef/.idea/contentModel.xml
generated
13
.idea/.idea.DiscImageChef/.idea/contentModel.xml
generated
@@ -184,6 +184,18 @@
|
|||||||
<e p="Partition.cs" t="Include" />
|
<e p="Partition.cs" t="Include" />
|
||||||
<e p="PluginBase.cs" t="Include" />
|
<e p="PluginBase.cs" t="Include" />
|
||||||
<e p="Structs" t="Include">
|
<e p="Structs" t="Include">
|
||||||
|
<e p="Devices" t="Include">
|
||||||
|
<e p="ATA" t="Include">
|
||||||
|
<e p="Identify.cs" t="Include" />
|
||||||
|
</e>
|
||||||
|
<e p="SCSI" t="Include">
|
||||||
|
<e p="Enums.cs" t="Include" />
|
||||||
|
<e p="Inquiry.cs" t="Include" />
|
||||||
|
<e p="Modes" t="Include">
|
||||||
|
<e p="2A.cs" t="Include" />
|
||||||
|
</e>
|
||||||
|
</e>
|
||||||
|
</e>
|
||||||
<e p="Filesystems.cs" t="Include" />
|
<e p="Filesystems.cs" t="Include" />
|
||||||
<e p="Images.cs" t="Include" />
|
<e p="Images.cs" t="Include" />
|
||||||
<e p="TapeFile.cs" t="Include" />
|
<e p="TapeFile.cs" t="Include" />
|
||||||
@@ -515,7 +527,6 @@
|
|||||||
<e p="SCSI" t="Include">
|
<e p="SCSI" t="Include">
|
||||||
<e p="DiscStructureCapabilities.cs" t="Include" />
|
<e p="DiscStructureCapabilities.cs" t="Include" />
|
||||||
<e p="EVPD.cs" t="Include" />
|
<e p="EVPD.cs" t="Include" />
|
||||||
<e p="Enums.cs" t="Include" />
|
|
||||||
<e p="Inquiry.cs" t="Include" />
|
<e p="Inquiry.cs" t="Include" />
|
||||||
<e p="MMC" t="Include">
|
<e p="MMC" t="Include">
|
||||||
<e p="AACS.cs" t="Include" />
|
<e p="AACS.cs" t="Include" />
|
||||||
|
|||||||
Submodule DiscImageChef.CommonTypes updated: afa1525f0c...1a2a4242eb
@@ -39,8 +39,8 @@ using DiscImageChef.CommonTypes;
|
|||||||
using DiscImageChef.CommonTypes.Enums;
|
using DiscImageChef.CommonTypes.Enums;
|
||||||
using DiscImageChef.CommonTypes.Extents;
|
using DiscImageChef.CommonTypes.Extents;
|
||||||
using DiscImageChef.CommonTypes.Interfaces;
|
using DiscImageChef.CommonTypes.Interfaces;
|
||||||
|
using DiscImageChef.CommonTypes.Structs.Devices.ATA;
|
||||||
using DiscImageChef.Core.Logging;
|
using DiscImageChef.Core.Logging;
|
||||||
using DiscImageChef.Decoders.ATA;
|
|
||||||
using DiscImageChef.Decoders.PCMCIA;
|
using DiscImageChef.Decoders.PCMCIA;
|
||||||
using Schemas;
|
using Schemas;
|
||||||
using Tuple = DiscImageChef.Decoders.PCMCIA.Tuple;
|
using Tuple = DiscImageChef.Decoders.PCMCIA.Tuple;
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using DiscImageChef.CommonTypes.Enums;
|
using DiscImageChef.CommonTypes.Enums;
|
||||||
using DiscImageChef.CommonTypes.Extents;
|
using DiscImageChef.CommonTypes.Extents;
|
||||||
|
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
|
||||||
using DiscImageChef.Console;
|
using DiscImageChef.Console;
|
||||||
using DiscImageChef.Decoders.SCSI;
|
using DiscImageChef.Decoders.SCSI;
|
||||||
using DiscImageChef.Devices;
|
using DiscImageChef.Devices;
|
||||||
|
|||||||
@@ -34,9 +34,9 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using DiscImageChef.CommonTypes;
|
using DiscImageChef.CommonTypes;
|
||||||
using DiscImageChef.CommonTypes.Enums;
|
using DiscImageChef.CommonTypes.Enums;
|
||||||
|
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
|
||||||
using DiscImageChef.Decoders.Bluray;
|
using DiscImageChef.Decoders.Bluray;
|
||||||
using DiscImageChef.Decoders.DVD;
|
using DiscImageChef.Decoders.DVD;
|
||||||
using DiscImageChef.Decoders.SCSI;
|
|
||||||
using DiscImageChef.Decoders.SCSI.MMC;
|
using DiscImageChef.Decoders.SCSI.MMC;
|
||||||
using DiscImageChef.Devices;
|
using DiscImageChef.Devices;
|
||||||
using Schemas;
|
using Schemas;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ using DiscImageChef.CommonTypes.Extents;
|
|||||||
using DiscImageChef.CommonTypes.Interfaces;
|
using DiscImageChef.CommonTypes.Interfaces;
|
||||||
using DiscImageChef.CommonTypes.Metadata;
|
using DiscImageChef.CommonTypes.Metadata;
|
||||||
using DiscImageChef.CommonTypes.Structs;
|
using DiscImageChef.CommonTypes.Structs;
|
||||||
|
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
|
||||||
using DiscImageChef.Console;
|
using DiscImageChef.Console;
|
||||||
using DiscImageChef.Core.Logging;
|
using DiscImageChef.Core.Logging;
|
||||||
using DiscImageChef.Decoders.SCSI;
|
using DiscImageChef.Decoders.SCSI;
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ using DiscImageChef.CommonTypes.Extents;
|
|||||||
using DiscImageChef.CommonTypes.Interfaces;
|
using DiscImageChef.CommonTypes.Interfaces;
|
||||||
using DiscImageChef.CommonTypes.Metadata;
|
using DiscImageChef.CommonTypes.Metadata;
|
||||||
using DiscImageChef.CommonTypes.Structs;
|
using DiscImageChef.CommonTypes.Structs;
|
||||||
|
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
|
||||||
using DiscImageChef.Console;
|
using DiscImageChef.Console;
|
||||||
using DiscImageChef.Core.Logging;
|
using DiscImageChef.Core.Logging;
|
||||||
using DiscImageChef.Decoders.SCSI;
|
using DiscImageChef.Decoders.SCSI;
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using DiscImageChef.CommonTypes;
|
using DiscImageChef.CommonTypes;
|
||||||
using DiscImageChef.CommonTypes.Interfaces;
|
using DiscImageChef.CommonTypes.Interfaces;
|
||||||
|
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
|
||||||
using DiscImageChef.Decoders.SCSI;
|
using DiscImageChef.Decoders.SCSI;
|
||||||
|
|
||||||
namespace DiscImageChef.Core.Devices.Dumping
|
namespace DiscImageChef.Core.Devices.Dumping
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ using DiscImageChef.CommonTypes.Extents;
|
|||||||
using DiscImageChef.CommonTypes.Interfaces;
|
using DiscImageChef.CommonTypes.Interfaces;
|
||||||
using DiscImageChef.CommonTypes.Interop;
|
using DiscImageChef.CommonTypes.Interop;
|
||||||
using DiscImageChef.CommonTypes.Structs;
|
using DiscImageChef.CommonTypes.Structs;
|
||||||
|
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
|
||||||
using DiscImageChef.Console;
|
using DiscImageChef.Console;
|
||||||
using DiscImageChef.Core.Logging;
|
using DiscImageChef.Core.Logging;
|
||||||
using DiscImageChef.Decoders.DVD;
|
using DiscImageChef.Decoders.DVD;
|
||||||
|
|||||||
@@ -33,10 +33,12 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using DiscImageChef.CommonTypes.Enums;
|
using DiscImageChef.CommonTypes.Enums;
|
||||||
|
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
|
||||||
using DiscImageChef.Console;
|
using DiscImageChef.Console;
|
||||||
using DiscImageChef.Decoders.ATA;
|
using DiscImageChef.Decoders.ATA;
|
||||||
using DiscImageChef.Decoders.SCSI;
|
using DiscImageChef.Decoders.SCSI;
|
||||||
using DiscImageChef.Devices;
|
using DiscImageChef.Devices;
|
||||||
|
using Inquiry = DiscImageChef.CommonTypes.Structs.Devices.SCSI.Inquiry;
|
||||||
|
|
||||||
namespace DiscImageChef.Core.Devices.Info
|
namespace DiscImageChef.Core.Devices.Info
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -32,10 +32,12 @@
|
|||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using DiscImageChef.CommonTypes.Enums;
|
using DiscImageChef.CommonTypes.Enums;
|
||||||
|
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
|
||||||
using DiscImageChef.Decoders.ATA;
|
using DiscImageChef.Decoders.ATA;
|
||||||
using DiscImageChef.Decoders.SCSI;
|
using DiscImageChef.Decoders.SCSI;
|
||||||
using DiscImageChef.Decoders.SCSI.SSC;
|
using DiscImageChef.Decoders.SCSI.SSC;
|
||||||
using DiscImageChef.Devices;
|
using DiscImageChef.Devices;
|
||||||
|
using Inquiry = DiscImageChef.CommonTypes.Structs.Devices.SCSI.Inquiry;
|
||||||
|
|
||||||
namespace DiscImageChef.Core.Devices.Info
|
namespace DiscImageChef.Core.Devices.Info
|
||||||
{
|
{
|
||||||
@@ -44,7 +46,7 @@ namespace DiscImageChef.Core.Devices.Info
|
|||||||
public byte[] AtaIdentify { get; }
|
public byte[] AtaIdentify { get; }
|
||||||
public byte[] AtapiIdentify { get; }
|
public byte[] AtapiIdentify { get; }
|
||||||
public byte[] ScsiInquiryData { get; }
|
public byte[] ScsiInquiryData { get; }
|
||||||
public Inquiry.SCSIInquiry? ScsiInquiry { get; }
|
public Inquiry? ScsiInquiry { get; }
|
||||||
public AtaErrorRegistersChs? AtaMcptError { get; }
|
public AtaErrorRegistersChs? AtaMcptError { get; }
|
||||||
public Dictionary<byte, byte[]> ScsiEvpdPages { get; }
|
public Dictionary<byte, byte[]> ScsiEvpdPages { get; }
|
||||||
public Modes.DecodedMode? ScsiMode { get; }
|
public Modes.DecodedMode? ScsiMode { get; }
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using DiscImageChef.CommonTypes.Enums;
|
using DiscImageChef.CommonTypes.Enums;
|
||||||
using DiscImageChef.Decoders.ATA;
|
using DiscImageChef.CommonTypes.Structs.Devices.ATA;
|
||||||
using DiscImageChef.Devices;
|
using DiscImageChef.Devices;
|
||||||
|
|
||||||
namespace DiscImageChef.Core.Devices
|
namespace DiscImageChef.Core.Devices
|
||||||
|
|||||||
@@ -34,10 +34,11 @@ using System;
|
|||||||
using DiscImageChef.CommonTypes.Enums;
|
using DiscImageChef.CommonTypes.Enums;
|
||||||
using DiscImageChef.Console;
|
using DiscImageChef.Console;
|
||||||
using DiscImageChef.Decoders.ATA;
|
using DiscImageChef.Decoders.ATA;
|
||||||
|
using Identify = DiscImageChef.CommonTypes.Structs.Devices.ATA.Identify;
|
||||||
|
|
||||||
namespace DiscImageChef.Core.Devices
|
namespace DiscImageChef.Core.Devices
|
||||||
{
|
{
|
||||||
partial class Reader
|
internal partial class Reader
|
||||||
{
|
{
|
||||||
Identify.IdentifyDevice ataId;
|
Identify.IdentifyDevice ataId;
|
||||||
bool ataRead;
|
bool ataRead;
|
||||||
@@ -60,9 +61,12 @@ namespace DiscImageChef.Core.Devices
|
|||||||
|
|
||||||
(uint, byte, byte) GetDeviceChs()
|
(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)
|
if(ataId.CurrentCylinders > 0 &&
|
||||||
|
ataId.CurrentHeads > 0 &&
|
||||||
|
ataId.CurrentSectorsPerTrack > 0)
|
||||||
{
|
{
|
||||||
Cylinders = ataId.CurrentCylinders;
|
Cylinders = ataId.CurrentCylinders;
|
||||||
Heads = (byte)ataId.CurrentHeads;
|
Heads = (byte)ataId.CurrentHeads;
|
||||||
@@ -70,17 +74,18 @@ namespace DiscImageChef.Core.Devices
|
|||||||
Blocks = (ulong)(Cylinders * Heads * Sectors);
|
Blocks = (ulong)(Cylinders * Heads * Sectors);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ataId.CurrentCylinders != 0 && ataId.CurrentHeads != 0 && ataId.CurrentSectorsPerTrack != 0 ||
|
if((ataId.CurrentCylinders != 0 && ataId.CurrentHeads != 0 && ataId.CurrentSectorsPerTrack != 0) ||
|
||||||
ataId.Cylinders <= 0 ||
|
ataId.Cylinders <= 0 ||
|
||||||
ataId.Heads <= 0 ||
|
ataId.Heads <= 0 ||
|
||||||
ataId.SectorsPerTrack <= 0) return (Cylinders, Heads, Sectors);
|
ataId.SectorsPerTrack <= 0)
|
||||||
|
return(Cylinders, Heads, Sectors);
|
||||||
|
|
||||||
Cylinders = ataId.Cylinders;
|
Cylinders = ataId.Cylinders;
|
||||||
Heads = (byte)ataId.Heads;
|
Heads = (byte)ataId.Heads;
|
||||||
Sectors = (byte)ataId.SectorsPerTrack;
|
Sectors = (byte)ataId.SectorsPerTrack;
|
||||||
Blocks = (ulong)(Cylinders * Heads * Sectors);
|
Blocks = (ulong)(Cylinders * Heads * Sectors);
|
||||||
|
|
||||||
return (Cylinders, Heads, Sectors);
|
return(Cylinders, Heads, Sectors);
|
||||||
}
|
}
|
||||||
|
|
||||||
ulong AtaGetBlocks()
|
ulong AtaGetBlocks()
|
||||||
@@ -93,7 +98,8 @@ namespace DiscImageChef.Core.Devices
|
|||||||
IsLba = true;
|
IsLba = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!ataId.CommandSet2.HasFlag(Identify.CommandSetBit2.LBA48)) return Blocks;
|
if(!ataId.CommandSet2.HasFlag(Identify.CommandSetBit2.LBA48))
|
||||||
|
return Blocks;
|
||||||
|
|
||||||
Blocks = ataId.LBA48Sectors;
|
Blocks = ataId.LBA48Sectors;
|
||||||
IsLba = true;
|
IsLba = true;
|
||||||
@@ -105,6 +111,7 @@ namespace DiscImageChef.Core.Devices
|
|||||||
{
|
{
|
||||||
bool sense = dev.Read(out byte[] cmdBuf, out AtaErrorRegistersChs errorChs, false, 0, 0, 1, 1, timeout,
|
bool sense = dev.Read(out byte[] cmdBuf, out AtaErrorRegistersChs errorChs, false, 0, 0, 1, 1, timeout,
|
||||||
out _);
|
out _);
|
||||||
|
|
||||||
ataRead = !sense && (errorChs.Status & 0x27) == 0 && errorChs.Error == 0 && cmdBuf.Length > 0;
|
ataRead = !sense && (errorChs.Status & 0x27) == 0 && errorChs.Error == 0 && cmdBuf.Length > 0;
|
||||||
sense = dev.Read(out cmdBuf, out errorChs, true, 0, 0, 1, 1, timeout, out _);
|
sense = dev.Read(out cmdBuf, out errorChs, true, 0, 0, 1, 1, timeout, out _);
|
||||||
ataReadRetry = !sense && (errorChs.Status & 0x27) == 0 && errorChs.Error == 0 && cmdBuf.Length > 0;
|
ataReadRetry = !sense && (errorChs.Status & 0x27) == 0 && errorChs.Error == 0 && cmdBuf.Length > 0;
|
||||||
@@ -134,40 +141,62 @@ namespace DiscImageChef.Core.Devices
|
|||||||
|
|
||||||
if(IsLba)
|
if(IsLba)
|
||||||
{
|
{
|
||||||
if(Blocks > 0xFFFFFFF && !ataReadLba48 && !ataReadDmaLba48)
|
if(Blocks > 0xFFFFFFF &&
|
||||||
|
!ataReadLba48 &&
|
||||||
|
!ataReadDmaLba48)
|
||||||
{
|
{
|
||||||
ErrorMessage = "Device needs 48-bit LBA commands but I can't issue them... Aborting.";
|
ErrorMessage = "Device needs 48-bit LBA commands but I can't issue them... Aborting.";
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!ataReadLba && !ataReadRetryLba && !ataReadDmaLba && !ataReadDmaRetryLba)
|
if(!ataReadLba &&
|
||||||
|
!ataReadRetryLba &&
|
||||||
|
!ataReadDmaLba &&
|
||||||
|
!ataReadDmaRetryLba)
|
||||||
{
|
{
|
||||||
ErrorMessage = "Device needs 28-bit LBA commands but I can't issue them... Aborting.";
|
ErrorMessage = "Device needs 28-bit LBA commands but I can't issue them... Aborting.";
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(!ataRead && !ataReadRetry && !ataReadDma && !ataReadDmaRetry)
|
if(!ataRead &&
|
||||||
|
!ataReadRetry &&
|
||||||
|
!ataReadDma &&
|
||||||
|
!ataReadDmaRetry)
|
||||||
{
|
{
|
||||||
ErrorMessage = "Device needs CHS commands but I can't issue them... Aborting.";
|
ErrorMessage = "Device needs CHS commands but I can't issue them... Aborting.";
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ataReadDmaLba48) DicConsole.WriteLine("Using ATA READ DMA EXT command.");
|
if(ataReadDmaLba48)
|
||||||
else if(ataReadLba48) DicConsole.WriteLine("Using ATA READ EXT command.");
|
DicConsole.WriteLine("Using ATA READ DMA EXT command.");
|
||||||
else if(ataReadDmaRetryLba) DicConsole.WriteLine("Using ATA READ DMA command with retries (LBA).");
|
else if(ataReadLba48)
|
||||||
else if(ataReadDmaLba) DicConsole.WriteLine("Using ATA READ DMA command (LBA).");
|
DicConsole.WriteLine("Using ATA READ EXT command.");
|
||||||
else if(ataReadRetryLba) DicConsole.WriteLine("Using ATA READ command with retries (LBA).");
|
else if(ataReadDmaRetryLba)
|
||||||
else if(ataReadLba) DicConsole.WriteLine("Using ATA READ command (LBA).");
|
DicConsole.WriteLine("Using ATA READ DMA command with retries (LBA).");
|
||||||
else if(ataReadDmaRetry) DicConsole.WriteLine("Using ATA READ DMA command with retries (CHS).");
|
else if(ataReadDmaLba)
|
||||||
else if(ataReadDma) DicConsole.WriteLine("Using ATA READ DMA command (CHS).");
|
DicConsole.WriteLine("Using ATA READ DMA command (LBA).");
|
||||||
else if(ataReadRetry) DicConsole.WriteLine("Using ATA READ command with retries (CHS).");
|
else if(ataReadRetryLba)
|
||||||
else if(ataRead) DicConsole.WriteLine("Using ATA READ command (CHS).");
|
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
|
else
|
||||||
{
|
{
|
||||||
ErrorMessage = "Could not get a working read command!";
|
ErrorMessage = "Could not get a working read command!";
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,18 +205,22 @@ namespace DiscImageChef.Core.Devices
|
|||||||
|
|
||||||
bool AtaGetBlockSize()
|
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.PhysLogSectorSize & 0x1000) == 0x1000)
|
||||||
if(ataId.LogicalSectorWords <= 255 || ataId.LogicalAlignment == 0xFFFF)
|
if(ataId.LogicalSectorWords <= 255 ||
|
||||||
|
ataId.LogicalAlignment == 0xFFFF)
|
||||||
LogicalBlockSize = 512;
|
LogicalBlockSize = 512;
|
||||||
else
|
else
|
||||||
LogicalBlockSize = ataId.LogicalSectorWords * 2;
|
LogicalBlockSize = ataId.LogicalSectorWords * 2;
|
||||||
else LogicalBlockSize = 512;
|
else
|
||||||
|
LogicalBlockSize = 512;
|
||||||
|
|
||||||
if((ataId.PhysLogSectorSize & 0x2000) == 0x2000)
|
if((ataId.PhysLogSectorSize & 0x2000) == 0x2000)
|
||||||
PhysicalBlockSize = LogicalBlockSize * (uint)Math.Pow(2, ataId.PhysLogSectorSize & 0xF);
|
PhysicalBlockSize = LogicalBlockSize * (uint)Math.Pow(2, ataId.PhysLogSectorSize & 0xF);
|
||||||
else PhysicalBlockSize = LogicalBlockSize;
|
else
|
||||||
|
PhysicalBlockSize = LogicalBlockSize;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -208,6 +241,7 @@ namespace DiscImageChef.Core.Devices
|
|||||||
if(!IsLba)
|
if(!IsLba)
|
||||||
{
|
{
|
||||||
BlocksToRead = 1;
|
BlocksToRead = 1;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,6 +252,7 @@ namespace DiscImageChef.Core.Devices
|
|||||||
byte[] cmdBuf;
|
byte[] cmdBuf;
|
||||||
bool sense;
|
bool sense;
|
||||||
AtaErrorRegistersLba48 errorLba48;
|
AtaErrorRegistersLba48 errorLba48;
|
||||||
|
|
||||||
if(ataReadDmaLba48)
|
if(ataReadDmaLba48)
|
||||||
{
|
{
|
||||||
sense = dev.ReadDma(out cmdBuf, out errorLba48, 0, (byte)BlocksToRead, timeout, out _);
|
sense = dev.ReadDma(out cmdBuf, out errorLba48, 0, (byte)BlocksToRead, timeout, out _);
|
||||||
@@ -231,6 +266,7 @@ namespace DiscImageChef.Core.Devices
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
AtaErrorRegistersLba28 errorLba;
|
AtaErrorRegistersLba28 errorLba;
|
||||||
|
|
||||||
if(ataReadDmaRetryLba)
|
if(ataReadDmaRetryLba)
|
||||||
{
|
{
|
||||||
sense = dev.ReadDma(out cmdBuf, out errorLba, true, 0, (byte)BlocksToRead, timeout, out _);
|
sense = dev.ReadDma(out cmdBuf, out errorLba, true, 0, (byte)BlocksToRead, timeout, out _);
|
||||||
@@ -253,15 +289,21 @@ namespace DiscImageChef.Core.Devices
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(error) BlocksToRead /= 2;
|
if(error)
|
||||||
|
BlocksToRead /= 2;
|
||||||
|
|
||||||
if(!error || BlocksToRead == 1) break;
|
if(!error ||
|
||||||
|
BlocksToRead == 1)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!error || !IsLba) return false;
|
if(!error ||
|
||||||
|
!IsLba)
|
||||||
|
return false;
|
||||||
|
|
||||||
BlocksToRead = 1;
|
BlocksToRead = 1;
|
||||||
ErrorMessage = $"Device error {dev.LastError} trying to guess ideal transfer length.";
|
ErrorMessage = $"Device error {dev.LastError} trying to guess ideal transfer length.";
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,6 +335,7 @@ namespace DiscImageChef.Core.Devices
|
|||||||
{
|
{
|
||||||
sense = dev.ReadDma(out buffer, out errorLba, true, (uint)block, (byte)count, timeout,
|
sense = dev.ReadDma(out buffer, out errorLba, true, (uint)block, (byte)count, timeout,
|
||||||
out duration);
|
out duration);
|
||||||
|
|
||||||
error = !(!sense && (errorLba.Status & 0x27) == 0 && errorLba.Error == 0 && buffer.Length > 0);
|
error = !(!sense && (errorLba.Status & 0x27) == 0 && errorLba.Error == 0 && buffer.Length > 0);
|
||||||
status = errorLba.Status;
|
status = errorLba.Status;
|
||||||
errorByte = errorLba.Error;
|
errorByte = errorLba.Error;
|
||||||
@@ -301,6 +344,7 @@ namespace DiscImageChef.Core.Devices
|
|||||||
{
|
{
|
||||||
sense = dev.ReadDma(out buffer, out errorLba, false, (uint)block, (byte)count, timeout,
|
sense = dev.ReadDma(out buffer, out errorLba, false, (uint)block, (byte)count, timeout,
|
||||||
out duration);
|
out duration);
|
||||||
|
|
||||||
error = !(!sense && (errorLba.Status & 0x27) == 0 && errorLba.Error == 0 && buffer.Length > 0);
|
error = !(!sense && (errorLba.Status & 0x27) == 0 && errorLba.Error == 0 && buffer.Length > 0);
|
||||||
status = errorLba.Status;
|
status = errorLba.Status;
|
||||||
errorByte = errorLba.Error;
|
errorByte = errorLba.Error;
|
||||||
@@ -320,7 +364,8 @@ namespace DiscImageChef.Core.Devices
|
|||||||
errorByte = errorLba.Error;
|
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;
|
return error;
|
||||||
}
|
}
|
||||||
@@ -338,6 +383,7 @@ namespace DiscImageChef.Core.Devices
|
|||||||
{
|
{
|
||||||
sense = dev.ReadDma(out buffer, out errorChs, true, cylinder, head, sectir, 1, timeout,
|
sense = dev.ReadDma(out buffer, out errorChs, true, cylinder, head, sectir, 1, timeout,
|
||||||
out duration);
|
out duration);
|
||||||
|
|
||||||
error = !(!sense && (errorChs.Status & 0x27) == 0 && errorChs.Error == 0 && buffer.Length > 0);
|
error = !(!sense && (errorChs.Status & 0x27) == 0 && errorChs.Error == 0 && buffer.Length > 0);
|
||||||
status = errorChs.Status;
|
status = errorChs.Status;
|
||||||
errorByte = errorChs.Error;
|
errorByte = errorChs.Error;
|
||||||
@@ -346,6 +392,7 @@ namespace DiscImageChef.Core.Devices
|
|||||||
{
|
{
|
||||||
sense = dev.ReadDma(out buffer, out errorChs, false, cylinder, head, sectir, 1, timeout,
|
sense = dev.ReadDma(out buffer, out errorChs, false, cylinder, head, sectir, 1, timeout,
|
||||||
out duration);
|
out duration);
|
||||||
|
|
||||||
error = !(!sense && (errorChs.Status & 0x27) == 0 && errorChs.Error == 0 && buffer.Length > 0);
|
error = !(!sense && (errorChs.Status & 0x27) == 0 && errorChs.Error == 0 && buffer.Length > 0);
|
||||||
status = errorChs.Status;
|
status = errorChs.Status;
|
||||||
errorByte = errorChs.Error;
|
errorByte = errorChs.Error;
|
||||||
@@ -365,7 +412,8 @@ namespace DiscImageChef.Core.Devices
|
|||||||
errorByte = errorChs.Error;
|
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;
|
return error;
|
||||||
}
|
}
|
||||||
@@ -373,13 +421,15 @@ namespace DiscImageChef.Core.Devices
|
|||||||
bool AtaSeek(ulong block, out double duration)
|
bool AtaSeek(ulong block, out double duration)
|
||||||
{
|
{
|
||||||
bool sense = dev.Seek(out AtaErrorRegistersLba28 errorLba, (uint)block, timeout, out duration);
|
bool sense = dev.Seek(out AtaErrorRegistersLba28 errorLba, (uint)block, timeout, out duration);
|
||||||
return !(!sense && (errorLba.Status & 0x27) == 0 && errorLba.Error == 0);
|
|
||||||
|
return!(!sense && (errorLba.Status & 0x27) == 0 && errorLba.Error == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AtaSeekChs(ushort cylinder, byte head, byte sector, out double duration)
|
bool AtaSeekChs(ushort cylinder, byte head, byte sector, out double duration)
|
||||||
{
|
{
|
||||||
bool sense = dev.Seek(out AtaErrorRegistersChs errorChs, cylinder, head, sector, timeout, out duration);
|
bool sense = dev.Seek(out AtaErrorRegistersChs errorChs, cylinder, head, sector, timeout, out duration);
|
||||||
return !(!sense && (errorChs.Status & 0x27) == 0 && errorChs.Error == 0);
|
|
||||||
|
return!(!sense && (errorChs.Status & 0x27) == 0 && errorChs.Error == 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -31,12 +31,13 @@
|
|||||||
// ****************************************************************************/
|
// ****************************************************************************/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
|
||||||
using DiscImageChef.Console;
|
using DiscImageChef.Console;
|
||||||
using DiscImageChef.Decoders.SCSI;
|
using DiscImageChef.Decoders.SCSI;
|
||||||
|
|
||||||
namespace DiscImageChef.Core.Devices
|
namespace DiscImageChef.Core.Devices
|
||||||
{
|
{
|
||||||
partial class Reader
|
internal partial class Reader
|
||||||
{
|
{
|
||||||
// TODO: Raw reading
|
// TODO: Raw reading
|
||||||
bool hldtstReadRaw;
|
bool hldtstReadRaw;
|
||||||
@@ -72,23 +73,34 @@ namespace DiscImageChef.Core.Devices
|
|||||||
|
|
||||||
seek10 = !dev.Seek10(out senseBuf, 0, timeout, out _);
|
seek10 = !dev.Seek10(out senseBuf, 0, timeout, out _);
|
||||||
|
|
||||||
if(!read6 && !read10 && !read12 && !read16)
|
if(!read6 &&
|
||||||
|
!read10 &&
|
||||||
|
!read12 &&
|
||||||
|
!read16)
|
||||||
{
|
{
|
||||||
ErrorMessage = "Cannot read medium, aborting scan...";
|
ErrorMessage = "Cannot read medium, aborting scan...";
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(read6 && !read10 && !read12 && !read16 && Blocks > 0x001FFFFF + 1)
|
if(read6 &&
|
||||||
|
!read10 &&
|
||||||
|
!read12 &&
|
||||||
|
!read16 &&
|
||||||
|
Blocks > 0x001FFFFF + 1)
|
||||||
{
|
{
|
||||||
ErrorMessage =
|
ErrorMessage =
|
||||||
$"Device only supports SCSI READ (6) but has more than {0x001FFFFF + 1} blocks ({Blocks} blocks total)";
|
$"Device only supports SCSI READ (6) but has more than {0x001FFFFF + 1} blocks ({Blocks} blocks total)";
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!read16 && Blocks > 0xFFFFFFFF + (long)1)
|
if(!read16 &&
|
||||||
|
Blocks > 0xFFFFFFFF + (long)1)
|
||||||
{
|
{
|
||||||
ErrorMessage =
|
ErrorMessage =
|
||||||
$"Device only supports SCSI READ (10) but has more than {0xFFFFFFFF + (long)1} blocks ({Blocks} blocks total)";
|
$"Device only supports SCSI READ (10) but has more than {0xFFFFFFFF + (long)1} blocks ({Blocks} blocks total)";
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,17 +132,23 @@ namespace DiscImageChef.Core.Devices
|
|||||||
|
|
||||||
testSense = dev.ReadLong10(out _, out senseBuf, false, false, 0, 0xFFFF, timeout, out _);
|
testSense = dev.ReadLong10(out _, out senseBuf, false, false, 0, 0xFFFF, timeout, out _);
|
||||||
FixedSense? decSense;
|
FixedSense? decSense;
|
||||||
|
|
||||||
if(testSense && !dev.Error)
|
if(testSense && !dev.Error)
|
||||||
{
|
{
|
||||||
decSense = Sense.DecodeFixed(senseBuf);
|
decSense = Sense.DecodeFixed(senseBuf);
|
||||||
|
|
||||||
if(decSense.HasValue)
|
if(decSense.HasValue)
|
||||||
if(decSense.Value.SenseKey == SenseKeys.IllegalRequest && decSense.Value.ASC == 0x24 &&
|
if(decSense.Value.SenseKey == SenseKeys.IllegalRequest &&
|
||||||
|
decSense.Value.ASC == 0x24 &&
|
||||||
decSense.Value.ASCQ == 0x00)
|
decSense.Value.ASCQ == 0x00)
|
||||||
{
|
{
|
||||||
CanReadRaw = true;
|
CanReadRaw = true;
|
||||||
if(decSense.Value.InformationValid && decSense.Value.ILI)
|
|
||||||
|
if(decSense.Value.InformationValid &&
|
||||||
|
decSense.Value.ILI)
|
||||||
{
|
{
|
||||||
LongBlockSize = 0xFFFF - (decSense.Value.Information & 0xFFFF);
|
LongBlockSize = 0xFFFF - (decSense.Value.Information & 0xFFFF);
|
||||||
|
|
||||||
readLong10 = !dev.ReadLong10(out _, out senseBuf, false, false, 0,
|
readLong10 = !dev.ReadLong10(out _, out senseBuf, false, false, 0,
|
||||||
(ushort)LongBlockSize, timeout, out _);
|
(ushort)LongBlockSize, timeout, out _);
|
||||||
}
|
}
|
||||||
@@ -143,29 +161,37 @@ namespace DiscImageChef.Core.Devices
|
|||||||
{
|
{
|
||||||
// Long sector sizes for floppies
|
// Long sector sizes for floppies
|
||||||
514,
|
514,
|
||||||
|
|
||||||
// Long sector sizes for SuperDisk
|
// Long sector sizes for SuperDisk
|
||||||
536, 558,
|
536, 558,
|
||||||
|
|
||||||
// Long sector sizes for 512-byte magneto-opticals
|
// Long sector sizes for 512-byte magneto-opticals
|
||||||
600, 610, 630
|
600, 610, 630
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
ushort testSize = (ushort)i;
|
ushort testSize = (ushort)i;
|
||||||
testSense = dev.ReadLong16(out _, out senseBuf, false, 0, testSize, timeout, out _);
|
testSense = dev.ReadLong16(out _, out senseBuf, false, 0, testSize, timeout, out _);
|
||||||
if(!testSense && !dev.Error)
|
|
||||||
|
if(!testSense &&
|
||||||
|
!dev.Error)
|
||||||
{
|
{
|
||||||
readLong16 = true;
|
readLong16 = true;
|
||||||
LongBlockSize = testSize;
|
LongBlockSize = testSize;
|
||||||
CanReadRaw = true;
|
CanReadRaw = true;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
testSense = dev.ReadLong10(out _, out senseBuf, false, false, 0, testSize, timeout,
|
testSense = dev.ReadLong10(out _, out senseBuf, false, false, 0, testSize, timeout,
|
||||||
out _);
|
out _);
|
||||||
if(testSense || dev.Error) continue;
|
|
||||||
|
if(testSense || dev.Error)
|
||||||
|
continue;
|
||||||
|
|
||||||
readLong10 = true;
|
readLong10 = true;
|
||||||
LongBlockSize = testSize;
|
LongBlockSize = testSize;
|
||||||
CanReadRaw = true;
|
CanReadRaw = true;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if(LogicalBlockSize == 1024)
|
else if(LogicalBlockSize == 1024)
|
||||||
@@ -173,33 +199,42 @@ namespace DiscImageChef.Core.Devices
|
|||||||
{
|
{
|
||||||
// Long sector sizes for floppies
|
// Long sector sizes for floppies
|
||||||
1026,
|
1026,
|
||||||
|
|
||||||
// Long sector sizes for 1024-byte magneto-opticals
|
// Long sector sizes for 1024-byte magneto-opticals
|
||||||
1200
|
1200
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
ushort testSize = (ushort)i;
|
ushort testSize = (ushort)i;
|
||||||
testSense = dev.ReadLong16(out _, out senseBuf, false, 0, testSize, timeout, out _);
|
testSense = dev.ReadLong16(out _, out senseBuf, false, 0, testSize, timeout, out _);
|
||||||
if(!testSense && !dev.Error)
|
|
||||||
|
if(!testSense &&
|
||||||
|
!dev.Error)
|
||||||
{
|
{
|
||||||
readLong16 = true;
|
readLong16 = true;
|
||||||
LongBlockSize = testSize;
|
LongBlockSize = testSize;
|
||||||
CanReadRaw = true;
|
CanReadRaw = true;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
testSense = dev.ReadLong10(out _, out senseBuf, false, false, 0, testSize, timeout,
|
testSense = dev.ReadLong10(out _, out senseBuf, false, false, 0, testSize, timeout,
|
||||||
out _);
|
out _);
|
||||||
if(testSense || dev.Error) continue;
|
|
||||||
|
if(testSense || dev.Error)
|
||||||
|
continue;
|
||||||
|
|
||||||
readLong10 = true;
|
readLong10 = true;
|
||||||
LongBlockSize = testSize;
|
LongBlockSize = testSize;
|
||||||
CanReadRaw = true;
|
CanReadRaw = true;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if(LogicalBlockSize == 2048)
|
else if(LogicalBlockSize == 2048)
|
||||||
{
|
{
|
||||||
testSense = dev.ReadLong16(out _, out senseBuf, false, 0, 2380, timeout, out _);
|
testSense = dev.ReadLong16(out _, out senseBuf, false, 0, 2380, timeout, out _);
|
||||||
if(!testSense && !dev.Error)
|
|
||||||
|
if(!testSense &&
|
||||||
|
!dev.Error)
|
||||||
{
|
{
|
||||||
readLong16 = true;
|
readLong16 = true;
|
||||||
LongBlockSize = 2380;
|
LongBlockSize = 2380;
|
||||||
@@ -208,7 +243,9 @@ namespace DiscImageChef.Core.Devices
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
testSense = dev.ReadLong10(out _, out senseBuf, false, false, 0, 2380, timeout, out _);
|
testSense = dev.ReadLong10(out _, out senseBuf, false, false, 0, 2380, timeout, out _);
|
||||||
if(!testSense && !dev.Error)
|
|
||||||
|
if(!testSense &&
|
||||||
|
!dev.Error)
|
||||||
{
|
{
|
||||||
readLong10 = true;
|
readLong10 = true;
|
||||||
LongBlockSize = 2380;
|
LongBlockSize = 2380;
|
||||||
@@ -219,7 +256,9 @@ namespace DiscImageChef.Core.Devices
|
|||||||
else if(LogicalBlockSize == 4096)
|
else if(LogicalBlockSize == 4096)
|
||||||
{
|
{
|
||||||
testSense = dev.ReadLong16(out _, out senseBuf, false, 0, 4760, timeout, out _);
|
testSense = dev.ReadLong16(out _, out senseBuf, false, 0, 4760, timeout, out _);
|
||||||
if(!testSense && !dev.Error)
|
|
||||||
|
if(!testSense &&
|
||||||
|
!dev.Error)
|
||||||
{
|
{
|
||||||
readLong16 = true;
|
readLong16 = true;
|
||||||
LongBlockSize = 4760;
|
LongBlockSize = 4760;
|
||||||
@@ -228,7 +267,9 @@ namespace DiscImageChef.Core.Devices
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
testSense = dev.ReadLong10(out _, out senseBuf, false, false, 0, 4760, timeout, out _);
|
testSense = dev.ReadLong10(out _, out senseBuf, false, false, 0, 4760, timeout, out _);
|
||||||
if(!testSense && !dev.Error)
|
|
||||||
|
if(!testSense &&
|
||||||
|
!dev.Error)
|
||||||
{
|
{
|
||||||
readLong10 = true;
|
readLong10 = true;
|
||||||
LongBlockSize = 4760;
|
LongBlockSize = 4760;
|
||||||
@@ -239,7 +280,9 @@ namespace DiscImageChef.Core.Devices
|
|||||||
else if(LogicalBlockSize == 8192)
|
else if(LogicalBlockSize == 8192)
|
||||||
{
|
{
|
||||||
testSense = dev.ReadLong16(out _, out senseBuf, false, 0, 9424, timeout, out _);
|
testSense = dev.ReadLong16(out _, out senseBuf, false, 0, 9424, timeout, out _);
|
||||||
if(!testSense && !dev.Error)
|
|
||||||
|
if(!testSense &&
|
||||||
|
!dev.Error)
|
||||||
{
|
{
|
||||||
readLong16 = true;
|
readLong16 = true;
|
||||||
LongBlockSize = 9424;
|
LongBlockSize = 9424;
|
||||||
@@ -248,7 +291,9 @@ namespace DiscImageChef.Core.Devices
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
testSense = dev.ReadLong10(out _, out senseBuf, false, false, 0, 9424, timeout, out _);
|
testSense = dev.ReadLong10(out _, out senseBuf, false, false, 0, 9424, timeout, out _);
|
||||||
if(!testSense && !dev.Error)
|
|
||||||
|
if(!testSense &&
|
||||||
|
!dev.Error)
|
||||||
{
|
{
|
||||||
readLong10 = true;
|
readLong10 = true;
|
||||||
LongBlockSize = 9424;
|
LongBlockSize = 9424;
|
||||||
@@ -257,20 +302,27 @@ namespace DiscImageChef.Core.Devices
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!CanReadRaw && dev.Manufacturer == "SYQUEST")
|
if(!CanReadRaw &&
|
||||||
|
dev.Manufacturer == "SYQUEST")
|
||||||
{
|
{
|
||||||
testSense = dev.SyQuestReadLong10(out _, out senseBuf, 0, 0xFFFF, timeout, out _);
|
testSense = dev.SyQuestReadLong10(out _, out senseBuf, 0, 0xFFFF, timeout, out _);
|
||||||
|
|
||||||
if(testSense)
|
if(testSense)
|
||||||
{
|
{
|
||||||
decSense = Sense.DecodeFixed(senseBuf);
|
decSense = Sense.DecodeFixed(senseBuf);
|
||||||
|
|
||||||
if(decSense.HasValue)
|
if(decSense.HasValue)
|
||||||
if(decSense.Value.SenseKey == SenseKeys.IllegalRequest && decSense.Value.ASC == 0x24 &&
|
if(decSense.Value.SenseKey == SenseKeys.IllegalRequest &&
|
||||||
|
decSense.Value.ASC == 0x24 &&
|
||||||
decSense.Value.ASCQ == 0x00)
|
decSense.Value.ASCQ == 0x00)
|
||||||
{
|
{
|
||||||
CanReadRaw = true;
|
CanReadRaw = true;
|
||||||
if(decSense.Value.InformationValid && decSense.Value.ILI)
|
|
||||||
|
if(decSense.Value.InformationValid &&
|
||||||
|
decSense.Value.ILI)
|
||||||
{
|
{
|
||||||
LongBlockSize = 0xFFFF - (decSense.Value.Information & 0xFFFF);
|
LongBlockSize = 0xFFFF - (decSense.Value.Information & 0xFFFF);
|
||||||
|
|
||||||
syqReadLong10 =
|
syqReadLong10 =
|
||||||
!dev.SyQuestReadLong10(out _, out senseBuf, 0, LongBlockSize, timeout,
|
!dev.SyQuestReadLong10(out _, out senseBuf, 0, LongBlockSize, timeout,
|
||||||
out _);
|
out _);
|
||||||
@@ -279,18 +331,23 @@ namespace DiscImageChef.Core.Devices
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
testSense = dev.SyQuestReadLong6(out _, out senseBuf, 0, 0xFFFF, timeout, out _);
|
testSense = dev.SyQuestReadLong6(out _, out senseBuf, 0, 0xFFFF, timeout, out _);
|
||||||
|
|
||||||
if(testSense)
|
if(testSense)
|
||||||
{
|
{
|
||||||
decSense = Sense.DecodeFixed(senseBuf);
|
decSense = Sense.DecodeFixed(senseBuf);
|
||||||
|
|
||||||
if(decSense.HasValue)
|
if(decSense.HasValue)
|
||||||
if(decSense.Value.SenseKey == SenseKeys.IllegalRequest &&
|
if(decSense.Value.SenseKey == SenseKeys.IllegalRequest &&
|
||||||
decSense.Value.ASC == 0x24 &&
|
decSense.Value.ASC == 0x24 &&
|
||||||
decSense.Value.ASCQ == 0x00)
|
decSense.Value.ASCQ == 0x00)
|
||||||
{
|
{
|
||||||
CanReadRaw = true;
|
CanReadRaw = true;
|
||||||
if(decSense.Value.InformationValid && decSense.Value.ILI)
|
|
||||||
|
if(decSense.Value.InformationValid &&
|
||||||
|
decSense.Value.ILI)
|
||||||
{
|
{
|
||||||
LongBlockSize = 0xFFFF - (decSense.Value.Information & 0xFFFF);
|
LongBlockSize = 0xFFFF - (decSense.Value.Information & 0xFFFF);
|
||||||
|
|
||||||
syqReadLong6 =
|
syqReadLong6 =
|
||||||
!dev.SyQuestReadLong6(out _, out senseBuf, 0, LongBlockSize,
|
!dev.SyQuestReadLong6(out _, out senseBuf, 0, LongBlockSize,
|
||||||
timeout, out _);
|
timeout, out _);
|
||||||
@@ -300,10 +357,13 @@ namespace DiscImageChef.Core.Devices
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!CanReadRaw && LogicalBlockSize == 256)
|
if(!CanReadRaw &&
|
||||||
|
LogicalBlockSize == 256)
|
||||||
{
|
{
|
||||||
testSense = dev.SyQuestReadLong6(out _, out senseBuf, 0, 262, timeout, out _);
|
testSense = dev.SyQuestReadLong6(out _, out senseBuf, 0, 262, timeout, out _);
|
||||||
if(!testSense && !dev.Error)
|
|
||||||
|
if(!testSense &&
|
||||||
|
!dev.Error)
|
||||||
{
|
{
|
||||||
syqReadLong6 = true;
|
syqReadLong6 = true;
|
||||||
LongBlockSize = 262;
|
LongBlockSize = 262;
|
||||||
@@ -316,11 +376,13 @@ namespace DiscImageChef.Core.Devices
|
|||||||
{
|
{
|
||||||
switch(dev.Manufacturer)
|
switch(dev.Manufacturer)
|
||||||
{
|
{
|
||||||
case "HL-DT-ST":
|
case"HL-DT-ST":
|
||||||
hldtstReadRaw = !dev.HlDtStReadRawDvd(out _, out senseBuf, 0, 1, timeout, out _);
|
hldtstReadRaw = !dev.HlDtStReadRawDvd(out _, out senseBuf, 0, 1, timeout, out _);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case "PLEXTOR":
|
case"PLEXTOR":
|
||||||
plextorReadRaw = !dev.PlextorReadRawDvd(out _, out senseBuf, 0, 1, timeout, out _);
|
plextorReadRaw = !dev.PlextorReadRawDvd(out _, out senseBuf, 0, 1, timeout, out _);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -331,10 +393,13 @@ namespace DiscImageChef.Core.Devices
|
|||||||
}
|
}
|
||||||
|
|
||||||
// READ LONG (10) for some DVD drives
|
// READ LONG (10) for some DVD drives
|
||||||
if(!CanReadRaw && dev.Manufacturer == "MATSHITA")
|
if(!CanReadRaw &&
|
||||||
|
dev.Manufacturer == "MATSHITA")
|
||||||
{
|
{
|
||||||
testSense = dev.ReadLong10(out _, out senseBuf, false, false, 0, 37856, timeout, out _);
|
testSense = dev.ReadLong10(out _, out senseBuf, false, false, 0, 37856, timeout, out _);
|
||||||
if(!testSense && !dev.Error)
|
|
||||||
|
if(!testSense &&
|
||||||
|
!dev.Error)
|
||||||
{
|
{
|
||||||
readLongDvd = true;
|
readLongDvd = true;
|
||||||
LongBlockSize = 37856;
|
LongBlockSize = 37856;
|
||||||
@@ -346,17 +411,27 @@ namespace DiscImageChef.Core.Devices
|
|||||||
|
|
||||||
if(CanReadRaw)
|
if(CanReadRaw)
|
||||||
{
|
{
|
||||||
if(readLong16) DicConsole.WriteLine("Using SCSI READ LONG (16) command.");
|
if(readLong16)
|
||||||
else if(readLong10 || readLongDvd) DicConsole.WriteLine("Using SCSI READ LONG (10) command.");
|
DicConsole.WriteLine("Using SCSI READ LONG (16) command.");
|
||||||
else if(syqReadLong10) DicConsole.WriteLine("Using SyQuest READ LONG (10) command.");
|
else if(readLong10 || readLongDvd)
|
||||||
else if(syqReadLong6) DicConsole.WriteLine("Using SyQuest READ LONG (6) command.");
|
DicConsole.WriteLine("Using SCSI READ LONG (10) command.");
|
||||||
else if(hldtstReadRaw) DicConsole.WriteLine("Using HL-DT-ST raw DVD reading.");
|
else if(syqReadLong10)
|
||||||
else if(plextorReadRaw) DicConsole.WriteLine("Using Plextor raw DVD reading.");
|
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(read16)
|
||||||
else if(read12) DicConsole.WriteLine("Using SCSI READ (12) command.");
|
DicConsole.WriteLine("Using SCSI READ (16) command.");
|
||||||
else if(read10) DicConsole.WriteLine("Using SCSI READ (10) command.");
|
else if(read12)
|
||||||
else if(read6) DicConsole.WriteLine("Using SCSI READ (6) command.");
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -367,6 +442,7 @@ namespace DiscImageChef.Core.Devices
|
|||||||
Blocks = 0;
|
Blocks = 0;
|
||||||
|
|
||||||
sense = dev.ReadCapacity(out byte[] cmdBuf, out byte[] senseBuf, timeout, out _);
|
sense = dev.ReadCapacity(out byte[] cmdBuf, out byte[] senseBuf, timeout, out _);
|
||||||
|
|
||||||
if(!sense)
|
if(!sense)
|
||||||
{
|
{
|
||||||
Blocks = (ulong)((cmdBuf[0] << 24) + (cmdBuf[1] << 16) + (cmdBuf[2] << 8) + cmdBuf[3]);
|
Blocks = (ulong)((cmdBuf[0] << 24) + (cmdBuf[1] << 16) + (cmdBuf[2] << 8) + cmdBuf[3]);
|
||||||
@@ -398,6 +474,7 @@ namespace DiscImageChef.Core.Devices
|
|||||||
|
|
||||||
PhysicalBlockSize = LogicalBlockSize;
|
PhysicalBlockSize = LogicalBlockSize;
|
||||||
LongBlockSize = LogicalBlockSize;
|
LongBlockSize = LogicalBlockSize;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -411,33 +488,45 @@ namespace DiscImageChef.Core.Devices
|
|||||||
{
|
{
|
||||||
dev.Read16(out _, out _, 0, false, true, false, 0, LogicalBlockSize, 0, BlocksToRead, false,
|
dev.Read16(out _, out _, 0, false, true, false, 0, LogicalBlockSize, 0, BlocksToRead, false,
|
||||||
timeout, out _);
|
timeout, out _);
|
||||||
if(dev.Error) BlocksToRead /= 2;
|
|
||||||
|
if(dev.Error)
|
||||||
|
BlocksToRead /= 2;
|
||||||
}
|
}
|
||||||
else if(read12)
|
else if(read12)
|
||||||
{
|
{
|
||||||
dev.Read12(out _, out _, 0, false, false, false, false, 0, LogicalBlockSize, 0, BlocksToRead, false,
|
dev.Read12(out _, out _, 0, false, false, false, false, 0, LogicalBlockSize, 0, BlocksToRead, false,
|
||||||
timeout, out _);
|
timeout, out _);
|
||||||
if(dev.Error) BlocksToRead /= 2;
|
|
||||||
|
if(dev.Error)
|
||||||
|
BlocksToRead /= 2;
|
||||||
}
|
}
|
||||||
else if(read10)
|
else if(read10)
|
||||||
{
|
{
|
||||||
dev.Read10(out _, out _, 0, false, true, false, false, 0, LogicalBlockSize, 0, (ushort)BlocksToRead,
|
dev.Read10(out _, out _, 0, false, true, false, false, 0, LogicalBlockSize, 0, (ushort)BlocksToRead,
|
||||||
timeout, out _);
|
timeout, out _);
|
||||||
if(dev.Error) BlocksToRead /= 2;
|
|
||||||
|
if(dev.Error)
|
||||||
|
BlocksToRead /= 2;
|
||||||
}
|
}
|
||||||
else if(read6)
|
else if(read6)
|
||||||
{
|
{
|
||||||
dev.Read6(out _, out _, 0, LogicalBlockSize, (byte)BlocksToRead, timeout, out _);
|
dev.Read6(out _, out _, 0, LogicalBlockSize, (byte)BlocksToRead, timeout, out _);
|
||||||
if(dev.Error) BlocksToRead /= 2;
|
|
||||||
|
if(dev.Error)
|
||||||
|
BlocksToRead /= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!dev.Error || BlocksToRead == 1) break;
|
if(!dev.Error ||
|
||||||
|
BlocksToRead == 1)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!dev.Error) return false;
|
if(!dev.Error)
|
||||||
|
return false;
|
||||||
|
|
||||||
BlocksToRead = 1;
|
BlocksToRead = 1;
|
||||||
ErrorMessage = $"Device error {dev.LastError} trying to guess ideal transfer length.";
|
ErrorMessage = $"Device error {dev.LastError} trying to guess ideal transfer length.";
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -467,7 +556,8 @@ namespace DiscImageChef.Core.Devices
|
|||||||
else if(plextorReadRaw)
|
else if(plextorReadRaw)
|
||||||
sense = dev.PlextorReadRawDvd(out buffer, out senseBuf, (uint)block, LongBlockSize, timeout,
|
sense = dev.PlextorReadRawDvd(out buffer, out senseBuf, (uint)block, LongBlockSize, timeout,
|
||||||
out duration);
|
out duration);
|
||||||
else return true;
|
else
|
||||||
|
return true;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(read16)
|
if(read16)
|
||||||
@@ -482,12 +572,16 @@ namespace DiscImageChef.Core.Devices
|
|||||||
else if(read6)
|
else if(read6)
|
||||||
sense = dev.Read6(out buffer, out senseBuf, (uint)block, LogicalBlockSize, (byte)count, timeout,
|
sense = dev.Read6(out buffer, out senseBuf, (uint)block, LogicalBlockSize, (byte)count, timeout,
|
||||||
out duration);
|
out duration);
|
||||||
else return true;
|
else
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!sense && !dev.Error) return false;
|
if(!sense &&
|
||||||
|
!dev.Error)
|
||||||
|
return false;
|
||||||
|
|
||||||
DicConsole.DebugWriteLine("SCSI Reader", "READ error:\n{0}", Sense.PrettifySense(senseBuf));
|
DicConsole.DebugWriteLine("SCSI Reader", "READ error:\n{0}", Sense.PrettifySense(senseBuf));
|
||||||
|
|
||||||
return sense;
|
return sense;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -496,8 +590,10 @@ namespace DiscImageChef.Core.Devices
|
|||||||
bool sense = true;
|
bool sense = true;
|
||||||
duration = 0;
|
duration = 0;
|
||||||
|
|
||||||
if(seek6) sense = dev.Seek6(out _, (uint)block, timeout, out duration);
|
if(seek6)
|
||||||
else if(seek10) sense = dev.Seek10(out _, (uint)block, timeout, out duration);
|
sense = dev.Seek6(out _, (uint)block, timeout, out duration);
|
||||||
|
else if(seek10)
|
||||||
|
sense = dev.Seek10(out _, (uint)block, timeout, out duration);
|
||||||
|
|
||||||
return sense;
|
return sense;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ using DiscImageChef.CommonTypes.Metadata;
|
|||||||
using DiscImageChef.Console;
|
using DiscImageChef.Console;
|
||||||
using DiscImageChef.Decoders.ATA;
|
using DiscImageChef.Decoders.ATA;
|
||||||
using DiscImageChef.Devices;
|
using DiscImageChef.Devices;
|
||||||
|
using Identify = DiscImageChef.CommonTypes.Structs.Devices.ATA.Identify;
|
||||||
|
|
||||||
namespace DiscImageChef.Core.Devices.Report
|
namespace DiscImageChef.Core.Devices.Report
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -34,9 +34,11 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using DiscImageChef.CommonTypes.Metadata;
|
using DiscImageChef.CommonTypes.Metadata;
|
||||||
|
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
|
||||||
using DiscImageChef.Console;
|
using DiscImageChef.Console;
|
||||||
using DiscImageChef.Decoders.SCSI;
|
using DiscImageChef.Decoders.SCSI;
|
||||||
using DiscImageChef.Devices;
|
using DiscImageChef.Devices;
|
||||||
|
using Inquiry = DiscImageChef.CommonTypes.Structs.Devices.SCSI.Inquiry;
|
||||||
|
|
||||||
namespace DiscImageChef.Core.Devices.Report
|
namespace DiscImageChef.Core.Devices.Report
|
||||||
{
|
{
|
||||||
@@ -52,12 +54,12 @@ namespace DiscImageChef.Core.Devices.Report
|
|||||||
if(sense)
|
if(sense)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
Inquiry.SCSIInquiry? decodedNullable = Inquiry.Decode(buffer);
|
Inquiry? decodedNullable = Inquiry.Decode(buffer);
|
||||||
|
|
||||||
if(!decodedNullable.HasValue)
|
if(!decodedNullable.HasValue)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
Inquiry.SCSIInquiry decoded = decodedNullable.Value;
|
Inquiry decoded = decodedNullable.Value;
|
||||||
|
|
||||||
// Clear Seagate serial number
|
// Clear Seagate serial number
|
||||||
if(decoded.SeagatePresent &&
|
if(decoded.SeagatePresent &&
|
||||||
|
|||||||
@@ -32,38 +32,39 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using DiscImageChef.CommonTypes.Structs.Devices.ATA;
|
||||||
using DiscImageChef.Core.Logging;
|
using DiscImageChef.Core.Logging;
|
||||||
using DiscImageChef.Decoders.ATA;
|
|
||||||
|
|
||||||
namespace DiscImageChef.Core.Devices.Scanning
|
namespace DiscImageChef.Core.Devices.Scanning
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>Implements scanning the media from an ATA device</summary>
|
||||||
/// Implements scanning the media from an ATA device
|
|
||||||
/// </summary>
|
|
||||||
public partial class MediaScan
|
public partial class MediaScan
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>Scans the media from an ATA device</summary>
|
||||||
/// Scans the media from an ATA device
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>Scanning results</returns>
|
/// <returns>Scanning results</returns>
|
||||||
ScanResults Ata()
|
ScanResults Ata()
|
||||||
{
|
{
|
||||||
ScanResults results = new ScanResults();
|
var results = new ScanResults();
|
||||||
bool sense;
|
bool sense;
|
||||||
results.Blocks = 0;
|
results.Blocks = 0;
|
||||||
const ushort ATA_PROFILE = 0x0001;
|
const ushort ATA_PROFILE = 0x0001;
|
||||||
const uint TIMEOUT = 5;
|
const uint TIMEOUT = 5;
|
||||||
|
|
||||||
sense = dev.AtaIdentify(out byte[] cmdBuf, out _);
|
sense = dev.AtaIdentify(out byte[] cmdBuf, out _);
|
||||||
if(!sense && Identify.Decode(cmdBuf).HasValue)
|
|
||||||
|
if(!sense &&
|
||||||
|
Identify.Decode(cmdBuf).HasValue)
|
||||||
{
|
{
|
||||||
// Initializate reader
|
// Initializate reader
|
||||||
Reader ataReader = new Reader(dev, TIMEOUT, cmdBuf);
|
var ataReader = new Reader(dev, TIMEOUT, cmdBuf);
|
||||||
|
|
||||||
// Fill reader blocks
|
// Fill reader blocks
|
||||||
results.Blocks = ataReader.GetDeviceBlocks();
|
results.Blocks = ataReader.GetDeviceBlocks();
|
||||||
|
|
||||||
if(ataReader.FindReadCommand())
|
if(ataReader.FindReadCommand())
|
||||||
{
|
{
|
||||||
StoppingErrorMessage?.Invoke(ataReader.ErrorMessage);
|
StoppingErrorMessage?.Invoke(ataReader.ErrorMessage);
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,14 +72,17 @@ namespace DiscImageChef.Core.Devices.Scanning
|
|||||||
if(ataReader.GetBlockSize())
|
if(ataReader.GetBlockSize())
|
||||||
{
|
{
|
||||||
StoppingErrorMessage?.Invoke(ataReader.ErrorMessage);
|
StoppingErrorMessage?.Invoke(ataReader.ErrorMessage);
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint blockSize = ataReader.LogicalBlockSize;
|
uint blockSize = ataReader.LogicalBlockSize;
|
||||||
|
|
||||||
// Check how many blocks to read, if error show and return
|
// Check how many blocks to read, if error show and return
|
||||||
if(ataReader.GetBlocksToRead())
|
if(ataReader.GetBlocksToRead())
|
||||||
{
|
{
|
||||||
StoppingErrorMessage?.Invoke(ataReader.ErrorMessage);
|
StoppingErrorMessage?.Invoke(ataReader.ErrorMessage);
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,11 +112,12 @@ namespace DiscImageChef.Core.Devices.Scanning
|
|||||||
|
|
||||||
double seekCur;
|
double seekCur;
|
||||||
|
|
||||||
Random rnd = new Random();
|
var rnd = new Random();
|
||||||
|
|
||||||
MhddLog mhddLog;
|
MhddLog mhddLog;
|
||||||
IbgLog ibgLog;
|
IbgLog ibgLog;
|
||||||
double duration;
|
double duration;
|
||||||
|
|
||||||
if(ataReader.IsLba)
|
if(ataReader.IsLba)
|
||||||
{
|
{
|
||||||
UpdateStatus?.Invoke($"Reading {blocksToRead} sectors at a time.");
|
UpdateStatus?.Invoke($"Reading {blocksToRead} sectors at a time.");
|
||||||
@@ -125,15 +130,23 @@ namespace DiscImageChef.Core.Devices.Scanning
|
|||||||
DateTime timeSpeedStart = DateTime.UtcNow;
|
DateTime timeSpeedStart = DateTime.UtcNow;
|
||||||
ulong sectorSpeedStart = 0;
|
ulong sectorSpeedStart = 0;
|
||||||
InitProgress?.Invoke();
|
InitProgress?.Invoke();
|
||||||
|
|
||||||
for(ulong i = 0; i < results.Blocks; i += blocksToRead)
|
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
|
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
|
||||||
if(currentSpeed > results.MaxSpeed && currentSpeed != 0) results.MaxSpeed = currentSpeed;
|
if(currentSpeed > results.MaxSpeed &&
|
||||||
if(currentSpeed < results.MinSpeed && currentSpeed != 0) results.MinSpeed = currentSpeed;
|
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
|
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
|
||||||
|
|
||||||
UpdateProgress?.Invoke($"Reading sector {i} of {results.Blocks} ({currentSpeed:F3} MiB/sec.)",
|
UpdateProgress?.Invoke($"Reading sector {i} of {results.Blocks} ({currentSpeed:F3} MiB/sec.)",
|
||||||
@@ -143,12 +156,18 @@ namespace DiscImageChef.Core.Devices.Scanning
|
|||||||
|
|
||||||
if(!error)
|
if(!error)
|
||||||
{
|
{
|
||||||
if(duration >= 500) results.F += blocksToRead;
|
if(duration >= 500)
|
||||||
else if(duration >= 150) results.E += blocksToRead;
|
results.F += blocksToRead;
|
||||||
else if(duration >= 50) results.D += blocksToRead;
|
else if(duration >= 150)
|
||||||
else if(duration >= 10) results.C += blocksToRead;
|
results.E += blocksToRead;
|
||||||
else if(duration >= 3) results.B += blocksToRead;
|
else if(duration >= 50)
|
||||||
else results.A += blocksToRead;
|
results.D += blocksToRead;
|
||||||
|
else if(duration >= 10)
|
||||||
|
results.C += blocksToRead;
|
||||||
|
else if(duration >= 3)
|
||||||
|
results.B += blocksToRead;
|
||||||
|
else
|
||||||
|
results.A += blocksToRead;
|
||||||
|
|
||||||
ScanTime?.Invoke(i, duration);
|
ScanTime?.Invoke(i, duration);
|
||||||
mhddLog.Write(i, duration);
|
mhddLog.Write(i, duration);
|
||||||
@@ -158,7 +177,9 @@ namespace DiscImageChef.Core.Devices.Scanning
|
|||||||
{
|
{
|
||||||
ScanUnreadable?.Invoke(i);
|
ScanUnreadable?.Invoke(i);
|
||||||
results.Errored += blocksToRead;
|
results.Errored += blocksToRead;
|
||||||
for(ulong b = i; b < i + blocksToRead; b++) results.UnreadableSectors.Add(b);
|
|
||||||
|
for(ulong b = i; b < i + blocksToRead; b++)
|
||||||
|
results.UnreadableSectors.Add(b);
|
||||||
|
|
||||||
mhddLog.Write(i, duration < 500 ? 65535 : duration);
|
mhddLog.Write(i, duration < 500 ? 65535 : duration);
|
||||||
|
|
||||||
@@ -168,10 +189,12 @@ namespace DiscImageChef.Core.Devices.Scanning
|
|||||||
sectorSpeedStart += blocksToRead;
|
sectorSpeedStart += blocksToRead;
|
||||||
|
|
||||||
double elapsed = (DateTime.UtcNow - timeSpeedStart).TotalSeconds;
|
double elapsed = (DateTime.UtcNow - timeSpeedStart).TotalSeconds;
|
||||||
if(elapsed < 1) continue;
|
|
||||||
|
|
||||||
currentSpeed = sectorSpeedStart * blockSize / (1048576 * elapsed);
|
if(elapsed < 1)
|
||||||
ScanSpeed?.Invoke(i, currentSpeed * 1024);
|
continue;
|
||||||
|
|
||||||
|
currentSpeed = (sectorSpeedStart * blockSize) / (1048576 * elapsed);
|
||||||
|
ScanSpeed?.Invoke(i, currentSpeed * 1024);
|
||||||
sectorSpeedStart = 0;
|
sectorSpeedStart = 0;
|
||||||
timeSpeedStart = DateTime.UtcNow;
|
timeSpeedStart = DateTime.UtcNow;
|
||||||
}
|
}
|
||||||
@@ -179,16 +202,19 @@ namespace DiscImageChef.Core.Devices.Scanning
|
|||||||
end = DateTime.UtcNow;
|
end = DateTime.UtcNow;
|
||||||
EndProgress?.Invoke();
|
EndProgress?.Invoke();
|
||||||
mhddLog.Close();
|
mhddLog.Close();
|
||||||
|
|
||||||
ibgLog.Close(dev, results.Blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
|
ibgLog.Close(dev, results.Blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
|
||||||
blockSize * (double)(results.Blocks + 1) / 1024 /
|
(blockSize * (double)(results.Blocks + 1)) / 1024 /
|
||||||
(results.ProcessingTime / 1000),
|
(results.ProcessingTime / 1000),
|
||||||
devicePath);
|
devicePath);
|
||||||
|
|
||||||
InitProgress?.Invoke();
|
InitProgress?.Invoke();
|
||||||
|
|
||||||
if(ataReader.CanSeekLba)
|
if(ataReader.CanSeekLba)
|
||||||
for(int i = 0; i < SEEK_TIMES; i++)
|
for(int i = 0; i < SEEK_TIMES; i++)
|
||||||
{
|
{
|
||||||
if(aborted) break;
|
if(aborted)
|
||||||
|
break;
|
||||||
|
|
||||||
uint seekPos = (uint)rnd.Next((int)results.Blocks);
|
uint seekPos = (uint)rnd.Next((int)results.Blocks);
|
||||||
|
|
||||||
@@ -197,8 +223,13 @@ namespace DiscImageChef.Core.Devices.Scanning
|
|||||||
ataReader.Seek(seekPos, out seekCur);
|
ataReader.Seek(seekPos, out seekCur);
|
||||||
|
|
||||||
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
|
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
|
||||||
if(seekCur > results.SeekMax && seekCur != 0) results.SeekMax = seekCur;
|
if(seekCur > results.SeekMax &&
|
||||||
if(seekCur < results.SeekMin && seekCur != 0) results.SeekMin = seekCur;
|
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
|
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
|
||||||
|
|
||||||
results.SeekTotal += seekCur;
|
results.SeekTotal += seekCur;
|
||||||
@@ -219,34 +250,45 @@ namespace DiscImageChef.Core.Devices.Scanning
|
|||||||
DateTime timeSpeedStart = DateTime.UtcNow;
|
DateTime timeSpeedStart = DateTime.UtcNow;
|
||||||
ulong sectorSpeedStart = 0;
|
ulong sectorSpeedStart = 0;
|
||||||
InitProgress?.Invoke();
|
InitProgress?.Invoke();
|
||||||
|
|
||||||
for(ushort cy = 0; cy < cylinders; cy++)
|
for(ushort cy = 0; cy < cylinders; cy++)
|
||||||
{
|
{
|
||||||
for(byte hd = 0; hd < heads; hd++)
|
for(byte hd = 0; hd < heads; hd++)
|
||||||
{
|
{
|
||||||
for(byte sc = 1; sc < sectors; sc++)
|
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
|
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
|
||||||
if(currentSpeed > results.MaxSpeed && currentSpeed != 0)
|
if(currentSpeed > results.MaxSpeed &&
|
||||||
|
currentSpeed != 0)
|
||||||
results.MaxSpeed = currentSpeed;
|
results.MaxSpeed = currentSpeed;
|
||||||
if(currentSpeed < results.MinSpeed && currentSpeed != 0)
|
|
||||||
|
if(currentSpeed < results.MinSpeed &&
|
||||||
|
currentSpeed != 0)
|
||||||
results.MinSpeed = currentSpeed;
|
results.MinSpeed = currentSpeed;
|
||||||
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
|
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
|
||||||
|
|
||||||
PulseProgress
|
PulseProgress?.
|
||||||
?.Invoke($"Reading cylinder {cy} head {hd} sector {sc} ({currentSpeed:F3} MiB/sec.)");
|
Invoke($"Reading cylinder {cy} head {hd} sector {sc} ({currentSpeed:F3} MiB/sec.)");
|
||||||
|
|
||||||
bool error = ataReader.ReadChs(out cmdBuf, cy, hd, sc, out duration);
|
bool error = ataReader.ReadChs(out cmdBuf, cy, hd, sc, out duration);
|
||||||
|
|
||||||
if(!error)
|
if(!error)
|
||||||
{
|
{
|
||||||
if(duration >= 500) results.F += blocksToRead;
|
if(duration >= 500)
|
||||||
else if(duration >= 150) results.E += blocksToRead;
|
results.F += blocksToRead;
|
||||||
else if(duration >= 50) results.D += blocksToRead;
|
else if(duration >= 150)
|
||||||
else if(duration >= 10) results.C += blocksToRead;
|
results.E += blocksToRead;
|
||||||
else if(duration >= 3) results.B += blocksToRead;
|
else if(duration >= 50)
|
||||||
else results.A += blocksToRead;
|
results.D += blocksToRead;
|
||||||
|
else if(duration >= 10)
|
||||||
|
results.C += blocksToRead;
|
||||||
|
else if(duration >= 3)
|
||||||
|
results.B += blocksToRead;
|
||||||
|
else
|
||||||
|
results.A += blocksToRead;
|
||||||
|
|
||||||
ScanTime?.Invoke(currentBlock, duration);
|
ScanTime?.Invoke(currentBlock, duration);
|
||||||
mhddLog.Write(currentBlock, duration);
|
mhddLog.Write(currentBlock, duration);
|
||||||
@@ -266,10 +308,12 @@ namespace DiscImageChef.Core.Devices.Scanning
|
|||||||
currentBlock++;
|
currentBlock++;
|
||||||
|
|
||||||
double elapsed = (DateTime.UtcNow - timeSpeedStart).TotalSeconds;
|
double elapsed = (DateTime.UtcNow - timeSpeedStart).TotalSeconds;
|
||||||
if(elapsed < 1) continue;
|
|
||||||
|
|
||||||
currentSpeed = sectorSpeedStart * blockSize / (1048576 * elapsed);
|
if(elapsed < 1)
|
||||||
ScanSpeed?.Invoke(currentBlock, currentSpeed * 1024);
|
continue;
|
||||||
|
|
||||||
|
currentSpeed = (sectorSpeedStart * blockSize) / (1048576 * elapsed);
|
||||||
|
ScanSpeed?.Invoke(currentBlock, currentSpeed * 1024);
|
||||||
sectorSpeedStart = 0;
|
sectorSpeedStart = 0;
|
||||||
timeSpeedStart = DateTime.UtcNow;
|
timeSpeedStart = DateTime.UtcNow;
|
||||||
}
|
}
|
||||||
@@ -279,29 +323,37 @@ namespace DiscImageChef.Core.Devices.Scanning
|
|||||||
end = DateTime.UtcNow;
|
end = DateTime.UtcNow;
|
||||||
EndProgress?.Invoke();
|
EndProgress?.Invoke();
|
||||||
mhddLog.Close();
|
mhddLog.Close();
|
||||||
|
|
||||||
ibgLog.Close(dev, results.Blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
|
ibgLog.Close(dev, results.Blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
|
||||||
blockSize * (double)(results.Blocks + 1) / 1024 /
|
(blockSize * (double)(results.Blocks + 1)) / 1024 /
|
||||||
(results.ProcessingTime / 1000),
|
(results.ProcessingTime / 1000),
|
||||||
devicePath);
|
devicePath);
|
||||||
|
|
||||||
InitProgress?.Invoke();
|
InitProgress?.Invoke();
|
||||||
|
|
||||||
if(ataReader.CanSeek)
|
if(ataReader.CanSeek)
|
||||||
for(int i = 0; i < SEEK_TIMES; i++)
|
for(int i = 0; i < SEEK_TIMES; i++)
|
||||||
{
|
{
|
||||||
if(aborted) break;
|
if(aborted)
|
||||||
|
break;
|
||||||
|
|
||||||
ushort seekCy = (ushort)rnd.Next(cylinders);
|
ushort seekCy = (ushort)rnd.Next(cylinders);
|
||||||
byte seekHd = (byte)rnd.Next(heads);
|
byte seekHd = (byte)rnd.Next(heads);
|
||||||
byte seekSc = (byte)rnd.Next(sectors);
|
byte seekSc = (byte)rnd.Next(sectors);
|
||||||
|
|
||||||
PulseProgress
|
PulseProgress?.
|
||||||
?.Invoke($"\rSeeking to cylinder {seekCy}, head {seekHd}, sector {seekSc}...\t\t");
|
Invoke($"\rSeeking to cylinder {seekCy}, head {seekHd}, sector {seekSc}...\t\t");
|
||||||
|
|
||||||
ataReader.SeekChs(seekCy, seekHd, seekSc, out seekCur);
|
ataReader.SeekChs(seekCy, seekHd, seekSc, out seekCur);
|
||||||
|
|
||||||
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
|
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
|
||||||
if(seekCur > results.SeekMax && seekCur != 0) results.SeekMax = seekCur;
|
if(seekCur > results.SeekMax &&
|
||||||
if(seekCur < results.SeekMin && seekCur != 0) results.SeekMin = seekCur;
|
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
|
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
|
||||||
|
|
||||||
results.SeekTotal += seekCur;
|
results.SeekTotal += seekCur;
|
||||||
@@ -313,13 +365,14 @@ namespace DiscImageChef.Core.Devices.Scanning
|
|||||||
|
|
||||||
results.ProcessingTime /= 1000;
|
results.ProcessingTime /= 1000;
|
||||||
results.TotalTime = (end - start).TotalSeconds;
|
results.TotalTime = (end - start).TotalSeconds;
|
||||||
results.AvgSpeed = blockSize * (double)(results.Blocks + 1) / 1048576 / results.ProcessingTime;
|
results.AvgSpeed = (blockSize * (double)(results.Blocks + 1)) / 1048576 / results.ProcessingTime;
|
||||||
results.SeekTimes = SEEK_TIMES;
|
results.SeekTimes = SEEK_TIMES;
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
StoppingErrorMessage?.Invoke("Unable to communicate with ATA device.");
|
StoppingErrorMessage?.Invoke("Unable to communicate with ATA device.");
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
|
||||||
using DiscImageChef.Console;
|
using DiscImageChef.Console;
|
||||||
using DiscImageChef.Core.Logging;
|
using DiscImageChef.Core.Logging;
|
||||||
using DiscImageChef.Decoders.CD;
|
using DiscImageChef.Decoders.CD;
|
||||||
@@ -42,18 +43,16 @@ using DiscImageChef.Devices;
|
|||||||
|
|
||||||
namespace DiscImageChef.Core.Devices.Scanning
|
namespace DiscImageChef.Core.Devices.Scanning
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>Implements scanning the media from an SCSI device</summary>
|
||||||
/// Implements scanning the media from an SCSI device
|
|
||||||
/// </summary>
|
|
||||||
public partial class MediaScan
|
public partial class MediaScan
|
||||||
{
|
{
|
||||||
ScanResults Scsi()
|
ScanResults Scsi()
|
||||||
{
|
{
|
||||||
ScanResults results = new ScanResults();
|
var results = new ScanResults();
|
||||||
MhddLog mhddLog;
|
MhddLog mhddLog;
|
||||||
IbgLog ibgLog;
|
IbgLog ibgLog;
|
||||||
byte[] senseBuf;
|
byte[] senseBuf;
|
||||||
bool sense = false;
|
bool sense = false;
|
||||||
results.Blocks = 0;
|
results.Blocks = 0;
|
||||||
uint blockSize = 0;
|
uint blockSize = 0;
|
||||||
ushort currentProfile = 0x0001;
|
ushort currentProfile = 0x0001;
|
||||||
@@ -61,20 +60,25 @@ namespace DiscImageChef.Core.Devices.Scanning
|
|||||||
if(dev.IsRemovable)
|
if(dev.IsRemovable)
|
||||||
{
|
{
|
||||||
sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out _);
|
sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out _);
|
||||||
|
|
||||||
if(sense)
|
if(sense)
|
||||||
{
|
{
|
||||||
InitProgress?.Invoke();
|
InitProgress?.Invoke();
|
||||||
FixedSense? decSense = Sense.DecodeFixed(senseBuf);
|
FixedSense? decSense = Sense.DecodeFixed(senseBuf);
|
||||||
|
|
||||||
if(decSense.HasValue)
|
if(decSense.HasValue)
|
||||||
if(decSense.Value.ASC == 0x3A)
|
if(decSense.Value.ASC == 0x3A)
|
||||||
{
|
{
|
||||||
int leftRetries = 5;
|
int leftRetries = 5;
|
||||||
|
|
||||||
while(leftRetries > 0)
|
while(leftRetries > 0)
|
||||||
{
|
{
|
||||||
PulseProgress?.Invoke("Waiting for drive to become ready");
|
PulseProgress?.Invoke("Waiting for drive to become ready");
|
||||||
Thread.Sleep(2000);
|
Thread.Sleep(2000);
|
||||||
sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out _);
|
sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out _);
|
||||||
if(!sense) break;
|
|
||||||
|
if(!sense)
|
||||||
|
break;
|
||||||
|
|
||||||
leftRetries--;
|
leftRetries--;
|
||||||
}
|
}
|
||||||
@@ -82,59 +86,72 @@ namespace DiscImageChef.Core.Devices.Scanning
|
|||||||
if(sense)
|
if(sense)
|
||||||
{
|
{
|
||||||
StoppingErrorMessage?.Invoke("Please insert media in drive");
|
StoppingErrorMessage?.Invoke("Please insert media in drive");
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(decSense.Value.ASC == 0x04 && decSense.Value.ASCQ == 0x01)
|
else if(decSense.Value.ASC == 0x04 &&
|
||||||
|
decSense.Value.ASCQ == 0x01)
|
||||||
{
|
{
|
||||||
int leftRetries = 10;
|
int leftRetries = 10;
|
||||||
|
|
||||||
while(leftRetries > 0)
|
while(leftRetries > 0)
|
||||||
{
|
{
|
||||||
PulseProgress?.Invoke("Waiting for drive to become ready");
|
PulseProgress?.Invoke("Waiting for drive to become ready");
|
||||||
Thread.Sleep(2000);
|
Thread.Sleep(2000);
|
||||||
sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out _);
|
sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out _);
|
||||||
if(!sense) break;
|
|
||||||
|
if(!sense)
|
||||||
|
break;
|
||||||
|
|
||||||
leftRetries--;
|
leftRetries--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(sense)
|
if(sense)
|
||||||
{
|
{
|
||||||
StoppingErrorMessage
|
StoppingErrorMessage?.
|
||||||
?.Invoke($"Error testing unit was ready:\n{Sense.PrettifySense(senseBuf)}");
|
Invoke($"Error testing unit was ready:\n{Sense.PrettifySense(senseBuf)}");
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// These should be trapped by the OS but seems in some cases they're not
|
// These should be trapped by the OS but seems in some cases they're not
|
||||||
else if(decSense.Value.ASC == 0x28)
|
else if(decSense.Value.ASC == 0x28)
|
||||||
{
|
{
|
||||||
int leftRetries = 10;
|
int leftRetries = 10;
|
||||||
|
|
||||||
while(leftRetries > 0)
|
while(leftRetries > 0)
|
||||||
{
|
{
|
||||||
PulseProgress?.Invoke("Waiting for drive to become ready");
|
PulseProgress?.Invoke("Waiting for drive to become ready");
|
||||||
Thread.Sleep(2000);
|
Thread.Sleep(2000);
|
||||||
sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out _);
|
sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out _);
|
||||||
if(!sense) break;
|
|
||||||
|
if(!sense)
|
||||||
|
break;
|
||||||
|
|
||||||
leftRetries--;
|
leftRetries--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(sense)
|
if(sense)
|
||||||
{
|
{
|
||||||
StoppingErrorMessage
|
StoppingErrorMessage?.
|
||||||
?.Invoke($"Error testing unit was ready:\n{Sense.PrettifySense(senseBuf)}");
|
Invoke($"Error testing unit was ready:\n{Sense.PrettifySense(senseBuf)}");
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
StoppingErrorMessage
|
StoppingErrorMessage?.
|
||||||
?.Invoke($"Error testing unit was ready:\n{Sense.PrettifySense(senseBuf)}");
|
Invoke($"Error testing unit was ready:\n{Sense.PrettifySense(senseBuf)}");
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
StoppingErrorMessage?.Invoke("Unknown testing unit was ready.");
|
StoppingErrorMessage?.Invoke("Unknown testing unit was ready.");
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,19 +171,23 @@ namespace DiscImageChef.Core.Devices.Scanning
|
|||||||
case PeripheralDeviceTypes.WriteOnceDevice:
|
case PeripheralDeviceTypes.WriteOnceDevice:
|
||||||
scsiReader = new Reader(dev, dev.Timeout, null);
|
scsiReader = new Reader(dev, dev.Timeout, null);
|
||||||
results.Blocks = scsiReader.GetDeviceBlocks();
|
results.Blocks = scsiReader.GetDeviceBlocks();
|
||||||
|
|
||||||
if(scsiReader.FindReadCommand())
|
if(scsiReader.FindReadCommand())
|
||||||
{
|
{
|
||||||
StoppingErrorMessage?.Invoke("Unable to read medium.");
|
StoppingErrorMessage?.Invoke("Unable to read medium.");
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
blockSize = scsiReader.LogicalBlockSize;
|
blockSize = scsiReader.LogicalBlockSize;
|
||||||
|
|
||||||
if(results.Blocks != 0 && blockSize != 0)
|
if(results.Blocks != 0 &&
|
||||||
|
blockSize != 0)
|
||||||
{
|
{
|
||||||
results.Blocks++;
|
results.Blocks++;
|
||||||
UpdateStatus
|
|
||||||
?.Invoke($"Media has {results.Blocks} blocks of {blockSize} bytes/each. (for a total of {results.Blocks * (ulong)blockSize} bytes)");
|
UpdateStatus?.
|
||||||
|
Invoke($"Media has {results.Blocks} blocks of {blockSize} bytes/each. (for a total of {results.Blocks * (ulong)blockSize} bytes)");
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -174,12 +195,14 @@ namespace DiscImageChef.Core.Devices.Scanning
|
|||||||
StoppingErrorMessage?.Invoke("Scanning will never be supported on SCSI Streaming Devices." +
|
StoppingErrorMessage?.Invoke("Scanning will never be supported on SCSI Streaming Devices." +
|
||||||
Environment.NewLine +
|
Environment.NewLine +
|
||||||
"It has no sense to do it, and it will put too much strain on the tape.");
|
"It has no sense to do it, and it will put too much strain on the tape.");
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(results.Blocks == 0)
|
if(results.Blocks == 0)
|
||||||
{
|
{
|
||||||
StoppingErrorMessage?.Invoke("Unable to read medium or empty medium present...");
|
StoppingErrorMessage?.Invoke("Unable to read medium or empty medium present...");
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,6 +213,7 @@ namespace DiscImageChef.Core.Devices.Scanning
|
|||||||
{
|
{
|
||||||
sense = dev.GetConfiguration(out byte[] cmdBuf, out senseBuf, 0, MmcGetConfigurationRt.Current,
|
sense = dev.GetConfiguration(out byte[] cmdBuf, out senseBuf, 0, MmcGetConfigurationRt.Current,
|
||||||
dev.Timeout, out _);
|
dev.Timeout, out _);
|
||||||
|
|
||||||
if(!sense)
|
if(!sense)
|
||||||
{
|
{
|
||||||
Features.SeparatedFeatures ftr = Features.Separate(cmdBuf);
|
Features.SeparatedFeatures ftr = Features.Separate(cmdBuf);
|
||||||
@@ -207,6 +231,7 @@ namespace DiscImageChef.Core.Devices.Scanning
|
|||||||
case 0x0022: break;
|
case 0x0022: break;
|
||||||
default:
|
default:
|
||||||
compactDisc = false;
|
compactDisc = false;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -214,13 +239,17 @@ namespace DiscImageChef.Core.Devices.Scanning
|
|||||||
if(compactDisc)
|
if(compactDisc)
|
||||||
{
|
{
|
||||||
currentProfile = 0x0008;
|
currentProfile = 0x0008;
|
||||||
|
|
||||||
// We discarded all discs that falsify a TOC before requesting a real TOC
|
// We discarded all discs that falsify a TOC before requesting a real TOC
|
||||||
// No TOC, no CD (or an empty one)
|
// No TOC, no CD (or an empty one)
|
||||||
bool tocSense = dev.ReadRawToc(out cmdBuf, out senseBuf, 1, dev.Timeout, out _);
|
bool tocSense = dev.ReadRawToc(out cmdBuf, out senseBuf, 1, dev.Timeout, out _);
|
||||||
if(!tocSense) toc = FullTOC.Decode(cmdBuf);
|
|
||||||
|
if(!tocSense)
|
||||||
|
toc = FullTOC.Decode(cmdBuf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else compactDisc = false;
|
else
|
||||||
|
compactDisc = false;
|
||||||
|
|
||||||
uint blocksToRead = 64;
|
uint blocksToRead = 64;
|
||||||
|
|
||||||
@@ -245,6 +274,7 @@ namespace DiscImageChef.Core.Devices.Scanning
|
|||||||
if(toc == null)
|
if(toc == null)
|
||||||
{
|
{
|
||||||
StoppingErrorMessage?.Invoke("Error trying to decode TOC...");
|
StoppingErrorMessage?.Invoke("Error trying to decode TOC...");
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,7 +282,8 @@ namespace DiscImageChef.Core.Devices.Scanning
|
|||||||
MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, MmcSubchannel.None,
|
MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, MmcSubchannel.None,
|
||||||
dev.Timeout, out _);
|
dev.Timeout, out _);
|
||||||
|
|
||||||
if(readcd) UpdateStatus?.Invoke("Using MMC READ CD command.");
|
if(readcd)
|
||||||
|
UpdateStatus?.Invoke("Using MMC READ CD command.");
|
||||||
|
|
||||||
start = DateTime.UtcNow;
|
start = DateTime.UtcNow;
|
||||||
|
|
||||||
@@ -263,16 +294,21 @@ namespace DiscImageChef.Core.Devices.Scanning
|
|||||||
sense = dev.ReadCd(out _, out senseBuf, 0, 2352, blocksToRead, MmcSectorTypes.AllTypes, false,
|
sense = dev.ReadCd(out _, out senseBuf, 0, 2352, blocksToRead, MmcSectorTypes.AllTypes, false,
|
||||||
false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None,
|
false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None,
|
||||||
MmcSubchannel.None, dev.Timeout, out _);
|
MmcSubchannel.None, dev.Timeout, out _);
|
||||||
if(dev.Error) blocksToRead /= 2;
|
|
||||||
|
if(dev.Error)
|
||||||
|
blocksToRead /= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!dev.Error || blocksToRead == 1) break;
|
if(!dev.Error ||
|
||||||
|
blocksToRead == 1)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dev.Error)
|
if(dev.Error)
|
||||||
{
|
{
|
||||||
StoppingErrorMessage
|
StoppingErrorMessage?.
|
||||||
?.Invoke($"Device error {dev.LastError} trying to guess ideal transfer length.");
|
Invoke($"Device error {dev.LastError} trying to guess ideal transfer length.");
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,17 +321,25 @@ namespace DiscImageChef.Core.Devices.Scanning
|
|||||||
ulong sectorSpeedStart = 0;
|
ulong sectorSpeedStart = 0;
|
||||||
|
|
||||||
InitProgress?.Invoke();
|
InitProgress?.Invoke();
|
||||||
|
|
||||||
for(ulong i = 0; i < results.Blocks; i += blocksToRead)
|
for(ulong i = 0; i < results.Blocks; i += blocksToRead)
|
||||||
{
|
{
|
||||||
if(aborted) break;
|
if(aborted)
|
||||||
|
break;
|
||||||
|
|
||||||
double cmdDuration = 0;
|
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
|
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
|
||||||
if(currentSpeed > results.MaxSpeed && currentSpeed != 0) results.MaxSpeed = currentSpeed;
|
if(currentSpeed > results.MaxSpeed &&
|
||||||
if(currentSpeed < results.MinSpeed && currentSpeed != 0) results.MinSpeed = currentSpeed;
|
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
|
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
|
||||||
|
|
||||||
UpdateProgress?.Invoke($"Reading sector {i} of {results.Blocks} ({currentSpeed:F3} MiB/sec.)",
|
UpdateProgress?.Invoke($"Reading sector {i} of {results.Blocks} ({currentSpeed:F3} MiB/sec.)",
|
||||||
@@ -306,17 +350,24 @@ namespace DiscImageChef.Core.Devices.Scanning
|
|||||||
sense = dev.ReadCd(out _, out senseBuf, (uint)i, 2352, blocksToRead, MmcSectorTypes.AllTypes,
|
sense = dev.ReadCd(out _, out senseBuf, (uint)i, 2352, blocksToRead, MmcSectorTypes.AllTypes,
|
||||||
false, false, true, MmcHeaderCodes.AllHeaders, true, true,
|
false, false, true, MmcHeaderCodes.AllHeaders, true, true,
|
||||||
MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out cmdDuration);
|
MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out cmdDuration);
|
||||||
|
|
||||||
results.ProcessingTime += cmdDuration;
|
results.ProcessingTime += cmdDuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!sense)
|
if(!sense)
|
||||||
{
|
{
|
||||||
if(cmdDuration >= 500) results.F += blocksToRead;
|
if(cmdDuration >= 500)
|
||||||
else if(cmdDuration >= 150) results.E += blocksToRead;
|
results.F += blocksToRead;
|
||||||
else if(cmdDuration >= 50) results.D += blocksToRead;
|
else if(cmdDuration >= 150)
|
||||||
else if(cmdDuration >= 10) results.C += blocksToRead;
|
results.E += blocksToRead;
|
||||||
else if(cmdDuration >= 3) results.B += blocksToRead;
|
else if(cmdDuration >= 50)
|
||||||
else results.A += blocksToRead;
|
results.D += blocksToRead;
|
||||||
|
else if(cmdDuration >= 10)
|
||||||
|
results.C += blocksToRead;
|
||||||
|
else if(cmdDuration >= 3)
|
||||||
|
results.B += blocksToRead;
|
||||||
|
else
|
||||||
|
results.A += blocksToRead;
|
||||||
|
|
||||||
ScanTime?.Invoke(i, cmdDuration);
|
ScanTime?.Invoke(i, cmdDuration);
|
||||||
mhddLog.Write(i, cmdDuration);
|
mhddLog.Write(i, cmdDuration);
|
||||||
@@ -327,17 +378,21 @@ namespace DiscImageChef.Core.Devices.Scanning
|
|||||||
DicConsole.DebugWriteLine("Media-Scan", "READ CD error:\n{0}", Sense.PrettifySense(senseBuf));
|
DicConsole.DebugWriteLine("Media-Scan", "READ CD error:\n{0}", Sense.PrettifySense(senseBuf));
|
||||||
|
|
||||||
FixedSense? senseDecoded = Sense.DecodeFixed(senseBuf);
|
FixedSense? senseDecoded = Sense.DecodeFixed(senseBuf);
|
||||||
|
|
||||||
if(senseDecoded.HasValue)
|
if(senseDecoded.HasValue)
|
||||||
{
|
{
|
||||||
// TODO: This error happens when changing from track type afaik. Need to solve that more cleanly
|
// TODO: This error happens when changing from track type afaik. Need to solve that more cleanly
|
||||||
// LOGICAL BLOCK ADDRESS OUT OF RANGE
|
// LOGICAL BLOCK ADDRESS OUT OF RANGE
|
||||||
if((senseDecoded.Value.ASC != 0x21 || senseDecoded.Value.ASCQ != 0x00) &&
|
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
|
// 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)
|
// are in a track where subchannel indicates data)
|
||||||
(senseDecoded.Value.ASC != 0x64 || senseDecoded.Value.ASCQ != 0x00))
|
(senseDecoded.Value.ASC != 0x64 || senseDecoded.Value.ASCQ != 0x00))
|
||||||
{
|
{
|
||||||
results.Errored += blocksToRead;
|
results.Errored += blocksToRead;
|
||||||
for(ulong b = i; b < i + blocksToRead; b++) results.UnreadableSectors.Add(b);
|
|
||||||
|
for(ulong b = i; b < i + blocksToRead; b++)
|
||||||
|
results.UnreadableSectors.Add(b);
|
||||||
|
|
||||||
ScanUnreadable?.Invoke(i);
|
ScanUnreadable?.Invoke(i);
|
||||||
mhddLog.Write(i, cmdDuration < 500 ? 65535 : cmdDuration);
|
mhddLog.Write(i, cmdDuration < 500 ? 65535 : cmdDuration);
|
||||||
@@ -349,7 +404,9 @@ namespace DiscImageChef.Core.Devices.Scanning
|
|||||||
{
|
{
|
||||||
ScanUnreadable?.Invoke(i);
|
ScanUnreadable?.Invoke(i);
|
||||||
results.Errored += blocksToRead;
|
results.Errored += blocksToRead;
|
||||||
for(ulong b = i; b < i + blocksToRead; b++) results.UnreadableSectors.Add(b);
|
|
||||||
|
for(ulong b = i; b < i + blocksToRead; b++)
|
||||||
|
results.UnreadableSectors.Add(b);
|
||||||
|
|
||||||
mhddLog.Write(i, cmdDuration < 500 ? 65535 : cmdDuration);
|
mhddLog.Write(i, cmdDuration < 500 ? 65535 : cmdDuration);
|
||||||
|
|
||||||
@@ -360,10 +417,12 @@ namespace DiscImageChef.Core.Devices.Scanning
|
|||||||
sectorSpeedStart += blocksToRead;
|
sectorSpeedStart += blocksToRead;
|
||||||
|
|
||||||
double elapsed = (DateTime.UtcNow - timeSpeedStart).TotalSeconds;
|
double elapsed = (DateTime.UtcNow - timeSpeedStart).TotalSeconds;
|
||||||
if(elapsed < 1) continue;
|
|
||||||
|
|
||||||
currentSpeed = sectorSpeedStart * blockSize / (1048576 * elapsed);
|
if(elapsed < 1)
|
||||||
ScanSpeed?.Invoke(i, currentSpeed * 1024);
|
continue;
|
||||||
|
|
||||||
|
currentSpeed = (sectorSpeedStart * blockSize) / (1048576 * elapsed);
|
||||||
|
ScanSpeed?.Invoke(i, currentSpeed * 1024);
|
||||||
sectorSpeedStart = 0;
|
sectorSpeedStart = 0;
|
||||||
timeSpeedStart = DateTime.UtcNow;
|
timeSpeedStart = DateTime.UtcNow;
|
||||||
}
|
}
|
||||||
@@ -371,8 +430,9 @@ namespace DiscImageChef.Core.Devices.Scanning
|
|||||||
end = DateTime.UtcNow;
|
end = DateTime.UtcNow;
|
||||||
EndProgress?.Invoke();
|
EndProgress?.Invoke();
|
||||||
mhddLog.Close();
|
mhddLog.Close();
|
||||||
|
|
||||||
ibgLog.Close(dev, results.Blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
|
ibgLog.Close(dev, results.Blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
|
||||||
blockSize * (double)(results.Blocks + 1) / 1024 /
|
(blockSize * (double)(results.Blocks + 1)) / 1024 /
|
||||||
(results.ProcessingTime / 1000),
|
(results.ProcessingTime / 1000),
|
||||||
devicePath);
|
devicePath);
|
||||||
}
|
}
|
||||||
@@ -389,15 +449,23 @@ namespace DiscImageChef.Core.Devices.Scanning
|
|||||||
ulong sectorSpeedStart = 0;
|
ulong sectorSpeedStart = 0;
|
||||||
|
|
||||||
InitProgress?.Invoke();
|
InitProgress?.Invoke();
|
||||||
|
|
||||||
for(ulong i = 0; i < results.Blocks; i += blocksToRead)
|
for(ulong i = 0; i < results.Blocks; i += blocksToRead)
|
||||||
{
|
{
|
||||||
if(aborted) break;
|
if(aborted)
|
||||||
|
break;
|
||||||
|
|
||||||
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
|
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
|
||||||
if(currentSpeed > results.MaxSpeed && currentSpeed != 0) results.MaxSpeed = currentSpeed;
|
if(currentSpeed > results.MaxSpeed &&
|
||||||
if(currentSpeed < results.MinSpeed && currentSpeed != 0) results.MinSpeed = currentSpeed;
|
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
|
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
|
||||||
|
|
||||||
UpdateProgress?.Invoke($"Reading sector {i} of {results.Blocks} ({currentSpeed:F3} MiB/sec.)",
|
UpdateProgress?.Invoke($"Reading sector {i} of {results.Blocks} ({currentSpeed:F3} MiB/sec.)",
|
||||||
@@ -406,25 +474,35 @@ namespace DiscImageChef.Core.Devices.Scanning
|
|||||||
sense = scsiReader.ReadBlocks(out _, i, blocksToRead, out double cmdDuration);
|
sense = scsiReader.ReadBlocks(out _, i, blocksToRead, out double cmdDuration);
|
||||||
results.ProcessingTime += cmdDuration;
|
results.ProcessingTime += cmdDuration;
|
||||||
|
|
||||||
if(!sense && !dev.Error)
|
if(!sense &&
|
||||||
|
!dev.Error)
|
||||||
{
|
{
|
||||||
if(cmdDuration >= 500) results.F += blocksToRead;
|
if(cmdDuration >= 500)
|
||||||
else if(cmdDuration >= 150) results.E += blocksToRead;
|
results.F += blocksToRead;
|
||||||
else if(cmdDuration >= 50) results.D += blocksToRead;
|
else if(cmdDuration >= 150)
|
||||||
else if(cmdDuration >= 10) results.C += blocksToRead;
|
results.E += blocksToRead;
|
||||||
else if(cmdDuration >= 3) results.B += blocksToRead;
|
else if(cmdDuration >= 50)
|
||||||
else results.A += blocksToRead;
|
results.D += blocksToRead;
|
||||||
|
else if(cmdDuration >= 10)
|
||||||
|
results.C += blocksToRead;
|
||||||
|
else if(cmdDuration >= 3)
|
||||||
|
results.B += blocksToRead;
|
||||||
|
else
|
||||||
|
results.A += blocksToRead;
|
||||||
|
|
||||||
ScanTime?.Invoke(i, cmdDuration);
|
ScanTime?.Invoke(i, cmdDuration);
|
||||||
mhddLog.Write(i, cmdDuration);
|
mhddLog.Write(i, cmdDuration);
|
||||||
ibgLog.Write(i, currentSpeed * 1024);
|
ibgLog.Write(i, currentSpeed * 1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Separate errors on kind of errors.
|
// TODO: Separate errors on kind of errors.
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ScanUnreadable?.Invoke(i);
|
ScanUnreadable?.Invoke(i);
|
||||||
results.Errored += blocksToRead;
|
results.Errored += blocksToRead;
|
||||||
for(ulong b = i; b < i + blocksToRead; b++) results.UnreadableSectors.Add(b);
|
|
||||||
|
for(ulong b = i; b < i + blocksToRead; b++)
|
||||||
|
results.UnreadableSectors.Add(b);
|
||||||
|
|
||||||
mhddLog.Write(i, cmdDuration < 500 ? 65535 : cmdDuration);
|
mhddLog.Write(i, cmdDuration < 500 ? 65535 : cmdDuration);
|
||||||
ibgLog.Write(i, 0);
|
ibgLog.Write(i, 0);
|
||||||
@@ -433,10 +511,12 @@ namespace DiscImageChef.Core.Devices.Scanning
|
|||||||
sectorSpeedStart += blocksToRead;
|
sectorSpeedStart += blocksToRead;
|
||||||
|
|
||||||
double elapsed = (DateTime.UtcNow - timeSpeedStart).TotalSeconds;
|
double elapsed = (DateTime.UtcNow - timeSpeedStart).TotalSeconds;
|
||||||
if(elapsed < 1) continue;
|
|
||||||
|
|
||||||
currentSpeed = sectorSpeedStart * blockSize / (1048576 * elapsed);
|
if(elapsed < 1)
|
||||||
ScanSpeed?.Invoke(i, currentSpeed * 1024);
|
continue;
|
||||||
|
|
||||||
|
currentSpeed = (sectorSpeedStart * blockSize) / (1048576 * elapsed);
|
||||||
|
ScanSpeed?.Invoke(i, currentSpeed * 1024);
|
||||||
sectorSpeedStart = 0;
|
sectorSpeedStart = 0;
|
||||||
timeSpeedStart = DateTime.UtcNow;
|
timeSpeedStart = DateTime.UtcNow;
|
||||||
}
|
}
|
||||||
@@ -444,8 +524,9 @@ namespace DiscImageChef.Core.Devices.Scanning
|
|||||||
end = DateTime.UtcNow;
|
end = DateTime.UtcNow;
|
||||||
EndProgress?.Invoke();
|
EndProgress?.Invoke();
|
||||||
mhddLog.Close();
|
mhddLog.Close();
|
||||||
|
|
||||||
ibgLog.Close(dev, results.Blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
|
ibgLog.Close(dev, results.Blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
|
||||||
blockSize * (double)(results.Blocks + 1) / 1024 /
|
(blockSize * (double)(results.Blocks + 1)) / 1024 /
|
||||||
(results.ProcessingTime / 1000),
|
(results.ProcessingTime / 1000),
|
||||||
devicePath);
|
devicePath);
|
||||||
}
|
}
|
||||||
@@ -455,24 +536,34 @@ namespace DiscImageChef.Core.Devices.Scanning
|
|||||||
results.SeekTotal = 0;
|
results.SeekTotal = 0;
|
||||||
const int SEEK_TIMES = 1000;
|
const int SEEK_TIMES = 1000;
|
||||||
|
|
||||||
Random rnd = new Random();
|
var rnd = new Random();
|
||||||
|
|
||||||
InitProgress?.Invoke();
|
InitProgress?.Invoke();
|
||||||
|
|
||||||
for(int i = 0; i < SEEK_TIMES; i++)
|
for(int i = 0; i < SEEK_TIMES; i++)
|
||||||
{
|
{
|
||||||
if(aborted) break;
|
if(aborted)
|
||||||
|
break;
|
||||||
|
|
||||||
uint seekPos = (uint)rnd.Next((int)results.Blocks);
|
uint seekPos = (uint)rnd.Next((int)results.Blocks);
|
||||||
|
|
||||||
PulseProgress?.Invoke($"Seeking to sector {seekPos}...\t\t");
|
PulseProgress?.Invoke($"Seeking to sector {seekPos}...\t\t");
|
||||||
|
|
||||||
double seekCur;
|
double seekCur;
|
||||||
if(scsiReader.CanSeek) scsiReader.Seek(seekPos, out seekCur);
|
|
||||||
else scsiReader.ReadBlock(out _, seekPos, out seekCur);
|
if(scsiReader.CanSeek)
|
||||||
|
scsiReader.Seek(seekPos, out seekCur);
|
||||||
|
else
|
||||||
|
scsiReader.ReadBlock(out _, seekPos, out seekCur);
|
||||||
|
|
||||||
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
|
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
|
||||||
if(seekCur > results.SeekMax && seekCur != 0) results.SeekMax = seekCur;
|
if(seekCur > results.SeekMax &&
|
||||||
if(seekCur < results.SeekMin && seekCur != 0) results.SeekMin = seekCur;
|
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
|
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
|
||||||
|
|
||||||
results.SeekTotal += seekCur;
|
results.SeekTotal += seekCur;
|
||||||
@@ -483,7 +574,7 @@ namespace DiscImageChef.Core.Devices.Scanning
|
|||||||
|
|
||||||
results.ProcessingTime /= 1000;
|
results.ProcessingTime /= 1000;
|
||||||
results.TotalTime = (end - start).TotalSeconds;
|
results.TotalTime = (end - start).TotalSeconds;
|
||||||
results.AvgSpeed = blockSize * (double)(results.Blocks + 1) / 1048576 / results.ProcessingTime;
|
results.AvgSpeed = (blockSize * (double)(results.Blocks + 1)) / 1048576 / results.ProcessingTime;
|
||||||
results.SeekTimes = SEEK_TIMES;
|
results.SeekTimes = SEEK_TIMES;
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ using System.Text;
|
|||||||
using DiscImageChef.CommonTypes.Enums;
|
using DiscImageChef.CommonTypes.Enums;
|
||||||
using DiscImageChef.CommonTypes.Interfaces;
|
using DiscImageChef.CommonTypes.Interfaces;
|
||||||
using DiscImageChef.CommonTypes.Structs;
|
using DiscImageChef.CommonTypes.Structs;
|
||||||
|
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
|
||||||
using DiscImageChef.Console;
|
using DiscImageChef.Console;
|
||||||
using DiscImageChef.Decoders.ATA;
|
using DiscImageChef.Decoders.ATA;
|
||||||
using DiscImageChef.Decoders.Bluray;
|
using DiscImageChef.Decoders.Bluray;
|
||||||
@@ -47,6 +48,7 @@ using DiscImageChef.Decoders.Xbox;
|
|||||||
using Schemas;
|
using Schemas;
|
||||||
using DDS = DiscImageChef.Decoders.DVD.DDS;
|
using DDS = DiscImageChef.Decoders.DVD.DDS;
|
||||||
using DMI = DiscImageChef.Decoders.Xbox.DMI;
|
using DMI = DiscImageChef.Decoders.Xbox.DMI;
|
||||||
|
using Inquiry = DiscImageChef.Decoders.SCSI.Inquiry;
|
||||||
using Session = DiscImageChef.CommonTypes.Structs.Session;
|
using Session = DiscImageChef.CommonTypes.Structs.Session;
|
||||||
using Tuple = DiscImageChef.Decoders.PCMCIA.Tuple;
|
using Tuple = DiscImageChef.Decoders.PCMCIA.Tuple;
|
||||||
|
|
||||||
@@ -57,55 +59,80 @@ namespace DiscImageChef.Core
|
|||||||
public static void PrintImageInfo(IMediaImage imageFormat)
|
public static void PrintImageInfo(IMediaImage imageFormat)
|
||||||
{
|
{
|
||||||
DicConsole.WriteLine("Image information:");
|
DicConsole.WriteLine("Image information:");
|
||||||
|
|
||||||
if(!string.IsNullOrWhiteSpace(imageFormat.Info.Version))
|
if(!string.IsNullOrWhiteSpace(imageFormat.Info.Version))
|
||||||
DicConsole.WriteLine("Format: {0} version {1}", imageFormat.Format, imageFormat.Info.Version);
|
DicConsole.WriteLine("Format: {0} version {1}", imageFormat.Format, imageFormat.Info.Version);
|
||||||
else DicConsole.WriteLine("Format: {0}", imageFormat.Format);
|
else
|
||||||
|
DicConsole.WriteLine("Format: {0}", imageFormat.Format);
|
||||||
|
|
||||||
if(!string.IsNullOrWhiteSpace(imageFormat.Info.Application) &&
|
if(!string.IsNullOrWhiteSpace(imageFormat.Info.Application) &&
|
||||||
!string.IsNullOrWhiteSpace(imageFormat.Info.ApplicationVersion))
|
!string.IsNullOrWhiteSpace(imageFormat.Info.ApplicationVersion))
|
||||||
DicConsole.WriteLine("Was created with {0} version {1}", imageFormat.Info.Application,
|
DicConsole.WriteLine("Was created with {0} version {1}", imageFormat.Info.Application,
|
||||||
imageFormat.Info.ApplicationVersion);
|
imageFormat.Info.ApplicationVersion);
|
||||||
else if(!string.IsNullOrWhiteSpace(imageFormat.Info.Application))
|
else if(!string.IsNullOrWhiteSpace(imageFormat.Info.Application))
|
||||||
DicConsole.WriteLine("Was created with {0}", imageFormat.Info.Application);
|
DicConsole.WriteLine("Was created with {0}", imageFormat.Info.Application);
|
||||||
|
|
||||||
DicConsole.WriteLine("Image without headers is {0} bytes long", imageFormat.Info.ImageSize);
|
DicConsole.WriteLine("Image without headers is {0} bytes long", imageFormat.Info.ImageSize);
|
||||||
|
|
||||||
DicConsole.WriteLine("Contains a media of {0} sectors with a maximum sector size of {1} bytes (if all sectors are of the same size this would be {2} bytes)",
|
DicConsole.WriteLine("Contains a media of {0} sectors with a maximum sector size of {1} bytes (if all sectors are of the same size this would be {2} bytes)",
|
||||||
imageFormat.Info.Sectors, imageFormat.Info.SectorSize,
|
imageFormat.Info.Sectors, imageFormat.Info.SectorSize,
|
||||||
imageFormat.Info.Sectors * imageFormat.Info.SectorSize);
|
imageFormat.Info.Sectors * imageFormat.Info.SectorSize);
|
||||||
|
|
||||||
if(!string.IsNullOrWhiteSpace(imageFormat.Info.Creator))
|
if(!string.IsNullOrWhiteSpace(imageFormat.Info.Creator))
|
||||||
DicConsole.WriteLine("Created by: {0}", imageFormat.Info.Creator);
|
DicConsole.WriteLine("Created by: {0}", imageFormat.Info.Creator);
|
||||||
|
|
||||||
if(imageFormat.Info.CreationTime != DateTime.MinValue)
|
if(imageFormat.Info.CreationTime != DateTime.MinValue)
|
||||||
DicConsole.WriteLine("Created on {0}", imageFormat.Info.CreationTime);
|
DicConsole.WriteLine("Created on {0}", imageFormat.Info.CreationTime);
|
||||||
|
|
||||||
if(imageFormat.Info.LastModificationTime != DateTime.MinValue)
|
if(imageFormat.Info.LastModificationTime != DateTime.MinValue)
|
||||||
DicConsole.WriteLine("Last modified on {0}", imageFormat.Info.LastModificationTime);
|
DicConsole.WriteLine("Last modified on {0}", imageFormat.Info.LastModificationTime);
|
||||||
|
|
||||||
DicConsole.WriteLine("Contains a media of type {0} and XML type {1}", imageFormat.Info.MediaType,
|
DicConsole.WriteLine("Contains a media of type {0} and XML type {1}", imageFormat.Info.MediaType,
|
||||||
imageFormat.Info.XmlMediaType);
|
imageFormat.Info.XmlMediaType);
|
||||||
|
|
||||||
DicConsole.WriteLine("{0} partitions", imageFormat.Info.HasPartitions ? "Has" : "Doesn't have");
|
DicConsole.WriteLine("{0} partitions", imageFormat.Info.HasPartitions ? "Has" : "Doesn't have");
|
||||||
DicConsole.WriteLine("{0} sessions", imageFormat.Info.HasSessions ? "Has" : "Doesn't have");
|
DicConsole.WriteLine("{0} sessions", imageFormat.Info.HasSessions ? "Has" : "Doesn't have");
|
||||||
|
|
||||||
if(!string.IsNullOrWhiteSpace(imageFormat.Info.Comments))
|
if(!string.IsNullOrWhiteSpace(imageFormat.Info.Comments))
|
||||||
DicConsole.WriteLine("Comments: {0}", imageFormat.Info.Comments);
|
DicConsole.WriteLine("Comments: {0}", imageFormat.Info.Comments);
|
||||||
if(imageFormat.Info.MediaSequence != 0 && imageFormat.Info.LastMediaSequence != 0)
|
|
||||||
|
if(imageFormat.Info.MediaSequence != 0 &&
|
||||||
|
imageFormat.Info.LastMediaSequence != 0)
|
||||||
DicConsole.WriteLine("Media is number {0} on a set of {1} medias", imageFormat.Info.MediaSequence,
|
DicConsole.WriteLine("Media is number {0} on a set of {1} medias", imageFormat.Info.MediaSequence,
|
||||||
imageFormat.Info.LastMediaSequence);
|
imageFormat.Info.LastMediaSequence);
|
||||||
|
|
||||||
if(!string.IsNullOrWhiteSpace(imageFormat.Info.MediaTitle))
|
if(!string.IsNullOrWhiteSpace(imageFormat.Info.MediaTitle))
|
||||||
DicConsole.WriteLine("Media title: {0}", imageFormat.Info.MediaTitle);
|
DicConsole.WriteLine("Media title: {0}", imageFormat.Info.MediaTitle);
|
||||||
|
|
||||||
if(!string.IsNullOrWhiteSpace(imageFormat.Info.MediaManufacturer))
|
if(!string.IsNullOrWhiteSpace(imageFormat.Info.MediaManufacturer))
|
||||||
DicConsole.WriteLine("Media manufacturer: {0}", imageFormat.Info.MediaManufacturer);
|
DicConsole.WriteLine("Media manufacturer: {0}", imageFormat.Info.MediaManufacturer);
|
||||||
|
|
||||||
if(!string.IsNullOrWhiteSpace(imageFormat.Info.MediaModel))
|
if(!string.IsNullOrWhiteSpace(imageFormat.Info.MediaModel))
|
||||||
DicConsole.WriteLine("Media model: {0}", imageFormat.Info.MediaModel);
|
DicConsole.WriteLine("Media model: {0}", imageFormat.Info.MediaModel);
|
||||||
|
|
||||||
if(!string.IsNullOrWhiteSpace(imageFormat.Info.MediaSerialNumber))
|
if(!string.IsNullOrWhiteSpace(imageFormat.Info.MediaSerialNumber))
|
||||||
DicConsole.WriteLine("Media serial number: {0}", imageFormat.Info.MediaSerialNumber);
|
DicConsole.WriteLine("Media serial number: {0}", imageFormat.Info.MediaSerialNumber);
|
||||||
|
|
||||||
if(!string.IsNullOrWhiteSpace(imageFormat.Info.MediaBarcode))
|
if(!string.IsNullOrWhiteSpace(imageFormat.Info.MediaBarcode))
|
||||||
DicConsole.WriteLine("Media barcode: {0}", imageFormat.Info.MediaBarcode);
|
DicConsole.WriteLine("Media barcode: {0}", imageFormat.Info.MediaBarcode);
|
||||||
|
|
||||||
if(!string.IsNullOrWhiteSpace(imageFormat.Info.MediaPartNumber))
|
if(!string.IsNullOrWhiteSpace(imageFormat.Info.MediaPartNumber))
|
||||||
DicConsole.WriteLine("Media part number: {0}", imageFormat.Info.MediaPartNumber);
|
DicConsole.WriteLine("Media part number: {0}", imageFormat.Info.MediaPartNumber);
|
||||||
|
|
||||||
if(!string.IsNullOrWhiteSpace(imageFormat.Info.DriveManufacturer))
|
if(!string.IsNullOrWhiteSpace(imageFormat.Info.DriveManufacturer))
|
||||||
DicConsole.WriteLine("Drive manufacturer: {0}", imageFormat.Info.DriveManufacturer);
|
DicConsole.WriteLine("Drive manufacturer: {0}", imageFormat.Info.DriveManufacturer);
|
||||||
|
|
||||||
if(!string.IsNullOrWhiteSpace(imageFormat.Info.DriveModel))
|
if(!string.IsNullOrWhiteSpace(imageFormat.Info.DriveModel))
|
||||||
DicConsole.WriteLine("Drive model: {0}", imageFormat.Info.DriveModel);
|
DicConsole.WriteLine("Drive model: {0}", imageFormat.Info.DriveModel);
|
||||||
|
|
||||||
if(!string.IsNullOrWhiteSpace(imageFormat.Info.DriveSerialNumber))
|
if(!string.IsNullOrWhiteSpace(imageFormat.Info.DriveSerialNumber))
|
||||||
DicConsole.WriteLine("Drive serial number: {0}", imageFormat.Info.DriveSerialNumber);
|
DicConsole.WriteLine("Drive serial number: {0}", imageFormat.Info.DriveSerialNumber);
|
||||||
|
|
||||||
if(!string.IsNullOrWhiteSpace(imageFormat.Info.DriveFirmwareRevision))
|
if(!string.IsNullOrWhiteSpace(imageFormat.Info.DriveFirmwareRevision))
|
||||||
DicConsole.WriteLine("Drive firmware info: {0}", imageFormat.Info.DriveFirmwareRevision);
|
DicConsole.WriteLine("Drive firmware info: {0}", imageFormat.Info.DriveFirmwareRevision);
|
||||||
if(imageFormat.Info.Cylinders > 0 && imageFormat.Info.Heads > 0 &&
|
|
||||||
|
if(imageFormat.Info.Cylinders > 0 &&
|
||||||
|
imageFormat.Info.Heads > 0 &&
|
||||||
imageFormat.Info.SectorsPerTrack > 0 &&
|
imageFormat.Info.SectorsPerTrack > 0 &&
|
||||||
imageFormat.Info.XmlMediaType != XmlMediaType.OpticalDisc &&
|
imageFormat.Info.XmlMediaType != XmlMediaType.OpticalDisc &&
|
||||||
(!(imageFormat is ITapeImage tapeImage) || !tapeImage.IsTape))
|
(!(imageFormat is ITapeImage tapeImage) || !tapeImage.IsTape))
|
||||||
@@ -113,19 +140,25 @@ namespace DiscImageChef.Core
|
|||||||
imageFormat.Info.Cylinders, imageFormat.Info.Heads,
|
imageFormat.Info.Cylinders, imageFormat.Info.Heads,
|
||||||
imageFormat.Info.SectorsPerTrack);
|
imageFormat.Info.SectorsPerTrack);
|
||||||
|
|
||||||
if(imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Count > 0)
|
if(imageFormat.Info.ReadableMediaTags != null &&
|
||||||
|
imageFormat.Info.ReadableMediaTags.Count > 0)
|
||||||
{
|
{
|
||||||
DicConsole.WriteLine("Contains {0} readable media tags:", imageFormat.Info.ReadableMediaTags.Count);
|
DicConsole.WriteLine("Contains {0} readable media tags:", imageFormat.Info.ReadableMediaTags.Count);
|
||||||
|
|
||||||
foreach(MediaTagType tag in imageFormat.Info.ReadableMediaTags.OrderBy(t => t))
|
foreach(MediaTagType tag in imageFormat.Info.ReadableMediaTags.OrderBy(t => t))
|
||||||
DicConsole.Write("{0} ", tag);
|
DicConsole.Write("{0} ", tag);
|
||||||
|
|
||||||
DicConsole.WriteLine();
|
DicConsole.WriteLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(imageFormat.Info.ReadableSectorTags != null && imageFormat.Info.ReadableSectorTags.Count > 0)
|
if(imageFormat.Info.ReadableSectorTags != null &&
|
||||||
|
imageFormat.Info.ReadableSectorTags.Count > 0)
|
||||||
{
|
{
|
||||||
DicConsole.WriteLine("Contains {0} readable sector tags:", imageFormat.Info.ReadableSectorTags.Count);
|
DicConsole.WriteLine("Contains {0} readable sector tags:", imageFormat.Info.ReadableSectorTags.Count);
|
||||||
|
|
||||||
foreach(SectorTagType tag in imageFormat.Info.ReadableSectorTags.OrderBy(t => t))
|
foreach(SectorTagType tag in imageFormat.Info.ReadableSectorTags.OrderBy(t => t))
|
||||||
DicConsole.Write("{0} ", tag);
|
DicConsole.Write("{0} ", tag);
|
||||||
|
|
||||||
DicConsole.WriteLine();
|
DicConsole.WriteLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,6 +172,7 @@ namespace DiscImageChef.Core
|
|||||||
byte[] inquiry = imageFormat.ReadDiskTag(MediaTagType.SCSI_INQUIRY);
|
byte[] inquiry = imageFormat.ReadDiskTag(MediaTagType.SCSI_INQUIRY);
|
||||||
|
|
||||||
scsiDeviceType = (PeripheralDeviceTypes)(inquiry[0] & 0x1F);
|
scsiDeviceType = (PeripheralDeviceTypes)(inquiry[0] & 0x1F);
|
||||||
|
|
||||||
if(inquiry.Length >= 16)
|
if(inquiry.Length >= 16)
|
||||||
{
|
{
|
||||||
scsiVendorId = new byte[8];
|
scsiVendorId = new byte[8];
|
||||||
@@ -213,6 +247,7 @@ namespace DiscImageChef.Core
|
|||||||
if(toc.Length > 0)
|
if(toc.Length > 0)
|
||||||
{
|
{
|
||||||
ushort dataLen = Swapping.Swap(BitConverter.ToUInt16(toc, 0));
|
ushort dataLen = Swapping.Swap(BitConverter.ToUInt16(toc, 0));
|
||||||
|
|
||||||
if(dataLen + 2 != toc.Length)
|
if(dataLen + 2 != toc.Length)
|
||||||
{
|
{
|
||||||
byte[] tmp = new byte[toc.Length + 2];
|
byte[] tmp = new byte[toc.Length + 2];
|
||||||
@@ -236,6 +271,7 @@ namespace DiscImageChef.Core
|
|||||||
if(pma.Length > 0)
|
if(pma.Length > 0)
|
||||||
{
|
{
|
||||||
ushort dataLen = Swapping.Swap(BitConverter.ToUInt16(pma, 0));
|
ushort dataLen = Swapping.Swap(BitConverter.ToUInt16(pma, 0));
|
||||||
|
|
||||||
if(dataLen + 2 != pma.Length)
|
if(dataLen + 2 != pma.Length)
|
||||||
{
|
{
|
||||||
byte[] tmp = new byte[pma.Length + 2];
|
byte[] tmp = new byte[pma.Length + 2];
|
||||||
@@ -257,6 +293,7 @@ namespace DiscImageChef.Core
|
|||||||
byte[] atip = imageFormat.ReadDiskTag(MediaTagType.CD_ATIP);
|
byte[] atip = imageFormat.ReadDiskTag(MediaTagType.CD_ATIP);
|
||||||
|
|
||||||
uint dataLen = Swapping.Swap(BitConverter.ToUInt32(atip, 0));
|
uint dataLen = Swapping.Swap(BitConverter.ToUInt32(atip, 0));
|
||||||
|
|
||||||
if(dataLen + 4 != atip.Length)
|
if(dataLen + 4 != atip.Length)
|
||||||
{
|
{
|
||||||
byte[] tmp = new byte[atip.Length + 4];
|
byte[] tmp = new byte[atip.Length + 4];
|
||||||
@@ -279,6 +316,7 @@ namespace DiscImageChef.Core
|
|||||||
byte[] cdtext = imageFormat.ReadDiskTag(MediaTagType.CD_TEXT);
|
byte[] cdtext = imageFormat.ReadDiskTag(MediaTagType.CD_TEXT);
|
||||||
|
|
||||||
uint dataLen = Swapping.Swap(BitConverter.ToUInt32(cdtext, 0));
|
uint dataLen = Swapping.Swap(BitConverter.ToUInt32(cdtext, 0));
|
||||||
|
|
||||||
if(dataLen + 4 != cdtext.Length)
|
if(dataLen + 4 != cdtext.Length)
|
||||||
{
|
{
|
||||||
byte[] tmp = new byte[cdtext.Length + 4];
|
byte[] tmp = new byte[cdtext.Length + 4];
|
||||||
@@ -302,6 +340,7 @@ namespace DiscImageChef.Core
|
|||||||
|
|
||||||
DicConsole.WriteLine("CompactDisc Media Catalogue Number contained in image: {0}",
|
DicConsole.WriteLine("CompactDisc Media Catalogue Number contained in image: {0}",
|
||||||
Encoding.UTF8.GetString(mcn));
|
Encoding.UTF8.GetString(mcn));
|
||||||
|
|
||||||
DicConsole.WriteLine();
|
DicConsole.WriteLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -362,6 +401,7 @@ namespace DiscImageChef.Core
|
|||||||
|
|
||||||
DicConsole.WriteLine("PCMCIA CIS:");
|
DicConsole.WriteLine("PCMCIA CIS:");
|
||||||
Tuple[] tuples = CIS.GetTuples(cis);
|
Tuple[] tuples = CIS.GetTuples(cis);
|
||||||
|
|
||||||
if(tuples != null)
|
if(tuples != null)
|
||||||
foreach(Tuple tuple in tuples)
|
foreach(Tuple tuple in tuples)
|
||||||
switch(tuple.Code)
|
switch(tuple.Code)
|
||||||
@@ -371,12 +411,15 @@ namespace DiscImageChef.Core
|
|||||||
case TupleCodes.CISTPL_DEVICEGEO:
|
case TupleCodes.CISTPL_DEVICEGEO:
|
||||||
case TupleCodes.CISTPL_DEVICEGEO_A:
|
case TupleCodes.CISTPL_DEVICEGEO_A:
|
||||||
DicConsole.WriteLine("{0}", CIS.PrettifyDeviceGeometryTuple(tuple));
|
DicConsole.WriteLine("{0}", CIS.PrettifyDeviceGeometryTuple(tuple));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case TupleCodes.CISTPL_MANFID:
|
case TupleCodes.CISTPL_MANFID:
|
||||||
DicConsole.WriteLine("{0}", CIS.PrettifyManufacturerIdentificationTuple(tuple));
|
DicConsole.WriteLine("{0}", CIS.PrettifyManufacturerIdentificationTuple(tuple));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case TupleCodes.CISTPL_VERS_1:
|
case TupleCodes.CISTPL_VERS_1:
|
||||||
DicConsole.WriteLine("{0}", CIS.PrettifyLevel1VersionTuple(tuple));
|
DicConsole.WriteLine("{0}", CIS.PrettifyLevel1VersionTuple(tuple));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case TupleCodes.CISTPL_ALTSTR:
|
case TupleCodes.CISTPL_ALTSTR:
|
||||||
case TupleCodes.CISTPL_BAR:
|
case TupleCodes.CISTPL_BAR:
|
||||||
@@ -414,13 +457,16 @@ namespace DiscImageChef.Core
|
|||||||
case TupleCodes.CISTPL_VERS_2:
|
case TupleCodes.CISTPL_VERS_2:
|
||||||
DicConsole.DebugWriteLine("Device-Info command", "Found undecoded tuple ID {0}",
|
DicConsole.DebugWriteLine("Device-Info command", "Found undecoded tuple ID {0}",
|
||||||
tuple.Code);
|
tuple.Code);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DicConsole.DebugWriteLine("Device-Info command", "Found unknown tuple ID 0x{0:X2}",
|
DicConsole.DebugWriteLine("Device-Info command", "Found unknown tuple ID 0x{0:X2}",
|
||||||
(byte)tuple.Code);
|
(byte)tuple.Code);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else DicConsole.DebugWriteLine("Device-Info command", "Could not get tuples");
|
else
|
||||||
|
DicConsole.DebugWriteLine("Device-Info command", "Could not get tuples");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(imageFormat.Info.ReadableMediaTags != null &&
|
if(imageFormat.Info.ReadableMediaTags != null &&
|
||||||
@@ -521,6 +567,7 @@ namespace DiscImageChef.Core
|
|||||||
if(DMI.IsXbox(xdmi))
|
if(DMI.IsXbox(xdmi))
|
||||||
{
|
{
|
||||||
DMI.XboxDMI? xmi = DMI.DecodeXbox(xdmi);
|
DMI.XboxDMI? xmi = DMI.DecodeXbox(xdmi);
|
||||||
|
|
||||||
if(xmi.HasValue)
|
if(xmi.HasValue)
|
||||||
{
|
{
|
||||||
DicConsole.WriteLine("Xbox DMI contained in image:");
|
DicConsole.WriteLine("Xbox DMI contained in image:");
|
||||||
@@ -532,6 +579,7 @@ namespace DiscImageChef.Core
|
|||||||
if(DMI.IsXbox360(xdmi))
|
if(DMI.IsXbox360(xdmi))
|
||||||
{
|
{
|
||||||
DMI.Xbox360DMI? xmi = DMI.DecodeXbox360(xdmi);
|
DMI.Xbox360DMI? xmi = DMI.DecodeXbox360(xdmi);
|
||||||
|
|
||||||
if(xmi.HasValue)
|
if(xmi.HasValue)
|
||||||
{
|
{
|
||||||
DicConsole.WriteLine("Xbox 360 DMI contained in image:");
|
DicConsole.WriteLine("Xbox 360 DMI contained in image:");
|
||||||
@@ -555,16 +603,21 @@ namespace DiscImageChef.Core
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if(opticalImage.Sessions != null && opticalImage.Sessions.Count > 0)
|
if(opticalImage.Sessions != null &&
|
||||||
|
opticalImage.Sessions.Count > 0)
|
||||||
{
|
{
|
||||||
DicConsole.WriteLine("Image sessions:");
|
DicConsole.WriteLine("Image sessions:");
|
||||||
|
|
||||||
DicConsole.WriteLine("{0,-9}{1,-13}{2,-12}{3,-12}{4,-12}", "Session", "First track",
|
DicConsole.WriteLine("{0,-9}{1,-13}{2,-12}{3,-12}{4,-12}", "Session", "First track",
|
||||||
"Last track", "Start", "End");
|
"Last track", "Start", "End");
|
||||||
|
|
||||||
DicConsole.WriteLine("=========================================================");
|
DicConsole.WriteLine("=========================================================");
|
||||||
|
|
||||||
foreach(Session session in opticalImage.Sessions)
|
foreach(Session session in opticalImage.Sessions)
|
||||||
DicConsole.WriteLine("{0,-9}{1,-13}{2,-12}{3,-12}{4,-12}", session.SessionSequence,
|
DicConsole.WriteLine("{0,-9}{1,-13}{2,-12}{3,-12}{4,-12}", session.SessionSequence,
|
||||||
session.StartTrack, session.EndTrack, session.StartSector,
|
session.StartTrack, session.EndTrack, session.StartSector,
|
||||||
session.EndSector);
|
session.EndSector);
|
||||||
|
|
||||||
DicConsole.WriteLine();
|
DicConsole.WriteLine();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -575,18 +628,23 @@ namespace DiscImageChef.Core
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if(opticalImage.Tracks != null && opticalImage.Tracks.Count > 0)
|
if(opticalImage.Tracks != null &&
|
||||||
|
opticalImage.Tracks.Count > 0)
|
||||||
{
|
{
|
||||||
DicConsole.WriteLine("Image tracks:");
|
DicConsole.WriteLine("Image tracks:");
|
||||||
|
|
||||||
DicConsole.WriteLine("{0,-7}{1,-17}{2,-6}{3,-8}{4,-12}{5,-8}{6,-12}{7,-12}", "Track", "Type",
|
DicConsole.WriteLine("{0,-7}{1,-17}{2,-6}{3,-8}{4,-12}{5,-8}{6,-12}{7,-12}", "Track", "Type",
|
||||||
"Bps", "Raw bps", "Subchannel", "Pregap", "Start", "End");
|
"Bps", "Raw bps", "Subchannel", "Pregap", "Start", "End");
|
||||||
DicConsole
|
|
||||||
.WriteLine("=================================================================================");
|
DicConsole.
|
||||||
|
WriteLine("=================================================================================");
|
||||||
|
|
||||||
foreach(Track track in opticalImage.Tracks)
|
foreach(Track track in opticalImage.Tracks)
|
||||||
DicConsole.WriteLine("{0,-7}{1,-17}{2,-6}{3,-8}{4,-12}{5,-8}{6,-12}{7,-12}",
|
DicConsole.WriteLine("{0,-7}{1,-17}{2,-6}{3,-8}{4,-12}{5,-8}{6,-12}{7,-12}",
|
||||||
track.TrackSequence, track.TrackType, track.TrackBytesPerSector,
|
track.TrackSequence, track.TrackType, track.TrackBytesPerSector,
|
||||||
track.TrackRawBytesPerSector, track.TrackSubchannelType,
|
track.TrackRawBytesPerSector, track.TrackSubchannelType,
|
||||||
track.TrackPregap, track.TrackStartSector, track.TrackEndSector);
|
track.TrackPregap, track.TrackStartSector, track.TrackEndSector);
|
||||||
|
|
||||||
DicConsole.WriteLine();
|
DicConsole.WriteLine();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -596,7 +654,8 @@ namespace DiscImageChef.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(imageFormat.DumpHardware == null) return;
|
if(imageFormat.DumpHardware == null)
|
||||||
|
return;
|
||||||
|
|
||||||
const string MANUFACTURER_STRING = "Manufacturer";
|
const string MANUFACTURER_STRING = "Manufacturer";
|
||||||
const string MODEL_STRING = "Model";
|
const string MODEL_STRING = "Model";
|
||||||
@@ -616,19 +675,31 @@ namespace DiscImageChef.Core
|
|||||||
|
|
||||||
foreach(DumpHardwareType dump in imageFormat.DumpHardware)
|
foreach(DumpHardwareType dump in imageFormat.DumpHardware)
|
||||||
{
|
{
|
||||||
if(dump.Manufacturer?.Length > manufacturerLen) manufacturerLen = dump.Manufacturer.Length;
|
if(dump.Manufacturer?.Length > manufacturerLen)
|
||||||
if(dump.Model?.Length > modelLen) modelLen = dump.Model.Length;
|
manufacturerLen = dump.Manufacturer.Length;
|
||||||
if(dump.Serial?.Length > serialLen) serialLen = dump.Serial.Length;
|
|
||||||
|
if(dump.Model?.Length > modelLen)
|
||||||
|
modelLen = dump.Model.Length;
|
||||||
|
|
||||||
|
if(dump.Serial?.Length > serialLen)
|
||||||
|
serialLen = dump.Serial.Length;
|
||||||
|
|
||||||
if(dump.Software?.Name?.Length > softwareLen)
|
if(dump.Software?.Name?.Length > softwareLen)
|
||||||
softwareLen = dump.Software.Name.Length;
|
softwareLen = dump.Software.Name.Length;
|
||||||
|
|
||||||
if(dump.Software?.Version?.Length > versionLen)
|
if(dump.Software?.Version?.Length > versionLen)
|
||||||
versionLen = dump.Software.Version.Length;
|
versionLen = dump.Software.Version.Length;
|
||||||
|
|
||||||
if(dump.Software?.OperatingSystem?.Length > osLen)
|
if(dump.Software?.OperatingSystem?.Length > osLen)
|
||||||
osLen = dump.Software.OperatingSystem.Length;
|
osLen = dump.Software.OperatingSystem.Length;
|
||||||
|
|
||||||
foreach(ExtentType extent in dump.Extents)
|
foreach(ExtentType extent in dump.Extents)
|
||||||
{
|
{
|
||||||
if($"{extent.Start}".Length > sectorLen) sectorLen = $"{extent.Start}".Length;
|
if($"{extent.Start}".Length > sectorLen)
|
||||||
if($"{extent.End}".Length > sectorLen) sectorLen = $"{extent.End}".Length;
|
sectorLen = $"{extent.Start}".Length;
|
||||||
|
|
||||||
|
if($"{extent.End}".Length > sectorLen)
|
||||||
|
sectorLen = $"{extent.End}".Length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -643,14 +714,20 @@ namespace DiscImageChef.Core
|
|||||||
|
|
||||||
char[] separator = new char[manufacturerLen + modelLen + serialLen + softwareLen + versionLen + osLen +
|
char[] separator = new char[manufacturerLen + modelLen + serialLen + softwareLen + versionLen + osLen +
|
||||||
sectorLen + sectorLen];
|
sectorLen + sectorLen];
|
||||||
for(int i = 0; i < separator.Length; i++) separator[i] = '=';
|
|
||||||
|
for(int i = 0; i < separator.Length; i++)
|
||||||
|
separator[i] = '=';
|
||||||
|
|
||||||
string format =
|
string format =
|
||||||
$"{{0,-{manufacturerLen}}}{{1,-{modelLen}}}{{2,-{serialLen}}}{{3,-{softwareLen}}}{{4,-{versionLen}}}{{5,-{osLen}}}{{6,-{sectorLen}}}{{7,-{sectorLen}}}";
|
$"{{0,-{manufacturerLen}}}{{1,-{modelLen}}}{{2,-{serialLen}}}{{3,-{softwareLen}}}{{4,-{versionLen}}}{{5,-{osLen}}}{{6,-{sectorLen}}}{{7,-{sectorLen}}}";
|
||||||
|
|
||||||
DicConsole.WriteLine("Dump hardware information:");
|
DicConsole.WriteLine("Dump hardware information:");
|
||||||
|
|
||||||
DicConsole.WriteLine(format, MANUFACTURER_STRING, MODEL_STRING, SERIAL_STRING, SOFTWARE_STRING,
|
DicConsole.WriteLine(format, MANUFACTURER_STRING, MODEL_STRING, SERIAL_STRING, SOFTWARE_STRING,
|
||||||
VERSION_STRING, OS_STRING, START_STRING, END_STRING);
|
VERSION_STRING, OS_STRING, START_STRING, END_STRING);
|
||||||
|
|
||||||
DicConsole.WriteLine(new string(separator));
|
DicConsole.WriteLine(new string(separator));
|
||||||
|
|
||||||
foreach(DumpHardwareType dump in imageFormat.DumpHardware)
|
foreach(DumpHardwareType dump in imageFormat.DumpHardware)
|
||||||
{
|
{
|
||||||
foreach(ExtentType extent in dump.Extents)
|
foreach(ExtentType extent in dump.Extents)
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ using System.Linq;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using DiscImageChef.CommonTypes;
|
using DiscImageChef.CommonTypes;
|
||||||
using DiscImageChef.CommonTypes.Enums;
|
using DiscImageChef.CommonTypes.Enums;
|
||||||
|
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
|
||||||
using DiscImageChef.Console;
|
using DiscImageChef.Console;
|
||||||
using DiscImageChef.Core.Media.Detection;
|
using DiscImageChef.Core.Media.Detection;
|
||||||
using DiscImageChef.Decoders.CD;
|
using DiscImageChef.Decoders.CD;
|
||||||
@@ -47,6 +48,7 @@ using DiscImageChef.Decoders.Xbox;
|
|||||||
using DiscImageChef.Devices;
|
using DiscImageChef.Devices;
|
||||||
using DeviceInfo = DiscImageChef.Core.Devices.Info.DeviceInfo;
|
using DeviceInfo = DiscImageChef.Core.Devices.Info.DeviceInfo;
|
||||||
using DMI = DiscImageChef.Decoders.Xbox.DMI;
|
using DMI = DiscImageChef.Decoders.Xbox.DMI;
|
||||||
|
using Inquiry = DiscImageChef.Decoders.SCSI.Inquiry;
|
||||||
|
|
||||||
namespace DiscImageChef.Core.Media.Info
|
namespace DiscImageChef.Core.Media.Info
|
||||||
{
|
{
|
||||||
@@ -1289,7 +1291,7 @@ namespace DiscImageChef.Core.Media.Info
|
|||||||
|
|
||||||
if(!sense)
|
if(!sense)
|
||||||
{
|
{
|
||||||
Inquiry.SCSIInquiry? inq = Inquiry.Decode(inqBuffer);
|
var inq = CommonTypes.Structs.Devices.SCSI.Inquiry.Decode(inqBuffer);
|
||||||
|
|
||||||
if(inq.HasValue &&
|
if(inq.HasValue &&
|
||||||
inq.Value.KreonPresent)
|
inq.Value.KreonPresent)
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
// Copyright © 2011-2020 Natalia Portillo
|
// Copyright © 2011-2020 Natalia Portillo
|
||||||
// ****************************************************************************/
|
// ****************************************************************************/
|
||||||
|
|
||||||
|
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
|
||||||
using DiscImageChef.Console;
|
using DiscImageChef.Console;
|
||||||
using DiscImageChef.Decoders.SCSI;
|
using DiscImageChef.Decoders.SCSI;
|
||||||
|
|
||||||
@@ -41,22 +42,26 @@ namespace DiscImageChef.Core
|
|||||||
{
|
{
|
||||||
DicConsole.WriteLine(Modes.PrettifyModeHeader(decMode.Header, devType));
|
DicConsole.WriteLine(Modes.PrettifyModeHeader(decMode.Header, devType));
|
||||||
|
|
||||||
if(decMode.Pages == null) return;
|
if(decMode.Pages == null)
|
||||||
|
return;
|
||||||
|
|
||||||
foreach(Modes.ModePage page in decMode.Pages)
|
foreach(Modes.ModePage page in decMode.Pages)
|
||||||
|
|
||||||
//DicConsole.WriteLine("Page {0:X2}h subpage {1:X2}h is {2} bytes long", page.Page, page.Subpage, page.PageResponse.Length);
|
//DicConsole.WriteLine("Page {0:X2}h subpage {1:X2}h is {2} bytes long", page.Page, page.Subpage, page.PageResponse.Length);
|
||||||
switch(page.Page)
|
switch(page.Page)
|
||||||
{
|
{
|
||||||
case 0x00:
|
case 0x00:
|
||||||
{
|
{
|
||||||
if(devType == PeripheralDeviceTypes.MultiMediaDevice && page.Subpage == 0)
|
if(devType == PeripheralDeviceTypes.MultiMediaDevice &&
|
||||||
|
page.Subpage == 0)
|
||||||
DicConsole.WriteLine(Modes.PrettifyModePage_00_SFF(page.PageResponse));
|
DicConsole.WriteLine(Modes.PrettifyModePage_00_SFF(page.PageResponse));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(page.Subpage != 0)
|
if(page.Subpage != 0)
|
||||||
DicConsole.WriteLine("Found unknown vendor mode page {0:X2}h subpage {1:X2}h",
|
DicConsole.WriteLine("Found unknown vendor mode page {0:X2}h subpage {1:X2}h",
|
||||||
page.Page, page.Subpage);
|
page.Page, page.Subpage);
|
||||||
else DicConsole.WriteLine("Found unknown vendor mode page {0:X2}h", page.Page);
|
else
|
||||||
|
DicConsole.WriteLine("Found unknown vendor mode page {0:X2}h", page.Page);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -67,42 +72,53 @@ namespace DiscImageChef.Core
|
|||||||
DicConsole.WriteLine(devType == PeripheralDeviceTypes.MultiMediaDevice
|
DicConsole.WriteLine(devType == PeripheralDeviceTypes.MultiMediaDevice
|
||||||
? Modes.PrettifyModePage_01_MMC(page.PageResponse)
|
? Modes.PrettifyModePage_01_MMC(page.PageResponse)
|
||||||
: Modes.PrettifyModePage_01(page.PageResponse));
|
: Modes.PrettifyModePage_01(page.PageResponse));
|
||||||
else goto default;
|
else
|
||||||
|
goto default;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x02:
|
case 0x02:
|
||||||
{
|
{
|
||||||
if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_02(page.PageResponse));
|
if(page.Subpage == 0)
|
||||||
else goto default;
|
DicConsole.WriteLine(Modes.PrettifyModePage_02(page.PageResponse));
|
||||||
|
else
|
||||||
|
goto default;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x03:
|
case 0x03:
|
||||||
{
|
{
|
||||||
if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_03(page.PageResponse));
|
if(page.Subpage == 0)
|
||||||
else goto default;
|
DicConsole.WriteLine(Modes.PrettifyModePage_03(page.PageResponse));
|
||||||
|
else
|
||||||
|
goto default;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x04:
|
case 0x04:
|
||||||
{
|
{
|
||||||
if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_04(page.PageResponse));
|
if(page.Subpage == 0)
|
||||||
else goto default;
|
DicConsole.WriteLine(Modes.PrettifyModePage_04(page.PageResponse));
|
||||||
|
else
|
||||||
|
goto default;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x05:
|
case 0x05:
|
||||||
{
|
{
|
||||||
if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_05(page.PageResponse));
|
if(page.Subpage == 0)
|
||||||
else goto default;
|
DicConsole.WriteLine(Modes.PrettifyModePage_05(page.PageResponse));
|
||||||
|
else
|
||||||
|
goto default;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x06:
|
case 0x06:
|
||||||
{
|
{
|
||||||
if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_06(page.PageResponse));
|
if(page.Subpage == 0)
|
||||||
else goto default;
|
DicConsole.WriteLine(Modes.PrettifyModePage_06(page.PageResponse));
|
||||||
|
else
|
||||||
|
goto default;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -112,51 +128,64 @@ namespace DiscImageChef.Core
|
|||||||
DicConsole.WriteLine(devType == PeripheralDeviceTypes.MultiMediaDevice
|
DicConsole.WriteLine(devType == PeripheralDeviceTypes.MultiMediaDevice
|
||||||
? Modes.PrettifyModePage_07_MMC(page.PageResponse)
|
? Modes.PrettifyModePage_07_MMC(page.PageResponse)
|
||||||
: Modes.PrettifyModePage_07(page.PageResponse));
|
: Modes.PrettifyModePage_07(page.PageResponse));
|
||||||
else goto default;
|
else
|
||||||
|
goto default;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x08:
|
case 0x08:
|
||||||
{
|
{
|
||||||
if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_08(page.PageResponse));
|
if(page.Subpage == 0)
|
||||||
else goto default;
|
DicConsole.WriteLine(Modes.PrettifyModePage_08(page.PageResponse));
|
||||||
|
else
|
||||||
|
goto default;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x0A:
|
case 0x0A:
|
||||||
{
|
{
|
||||||
if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_0A(page.PageResponse));
|
if(page.Subpage == 0)
|
||||||
|
DicConsole.WriteLine(Modes.PrettifyModePage_0A(page.PageResponse));
|
||||||
else if(page.Subpage == 1)
|
else if(page.Subpage == 1)
|
||||||
DicConsole.WriteLine(Modes.PrettifyModePage_0A_S01(page.PageResponse));
|
DicConsole.WriteLine(Modes.PrettifyModePage_0A_S01(page.PageResponse));
|
||||||
else goto default;
|
else
|
||||||
|
goto default;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x0B:
|
case 0x0B:
|
||||||
{
|
{
|
||||||
if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_0B(page.PageResponse));
|
if(page.Subpage == 0)
|
||||||
else goto default;
|
DicConsole.WriteLine(Modes.PrettifyModePage_0B(page.PageResponse));
|
||||||
|
else
|
||||||
|
goto default;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x0D:
|
case 0x0D:
|
||||||
{
|
{
|
||||||
if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_0D(page.PageResponse));
|
if(page.Subpage == 0)
|
||||||
else goto default;
|
DicConsole.WriteLine(Modes.PrettifyModePage_0D(page.PageResponse));
|
||||||
|
else
|
||||||
|
goto default;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x0E:
|
case 0x0E:
|
||||||
{
|
{
|
||||||
if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_0E(page.PageResponse));
|
if(page.Subpage == 0)
|
||||||
else goto default;
|
DicConsole.WriteLine(Modes.PrettifyModePage_0E(page.PageResponse));
|
||||||
|
else
|
||||||
|
goto default;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x0F:
|
case 0x0F:
|
||||||
{
|
{
|
||||||
if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_0F(page.PageResponse));
|
if(page.Subpage == 0)
|
||||||
else goto default;
|
DicConsole.WriteLine(Modes.PrettifyModePage_0F(page.PageResponse));
|
||||||
|
else
|
||||||
|
goto default;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -166,14 +195,17 @@ namespace DiscImageChef.Core
|
|||||||
DicConsole.WriteLine(devType == PeripheralDeviceTypes.SequentialAccess
|
DicConsole.WriteLine(devType == PeripheralDeviceTypes.SequentialAccess
|
||||||
? Modes.PrettifyModePage_10_SSC(page.PageResponse)
|
? Modes.PrettifyModePage_10_SSC(page.PageResponse)
|
||||||
: Modes.PrettifyModePage_10(page.PageResponse));
|
: Modes.PrettifyModePage_10(page.PageResponse));
|
||||||
else goto default;
|
else
|
||||||
|
goto default;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x11:
|
case 0x11:
|
||||||
{
|
{
|
||||||
if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_11(page.PageResponse));
|
if(page.Subpage == 0)
|
||||||
else goto default;
|
DicConsole.WriteLine(Modes.PrettifyModePage_11(page.PageResponse));
|
||||||
|
else
|
||||||
|
goto default;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -181,24 +213,30 @@ namespace DiscImageChef.Core
|
|||||||
case 0x13:
|
case 0x13:
|
||||||
case 0x14:
|
case 0x14:
|
||||||
{
|
{
|
||||||
if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_12_13_14(page.PageResponse));
|
if(page.Subpage == 0)
|
||||||
else goto default;
|
DicConsole.WriteLine(Modes.PrettifyModePage_12_13_14(page.PageResponse));
|
||||||
|
else
|
||||||
|
goto default;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x1A:
|
case 0x1A:
|
||||||
{
|
{
|
||||||
if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_1A(page.PageResponse));
|
if(page.Subpage == 0)
|
||||||
|
DicConsole.WriteLine(Modes.PrettifyModePage_1A(page.PageResponse));
|
||||||
else if(page.Subpage == 1)
|
else if(page.Subpage == 1)
|
||||||
DicConsole.WriteLine(Modes.PrettifyModePage_1A_S01(page.PageResponse));
|
DicConsole.WriteLine(Modes.PrettifyModePage_1A_S01(page.PageResponse));
|
||||||
else goto default;
|
else
|
||||||
|
goto default;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x1B:
|
case 0x1B:
|
||||||
{
|
{
|
||||||
if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_1B(page.PageResponse));
|
if(page.Subpage == 0)
|
||||||
else goto default;
|
DicConsole.WriteLine(Modes.PrettifyModePage_1B(page.PageResponse));
|
||||||
|
else
|
||||||
|
goto default;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -210,14 +248,17 @@ namespace DiscImageChef.Core
|
|||||||
: Modes.PrettifyModePage_1C(page.PageResponse));
|
: Modes.PrettifyModePage_1C(page.PageResponse));
|
||||||
else if(page.Subpage == 1)
|
else if(page.Subpage == 1)
|
||||||
DicConsole.WriteLine(Modes.PrettifyModePage_1C_S01(page.PageResponse));
|
DicConsole.WriteLine(Modes.PrettifyModePage_1C_S01(page.PageResponse));
|
||||||
else goto default;
|
else
|
||||||
|
goto default;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x1D:
|
case 0x1D:
|
||||||
{
|
{
|
||||||
if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_1D(page.PageResponse));
|
if(page.Subpage == 0)
|
||||||
else goto default;
|
DicConsole.WriteLine(Modes.PrettifyModePage_1D(page.PageResponse));
|
||||||
|
else
|
||||||
|
goto default;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -225,7 +266,8 @@ namespace DiscImageChef.Core
|
|||||||
{
|
{
|
||||||
if(StringHandlers.CToString(vendorId).Trim() == "CERTANCE")
|
if(StringHandlers.CToString(vendorId).Trim() == "CERTANCE")
|
||||||
DicConsole.WriteLine(Modes.PrettifyCertanceModePage_21(page.PageResponse));
|
DicConsole.WriteLine(Modes.PrettifyCertanceModePage_21(page.PageResponse));
|
||||||
else goto default;
|
else
|
||||||
|
goto default;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -233,7 +275,8 @@ namespace DiscImageChef.Core
|
|||||||
{
|
{
|
||||||
if(StringHandlers.CToString(vendorId).Trim() == "CERTANCE")
|
if(StringHandlers.CToString(vendorId).Trim() == "CERTANCE")
|
||||||
DicConsole.WriteLine(Modes.PrettifyCertanceModePage_22(page.PageResponse));
|
DicConsole.WriteLine(Modes.PrettifyCertanceModePage_22(page.PageResponse));
|
||||||
else goto default;
|
else
|
||||||
|
goto default;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -241,14 +284,17 @@ namespace DiscImageChef.Core
|
|||||||
{
|
{
|
||||||
if(StringHandlers.CToString(vendorId).Trim() == "IBM")
|
if(StringHandlers.CToString(vendorId).Trim() == "IBM")
|
||||||
DicConsole.WriteLine(Modes.PrettifyIBMModePage_24(page.PageResponse));
|
DicConsole.WriteLine(Modes.PrettifyIBMModePage_24(page.PageResponse));
|
||||||
else goto default;
|
else
|
||||||
|
goto default;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x2A:
|
case 0x2A:
|
||||||
{
|
{
|
||||||
if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_2A(page.PageResponse));
|
if(page.Subpage == 0)
|
||||||
else goto default;
|
DicConsole.WriteLine(Modes.PrettifyModePage_2A(page.PageResponse));
|
||||||
|
else
|
||||||
|
goto default;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -256,7 +302,8 @@ namespace DiscImageChef.Core
|
|||||||
{
|
{
|
||||||
if(StringHandlers.CToString(vendorId).Trim() == "IBM")
|
if(StringHandlers.CToString(vendorId).Trim() == "IBM")
|
||||||
DicConsole.WriteLine(Modes.PrettifyIBMModePage_2F(page.PageResponse));
|
DicConsole.WriteLine(Modes.PrettifyIBMModePage_2F(page.PageResponse));
|
||||||
else goto default;
|
else
|
||||||
|
goto default;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -264,7 +311,8 @@ namespace DiscImageChef.Core
|
|||||||
{
|
{
|
||||||
if(Modes.IsAppleModePage_30(page.PageResponse))
|
if(Modes.IsAppleModePage_30(page.PageResponse))
|
||||||
DicConsole.WriteLine("Drive identifies as Apple OEM drive");
|
DicConsole.WriteLine("Drive identifies as Apple OEM drive");
|
||||||
else goto default;
|
else
|
||||||
|
goto default;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -272,7 +320,8 @@ namespace DiscImageChef.Core
|
|||||||
{
|
{
|
||||||
if(StringHandlers.CToString(vendorId).Trim() == "HP")
|
if(StringHandlers.CToString(vendorId).Trim() == "HP")
|
||||||
DicConsole.WriteLine(Modes.PrettifyHPModePage_3B(page.PageResponse));
|
DicConsole.WriteLine(Modes.PrettifyHPModePage_3B(page.PageResponse));
|
||||||
else goto default;
|
else
|
||||||
|
goto default;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -280,7 +329,8 @@ namespace DiscImageChef.Core
|
|||||||
{
|
{
|
||||||
if(StringHandlers.CToString(vendorId).Trim() == "HP")
|
if(StringHandlers.CToString(vendorId).Trim() == "HP")
|
||||||
DicConsole.WriteLine(Modes.PrettifyHPModePage_3C(page.PageResponse));
|
DicConsole.WriteLine(Modes.PrettifyHPModePage_3C(page.PageResponse));
|
||||||
else goto default;
|
else
|
||||||
|
goto default;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -290,7 +340,8 @@ namespace DiscImageChef.Core
|
|||||||
DicConsole.WriteLine(Modes.PrettifyIBMModePage_3D(page.PageResponse));
|
DicConsole.WriteLine(Modes.PrettifyIBMModePage_3D(page.PageResponse));
|
||||||
else if(StringHandlers.CToString(vendorId).Trim() == "HP")
|
else if(StringHandlers.CToString(vendorId).Trim() == "HP")
|
||||||
DicConsole.WriteLine(Modes.PrettifyHPModePage_3D(page.PageResponse));
|
DicConsole.WriteLine(Modes.PrettifyHPModePage_3D(page.PageResponse));
|
||||||
else goto default;
|
else
|
||||||
|
goto default;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -300,7 +351,8 @@ namespace DiscImageChef.Core
|
|||||||
DicConsole.WriteLine(Modes.PrettifyFujitsuModePage_3E(page.PageResponse));
|
DicConsole.WriteLine(Modes.PrettifyFujitsuModePage_3E(page.PageResponse));
|
||||||
else if(StringHandlers.CToString(vendorId).Trim() == "HP")
|
else if(StringHandlers.CToString(vendorId).Trim() == "HP")
|
||||||
DicConsole.WriteLine(Modes.PrettifyHPModePage_3E(page.PageResponse));
|
DicConsole.WriteLine(Modes.PrettifyHPModePage_3E(page.PageResponse));
|
||||||
else goto default;
|
else
|
||||||
|
goto default;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -309,7 +361,9 @@ namespace DiscImageChef.Core
|
|||||||
if(page.Subpage != 0)
|
if(page.Subpage != 0)
|
||||||
DicConsole.WriteLine("Found unknown mode page {0:X2}h subpage {1:X2}h", page.Page,
|
DicConsole.WriteLine("Found unknown mode page {0:X2}h subpage {1:X2}h", page.Page,
|
||||||
page.Subpage);
|
page.Subpage);
|
||||||
else DicConsole.WriteLine("Found unknown mode page {0:X2}h", page.Page);
|
else
|
||||||
|
DicConsole.WriteLine("Found unknown mode page {0:X2}h", page.Page);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -681,7 +681,7 @@ namespace DiscImageChef.Core
|
|||||||
|
|
||||||
if(image.Info.ReadableMediaTags.Contains(MediaTagType.ATA_IDENTIFY))
|
if(image.Info.ReadableMediaTags.Contains(MediaTagType.ATA_IDENTIFY))
|
||||||
{
|
{
|
||||||
Identify.IdentifyDevice? ataId = Identify.Decode(image.ReadDiskTag(MediaTagType.ATA_IDENTIFY));
|
CommonTypes.Structs.Devices.ATA.Identify.IdentifyDevice? ataId = CommonTypes.Structs.Devices.ATA.Identify.Decode(image.ReadDiskTag(MediaTagType.ATA_IDENTIFY));
|
||||||
|
|
||||||
if(ataId.HasValue)
|
if(ataId.HasValue)
|
||||||
if(ataId.Value.CurrentCylinders > 0 &&
|
if(ataId.Value.CurrentCylinders > 0 &&
|
||||||
|
|||||||
Submodule DiscImageChef.Decoders updated: 785638f5f6...1856c6ddb4
@@ -37,7 +37,8 @@ using System.Linq;
|
|||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using DiscImageChef.CommonTypes.Enums;
|
using DiscImageChef.CommonTypes.Enums;
|
||||||
using DiscImageChef.CommonTypes.Interop;
|
using DiscImageChef.CommonTypes.Interop;
|
||||||
using DiscImageChef.Decoders.ATA;
|
using DiscImageChef.CommonTypes.Structs.Devices.ATA;
|
||||||
|
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
|
||||||
using DiscImageChef.Decoders.SCSI;
|
using DiscImageChef.Decoders.SCSI;
|
||||||
using DiscImageChef.Decoders.SCSI.MMC;
|
using DiscImageChef.Decoders.SCSI.MMC;
|
||||||
using DiscImageChef.Decoders.SecureDigital;
|
using DiscImageChef.Decoders.SecureDigital;
|
||||||
@@ -50,6 +51,7 @@ using FileAttributes = DiscImageChef.Devices.Windows.FileAttributes;
|
|||||||
using FileFlags = DiscImageChef.Devices.Linux.FileFlags;
|
using FileFlags = DiscImageChef.Devices.Linux.FileFlags;
|
||||||
using FileMode = DiscImageChef.Devices.Windows.FileMode;
|
using FileMode = DiscImageChef.Devices.Windows.FileMode;
|
||||||
using FileShare = DiscImageChef.Devices.Windows.FileShare;
|
using FileShare = DiscImageChef.Devices.Windows.FileShare;
|
||||||
|
using Inquiry = DiscImageChef.CommonTypes.Structs.Devices.SCSI.Inquiry;
|
||||||
using PlatformID = DiscImageChef.CommonTypes.Interop.PlatformID;
|
using PlatformID = DiscImageChef.CommonTypes.Interop.PlatformID;
|
||||||
using VendorString = DiscImageChef.Decoders.SecureDigital.VendorString;
|
using VendorString = DiscImageChef.Decoders.SecureDigital.VendorString;
|
||||||
|
|
||||||
@@ -761,7 +763,7 @@ namespace DiscImageChef.Devices
|
|||||||
|
|
||||||
if(!scsiSense)
|
if(!scsiSense)
|
||||||
{
|
{
|
||||||
Inquiry.SCSIInquiry? inquiry = Inquiry.Decode(inqBuf);
|
Inquiry? inquiry = Inquiry.Decode(inqBuf);
|
||||||
|
|
||||||
Type = DeviceType.SCSI;
|
Type = DeviceType.SCSI;
|
||||||
bool serialSense = ScsiInquiry(out inqBuf, out _, 0x80);
|
bool serialSense = ScsiInquiry(out inqBuf, out _, 0x80);
|
||||||
|
|||||||
@@ -32,211 +32,156 @@
|
|||||||
|
|
||||||
using DiscImageChef.CommonTypes.Enums;
|
using DiscImageChef.CommonTypes.Enums;
|
||||||
using DiscImageChef.CommonTypes.Interop;
|
using DiscImageChef.CommonTypes.Interop;
|
||||||
using DiscImageChef.Decoders.SCSI;
|
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
|
||||||
|
|
||||||
namespace DiscImageChef.Devices
|
namespace DiscImageChef.Devices
|
||||||
{
|
{
|
||||||
public partial class Device
|
public partial class Device
|
||||||
{
|
{
|
||||||
private readonly ushort usbVendor;
|
readonly ushort usbVendor;
|
||||||
private readonly ushort usbProduct;
|
readonly ushort usbProduct;
|
||||||
private readonly ulong firewireGuid;
|
readonly ulong firewireGuid;
|
||||||
private readonly uint firewireModel;
|
readonly uint firewireModel;
|
||||||
private readonly uint firewireVendor;
|
readonly uint firewireVendor;
|
||||||
|
|
||||||
// MMC and SecureDigital, values that need to be get with card idle, something that may
|
// MMC and SecureDigital, values that need to be get with card idle, something that may
|
||||||
// not be possible to do but usually is already done by the SDHCI driver.
|
// not be possible to do but usually is already done by the SDHCI driver.
|
||||||
private readonly byte[] cachedCsd;
|
readonly byte[] cachedCsd;
|
||||||
private readonly byte[] cachedCid;
|
readonly byte[] cachedCid;
|
||||||
private readonly byte[] cachedScr;
|
readonly byte[] cachedScr;
|
||||||
private readonly byte[] cachedOcr;
|
readonly byte[] cachedOcr;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Gets the Platform ID for this device</summary>
|
||||||
/// Gets the Platform ID for this device
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The Platform ID</value>
|
/// <value>The Platform ID</value>
|
||||||
public PlatformID PlatformId { get; }
|
public PlatformID PlatformId { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Gets the file handle representing this device</summary>
|
||||||
/// Gets the file handle representing this device
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The file handle</value>
|
/// <value>The file handle</value>
|
||||||
public object FileHandle { get; private set; }
|
public object FileHandle { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Gets or sets the standard timeout for commands sent to this device</summary>
|
||||||
/// Gets or sets the standard timeout for commands sent to this device
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The timeout in seconds</value>
|
/// <value>The timeout in seconds</value>
|
||||||
public uint Timeout { get; }
|
public uint Timeout { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Gets a value indicating whether this <see cref="Device" /> is in error.</summary>
|
||||||
/// Gets a value indicating whether this <see cref="Device" /> is in error.
|
|
||||||
/// </summary>
|
|
||||||
/// <value><c>true</c> if error; otherwise, <c>false</c>.</value>
|
/// <value><c>true</c> if error; otherwise, <c>false</c>.</value>
|
||||||
public bool Error { get; private set; }
|
public bool Error { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Gets the last error number.</summary>
|
||||||
/// Gets the last error number.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The last error.</value>
|
/// <value>The last error.</value>
|
||||||
public int LastError { get; private set; }
|
public int LastError { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Gets the device type.</summary>
|
||||||
/// Gets the device type.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The device type.</value>
|
/// <value>The device type.</value>
|
||||||
public DeviceType Type { get; }
|
public DeviceType Type { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Gets the device's manufacturer</summary>
|
||||||
/// Gets the device's manufacturer
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The manufacturer.</value>
|
/// <value>The manufacturer.</value>
|
||||||
public string Manufacturer { get; }
|
public string Manufacturer { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Gets the device model</summary>
|
||||||
/// Gets the device model
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The model.</value>
|
/// <value>The model.</value>
|
||||||
public string Model { get; }
|
public string Model { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Gets the device's firmware version.</summary>
|
||||||
/// Gets the device's firmware version.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The firmware version.</value>
|
/// <value>The firmware version.</value>
|
||||||
public string FirmwareRevision { get; }
|
public string FirmwareRevision { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Gets the device's serial number.</summary>
|
||||||
/// Gets the device's serial number.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The serial number.</value>
|
/// <value>The serial number.</value>
|
||||||
public string Serial { get; }
|
public string Serial { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Gets the device's SCSI peripheral device type</summary>
|
||||||
/// Gets the device's SCSI peripheral device type
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The SCSI peripheral device type.</value>
|
/// <value>The SCSI peripheral device type.</value>
|
||||||
public PeripheralDeviceTypes ScsiType { get; }
|
public PeripheralDeviceTypes ScsiType { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Gets a value indicating whether this device's media is removable.</summary>
|
||||||
/// Gets a value indicating whether this device's media is removable.
|
|
||||||
/// </summary>
|
|
||||||
/// <value><c>true</c> if this device's media is removable; otherwise, <c>false</c>.</value>
|
/// <value><c>true</c> if this device's media is removable; otherwise, <c>false</c>.</value>
|
||||||
public bool IsRemovable { get; }
|
public bool IsRemovable { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Gets a value indicating whether this device is attached via USB.</summary>
|
||||||
/// Gets a value indicating whether this device is attached via USB.
|
|
||||||
/// </summary>
|
|
||||||
/// <value><c>true</c> if this device is attached via USB; otherwise, <c>false</c>.</value>
|
/// <value><c>true</c> if this device is attached via USB; otherwise, <c>false</c>.</value>
|
||||||
public bool IsUsb { get; }
|
public bool IsUsb { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Gets the USB vendor ID.</summary>
|
||||||
/// Gets the USB vendor ID.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The USB vendor ID.</value>
|
/// <value>The USB vendor ID.</value>
|
||||||
public ushort UsbVendorId => usbVendor;
|
public ushort UsbVendorId => usbVendor;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Gets the USB product ID.</summary>
|
||||||
/// Gets the USB product ID.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The USB product ID.</value>
|
/// <value>The USB product ID.</value>
|
||||||
public ushort UsbProductId => usbProduct;
|
public ushort UsbProductId => usbProduct;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Gets the USB descriptors.</summary>
|
||||||
/// Gets the USB descriptors.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The USB descriptors.</value>
|
/// <value>The USB descriptors.</value>
|
||||||
public byte[] UsbDescriptors { get; }
|
public byte[] UsbDescriptors { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Gets the USB manufacturer string.</summary>
|
||||||
/// Gets the USB manufacturer string.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The USB manufacturer string.</value>
|
/// <value>The USB manufacturer string.</value>
|
||||||
public string UsbManufacturerString { get; }
|
public string UsbManufacturerString { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Gets the USB product string.</summary>
|
||||||
/// Gets the USB product string.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The USB product string.</value>
|
/// <value>The USB product string.</value>
|
||||||
public string UsbProductString { get; }
|
public string UsbProductString { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Gets the USB serial string.</summary>
|
||||||
/// Gets the USB serial string.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The USB serial string.</value>
|
/// <value>The USB serial string.</value>
|
||||||
public string UsbSerialString { get; }
|
public string UsbSerialString { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Gets a value indicating whether this device is attached via FireWire.</summary>
|
||||||
/// Gets a value indicating whether this device is attached via FireWire.
|
|
||||||
/// </summary>
|
|
||||||
/// <value><c>true</c> if this device is attached via FireWire; otherwise, <c>false</c>.</value>
|
/// <value><c>true</c> if this device is attached via FireWire; otherwise, <c>false</c>.</value>
|
||||||
public bool IsFireWire { get; }
|
public bool IsFireWire { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Gets the FireWire GUID</summary>
|
||||||
/// Gets the FireWire GUID
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The FireWire GUID.</value>
|
/// <value>The FireWire GUID.</value>
|
||||||
public ulong FireWireGuid => firewireGuid;
|
public ulong FireWireGuid => firewireGuid;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Gets the FireWire model number</summary>
|
||||||
/// Gets the FireWire model number
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The FireWire model.</value>
|
/// <value>The FireWire model.</value>
|
||||||
public uint FireWireModel => firewireModel;
|
public uint FireWireModel => firewireModel;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Gets the FireWire model name.</summary>
|
||||||
/// Gets the FireWire model name.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The FireWire model name.</value>
|
/// <value>The FireWire model name.</value>
|
||||||
public string FireWireModelName { get; }
|
public string FireWireModelName { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Gets the FireWire vendor number.</summary>
|
||||||
/// Gets the FireWire vendor number.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The FireWire vendor number.</value>
|
/// <value>The FireWire vendor number.</value>
|
||||||
public uint FireWireVendor => firewireVendor;
|
public uint FireWireVendor => firewireVendor;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Gets the FireWire vendor name.</summary>
|
||||||
/// Gets the FireWire vendor name.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The FireWire vendor name.</value>
|
/// <value>The FireWire vendor name.</value>
|
||||||
public string FireWireVendorName { get; }
|
public string FireWireVendorName { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Gets a value indicating whether this device is a CompactFlash device.</summary>
|
||||||
/// Gets a value indicating whether this device is a CompactFlash device.
|
|
||||||
/// </summary>
|
|
||||||
/// <value><c>true</c> if this device is a CompactFlash device; otherwise, <c>false</c>.</value>
|
/// <value><c>true</c> if this device is a CompactFlash device; otherwise, <c>false</c>.</value>
|
||||||
public bool IsCompactFlash { get; }
|
public bool IsCompactFlash { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Gets a value indicating whether this device is a PCMCIA device.</summary>
|
||||||
/// Gets a value indicating whether this device is a PCMCIA device.
|
|
||||||
/// </summary>
|
|
||||||
/// <value><c>true</c> if this device is a PCMCIA device; otherwise, <c>false</c>.</value>
|
/// <value><c>true</c> if this device is a PCMCIA device; otherwise, <c>false</c>.</value>
|
||||||
public bool IsPcmcia { get; }
|
public bool IsPcmcia { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>Contains the PCMCIA CIS if applicable</summary>
|
||||||
/// Contains the PCMCIA CIS if applicable
|
|
||||||
/// </summary>
|
|
||||||
public byte[] Cis { get; }
|
public byte[] Cis { get; }
|
||||||
|
|
||||||
private readonly Remote.Remote _remote;
|
readonly Remote.Remote _remote;
|
||||||
private bool? _isRemoteAdmin;
|
bool? _isRemoteAdmin;
|
||||||
|
|
||||||
public bool IsRemoteAdmin
|
public bool IsRemoteAdmin
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (_isRemoteAdmin is null) _isRemoteAdmin = _remote.IsRoot;
|
if(_isRemoteAdmin is null)
|
||||||
|
_isRemoteAdmin = _remote.IsRoot;
|
||||||
|
|
||||||
return _isRemoteAdmin == true;
|
return _isRemoteAdmin == true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsRemote => _remote != null;
|
public bool IsRemote => _remote != null;
|
||||||
public string RemoteApplication => _remote?.ServerApplication;
|
public string RemoteApplication => _remote?.ServerApplication;
|
||||||
public string RemoteVersion => _remote?.ServerVersion;
|
public string RemoteVersion => _remote?.ServerVersion;
|
||||||
public string RemoteOperatingSystem => _remote?.ServerOperatingSystem;
|
public string RemoteOperatingSystem => _remote?.ServerOperatingSystem;
|
||||||
public string RemoteOperatingSystemVersion => _remote?.ServerOperatingSystemVersion;
|
public string RemoteOperatingSystemVersion => _remote?.ServerOperatingSystemVersion;
|
||||||
public string RemoteArchitecture => _remote?.ServerArchitecture;
|
public string RemoteArchitecture => _remote?.ServerArchitecture;
|
||||||
public int RemoteProtocolVersion => _remote?.ServerProtocolVersion ?? 0;
|
public int RemoteProtocolVersion => _remote?.ServerProtocolVersion ?? 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -35,17 +35,15 @@ using System.Collections.Generic;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using DiscImageChef.Decoders.ATA;
|
using DiscImageChef.CommonTypes.Structs.Devices.ATA;
|
||||||
using DiscImageChef.Decoders.SCSI;
|
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
|
||||||
using static DiscImageChef.Devices.FreeBSD.Extern;
|
using static DiscImageChef.Devices.FreeBSD.Extern;
|
||||||
|
|
||||||
namespace DiscImageChef.Devices.FreeBSD
|
namespace DiscImageChef.Devices.FreeBSD
|
||||||
{
|
{
|
||||||
static class ListDevices
|
internal static class ListDevices
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>Gets a list of all known storage devices on FreeBSD</summary>
|
||||||
/// Gets a list of all known storage devices on FreeBSD
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>List of devices</returns>
|
/// <returns>List of devices</returns>
|
||||||
internal static DeviceInfo[] GetList()
|
internal static DeviceInfo[] GetList()
|
||||||
{
|
{
|
||||||
@@ -54,15 +52,16 @@ namespace DiscImageChef.Devices.FreeBSD
|
|||||||
|
|
||||||
foreach(string passDevice in passDevices)
|
foreach(string passDevice in passDevices)
|
||||||
{
|
{
|
||||||
DeviceInfo deviceInfo = new DeviceInfo();
|
var deviceInfo = new DeviceInfo();
|
||||||
IntPtr dev = cam_open_device(passDevice, FileFlags.ReadWrite);
|
IntPtr dev = cam_open_device(passDevice, FileFlags.ReadWrite);
|
||||||
CamDevice camDevice = (CamDevice)Marshal.PtrToStructure(dev, typeof(CamDevice));
|
var camDevice = (CamDevice)Marshal.PtrToStructure(dev, typeof(CamDevice));
|
||||||
|
|
||||||
IntPtr ccbPtr = cam_getccb(dev);
|
IntPtr ccbPtr = cam_getccb(dev);
|
||||||
|
|
||||||
if(ccbPtr.ToInt64() == 0) continue;
|
if(ccbPtr.ToInt64() == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
CcbGetdev cgd = (CcbGetdev)Marshal.PtrToStructure(ccbPtr, typeof(CcbGetdev));
|
var cgd = (CcbGetdev)Marshal.PtrToStructure(ccbPtr, typeof(CcbGetdev));
|
||||||
|
|
||||||
cgd.ccb_h.func_code = XptOpcode.XptGdevType;
|
cgd.ccb_h.func_code = XptOpcode.XptGdevType;
|
||||||
|
|
||||||
@@ -73,6 +72,7 @@ namespace DiscImageChef.Devices.FreeBSD
|
|||||||
if(error < 0)
|
if(error < 0)
|
||||||
{
|
{
|
||||||
cam_freeccb(ccbPtr);
|
cam_freeccb(ccbPtr);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,6 +96,7 @@ namespace DiscImageChef.Devices.FreeBSD
|
|||||||
// Little-endian FreeBSD gives it resorted
|
// Little-endian FreeBSD gives it resorted
|
||||||
// Big-endian FreeBSD, no idea
|
// Big-endian FreeBSD, no idea
|
||||||
byte[] atadTneid = new byte[512];
|
byte[] atadTneid = new byte[512];
|
||||||
|
|
||||||
for(int aIndex = 0; aIndex < 512; aIndex += 2)
|
for(int aIndex = 0; aIndex < 512; aIndex += 2)
|
||||||
{
|
{
|
||||||
atadTneid[aIndex] = cgd.ident_data[aIndex + 1];
|
atadTneid[aIndex] = cgd.ident_data[aIndex + 1];
|
||||||
@@ -103,6 +104,7 @@ namespace DiscImageChef.Devices.FreeBSD
|
|||||||
}
|
}
|
||||||
|
|
||||||
Identify.IdentifyDevice? idt = Identify.Decode(atadTneid);
|
Identify.IdentifyDevice? idt = Identify.Decode(atadTneid);
|
||||||
|
|
||||||
if(idt.HasValue)
|
if(idt.HasValue)
|
||||||
{
|
{
|
||||||
string[] separated = idt.Value.Model.Split(' ');
|
string[] separated = idt.Value.Model.Split(' ');
|
||||||
@@ -123,12 +125,15 @@ namespace DiscImageChef.Devices.FreeBSD
|
|||||||
deviceInfo.Supported = simName != "ata";
|
deviceInfo.Supported = simName != "ata";
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cgd.protocol == CamProto.ProtoAtapi) goto case CamProto.ProtoScsi;
|
if(cgd.protocol == CamProto.ProtoAtapi)
|
||||||
|
goto case CamProto.ProtoScsi;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CamProto.ProtoScsi:
|
case CamProto.ProtoScsi:
|
||||||
{
|
{
|
||||||
Inquiry.SCSIInquiry? inq = Inquiry.Decode(cgd.inq_data);
|
Inquiry? inq = Inquiry.Decode(cgd.inq_data);
|
||||||
|
|
||||||
if(inq.HasValue)
|
if(inq.HasValue)
|
||||||
{
|
{
|
||||||
deviceInfo.Vendor = StringHandlers.CToString(inq.Value.VendorIdentification).Trim();
|
deviceInfo.Vendor = StringHandlers.CToString(inq.Value.VendorIdentification).Trim();
|
||||||
@@ -142,11 +147,13 @@ namespace DiscImageChef.Devices.FreeBSD
|
|||||||
case CamProto.ProtoNvme:
|
case CamProto.ProtoNvme:
|
||||||
deviceInfo.Bus = "NVMe";
|
deviceInfo.Bus = "NVMe";
|
||||||
deviceInfo.Supported = false;
|
deviceInfo.Supported = false;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case CamProto.ProtoMmcsd:
|
case CamProto.ProtoMmcsd:
|
||||||
deviceInfo.Model = "Unknown card";
|
deviceInfo.Model = "Unknown card";
|
||||||
deviceInfo.Bus = "MMC/SD";
|
deviceInfo.Bus = "MMC/SD";
|
||||||
deviceInfo.Supported = false;
|
deviceInfo.Supported = false;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -33,31 +33,33 @@
|
|||||||
using System;
|
using System;
|
||||||
using DiscImageChef.CommonTypes;
|
using DiscImageChef.CommonTypes;
|
||||||
using DiscImageChef.CommonTypes.Enums;
|
using DiscImageChef.CommonTypes.Enums;
|
||||||
using DiscImageChef.Decoders.ATA;
|
using DiscImageChef.CommonTypes.Structs.Devices.ATA;
|
||||||
using DiscImageChef.Decoders.SCSI;
|
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
|
||||||
using DiscImageChef.Decoders.SecureDigital;
|
using DiscImageChef.Decoders.SecureDigital;
|
||||||
using DiscImageChef.Helpers;
|
using DiscImageChef.Helpers;
|
||||||
using VendorString = DiscImageChef.Decoders.SecureDigital.VendorString;
|
|
||||||
|
|
||||||
namespace DiscImageChef.DiscImages
|
namespace DiscImageChef.DiscImages
|
||||||
{
|
{
|
||||||
public partial class DiscImageChef
|
public partial class DiscImageChef
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>Checks for media tags that may contain metadata and sets it up if not already set</summary>
|
||||||
/// Checks for media tags that may contain metadata and sets it up if not already set
|
|
||||||
/// </summary>
|
|
||||||
void SetMetadataFromTags()
|
void SetMetadataFromTags()
|
||||||
{
|
{
|
||||||
// Search for SecureDigital CID
|
// Search for SecureDigital CID
|
||||||
if(mediaTags.TryGetValue(MediaTagType.SD_CID, out byte[] sdCid))
|
if(mediaTags.TryGetValue(MediaTagType.SD_CID, out byte[] sdCid))
|
||||||
{
|
{
|
||||||
CID decoded = Decoders.SecureDigital.Decoders.DecodeCID(sdCid);
|
CID decoded = Decoders.SecureDigital.Decoders.DecodeCID(sdCid);
|
||||||
|
|
||||||
if(string.IsNullOrWhiteSpace(imageInfo.DriveManufacturer))
|
if(string.IsNullOrWhiteSpace(imageInfo.DriveManufacturer))
|
||||||
imageInfo.DriveManufacturer = VendorString.Prettify(decoded.Manufacturer);
|
imageInfo.DriveManufacturer = VendorString.Prettify(decoded.Manufacturer);
|
||||||
if(string.IsNullOrWhiteSpace(imageInfo.DriveModel)) imageInfo.DriveModel = decoded.ProductName;
|
|
||||||
|
if(string.IsNullOrWhiteSpace(imageInfo.DriveModel))
|
||||||
|
imageInfo.DriveModel = decoded.ProductName;
|
||||||
|
|
||||||
if(string.IsNullOrWhiteSpace(imageInfo.DriveFirmwareRevision))
|
if(string.IsNullOrWhiteSpace(imageInfo.DriveFirmwareRevision))
|
||||||
imageInfo.DriveFirmwareRevision =
|
imageInfo.DriveFirmwareRevision =
|
||||||
$"{(decoded.ProductRevision & 0xF0) >> 4:X2}.{decoded.ProductRevision & 0x0F:X2}";
|
$"{(decoded.ProductRevision & 0xF0) >> 4:X2}.{decoded.ProductRevision & 0x0F:X2}";
|
||||||
|
|
||||||
if(string.IsNullOrWhiteSpace(imageInfo.DriveSerialNumber))
|
if(string.IsNullOrWhiteSpace(imageInfo.DriveSerialNumber))
|
||||||
imageInfo.DriveSerialNumber = $"{decoded.ProductSerialNumber}";
|
imageInfo.DriveSerialNumber = $"{decoded.ProductSerialNumber}";
|
||||||
}
|
}
|
||||||
@@ -66,12 +68,17 @@ namespace DiscImageChef.DiscImages
|
|||||||
if(mediaTags.TryGetValue(MediaTagType.MMC_CID, out byte[] mmcCid))
|
if(mediaTags.TryGetValue(MediaTagType.MMC_CID, out byte[] mmcCid))
|
||||||
{
|
{
|
||||||
Decoders.MMC.CID decoded = Decoders.MMC.Decoders.DecodeCID(mmcCid);
|
Decoders.MMC.CID decoded = Decoders.MMC.Decoders.DecodeCID(mmcCid);
|
||||||
|
|
||||||
if(string.IsNullOrWhiteSpace(imageInfo.DriveManufacturer))
|
if(string.IsNullOrWhiteSpace(imageInfo.DriveManufacturer))
|
||||||
imageInfo.DriveManufacturer = Decoders.MMC.VendorString.Prettify(decoded.Manufacturer);
|
imageInfo.DriveManufacturer = Decoders.MMC.VendorString.Prettify(decoded.Manufacturer);
|
||||||
if(string.IsNullOrWhiteSpace(imageInfo.DriveModel)) imageInfo.DriveModel = decoded.ProductName;
|
|
||||||
|
if(string.IsNullOrWhiteSpace(imageInfo.DriveModel))
|
||||||
|
imageInfo.DriveModel = decoded.ProductName;
|
||||||
|
|
||||||
if(string.IsNullOrWhiteSpace(imageInfo.DriveFirmwareRevision))
|
if(string.IsNullOrWhiteSpace(imageInfo.DriveFirmwareRevision))
|
||||||
imageInfo.DriveFirmwareRevision =
|
imageInfo.DriveFirmwareRevision =
|
||||||
$"{(decoded.ProductRevision & 0xF0) >> 4:X2}.{decoded.ProductRevision & 0x0F:X2}";
|
$"{(decoded.ProductRevision & 0xF0) >> 4:X2}.{decoded.ProductRevision & 0x0F:X2}";
|
||||||
|
|
||||||
if(string.IsNullOrWhiteSpace(imageInfo.DriveSerialNumber))
|
if(string.IsNullOrWhiteSpace(imageInfo.DriveSerialNumber))
|
||||||
imageInfo.DriveSerialNumber = $"{decoded.ProductSerialNumber}";
|
imageInfo.DriveSerialNumber = $"{decoded.ProductSerialNumber}";
|
||||||
}
|
}
|
||||||
@@ -79,15 +86,18 @@ namespace DiscImageChef.DiscImages
|
|||||||
// Search for SCSI INQUIRY
|
// Search for SCSI INQUIRY
|
||||||
if(mediaTags.TryGetValue(MediaTagType.SCSI_INQUIRY, out byte[] scsiInquiry))
|
if(mediaTags.TryGetValue(MediaTagType.SCSI_INQUIRY, out byte[] scsiInquiry))
|
||||||
{
|
{
|
||||||
Inquiry.SCSIInquiry? nullableInquiry = Inquiry.Decode(scsiInquiry);
|
Inquiry? nullableInquiry = Inquiry.Decode(scsiInquiry);
|
||||||
|
|
||||||
if(nullableInquiry.HasValue)
|
if(nullableInquiry.HasValue)
|
||||||
{
|
{
|
||||||
Inquiry.SCSIInquiry inquiry = nullableInquiry.Value;
|
Inquiry inquiry = nullableInquiry.Value;
|
||||||
|
|
||||||
if(string.IsNullOrWhiteSpace(imageInfo.DriveManufacturer))
|
if(string.IsNullOrWhiteSpace(imageInfo.DriveManufacturer))
|
||||||
imageInfo.DriveManufacturer = StringHandlers.CToString(inquiry.VendorIdentification)?.Trim();
|
imageInfo.DriveManufacturer = StringHandlers.CToString(inquiry.VendorIdentification)?.Trim();
|
||||||
|
|
||||||
if(string.IsNullOrWhiteSpace(imageInfo.DriveModel))
|
if(string.IsNullOrWhiteSpace(imageInfo.DriveModel))
|
||||||
imageInfo.DriveModel = StringHandlers.CToString(inquiry.ProductIdentification)?.Trim();
|
imageInfo.DriveModel = StringHandlers.CToString(inquiry.ProductIdentification)?.Trim();
|
||||||
|
|
||||||
if(string.IsNullOrWhiteSpace(imageInfo.DriveFirmwareRevision))
|
if(string.IsNullOrWhiteSpace(imageInfo.DriveFirmwareRevision))
|
||||||
imageInfo.DriveFirmwareRevision =
|
imageInfo.DriveFirmwareRevision =
|
||||||
StringHandlers.CToString(inquiry.ProductRevisionLevel)?.Trim();
|
StringHandlers.CToString(inquiry.ProductRevisionLevel)?.Trim();
|
||||||
@@ -95,29 +105,34 @@ namespace DiscImageChef.DiscImages
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Search for ATA or ATAPI IDENTIFY
|
// Search for ATA or ATAPI IDENTIFY
|
||||||
if(!mediaTags.TryGetValue(MediaTagType.ATA_IDENTIFY, out byte[] ataIdentify) &&
|
if(!mediaTags.TryGetValue(MediaTagType.ATA_IDENTIFY, out byte[] ataIdentify) &&
|
||||||
!mediaTags.TryGetValue(MediaTagType.ATAPI_IDENTIFY, out ataIdentify)) return;
|
!mediaTags.TryGetValue(MediaTagType.ATAPI_IDENTIFY, out ataIdentify))
|
||||||
|
return;
|
||||||
|
|
||||||
Identify.IdentifyDevice? nullableIdentify = Decoders.ATA.Identify.Decode(ataIdentify);
|
Identify.IdentifyDevice? nullableIdentify = CommonTypes.Structs.Devices.ATA.Identify.Decode(ataIdentify);
|
||||||
|
|
||||||
if(!nullableIdentify.HasValue) return;
|
if(!nullableIdentify.HasValue)
|
||||||
|
return;
|
||||||
|
|
||||||
Identify.IdentifyDevice identify = nullableIdentify.Value;
|
Identify.IdentifyDevice identify = nullableIdentify.Value;
|
||||||
|
|
||||||
string[] separated = identify.Model.Split(' ');
|
string[] separated = identify.Model.Split(' ');
|
||||||
|
|
||||||
if(separated.Length == 1)
|
if(separated.Length == 1)
|
||||||
if(string.IsNullOrWhiteSpace(imageInfo.DriveModel)) imageInfo.DriveModel = separated[0];
|
if(string.IsNullOrWhiteSpace(imageInfo.DriveModel))
|
||||||
|
imageInfo.DriveModel = separated[0];
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(string.IsNullOrWhiteSpace(imageInfo.DriveManufacturer))
|
if(string.IsNullOrWhiteSpace(imageInfo.DriveManufacturer))
|
||||||
imageInfo.DriveManufacturer = separated[0];
|
imageInfo.DriveManufacturer = separated[0];
|
||||||
|
|
||||||
if(string.IsNullOrWhiteSpace(imageInfo.DriveModel))
|
if(string.IsNullOrWhiteSpace(imageInfo.DriveModel))
|
||||||
imageInfo.DriveModel = separated[separated.Length - 1];
|
imageInfo.DriveModel = separated[separated.Length - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
if(string.IsNullOrWhiteSpace(imageInfo.DriveFirmwareRevision))
|
if(string.IsNullOrWhiteSpace(imageInfo.DriveFirmwareRevision))
|
||||||
imageInfo.DriveFirmwareRevision = identify.FirmwareRevision;
|
imageInfo.DriveFirmwareRevision = identify.FirmwareRevision;
|
||||||
|
|
||||||
if(string.IsNullOrWhiteSpace(imageInfo.DriveSerialNumber))
|
if(string.IsNullOrWhiteSpace(imageInfo.DriveSerialNumber))
|
||||||
imageInfo.DriveSerialNumber = identify.SerialNumber;
|
imageInfo.DriveSerialNumber = identify.SerialNumber;
|
||||||
}
|
}
|
||||||
@@ -225,9 +240,11 @@ namespace DiscImageChef.DiscImages
|
|||||||
// Gets a DDT entry
|
// Gets a DDT entry
|
||||||
ulong GetDdtEntry(ulong sectorAddress)
|
ulong GetDdtEntry(ulong sectorAddress)
|
||||||
{
|
{
|
||||||
if(inMemoryDdt) return userDataDdt[sectorAddress];
|
if(inMemoryDdt)
|
||||||
|
return userDataDdt[sectorAddress];
|
||||||
|
|
||||||
if(ddtEntryCache.TryGetValue(sectorAddress, out ulong entry)) return entry;
|
if(ddtEntryCache.TryGetValue(sectorAddress, out ulong entry))
|
||||||
|
return entry;
|
||||||
|
|
||||||
long oldPosition = imageStream.Position;
|
long oldPosition = imageStream.Position;
|
||||||
imageStream.Position = outMemoryDdtPosition + Marshal.SizeOf<DdtHeader>();
|
imageStream.Position = outMemoryDdtPosition + Marshal.SizeOf<DdtHeader>();
|
||||||
@@ -237,9 +254,11 @@ namespace DiscImageChef.DiscImages
|
|||||||
imageStream.Position = oldPosition;
|
imageStream.Position = oldPosition;
|
||||||
entry = BitConverter.ToUInt64(temp, 0);
|
entry = BitConverter.ToUInt64(temp, 0);
|
||||||
|
|
||||||
if(ddtEntryCache.Count >= MAX_DDT_ENTRY_CACHE) ddtEntryCache.Clear();
|
if(ddtEntryCache.Count >= MAX_DDT_ENTRY_CACHE)
|
||||||
|
ddtEntryCache.Clear();
|
||||||
|
|
||||||
ddtEntryCache.Add(sectorAddress, entry);
|
ddtEntryCache.Add(sectorAddress, entry);
|
||||||
|
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,8 +267,11 @@ namespace DiscImageChef.DiscImages
|
|||||||
{
|
{
|
||||||
if(inMemoryDdt)
|
if(inMemoryDdt)
|
||||||
{
|
{
|
||||||
if(IsTape) tapeDdt[sectorAddress] = pointer;
|
if(IsTape)
|
||||||
else userDataDdt[sectorAddress] = pointer;
|
tapeDdt[sectorAddress] = pointer;
|
||||||
|
else
|
||||||
|
userDataDdt[sectorAddress] = pointer;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ using DiscImageChef.CommonTypes;
|
|||||||
using DiscImageChef.CommonTypes.Enums;
|
using DiscImageChef.CommonTypes.Enums;
|
||||||
using DiscImageChef.CommonTypes.Exceptions;
|
using DiscImageChef.CommonTypes.Exceptions;
|
||||||
using DiscImageChef.CommonTypes.Interfaces;
|
using DiscImageChef.CommonTypes.Interfaces;
|
||||||
using DiscImageChef.Decoders.ATA;
|
using DiscImageChef.CommonTypes.Structs.Devices.ATA;
|
||||||
using DiscImageChef.Helpers;
|
using DiscImageChef.Helpers;
|
||||||
|
|
||||||
namespace DiscImageChef.DiscImages
|
namespace DiscImageChef.DiscImages
|
||||||
@@ -54,7 +54,8 @@ namespace DiscImageChef.DiscImages
|
|||||||
|
|
||||||
RsIdeHeader hdr = Marshal.ByteArrayToStructureLittleEndian<RsIdeHeader>(hdrB);
|
RsIdeHeader hdr = Marshal.ByteArrayToStructureLittleEndian<RsIdeHeader>(hdrB);
|
||||||
|
|
||||||
if(!hdr.magic.SequenceEqual(signature)) return false;
|
if(!hdr.magic.SequenceEqual(signature))
|
||||||
|
return false;
|
||||||
|
|
||||||
dataOff = hdr.dataOff;
|
dataOff = hdr.dataOff;
|
||||||
|
|
||||||
@@ -72,7 +73,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
{
|
{
|
||||||
identify = new byte[512];
|
identify = new byte[512];
|
||||||
Array.Copy(hdr.identify, 0, identify, 0, hdr.identify.Length);
|
Array.Copy(hdr.identify, 0, identify, 0, hdr.identify.Length);
|
||||||
Identify.IdentifyDevice? ataId = Decoders.ATA.Identify.Decode(identify);
|
Identify.IdentifyDevice? ataId = CommonTypes.Structs.Devices.ATA.Identify.Decode(identify);
|
||||||
|
|
||||||
if(ataId.HasValue)
|
if(ataId.HasValue)
|
||||||
{
|
{
|
||||||
@@ -88,7 +89,9 @@ namespace DiscImageChef.DiscImages
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(imageInfo.Cylinders == 0 || imageInfo.Heads == 0 || imageInfo.SectorsPerTrack == 0)
|
if(imageInfo.Cylinders == 0 ||
|
||||||
|
imageInfo.Heads == 0 ||
|
||||||
|
imageInfo.SectorsPerTrack == 0)
|
||||||
{
|
{
|
||||||
imageInfo.Cylinders = (uint)(imageInfo.Sectors / 16 / 63);
|
imageInfo.Cylinders = (uint)(imageInfo.Sectors / 16 / 63);
|
||||||
imageInfo.Heads = 16;
|
imageInfo.Heads = 16;
|
||||||
@@ -114,7 +117,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
|
|
||||||
Stream stream = rsIdeImageFilter.GetDataForkStream();
|
Stream stream = rsIdeImageFilter.GetDataForkStream();
|
||||||
|
|
||||||
stream.Seek((long)(dataOff + sectorAddress * imageInfo.SectorSize), SeekOrigin.Begin);
|
stream.Seek((long)(dataOff + (sectorAddress * imageInfo.SectorSize)), SeekOrigin.Begin);
|
||||||
|
|
||||||
stream.Read(buffer, 0, (int)(length * imageInfo.SectorSize));
|
stream.Read(buffer, 0, (int)(length * imageInfo.SectorSize));
|
||||||
|
|
||||||
@@ -123,11 +126,13 @@ namespace DiscImageChef.DiscImages
|
|||||||
|
|
||||||
public byte[] ReadDiskTag(MediaTagType tag)
|
public byte[] ReadDiskTag(MediaTagType tag)
|
||||||
{
|
{
|
||||||
if(!imageInfo.ReadableMediaTags.Contains(tag) || tag != MediaTagType.ATA_IDENTIFY)
|
if(!imageInfo.ReadableMediaTags.Contains(tag) ||
|
||||||
|
tag != MediaTagType.ATA_IDENTIFY)
|
||||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||||
|
|
||||||
byte[] buffer = new byte[512];
|
byte[] buffer = new byte[512];
|
||||||
Array.Copy(identify, 0, buffer, 0, 512);
|
Array.Copy(identify, 0, buffer, 0, 512);
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ using System.Linq;
|
|||||||
using DiscImageChef.CommonTypes;
|
using DiscImageChef.CommonTypes;
|
||||||
using DiscImageChef.CommonTypes.Enums;
|
using DiscImageChef.CommonTypes.Enums;
|
||||||
using DiscImageChef.CommonTypes.Structs;
|
using DiscImageChef.CommonTypes.Structs;
|
||||||
using DiscImageChef.Decoders.ATA;
|
using DiscImageChef.CommonTypes.Structs.Devices.ATA;
|
||||||
using DiscImageChef.Helpers;
|
using DiscImageChef.Helpers;
|
||||||
using Schemas;
|
using Schemas;
|
||||||
using Version = DiscImageChef.CommonTypes.Interop.Version;
|
using Version = DiscImageChef.CommonTypes.Interop.Version;
|
||||||
@@ -47,37 +47,49 @@ namespace DiscImageChef.DiscImages
|
|||||||
public partial class RsIde
|
public partial class RsIde
|
||||||
{
|
{
|
||||||
public bool Create(string path, MediaType mediaType, Dictionary<string, string> options, ulong sectors,
|
public bool Create(string path, MediaType mediaType, Dictionary<string, string> options, ulong sectors,
|
||||||
uint sectorSize)
|
uint sectorSize)
|
||||||
{
|
{
|
||||||
if(sectorSize != 256 && sectorSize != 512)
|
if(sectorSize != 256 &&
|
||||||
|
sectorSize != 512)
|
||||||
{
|
{
|
||||||
ErrorMessage = "Unsupported sector size";
|
ErrorMessage = "Unsupported sector size";
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(sectors > 63 * 16 * 1024)
|
if(sectors > 63 * 16 * 1024)
|
||||||
{
|
{
|
||||||
ErrorMessage = "Too many sectors";
|
ErrorMessage = "Too many sectors";
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!SupportedMediaTypes.Contains(mediaType))
|
if(!SupportedMediaTypes.Contains(mediaType))
|
||||||
{
|
{
|
||||||
ErrorMessage = $"Unsupport media format {mediaType}";
|
ErrorMessage = $"Unsupport media format {mediaType}";
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
imageInfo = new ImageInfo {MediaType = mediaType, SectorSize = sectorSize, Sectors = sectors};
|
imageInfo = new ImageInfo
|
||||||
|
{
|
||||||
|
MediaType = mediaType, SectorSize = sectorSize, Sectors = sectors
|
||||||
|
};
|
||||||
|
|
||||||
try { writingStream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None); }
|
try
|
||||||
|
{
|
||||||
|
writingStream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
|
||||||
|
}
|
||||||
catch(IOException e)
|
catch(IOException e)
|
||||||
{
|
{
|
||||||
ErrorMessage = $"Could not create new image file, exception {e.Message}";
|
ErrorMessage = $"Could not create new image file, exception {e.Message}";
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
IsWriting = true;
|
IsWriting = true;
|
||||||
ErrorMessage = null;
|
ErrorMessage = null;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,17 +98,20 @@ namespace DiscImageChef.DiscImages
|
|||||||
if(tag != MediaTagType.ATA_IDENTIFY)
|
if(tag != MediaTagType.ATA_IDENTIFY)
|
||||||
{
|
{
|
||||||
ErrorMessage = $"Unsupported media tag {tag}.";
|
ErrorMessage = $"Unsupported media tag {tag}.";
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!IsWriting)
|
if(!IsWriting)
|
||||||
{
|
{
|
||||||
ErrorMessage = "Tried to write on a non-writable image";
|
ErrorMessage = "Tried to write on a non-writable image";
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
identify = new byte[106];
|
identify = new byte[106];
|
||||||
Array.Copy(data, 0, identify, 0, 106);
|
Array.Copy(data, 0, identify, 0, 106);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,26 +120,31 @@ namespace DiscImageChef.DiscImages
|
|||||||
if(!IsWriting)
|
if(!IsWriting)
|
||||||
{
|
{
|
||||||
ErrorMessage = "Tried to write on a non-writable image";
|
ErrorMessage = "Tried to write on a non-writable image";
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(data.Length != imageInfo.SectorSize)
|
if(data.Length != imageInfo.SectorSize)
|
||||||
{
|
{
|
||||||
ErrorMessage = "Incorrect data size";
|
ErrorMessage = "Incorrect data size";
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(sectorAddress >= imageInfo.Sectors)
|
if(sectorAddress >= imageInfo.Sectors)
|
||||||
{
|
{
|
||||||
ErrorMessage = "Tried to write past image size";
|
ErrorMessage = "Tried to write past image size";
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
writingStream.Seek((long)((ulong)Marshal.SizeOf<RsIdeHeader>() + sectorAddress * imageInfo.SectorSize),
|
writingStream.Seek((long)((ulong)Marshal.SizeOf<RsIdeHeader>() + (sectorAddress * imageInfo.SectorSize)),
|
||||||
SeekOrigin.Begin);
|
SeekOrigin.Begin);
|
||||||
|
|
||||||
writingStream.Write(data, 0, data.Length);
|
writingStream.Write(data, 0, data.Length);
|
||||||
|
|
||||||
ErrorMessage = "";
|
ErrorMessage = "";
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,38 +153,45 @@ namespace DiscImageChef.DiscImages
|
|||||||
if(!IsWriting)
|
if(!IsWriting)
|
||||||
{
|
{
|
||||||
ErrorMessage = "Tried to write on a non-writable image";
|
ErrorMessage = "Tried to write on a non-writable image";
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(data.Length % imageInfo.SectorSize != 0)
|
if(data.Length % imageInfo.SectorSize != 0)
|
||||||
{
|
{
|
||||||
ErrorMessage = "Incorrect data size";
|
ErrorMessage = "Incorrect data size";
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(sectorAddress + length > imageInfo.Sectors)
|
if(sectorAddress + length > imageInfo.Sectors)
|
||||||
{
|
{
|
||||||
ErrorMessage = "Tried to write past image size";
|
ErrorMessage = "Tried to write past image size";
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
writingStream.Seek((long)((ulong)Marshal.SizeOf<RsIdeHeader>() + sectorAddress * imageInfo.SectorSize),
|
writingStream.Seek((long)((ulong)Marshal.SizeOf<RsIdeHeader>() + (sectorAddress * imageInfo.SectorSize)),
|
||||||
SeekOrigin.Begin);
|
SeekOrigin.Begin);
|
||||||
|
|
||||||
writingStream.Write(data, 0, data.Length);
|
writingStream.Write(data, 0, data.Length);
|
||||||
|
|
||||||
ErrorMessage = "";
|
ErrorMessage = "";
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool WriteSectorLong(byte[] data, ulong sectorAddress)
|
public bool WriteSectorLong(byte[] data, ulong sectorAddress)
|
||||||
{
|
{
|
||||||
ErrorMessage = "Writing sectors with tags is not supported.";
|
ErrorMessage = "Writing sectors with tags is not supported.";
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool WriteSectorsLong(byte[] data, ulong sectorAddress, uint length)
|
public bool WriteSectorsLong(byte[] data, ulong sectorAddress, uint length)
|
||||||
{
|
{
|
||||||
ErrorMessage = "Writing sectors with tags is not supported.";
|
ErrorMessage = "Writing sectors with tags is not supported.";
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,6 +200,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
if(!IsWriting)
|
if(!IsWriting)
|
||||||
{
|
{
|
||||||
ErrorMessage = "Image is not opened for writing";
|
ErrorMessage = "Image is not opened for writing";
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,52 +222,53 @@ namespace DiscImageChef.DiscImages
|
|||||||
|
|
||||||
imageInfo.Cylinders = (uint)(imageInfo.Sectors / imageInfo.Heads / imageInfo.SectorsPerTrack);
|
imageInfo.Cylinders = (uint)(imageInfo.Sectors / imageInfo.Heads / imageInfo.SectorsPerTrack);
|
||||||
|
|
||||||
if(imageInfo.Cylinders == 0 && imageInfo.Heads == 0 && imageInfo.SectorsPerTrack == 0) break;
|
if(imageInfo.Cylinders == 0 &&
|
||||||
|
imageInfo.Heads == 0 &&
|
||||||
|
imageInfo.SectorsPerTrack == 0)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RsIdeHeader header = new RsIdeHeader
|
var header = new RsIdeHeader
|
||||||
{
|
{
|
||||||
magic = signature,
|
magic = signature, identify = new byte[106], dataOff = (ushort)Marshal.SizeOf<RsIdeHeader>(),
|
||||||
identify = new byte[106],
|
revision = 1, reserved = new byte[11]
|
||||||
dataOff = (ushort)Marshal.SizeOf<RsIdeHeader>(),
|
|
||||||
revision = 1,
|
|
||||||
reserved = new byte[11]
|
|
||||||
};
|
};
|
||||||
if(imageInfo.SectorSize == 256) header.flags = RsIdeFlags.HalfSectors;
|
|
||||||
|
if(imageInfo.SectorSize == 256)
|
||||||
|
header.flags = RsIdeFlags.HalfSectors;
|
||||||
|
|
||||||
if(identify == null)
|
if(identify == null)
|
||||||
{
|
{
|
||||||
Identify.IdentifyDevice ataId = new Identify.IdentifyDevice
|
var ataId = new Identify.IdentifyDevice
|
||||||
{
|
{
|
||||||
GeneralConfiguration =
|
GeneralConfiguration =
|
||||||
Decoders.ATA.Identify.GeneralConfigurationBit.UltraFastIDE |
|
CommonTypes.Structs.Devices.ATA.Identify.GeneralConfigurationBit.UltraFastIDE |
|
||||||
Decoders.ATA.Identify.GeneralConfigurationBit.Fixed |
|
CommonTypes.Structs.Devices.ATA.Identify.GeneralConfigurationBit.Fixed |
|
||||||
Decoders.ATA.Identify.GeneralConfigurationBit.NotMFM |
|
CommonTypes.Structs.Devices.ATA.Identify.GeneralConfigurationBit.NotMFM |
|
||||||
Decoders.ATA.Identify.GeneralConfigurationBit.SoftSector,
|
CommonTypes.Structs.Devices.ATA.Identify.GeneralConfigurationBit.SoftSector,
|
||||||
Cylinders = (ushort)imageInfo.Cylinders,
|
Cylinders = (ushort)imageInfo.Cylinders, Heads = (ushort)imageInfo.Heads,
|
||||||
Heads = (ushort)imageInfo.Heads,
|
SectorsPerTrack = (ushort)imageInfo.SectorsPerTrack, VendorWord47 = 0x80,
|
||||||
SectorsPerTrack = (ushort)imageInfo.SectorsPerTrack,
|
Capabilities = CommonTypes.Structs.Devices.ATA.Identify.CapabilitiesBit.DMASupport |
|
||||||
VendorWord47 = 0x80,
|
CommonTypes.Structs.Devices.ATA.Identify.CapabilitiesBit.IORDY |
|
||||||
Capabilities =
|
CommonTypes.Structs.Devices.ATA.Identify.CapabilitiesBit.LBASupport,
|
||||||
Decoders.ATA.Identify.CapabilitiesBit.DMASupport |
|
ExtendedIdentify =
|
||||||
Decoders.ATA.Identify.CapabilitiesBit.IORDY |
|
CommonTypes.Structs.Devices.ATA.Identify.ExtendedIdentifyBit.Words54to58Valid,
|
||||||
Decoders.ATA.Identify.CapabilitiesBit.LBASupport,
|
CurrentCylinders = (ushort)imageInfo.Cylinders, CurrentHeads = (ushort)imageInfo.Heads,
|
||||||
ExtendedIdentify = Decoders.ATA.Identify.ExtendedIdentifyBit.Words54to58Valid,
|
|
||||||
CurrentCylinders = (ushort)imageInfo.Cylinders,
|
|
||||||
CurrentHeads = (ushort)imageInfo.Heads,
|
|
||||||
CurrentSectorsPerTrack = (ushort)imageInfo.SectorsPerTrack,
|
CurrentSectorsPerTrack = (ushort)imageInfo.SectorsPerTrack,
|
||||||
CurrentSectors = (uint)imageInfo.Sectors,
|
CurrentSectors = (uint)imageInfo.Sectors, LBASectors = (uint)imageInfo.Sectors,
|
||||||
LBASectors = (uint)imageInfo.Sectors,
|
DMASupported = CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode0,
|
||||||
DMASupported = Decoders.ATA.Identify.TransferMode.Mode0,
|
DMAActive = CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode0
|
||||||
DMAActive = Decoders.ATA.Identify.TransferMode.Mode0
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if(string.IsNullOrEmpty(imageInfo.DriveManufacturer)) imageInfo.DriveManufacturer = "DiscImageChef";
|
if(string.IsNullOrEmpty(imageInfo.DriveManufacturer))
|
||||||
|
imageInfo.DriveManufacturer = "DiscImageChef";
|
||||||
|
|
||||||
if(string.IsNullOrEmpty(imageInfo.DriveModel)) imageInfo.DriveModel = "";
|
if(string.IsNullOrEmpty(imageInfo.DriveModel))
|
||||||
|
imageInfo.DriveModel = "";
|
||||||
|
|
||||||
if(string.IsNullOrEmpty(imageInfo.DriveFirmwareRevision)) Version.GetVersion();
|
if(string.IsNullOrEmpty(imageInfo.DriveFirmwareRevision))
|
||||||
|
Version.GetVersion();
|
||||||
|
|
||||||
if(string.IsNullOrEmpty(imageInfo.DriveSerialNumber))
|
if(string.IsNullOrEmpty(imageInfo.DriveSerialNumber))
|
||||||
imageInfo.DriveSerialNumber = $"{new Random().NextDouble():16X}";
|
imageInfo.DriveSerialNumber = $"{new Random().NextDouble():16X}";
|
||||||
@@ -247,17 +276,21 @@ namespace DiscImageChef.DiscImages
|
|||||||
byte[] ataIdBytes = new byte[Marshal.SizeOf<Identify.IdentifyDevice>()];
|
byte[] ataIdBytes = new byte[Marshal.SizeOf<Identify.IdentifyDevice>()];
|
||||||
IntPtr ptr = System.Runtime.InteropServices.Marshal.AllocHGlobal(512);
|
IntPtr ptr = System.Runtime.InteropServices.Marshal.AllocHGlobal(512);
|
||||||
System.Runtime.InteropServices.Marshal.StructureToPtr(ataId, ptr, true);
|
System.Runtime.InteropServices.Marshal.StructureToPtr(ataId, ptr, true);
|
||||||
|
|
||||||
System.Runtime.InteropServices.Marshal.Copy(ptr, ataIdBytes, 0,
|
System.Runtime.InteropServices.Marshal.Copy(ptr, ataIdBytes, 0,
|
||||||
Marshal.SizeOf<Identify.IdentifyDevice>());
|
Marshal.SizeOf<Identify.IdentifyDevice>());
|
||||||
|
|
||||||
System.Runtime.InteropServices.Marshal.FreeHGlobal(ptr);
|
System.Runtime.InteropServices.Marshal.FreeHGlobal(ptr);
|
||||||
|
|
||||||
Array.Copy(ScrambleAtaString(imageInfo.DriveManufacturer + " " + imageInfo.DriveModel, 40), 0,
|
Array.Copy(ScrambleAtaString(imageInfo.DriveManufacturer + " " + imageInfo.DriveModel, 40), 0,
|
||||||
ataIdBytes, 27 * 2, 40);
|
ataIdBytes, 27 * 2, 40);
|
||||||
Array.Copy(ScrambleAtaString(imageInfo.DriveFirmwareRevision, 8), 0, ataIdBytes, 23 * 2, 8);
|
|
||||||
Array.Copy(ScrambleAtaString(imageInfo.DriveSerialNumber, 20), 0, ataIdBytes, 10 * 2, 20);
|
Array.Copy(ScrambleAtaString(imageInfo.DriveFirmwareRevision, 8), 0, ataIdBytes, 23 * 2, 8);
|
||||||
Array.Copy(ataIdBytes, 0, header.identify, 0, 106);
|
Array.Copy(ScrambleAtaString(imageInfo.DriveSerialNumber, 20), 0, ataIdBytes, 10 * 2, 20);
|
||||||
|
Array.Copy(ataIdBytes, 0, header.identify, 0, 106);
|
||||||
}
|
}
|
||||||
else Array.Copy(identify, 0, header.identify, 0, 106);
|
else
|
||||||
|
Array.Copy(identify, 0, header.identify, 0, 106);
|
||||||
|
|
||||||
byte[] hdr = new byte[Marshal.SizeOf<RsIdeHeader>()];
|
byte[] hdr = new byte[Marshal.SizeOf<RsIdeHeader>()];
|
||||||
IntPtr hdrPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(Marshal.SizeOf<RsIdeHeader>());
|
IntPtr hdrPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(Marshal.SizeOf<RsIdeHeader>());
|
||||||
@@ -273,6 +306,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
|
|
||||||
IsWriting = false;
|
IsWriting = false;
|
||||||
ErrorMessage = "";
|
ErrorMessage = "";
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,18 +325,21 @@ namespace DiscImageChef.DiscImages
|
|||||||
if(cylinders > ushort.MaxValue)
|
if(cylinders > ushort.MaxValue)
|
||||||
{
|
{
|
||||||
ErrorMessage = "Too many cylinders.";
|
ErrorMessage = "Too many cylinders.";
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(heads > ushort.MaxValue)
|
if(heads > ushort.MaxValue)
|
||||||
{
|
{
|
||||||
ErrorMessage = "Too many heads.";
|
ErrorMessage = "Too many heads.";
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(sectorsPerTrack > ushort.MaxValue)
|
if(sectorsPerTrack > ushort.MaxValue)
|
||||||
{
|
{
|
||||||
ErrorMessage = "Too many sectors per track.";
|
ErrorMessage = "Too many sectors per track.";
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,12 +353,14 @@ namespace DiscImageChef.DiscImages
|
|||||||
public bool WriteSectorTag(byte[] data, ulong sectorAddress, SectorTagType tag)
|
public bool WriteSectorTag(byte[] data, ulong sectorAddress, SectorTagType tag)
|
||||||
{
|
{
|
||||||
ErrorMessage = "Unsupported feature";
|
ErrorMessage = "Unsupported feature";
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool WriteSectorsTag(byte[] data, ulong sectorAddress, uint length, SectorTagType tag)
|
public bool WriteSectorsTag(byte[] data, ulong sectorAddress, uint length, SectorTagType tag)
|
||||||
{
|
{
|
||||||
ErrorMessage = "Unsupported feature";
|
ErrorMessage = "Unsupported feature";
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,12 +40,14 @@ using DiscImageChef.CommonTypes.Enums;
|
|||||||
using DiscImageChef.CommonTypes.Exceptions;
|
using DiscImageChef.CommonTypes.Exceptions;
|
||||||
using DiscImageChef.CommonTypes.Interfaces;
|
using DiscImageChef.CommonTypes.Interfaces;
|
||||||
using DiscImageChef.CommonTypes.Structs;
|
using DiscImageChef.CommonTypes.Structs;
|
||||||
|
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
|
||||||
using DiscImageChef.Console;
|
using DiscImageChef.Console;
|
||||||
using DiscImageChef.Decoders.CD;
|
using DiscImageChef.Decoders.CD;
|
||||||
using DiscImageChef.Decoders.DVD;
|
using DiscImageChef.Decoders.DVD;
|
||||||
using DiscImageChef.Decoders.SCSI;
|
using DiscImageChef.Decoders.SCSI;
|
||||||
using Schemas;
|
using Schemas;
|
||||||
using DMI = DiscImageChef.Decoders.Xbox.DMI;
|
using DMI = DiscImageChef.Decoders.Xbox.DMI;
|
||||||
|
using Inquiry = DiscImageChef.CommonTypes.Structs.Devices.SCSI.Inquiry;
|
||||||
using Session = DiscImageChef.CommonTypes.Structs.Session;
|
using Session = DiscImageChef.CommonTypes.Structs.Session;
|
||||||
using TrackType = DiscImageChef.CommonTypes.Enums.TrackType;
|
using TrackType = DiscImageChef.CommonTypes.Enums.TrackType;
|
||||||
|
|
||||||
@@ -781,7 +783,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
if (mediaTags.ContainsKey(MediaTagType.SCSI_INQUIRY))
|
if (mediaTags.ContainsKey(MediaTagType.SCSI_INQUIRY))
|
||||||
{
|
{
|
||||||
var devType = PeripheralDeviceTypes.DirectAccess;
|
var devType = PeripheralDeviceTypes.DirectAccess;
|
||||||
Inquiry.SCSIInquiry? scsiInq = null;
|
Inquiry? scsiInq = null;
|
||||||
if (mediaTags.TryGetValue(MediaTagType.SCSI_INQUIRY, out var inq))
|
if (mediaTags.TryGetValue(MediaTagType.SCSI_INQUIRY, out var inq))
|
||||||
{
|
{
|
||||||
scsiInq = Inquiry.Decode(inq);
|
scsiInq = Inquiry.Decode(inq);
|
||||||
@@ -858,7 +860,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
// It's ATA, check tags
|
// It's ATA, check tags
|
||||||
if (mediaTags.TryGetValue(MediaTagType.ATA_IDENTIFY, out var identifyBuf))
|
if (mediaTags.TryGetValue(MediaTagType.ATA_IDENTIFY, out var identifyBuf))
|
||||||
{
|
{
|
||||||
var ataId = Decoders.ATA.Identify.Decode(identifyBuf);
|
var ataId = CommonTypes.Structs.Devices.ATA.Identify.Decode(identifyBuf);
|
||||||
if (ataId.HasValue)
|
if (ataId.HasValue)
|
||||||
{
|
{
|
||||||
imageInfo.MediaType = (ushort) ataId.Value.GeneralConfiguration == 0x848A
|
imageInfo.MediaType = (ushort) ataId.Value.GeneralConfiguration == 0x848A
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ using System.Collections.ObjectModel;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using DiscImageChef.CommonTypes.Enums;
|
using DiscImageChef.CommonTypes.Enums;
|
||||||
using DiscImageChef.CommonTypes.Interfaces;
|
using DiscImageChef.CommonTypes.Interfaces;
|
||||||
|
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
|
||||||
using DiscImageChef.Decoders.ATA;
|
using DiscImageChef.Decoders.ATA;
|
||||||
using DiscImageChef.Decoders.Bluray;
|
using DiscImageChef.Decoders.Bluray;
|
||||||
using DiscImageChef.Decoders.CD;
|
using DiscImageChef.Decoders.CD;
|
||||||
@@ -48,6 +49,7 @@ using BCA = DiscImageChef.Decoders.Bluray.BCA;
|
|||||||
using Cartridge = DiscImageChef.Decoders.Bluray.Cartridge;
|
using Cartridge = DiscImageChef.Decoders.Bluray.Cartridge;
|
||||||
using DDS = DiscImageChef.Decoders.DVD.DDS;
|
using DDS = DiscImageChef.Decoders.DVD.DDS;
|
||||||
using DMI = DiscImageChef.Decoders.Xbox.DMI;
|
using DMI = DiscImageChef.Decoders.Xbox.DMI;
|
||||||
|
using Inquiry = DiscImageChef.Decoders.SCSI.Inquiry;
|
||||||
using Spare = DiscImageChef.Decoders.DVD.Spare;
|
using Spare = DiscImageChef.Decoders.DVD.Spare;
|
||||||
|
|
||||||
namespace DiscImageChef.Gui.Forms
|
namespace DiscImageChef.Gui.Forms
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ using DiscImageChef.CommonTypes;
|
|||||||
using DiscImageChef.CommonTypes.Enums;
|
using DiscImageChef.CommonTypes.Enums;
|
||||||
using DiscImageChef.CommonTypes.Interfaces;
|
using DiscImageChef.CommonTypes.Interfaces;
|
||||||
using DiscImageChef.CommonTypes.Structs;
|
using DiscImageChef.CommonTypes.Structs;
|
||||||
|
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
|
||||||
using DiscImageChef.Console;
|
using DiscImageChef.Console;
|
||||||
using DiscImageChef.Core;
|
using DiscImageChef.Core;
|
||||||
using DiscImageChef.Core.Media.Info;
|
using DiscImageChef.Core.Media.Info;
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ using System.Text;
|
|||||||
using DiscImageChef.CommonTypes.Enums;
|
using DiscImageChef.CommonTypes.Enums;
|
||||||
using DiscImageChef.CommonTypes.Interfaces;
|
using DiscImageChef.CommonTypes.Interfaces;
|
||||||
using DiscImageChef.CommonTypes.Structs;
|
using DiscImageChef.CommonTypes.Structs;
|
||||||
|
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
|
||||||
using DiscImageChef.Decoders.CD;
|
using DiscImageChef.Decoders.CD;
|
||||||
using DiscImageChef.Decoders.DVD;
|
using DiscImageChef.Decoders.DVD;
|
||||||
using DiscImageChef.Decoders.SCSI;
|
using DiscImageChef.Decoders.SCSI;
|
||||||
@@ -48,6 +49,7 @@ using Eto.Drawing;
|
|||||||
using Eto.Forms;
|
using Eto.Forms;
|
||||||
using Eto.Serialization.Xaml;
|
using Eto.Serialization.Xaml;
|
||||||
using Schemas;
|
using Schemas;
|
||||||
|
using Inquiry = DiscImageChef.Decoders.SCSI.Inquiry;
|
||||||
using Session = DiscImageChef.CommonTypes.Structs.Session;
|
using Session = DiscImageChef.CommonTypes.Structs.Session;
|
||||||
|
|
||||||
namespace DiscImageChef.Gui.Panels
|
namespace DiscImageChef.Gui.Panels
|
||||||
@@ -258,7 +260,7 @@ namespace DiscImageChef.Gui.Panels
|
|||||||
|
|
||||||
PeripheralDeviceTypes scsiDeviceType = PeripheralDeviceTypes.DirectAccess;
|
PeripheralDeviceTypes scsiDeviceType = PeripheralDeviceTypes.DirectAccess;
|
||||||
byte[] scsiInquiryData = null;
|
byte[] scsiInquiryData = null;
|
||||||
Inquiry.SCSIInquiry? scsiInquiry = null;
|
CommonTypes.Structs.Devices.SCSI.Inquiry? scsiInquiry = null;
|
||||||
Modes.DecodedMode? scsiMode = null;
|
Modes.DecodedMode? scsiMode = null;
|
||||||
byte[] scsiModeSense6 = null;
|
byte[] scsiModeSense6 = null;
|
||||||
byte[] scsiModeSense10 = null;
|
byte[] scsiModeSense10 = null;
|
||||||
@@ -270,7 +272,7 @@ namespace DiscImageChef.Gui.Panels
|
|||||||
|
|
||||||
scsiDeviceType = (PeripheralDeviceTypes)(scsiInquiryData[0] & 0x1F);
|
scsiDeviceType = (PeripheralDeviceTypes)(scsiInquiryData[0] & 0x1F);
|
||||||
|
|
||||||
scsiInquiry = Inquiry.Decode(scsiInquiryData);
|
scsiInquiry = CommonTypes.Structs.Devices.SCSI.Inquiry.Decode(scsiInquiryData);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(imageFormat.Info.ReadableMediaTags != null &&
|
if(imageFormat.Info.ReadableMediaTags != null &&
|
||||||
|
|||||||
@@ -34,11 +34,13 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
|
||||||
using DiscImageChef.Console;
|
using DiscImageChef.Console;
|
||||||
using DiscImageChef.Decoders.SCSI;
|
using DiscImageChef.Decoders.SCSI;
|
||||||
using DiscImageChef.Decoders.SCSI.MMC;
|
using DiscImageChef.Decoders.SCSI.MMC;
|
||||||
using Eto.Forms;
|
using Eto.Forms;
|
||||||
using Eto.Serialization.Xaml;
|
using Eto.Serialization.Xaml;
|
||||||
|
using Inquiry = DiscImageChef.Decoders.SCSI.Inquiry;
|
||||||
|
|
||||||
namespace DiscImageChef.Gui.Tabs
|
namespace DiscImageChef.Gui.Tabs
|
||||||
{
|
{
|
||||||
@@ -46,7 +48,7 @@ namespace DiscImageChef.Gui.Tabs
|
|||||||
{
|
{
|
||||||
private byte[] configuration;
|
private byte[] configuration;
|
||||||
private Dictionary<byte, byte[]> evpdPages;
|
private Dictionary<byte, byte[]> evpdPages;
|
||||||
private Inquiry.SCSIInquiry? inquiry;
|
private CommonTypes.Structs.Devices.SCSI.Inquiry? inquiry;
|
||||||
private byte[] inquiryData;
|
private byte[] inquiryData;
|
||||||
private Modes.DecodedMode? mode;
|
private Modes.DecodedMode? mode;
|
||||||
private byte[] modeSense10;
|
private byte[] modeSense10;
|
||||||
@@ -58,7 +60,7 @@ namespace DiscImageChef.Gui.Tabs
|
|||||||
XamlReader.Load(this);
|
XamlReader.Load(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void LoadData(byte[] scsiInquiryData, Inquiry.SCSIInquiry? scsiInquiry,
|
internal void LoadData(byte[] scsiInquiryData, CommonTypes.Structs.Devices.SCSI.Inquiry? scsiInquiry,
|
||||||
Dictionary<byte, byte[]> scsiEvpdPages, Modes.DecodedMode? scsiMode,
|
Dictionary<byte, byte[]> scsiEvpdPages, Modes.DecodedMode? scsiMode,
|
||||||
PeripheralDeviceTypes scsiType, byte[] scsiModeSense6,
|
PeripheralDeviceTypes scsiType, byte[] scsiModeSense6,
|
||||||
byte[] scsiModeSense10,
|
byte[] scsiModeSense10,
|
||||||
|
|||||||
@@ -251,6 +251,7 @@
|
|||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=leadout/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=leadout/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=manuallj/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=manuallj/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=mapfile/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=mapfile/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=MDMA/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=mediaid/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=mediaid/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=mediaserialnumber/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=mediaserialnumber/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=mhdd/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=mhdd/@EntryIndexedValue">True</s:Boolean>
|
||||||
@@ -287,6 +288,7 @@
|
|||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Reiser/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Reiser/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=remapanchor/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=remapanchor/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=reportdensitysupport/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=reportdensitysupport/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=SATA/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=SCMS/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=SCMS/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=SDHCI/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=SDHCI/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Secu/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Secu/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
|||||||
@@ -39,11 +39,12 @@ using System.Threading;
|
|||||||
using DiscImageChef.CommonTypes.Enums;
|
using DiscImageChef.CommonTypes.Enums;
|
||||||
using DiscImageChef.CommonTypes.Interop;
|
using DiscImageChef.CommonTypes.Interop;
|
||||||
using DiscImageChef.CommonTypes.Metadata;
|
using DiscImageChef.CommonTypes.Metadata;
|
||||||
|
using DiscImageChef.CommonTypes.Structs.Devices.ATA;
|
||||||
|
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
|
||||||
using DiscImageChef.Console;
|
using DiscImageChef.Console;
|
||||||
using DiscImageChef.Core;
|
using DiscImageChef.Core;
|
||||||
using DiscImageChef.Database;
|
using DiscImageChef.Database;
|
||||||
using DiscImageChef.Database.Models;
|
using DiscImageChef.Database.Models;
|
||||||
using DiscImageChef.Decoders.ATA;
|
|
||||||
using DiscImageChef.Decoders.SCSI;
|
using DiscImageChef.Decoders.SCSI;
|
||||||
using DiscImageChef.Devices;
|
using DiscImageChef.Devices;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ using System.CommandLine;
|
|||||||
using System.CommandLine.Invocation;
|
using System.CommandLine.Invocation;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using DiscImageChef.CommonTypes.Enums;
|
using DiscImageChef.CommonTypes.Enums;
|
||||||
|
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
|
||||||
using DiscImageChef.Console;
|
using DiscImageChef.Console;
|
||||||
using DiscImageChef.Core;
|
using DiscImageChef.Core;
|
||||||
using DiscImageChef.Database;
|
using DiscImageChef.Database;
|
||||||
@@ -47,6 +48,7 @@ using DiscImageChef.Decoders.SCSI.SSC;
|
|||||||
using DiscImageChef.Devices;
|
using DiscImageChef.Devices;
|
||||||
using Command = System.CommandLine.Command;
|
using Command = System.CommandLine.Command;
|
||||||
using DeviceInfo = DiscImageChef.Core.Devices.Info.DeviceInfo;
|
using DeviceInfo = DiscImageChef.Core.Devices.Info.DeviceInfo;
|
||||||
|
using Inquiry = DiscImageChef.Decoders.SCSI.Inquiry;
|
||||||
|
|
||||||
namespace DiscImageChef.Commands.Device
|
namespace DiscImageChef.Commands.Device
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ using System.CommandLine.Invocation;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using DiscImageChef.CommonTypes.Enums;
|
using DiscImageChef.CommonTypes.Enums;
|
||||||
using DiscImageChef.CommonTypes.Structs;
|
using DiscImageChef.CommonTypes.Structs;
|
||||||
|
using DiscImageChef.CommonTypes.Structs.Devices.SCSI;
|
||||||
using DiscImageChef.Console;
|
using DiscImageChef.Console;
|
||||||
using DiscImageChef.Core;
|
using DiscImageChef.Core;
|
||||||
using DiscImageChef.Core.Devices.Dumping;
|
using DiscImageChef.Core.Devices.Dumping;
|
||||||
@@ -46,7 +47,6 @@ using DiscImageChef.Database.Models;
|
|||||||
using DiscImageChef.Decoders.Bluray;
|
using DiscImageChef.Decoders.Bluray;
|
||||||
using DiscImageChef.Decoders.CD;
|
using DiscImageChef.Decoders.CD;
|
||||||
using DiscImageChef.Decoders.DVD;
|
using DiscImageChef.Decoders.DVD;
|
||||||
using DiscImageChef.Decoders.SCSI;
|
|
||||||
using DiscImageChef.Decoders.SCSI.MMC;
|
using DiscImageChef.Decoders.SCSI.MMC;
|
||||||
using DiscImageChef.Decoders.SCSI.SSC;
|
using DiscImageChef.Decoders.SCSI.SSC;
|
||||||
using DiscImageChef.Decoders.Xbox;
|
using DiscImageChef.Decoders.Xbox;
|
||||||
|
|||||||
Reference in New Issue
Block a user