diff --git a/Aaru.Core/Devices/Scanning/ATA.cs b/Aaru.Core/Devices/Scanning/ATA.cs index 8a5b47284..e833ee1a6 100644 --- a/Aaru.Core/Devices/Scanning/ATA.cs +++ b/Aaru.Core/Devices/Scanning/ATA.cs @@ -55,351 +55,351 @@ public sealed partial class MediaScan bool sense = _dev.AtaIdentify(out byte[] cmdBuf, out _); - if(!sense && Identify.Decode(cmdBuf).HasValue) + if(sense || !Identify.Decode(cmdBuf).HasValue) { - // Initialize reader - var ataReader = new Reader(_dev, timeout, cmdBuf, null); - - // Fill reader blocks - results.Blocks = ataReader.GetDeviceBlocks(); - - if(ataReader.FindReadCommand()) - { - StoppingErrorMessage?.Invoke(ataReader.ErrorMessage); - - return results; - } - - // Check block sizes - if(ataReader.GetBlockSize()) - { - StoppingErrorMessage?.Invoke(ataReader.ErrorMessage); - - return results; - } - - uint blockSize = ataReader.LogicalBlockSize; - - // Check how many blocks to read, if error show and return - if(ataReader.GetBlocksToRead()) - { - StoppingErrorMessage?.Invoke(ataReader.ErrorMessage); - - return results; - } - - uint blocksToRead = ataReader.BlocksToRead; - ushort cylinders = ataReader.Cylinders; - byte heads = ataReader.Heads; - byte sectors = ataReader.Sectors; - - results.A = 0; // <3ms - results.B = 0; // >=3ms, <10ms - results.C = 0; // >=10ms, <50ms - results.D = 0; // >=50ms, <150ms - results.E = 0; // >=150ms, <500ms - results.F = 0; // >=500ms - results.Errored = 0; - results.ProcessingTime = 0; - double currentSpeed = 0; - results.MaxSpeed = double.MinValue; - results.MinSpeed = double.MaxValue; - results.UnreadableSectors = []; - results.SeekMax = double.MinValue; - results.SeekMin = double.MaxValue; - results.SeekTotal = 0; - const int seekTimes = 1000; - - double seekCur; - - var rnd = new Random(); - - MhddLog mhddLog; - IbgLog ibgLog; - double duration; - - if(ataReader.IsLba) - { - UpdateStatus?.Invoke(string.Format(Localization.Core.Reading_0_sectors_at_a_time, blocksToRead)); - - InitBlockMap?.Invoke(results.Blocks, blockSize, blocksToRead, ataProfile); - mhddLog = new MhddLog(_mhddLogPath, _dev, results.Blocks, blockSize, blocksToRead, false); - ibgLog = new IbgLog(_ibgLogPath, ataProfile); - - InitProgress?.Invoke(); - uint accumulatedSpeedSectors = 0; - double accumulatedSpeedMs = 0; - - for(ulong i = 0; i < results.Blocks; i += blocksToRead) - { - if(_aborted) break; - - if(results.Blocks - i < blocksToRead) blocksToRead = (byte)(results.Blocks - i); - - if(currentSpeed > results.MaxSpeed && currentSpeed > 0) results.MaxSpeed = currentSpeed; - - if(currentSpeed < results.MinSpeed && currentSpeed > 0) results.MinSpeed = currentSpeed; - - UpdateProgress?.Invoke(string.Format(Localization.Core.Reading_sector_0_of_1_2, - i, - results.Blocks, - ByteSize.FromMegabytes(currentSpeed) - .Per(_oneSecond) - .Humanize()), - (long)i, - (long)results.Blocks); - - _speedStopwatch.Restart(); - bool error = ataReader.ReadBlocks(out cmdBuf, i, blocksToRead, out duration, out _, out _); - _speedStopwatch.Stop(); - accumulatedSpeedMs += _speedStopwatch.ElapsedMilliseconds; - accumulatedSpeedSectors += blocksToRead; - - if(!error) - { - switch(duration) - { - case >= 500: - results.F += blocksToRead; - - break; - case >= 150: - results.E += blocksToRead; - - break; - case >= 50: - results.D += blocksToRead; - - break; - case >= 10: - results.C += blocksToRead; - - break; - case >= 3: - results.B += blocksToRead; - - break; - default: - results.A += blocksToRead; - - break; - } - - ScanTime?.Invoke(i, duration); - mhddLog.Write(i, duration); - ibgLog.Write(i, currentSpeed * 1024); - } - else - { - ScanUnreadable?.Invoke(i); - results.Errored += blocksToRead; - - for(ulong b = i; b < i + blocksToRead; b++) results.UnreadableSectors.Add(b); - - mhddLog.Write(i, duration < 500 ? 65535 : duration); - - ibgLog.Write(i, 0); - } - - if(accumulatedSpeedMs >= 100) - { - currentSpeed = accumulatedSpeedSectors * blockSize / (1048576 * (accumulatedSpeedMs / 1000.0)); - ScanSpeed?.Invoke(i, currentSpeed * 1024); - accumulatedSpeedMs = 0; - accumulatedSpeedSectors = 0; - } - } - - _speedStopwatch.Stop(); - _scanStopwatch.Stop(); - EndProgress?.Invoke(); - mhddLog.Close(); - - currentSpeed = accumulatedSpeedSectors * blockSize / (1048576 * (accumulatedSpeedMs / 1000.0)); - - ibgLog.Close(_dev, - results.Blocks, - blockSize, - _scanStopwatch.Elapsed.TotalSeconds, - currentSpeed * 1024, - blockSize * (double)(results.Blocks + 1) / 1024 / (results.ProcessingTime / 1000), - _devicePath); - - InitProgress?.Invoke(); - - if(ataReader.CanSeekLba && _seekTest) - { - for(var i = 0; i < seekTimes; i++) - { - if(_aborted) break; - - var seekPos = (uint)rnd.Next((int)results.Blocks); - - PulseProgress?.Invoke(string.Format(Localization.Core.Seeking_to_sector_0, seekPos)); - - ataReader.Seek(seekPos, out seekCur); - - if(seekCur > results.SeekMax && seekCur > 0) results.SeekMax = seekCur; - - if(seekCur < results.SeekMin && seekCur > 0) results.SeekMin = seekCur; - - results.SeekTotal += seekCur; - GC.Collect(); - } - } - - EndProgress?.Invoke(); - } - else - { - InitBlockMap?.Invoke(results.Blocks, blockSize, blocksToRead, ataProfile); - mhddLog = new MhddLog(_mhddLogPath, _dev, results.Blocks, blockSize, blocksToRead, false); - ibgLog = new IbgLog(_ibgLogPath, ataProfile); - - ulong currentBlock = 0; - results.Blocks = (ulong)(cylinders * heads * sectors); - InitProgress?.Invoke(); - uint accumulatedSpeedSectors = 0; - double accumulatedSpeedMs = 0; - - for(ushort cy = 0; cy < cylinders; cy++) - { - for(byte hd = 0; hd < heads; hd++) - { - for(byte sc = 1; sc < sectors; sc++) - { - if(_aborted) break; - - if(currentSpeed > results.MaxSpeed && currentSpeed > 0) results.MaxSpeed = currentSpeed; - - if(currentSpeed < results.MinSpeed && currentSpeed > 0) results.MinSpeed = currentSpeed; - - PulseProgress?.Invoke(string.Format(Localization.Core.Reading_cylinder_0_head_1_sector_2_3, - cy, - hd, - sc, - ByteSize.FromMegabytes(currentSpeed) - .Per(_oneSecond) - .Humanize())); - - _speedStopwatch.Restart(); - bool error = ataReader.ReadChs(out cmdBuf, cy, hd, sc, out duration, out _); - accumulatedSpeedMs += _speedStopwatch.ElapsedMilliseconds; - accumulatedSpeedSectors++; - - if(!error) - { - switch(duration) - { - case >= 500: - results.F += blocksToRead; - - break; - case >= 150: - results.E += blocksToRead; - - break; - case >= 50: - results.D += blocksToRead; - - break; - case >= 10: - results.C += blocksToRead; - - break; - case >= 3: - results.B += blocksToRead; - - break; - default: - results.A += blocksToRead; - - break; - } - - ScanTime?.Invoke(currentBlock, duration); - mhddLog.Write(currentBlock, duration); - ibgLog.Write(currentBlock, currentSpeed * 1024); - } - else - { - ScanUnreadable?.Invoke(currentBlock); - results.Errored++; - results.UnreadableSectors.Add(currentBlock); - mhddLog.Write(currentBlock, duration < 500 ? 65535 : duration); - - ibgLog.Write(currentBlock, 0); - } - - if(accumulatedSpeedMs >= 100) - { - currentSpeed = accumulatedSpeedSectors * - blockSize / - (1048576 * (accumulatedSpeedMs / 1000.0)); - - ScanSpeed?.Invoke(currentBlock, currentSpeed * 1024); - accumulatedSpeedMs = 0; - accumulatedSpeedSectors = 0; - } - } - } - } - - _speedStopwatch.Stop(); - _scanStopwatch.Stop(); - EndProgress?.Invoke(); - mhddLog.Close(); - - currentSpeed = accumulatedSpeedSectors * blockSize / (1048576 * (accumulatedSpeedMs / 1000.0)); - - ibgLog.Close(_dev, - results.Blocks, - blockSize, - _scanStopwatch.Elapsed.TotalSeconds, - currentSpeed * 1024, - blockSize * (double)(results.Blocks + 1) / 1024 / (results.ProcessingTime / 1000), - _devicePath); - - InitProgress?.Invoke(); - - if(ataReader.CanSeek) - { - for(var i = 0; i < seekTimes; i++) - { - if(_aborted) break; - - var seekCy = (ushort)rnd.Next(cylinders); - var seekHd = (byte)rnd.Next(heads); - var seekSc = (byte)rnd.Next(sectors); - - PulseProgress?.Invoke(string.Format(Localization.Core.Seeking_to_cylinder_0_head_1_sector_2, - seekCy, - seekHd, - seekSc)); - - ataReader.SeekChs(seekCy, seekHd, seekSc, out seekCur); - - if(seekCur > results.SeekMax && seekCur > 0) results.SeekMax = seekCur; - - if(seekCur < results.SeekMin && seekCur > 0) results.SeekMin = seekCur; - - results.SeekTotal += seekCur; - GC.Collect(); - } - } - - EndProgress?.Invoke(); - } - - results.ProcessingTime /= 1000; - results.TotalTime = _scanStopwatch.Elapsed.TotalSeconds; - results.AvgSpeed = blockSize * (double)(results.Blocks + 1) / 1048576 / results.ProcessingTime; - results.SeekTimes = seekTimes; + StoppingErrorMessage?.Invoke(Localization.Core.Unable_to_communicate_with_ATA_device); return results; } - StoppingErrorMessage?.Invoke(Localization.Core.Unable_to_communicate_with_ATA_device); + // Initialize reader + var ataReader = new Reader(_dev, timeout, cmdBuf, null); + + // Fill reader blocks + results.Blocks = ataReader.GetDeviceBlocks(); + + if(ataReader.FindReadCommand()) + { + StoppingErrorMessage?.Invoke(ataReader.ErrorMessage); + + return results; + } + + // Check block sizes + if(ataReader.GetBlockSize()) + { + StoppingErrorMessage?.Invoke(ataReader.ErrorMessage); + + return results; + } + + uint blockSize = ataReader.LogicalBlockSize; + + // Check how many blocks to read, if error show and return + if(ataReader.GetBlocksToRead()) + { + StoppingErrorMessage?.Invoke(ataReader.ErrorMessage); + + return results; + } + + uint blocksToRead = ataReader.BlocksToRead; + ushort cylinders = ataReader.Cylinders; + byte heads = ataReader.Heads; + byte sectors = ataReader.Sectors; + + results.A = 0; // <3ms + results.B = 0; // >=3ms, <10ms + results.C = 0; // >=10ms, <50ms + results.D = 0; // >=50ms, <150ms + results.E = 0; // >=150ms, <500ms + results.F = 0; // >=500ms + results.Errored = 0; + results.ProcessingTime = 0; + double currentSpeed = 0; + results.MaxSpeed = double.MinValue; + results.MinSpeed = double.MaxValue; + results.UnreadableSectors = []; + results.SeekMax = double.MinValue; + results.SeekMin = double.MaxValue; + results.SeekTotal = 0; + const int seekTimes = 1000; + + double seekCur; + + var rnd = new Random(); + + MhddLog mhddLog; + IbgLog ibgLog; + double duration; + + if(ataReader.IsLba) + { + UpdateStatus?.Invoke(string.Format(Localization.Core.Reading_0_sectors_at_a_time, blocksToRead)); + + InitBlockMap?.Invoke(results.Blocks, blockSize, blocksToRead, ataProfile); + mhddLog = new MhddLog(_mhddLogPath, _dev, results.Blocks, blockSize, blocksToRead, false); + ibgLog = new IbgLog(_ibgLogPath, ataProfile); + + InitProgress?.Invoke(); + uint accumulatedSpeedSectors = 0; + double accumulatedSpeedMs = 0; + + for(ulong i = 0; i < results.Blocks; i += blocksToRead) + { + if(_aborted) break; + + if(results.Blocks - i < blocksToRead) blocksToRead = (byte)(results.Blocks - i); + + if(currentSpeed > results.MaxSpeed && currentSpeed > 0) results.MaxSpeed = currentSpeed; + + if(currentSpeed < results.MinSpeed && currentSpeed > 0) results.MinSpeed = currentSpeed; + + UpdateProgress?.Invoke(string.Format(Localization.Core.Reading_sector_0_of_1_2, + i, + results.Blocks, + ByteSize.FromMegabytes(currentSpeed) + .Per(_oneSecond) + .Humanize()), + (long)i, + (long)results.Blocks); + + _speedStopwatch.Restart(); + bool error = ataReader.ReadBlocks(out cmdBuf, i, blocksToRead, out duration, out _, out _); + _speedStopwatch.Stop(); + accumulatedSpeedMs += _speedStopwatch.ElapsedMilliseconds; + accumulatedSpeedSectors += blocksToRead; + + if(!error) + { + switch(duration) + { + case >= 500: + results.F += blocksToRead; + + break; + case >= 150: + results.E += blocksToRead; + + break; + case >= 50: + results.D += blocksToRead; + + break; + case >= 10: + results.C += blocksToRead; + + break; + case >= 3: + results.B += blocksToRead; + + break; + default: + results.A += blocksToRead; + + break; + } + + ScanTime?.Invoke(i, duration); + mhddLog.Write(i, duration); + ibgLog.Write(i, currentSpeed * 1024); + } + else + { + ScanUnreadable?.Invoke(i); + results.Errored += blocksToRead; + + for(ulong b = i; b < i + blocksToRead; b++) results.UnreadableSectors.Add(b); + + mhddLog.Write(i, duration < 500 ? 65535 : duration); + + ibgLog.Write(i, 0); + } + + if(accumulatedSpeedMs >= 100) + { + currentSpeed = accumulatedSpeedSectors * blockSize / (1048576 * (accumulatedSpeedMs / 1000.0)); + ScanSpeed?.Invoke(i, currentSpeed * 1024); + accumulatedSpeedMs = 0; + accumulatedSpeedSectors = 0; + } + } + + _speedStopwatch.Stop(); + _scanStopwatch.Stop(); + EndProgress?.Invoke(); + mhddLog.Close(); + + currentSpeed = accumulatedSpeedSectors * blockSize / (1048576 * (accumulatedSpeedMs / 1000.0)); + + ibgLog.Close(_dev, + results.Blocks, + blockSize, + _scanStopwatch.Elapsed.TotalSeconds, + currentSpeed * 1024, + blockSize * (double)(results.Blocks + 1) / 1024 / (results.ProcessingTime / 1000), + _devicePath); + + InitProgress?.Invoke(); + + if(ataReader.CanSeekLba && _seekTest) + { + for(var i = 0; i < seekTimes; i++) + { + if(_aborted) break; + + var seekPos = (uint)rnd.Next((int)results.Blocks); + + PulseProgress?.Invoke(string.Format(Localization.Core.Seeking_to_sector_0, seekPos)); + + ataReader.Seek(seekPos, out seekCur); + + if(seekCur > results.SeekMax && seekCur > 0) results.SeekMax = seekCur; + + if(seekCur < results.SeekMin && seekCur > 0) results.SeekMin = seekCur; + + results.SeekTotal += seekCur; + GC.Collect(); + } + } + + EndProgress?.Invoke(); + } + else + { + InitBlockMap?.Invoke(results.Blocks, blockSize, blocksToRead, ataProfile); + mhddLog = new MhddLog(_mhddLogPath, _dev, results.Blocks, blockSize, blocksToRead, false); + ibgLog = new IbgLog(_ibgLogPath, ataProfile); + + ulong currentBlock = 0; + results.Blocks = (ulong)(cylinders * heads * sectors); + InitProgress?.Invoke(); + uint accumulatedSpeedSectors = 0; + double accumulatedSpeedMs = 0; + + for(ushort cy = 0; cy < cylinders; cy++) + { + for(byte hd = 0; hd < heads; hd++) + { + for(byte sc = 1; sc < sectors; sc++) + { + if(_aborted) break; + + if(currentSpeed > results.MaxSpeed && currentSpeed > 0) results.MaxSpeed = currentSpeed; + + if(currentSpeed < results.MinSpeed && currentSpeed > 0) results.MinSpeed = currentSpeed; + + PulseProgress?.Invoke(string.Format(Localization.Core.Reading_cylinder_0_head_1_sector_2_3, + cy, + hd, + sc, + ByteSize.FromMegabytes(currentSpeed) + .Per(_oneSecond) + .Humanize())); + + _speedStopwatch.Restart(); + bool error = ataReader.ReadChs(out cmdBuf, cy, hd, sc, out duration, out _); + accumulatedSpeedMs += _speedStopwatch.ElapsedMilliseconds; + accumulatedSpeedSectors++; + + if(!error) + { + switch(duration) + { + case >= 500: + results.F += blocksToRead; + + break; + case >= 150: + results.E += blocksToRead; + + break; + case >= 50: + results.D += blocksToRead; + + break; + case >= 10: + results.C += blocksToRead; + + break; + case >= 3: + results.B += blocksToRead; + + break; + default: + results.A += blocksToRead; + + break; + } + + ScanTime?.Invoke(currentBlock, duration); + mhddLog.Write(currentBlock, duration); + ibgLog.Write(currentBlock, currentSpeed * 1024); + } + else + { + ScanUnreadable?.Invoke(currentBlock); + results.Errored++; + results.UnreadableSectors.Add(currentBlock); + mhddLog.Write(currentBlock, duration < 500 ? 65535 : duration); + + ibgLog.Write(currentBlock, 0); + } + + if(accumulatedSpeedMs >= 100) + { + currentSpeed = accumulatedSpeedSectors * + blockSize / + (1048576 * (accumulatedSpeedMs / 1000.0)); + + ScanSpeed?.Invoke(currentBlock, currentSpeed * 1024); + accumulatedSpeedMs = 0; + accumulatedSpeedSectors = 0; + } + } + } + } + + _speedStopwatch.Stop(); + _scanStopwatch.Stop(); + EndProgress?.Invoke(); + mhddLog.Close(); + + currentSpeed = accumulatedSpeedSectors * blockSize / (1048576 * (accumulatedSpeedMs / 1000.0)); + + ibgLog.Close(_dev, + results.Blocks, + blockSize, + _scanStopwatch.Elapsed.TotalSeconds, + currentSpeed * 1024, + blockSize * (double)(results.Blocks + 1) / 1024 / (results.ProcessingTime / 1000), + _devicePath); + + InitProgress?.Invoke(); + + if(ataReader.CanSeek) + { + for(var i = 0; i < seekTimes; i++) + { + if(_aborted) break; + + var seekCy = (ushort)rnd.Next(cylinders); + var seekHd = (byte)rnd.Next(heads); + var seekSc = (byte)rnd.Next(sectors); + + PulseProgress?.Invoke(string.Format(Localization.Core.Seeking_to_cylinder_0_head_1_sector_2, + seekCy, + seekHd, + seekSc)); + + ataReader.SeekChs(seekCy, seekHd, seekSc, out seekCur); + + if(seekCur > results.SeekMax && seekCur > 0) results.SeekMax = seekCur; + + if(seekCur < results.SeekMin && seekCur > 0) results.SeekMin = seekCur; + + results.SeekTotal += seekCur; + GC.Collect(); + } + } + + EndProgress?.Invoke(); + } + + results.ProcessingTime /= 1000; + results.TotalTime = _scanStopwatch.Elapsed.TotalSeconds; + results.AvgSpeed = blockSize * (double)(results.Blocks + 1) / 1048576 / results.ProcessingTime; + results.SeekTimes = seekTimes; return results; }