diff --git a/DiscImageChef.Core/Devices/Dumping/SecureDigital.cs b/DiscImageChef.Core/Devices/Dumping/SecureDigital.cs index f1ae5da3..d0385288 100644 --- a/DiscImageChef.Core/Devices/Dumping/SecureDigital.cs +++ b/DiscImageChef.Core/Devices/Dumping/SecureDigital.cs @@ -84,7 +84,7 @@ namespace DiscImageChef.Core.Devices.Dumping sidecar.BlockMedia[0].SecureDigital = new SecureDigitalType(); - uint blocksToRead = 256; + uint blocksToRead = 128; uint blockSize = 512; ulong blocks = 0; byte[] cid = null; @@ -94,6 +94,7 @@ namespace DiscImageChef.Core.Devices.Dumping byte[] scr = null; uint[] response; int physicalBlockSize = 0; + bool byteAddressed = true; if(dev.Type == DeviceType.MMC) { @@ -111,6 +112,8 @@ namespace DiscImageChef.Core.Devices.Dumping physicalBlockSize = 512; else if(ecsdDecoded.NativeSectorSize == 1) physicalBlockSize = 4096; + // Supposing it's high-capacity MMC if it has Extended CSD... + byteAddressed = false; } else ecsd = null; @@ -142,6 +145,8 @@ namespace DiscImageChef.Core.Devices.Dumping csdDecoded = Decoders.SecureDigital.Decoders.DecodeCSD(csd); blocks = (ulong)(csdDecoded.Structure == 0 ? (csdDecoded.Size + 1) * Math.Pow(2, csdDecoded.SizeMultiplier + 2) : (csdDecoded.Size + 1) * 1024); blockSize = (uint)Math.Pow(2, csdDecoded.ReadBlockLength); + // Structure >=1 for SDHC/SDXC, so that's block addressed + byteAddressed = csdDecoded.Structure == 0; } else csd = null; @@ -243,7 +248,7 @@ namespace DiscImageChef.Core.Devices.Dumping while(true) { - error = dev.Read(out cmdBuf, out response, 0, blockSize, blocksToRead, false, timeout, out duration); + error = dev.Read(out cmdBuf, out response, 0, blockSize, blocksToRead, byteAddressed, timeout, out duration); if(error) blocksToRead /= 2; @@ -295,7 +300,7 @@ namespace DiscImageChef.Core.Devices.Dumping DicConsole.Write("\rReading sector {0} of {1} ({2:F3} MiB/sec.)", i, blocks, currentSpeed); - error = dev.Read(out cmdBuf, out response, (uint)i, blockSize, blocksToRead, false, timeout, out duration); + error = dev.Read(out cmdBuf, out response, (uint)i, blockSize, blocksToRead, byteAddressed, timeout, out duration); if(!error) { @@ -350,7 +355,7 @@ namespace DiscImageChef.Core.Devices.Dumping DicConsole.Write("\rRetrying sector {0}, pass {1}, {3}{2}", badSector, pass + 1, forward ? "forward" : "reverse", runningPersistent ? "recovering partial data, " : ""); - error = dev.Read(out cmdBuf, out response, (uint)badSector, blockSize, 1, false, timeout, out duration); + error = dev.Read(out cmdBuf, out response, (uint)badSector, blockSize, 1, byteAddressed, timeout, out duration); totalDuration += duration; diff --git a/DiscImageChef.Core/Devices/Scanning/SecureDigital.cs b/DiscImageChef.Core/Devices/Scanning/SecureDigital.cs index 084278e9..d2fa4203 100644 --- a/DiscImageChef.Core/Devices/Scanning/SecureDigital.cs +++ b/DiscImageChef.Core/Devices/Scanning/SecureDigital.cs @@ -59,8 +59,9 @@ namespace DiscImageChef.Core.Devices.Scanning uint timeout = 5; double duration = 0; ushort currentProfile = 0x0001; - uint blocksToRead = 256; + uint blocksToRead = 128; uint blockSize = 512; + bool byteAddressed = true; if(dev.Type == DeviceType.MMC) { @@ -74,6 +75,8 @@ namespace DiscImageChef.Core.Devices.Scanning blocksToRead = ecsd.OptimalReadSize; results.blocks = ecsd.SectorCount; blockSize = (uint)(ecsd.SectorSize == 1 ? 4096 : 512); + // Supposing it's high-capacity MMC if it has Extended CSD... + byteAddressed = false; } if(sense || results.blocks == 0) @@ -97,6 +100,8 @@ namespace DiscImageChef.Core.Devices.Scanning csd = Decoders.SecureDigital.Decoders.DecodeCSD(cmdBuf); results.blocks = (ulong)(csd.Structure == 0 ? (csd.Size + 1) * Math.Pow(2, csd.SizeMultiplier + 2) : (csd.Size + 1) * 1024); blockSize = (uint)Math.Pow(2, csd.ReadBlockLength); + // Structure >=1 for SDHC/SDXC, so that's block addressed + byteAddressed = csd.Structure == 0; } } @@ -110,7 +115,7 @@ namespace DiscImageChef.Core.Devices.Scanning while(true) { - sense = dev.Read(out cmdBuf, out response, 0, blockSize, blocksToRead, false, timeout, out duration); + sense = dev.Read(out cmdBuf, out response, 0, blockSize, blocksToRead, byteAddressed, timeout, out duration); if(sense) blocksToRead /= 2; @@ -180,7 +185,7 @@ namespace DiscImageChef.Core.Devices.Scanning DicConsole.Write("\rReading sector {0} of {1} ({2:F3} MiB/sec.)", i, results.blocks, currentSpeed); - bool error = dev.Read(out cmdBuf, out response, (uint)i, blockSize, blocksToRead, false, timeout, out duration); + bool error = dev.Read(out cmdBuf, out response, (uint)i, blockSize, blocksToRead, byteAddressed, timeout, out duration); if(!error) { @@ -246,7 +251,7 @@ namespace DiscImageChef.Core.Devices.Scanning DicConsole.Write("\rSeeking to sector {0}...\t\t", seekPos); - dev.Read(out cmdBuf, out response, (uint)seekPos, blockSize, blocksToRead, false, timeout, out seekCur); + dev.Read(out cmdBuf, out response, (uint)seekPos, blockSize, blocksToRead, byteAddressed, timeout, out seekCur); #pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator if(seekCur > results.seekMax && seekCur != 0) diff --git a/DiscImageChef.Decoders/SecureDigital/VendorString.cs b/DiscImageChef.Decoders/SecureDigital/VendorString.cs index 586d0fe5..7b2eb8ad 100644 --- a/DiscImageChef.Decoders/SecureDigital/VendorString.cs +++ b/DiscImageChef.Decoders/SecureDigital/VendorString.cs @@ -38,6 +38,8 @@ namespace DiscImageChef.Decoders.SecureDigital { switch(SDVendorID) { + case 0xAA: + return "QEMU"; default: return string.Format("Unknown manufacturer ID 0x{0:X2}", SDVendorID); } diff --git a/DiscImageChef.Devices/Device/Commands.cs b/DiscImageChef.Devices/Device/Commands.cs index c0e18e40..cb93ca96 100644 --- a/DiscImageChef.Devices/Device/Commands.cs +++ b/DiscImageChef.Devices/Device/Commands.cs @@ -171,6 +171,19 @@ namespace DiscImageChef.Devices return 0; } + if((command == (MmcCommands)SecureDigitalCommands.SendOperatingCondition || + command == MmcCommands.SendOpCond) && cachedOcr != null) + { + System.DateTime start = System.DateTime.Now; + buffer = new byte[cachedOcr.Length]; + System.Array.Copy(cachedOcr, buffer, buffer.Length); + response = new uint[4]; + sense = false; + System.DateTime end = System.DateTime.Now; + duration = (end - start).TotalMilliseconds; + return 0; + } + return Command.SendMmcCommand(platformID, fd, command, write, isApplication, flags, argument, blockSize, blocks, ref buffer, out response, out duration, out sense, timeout); } diff --git a/DiscImageChef.Devices/Device/Constructor.cs b/DiscImageChef.Devices/Device/Constructor.cs index dfd593c6..1f820b57 100644 --- a/DiscImageChef.Devices/Device/Constructor.cs +++ b/DiscImageChef.Devices/Device/Constructor.cs @@ -211,6 +211,12 @@ namespace DiscImageChef.Devices if(len == 0) cachedScr = null; } + if(System.IO.File.Exists("/sys/block/" + devPath + "/device/ocr")) + { + int len = ConvertFromHexASCII("/sys/block/" + devPath + "/device/ocr", out cachedOcr); + if(len == 0) + cachedOcr = null; + } if(cachedCid != null) { diff --git a/DiscImageChef.Devices/Device/MmcCommands/MMC.cs b/DiscImageChef.Devices/Device/MmcCommands/MMC.cs index 9f02a8a9..7d64e20a 100644 --- a/DiscImageChef.Devices/Device/MmcCommands/MMC.cs +++ b/DiscImageChef.Devices/Device/MmcCommands/MMC.cs @@ -127,7 +127,13 @@ namespace DiscImageChef.Devices error = lastError != 0; if(transferLength > 1) + { + byte[] foo = new byte[0]; + SendMmcCommand(MmcCommands.StopTransmission, false, false, MmcFlags.Response_R1b | MmcFlags.ResponseSPI_R1b | MmcFlags.CommandAC, + 0, 0, 0, ref foo, out uint[] responseStop, out double stopDuration, out bool stopSense, timeout); + duration += stopDuration; DicConsole.DebugWriteLine("MMC Device", "READ_MULTIPLE_BLOCK took {0} ms.", duration); + } else DicConsole.DebugWriteLine("MMC Device", "READ_SINGLE_BLOCK took {0} ms.", duration); diff --git a/DiscImageChef.Devices/Device/Variables.cs b/DiscImageChef.Devices/Device/Variables.cs index 97aec359..5da1cb57 100644 --- a/DiscImageChef.Devices/Device/Variables.cs +++ b/DiscImageChef.Devices/Device/Variables.cs @@ -67,6 +67,7 @@ namespace DiscImageChef.Devices readonly byte[] cachedCsd; readonly byte[] cachedCid; readonly byte[] cachedScr; + readonly byte[] cachedOcr; /// /// Gets the Platform ID for this device