Files
Aaru/Aaru.Core/Devices/Report/ATA.cs

1010 lines
42 KiB
C#
Raw Normal View History

// /***************************************************************************
2020-02-27 12:31:25 +00:00
// Aaru Data Preservation Suite
// ----------------------------------------------------------------------------
//
// Filename : ATA.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : Core algorithms.
//
// --[ Description ] ----------------------------------------------------------
//
// Creates reports from ATA devices.
//
// --[ License ] --------------------------------------------------------------
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
2024-12-19 10:45:18 +00:00
// Copyright © 2011-2025 Natalia Portillo
// ****************************************************************************/
using System;
2020-02-27 00:33:26 +00:00
using Aaru.CommonTypes.Metadata;
using Aaru.Decoders.ATA;
using Aaru.Devices;
using Aaru.Logging;
using Spectre.Console;
2020-02-27 00:33:26 +00:00
using Identify = Aaru.CommonTypes.Structs.Devices.ATA.Identify;
namespace Aaru.Core.Devices.Report;
2022-03-06 13:29:38 +00:00
public sealed partial class DeviceReport
{
2022-03-06 13:29:38 +00:00
/// <summary>Creates a report for media inserted into an ATA device</summary>
/// <returns>Media report</returns>
public TestedMedia ReportAtaMedia()
{
2025-11-24 19:38:40 +00:00
var sense = true;
2022-03-06 13:29:38 +00:00
AtaErrorRegistersChs errorChs = new();
AtaErrorRegistersLba28 errorLba = new();
AtaErrorRegistersLba48 errorLba48 = new();
2024-05-01 04:39:38 +01:00
byte[] buffer = [];
byte[] readBuf = [];
2022-03-06 13:29:38 +00:00
var mediaTest = new TestedMedia
{
MediumTypeName = AnsiConsole.Ask<string>(Localization.Core.Please_write_description_of_media_type),
Model = AnsiConsole.Ask<string>(Localization.Core.Please_write_media_model),
2022-03-06 13:29:38 +00:00
MediaIsRecognized = true
};
2022-03-06 13:29:38 +00:00
Spectre.ProgressSingleSpinner(ctx =>
{
ctx.AddTask(Localization.Core.Querying_ATA_IDENTIFY).IsIndeterminate();
2022-03-06 13:29:38 +00:00
_dev.AtaIdentify(out buffer, out _, _dev.Timeout, out _);
});
2022-03-06 13:29:38 +00:00
mediaTest.IdentifyData = ClearIdentify(buffer);
mediaTest.IdentifyDevice = Identify.Decode(buffer);
2022-03-06 13:29:38 +00:00
if(mediaTest.IdentifyDevice.HasValue)
{
2022-03-06 13:29:38 +00:00
Identify.IdentifyDevice ataId = mediaTest.IdentifyDevice.Value;
2024-05-01 04:05:22 +01:00
if(ataId.UnformattedBPT != 0) mediaTest.UnformattedBPT = ataId.UnformattedBPT;
2024-05-01 04:05:22 +01:00
if(ataId.UnformattedBPS != 0) mediaTest.UnformattedBPS = ataId.UnformattedBPS;
if(ataId.Cylinders > 0 && ataId is { Heads: > 0, SectorsPerTrack: > 0 })
{
2022-03-06 13:29:38 +00:00
mediaTest.CHS = new Chs
{
2020-07-20 04:34:16 +01:00
Cylinders = ataId.Cylinders,
Heads = ataId.Heads,
Sectors = ataId.SectorsPerTrack
};
2019-12-27 18:00:03 +00:00
2022-03-06 13:29:38 +00:00
mediaTest.Blocks = (ulong)(ataId.Cylinders * ataId.Heads * ataId.SectorsPerTrack);
}
if(ataId.CurrentCylinders > 0 && ataId is { CurrentHeads: > 0, CurrentSectorsPerTrack: > 0 })
{
2022-03-06 13:29:38 +00:00
mediaTest.CurrentCHS = new Chs
{
2020-07-20 04:34:16 +01:00
Cylinders = ataId.CurrentCylinders,
Heads = ataId.CurrentHeads,
Sectors = ataId.CurrentSectorsPerTrack
};
2019-12-27 18:00:03 +00:00
2022-03-06 13:29:38 +00:00
if(mediaTest.Blocks == 0)
2023-10-03 22:57:50 +01:00
{
2022-03-06 13:29:38 +00:00
mediaTest.Blocks =
(ulong)(ataId.CurrentCylinders * ataId.CurrentHeads * ataId.CurrentSectorsPerTrack);
2023-10-03 22:57:50 +01:00
}
}
if(ataId.Capabilities.HasFlag(Identify.CapabilitiesBit.LBASupport))
{
2022-03-06 13:29:38 +00:00
mediaTest.LBASectors = ataId.LBASectors;
mediaTest.Blocks = ataId.LBASectors;
}
if(ataId.CommandSet2.HasFlag(Identify.CommandSetBit2.LBA48))
{
2022-03-06 13:29:38 +00:00
mediaTest.LBA48Sectors = ataId.LBA48Sectors;
mediaTest.Blocks = ataId.LBA48Sectors;
}
if(ataId.NominalRotationRate != 0x0000 && ataId.NominalRotationRate != 0xFFFF)
2023-10-03 22:57:50 +01:00
{
if(ataId.NominalRotationRate == 0x0001)
2022-03-06 13:29:38 +00:00
mediaTest.SolidStateDevice = true;
else
{
2022-03-06 13:29:38 +00:00
mediaTest.SolidStateDevice = false;
mediaTest.NominalRotationRate = ataId.NominalRotationRate;
}
2023-10-03 22:57:50 +01:00
}
2019-12-27 18:00:03 +00:00
uint logicalSectorSize;
uint physicalSectorSize;
if((ataId.PhysLogSectorSize & 0x8000) == 0x0000 && (ataId.PhysLogSectorSize & 0x4000) == 0x4000)
{
if((ataId.PhysLogSectorSize & 0x1000) == 0x1000)
2023-10-03 22:57:50 +01:00
{
if(ataId.LogicalSectorWords <= 255 || ataId.LogicalAlignment == 0xFFFF)
2019-12-27 18:00:03 +00:00
logicalSectorSize = 512;
else
2019-12-27 18:00:03 +00:00
logicalSectorSize = ataId.LogicalSectorWords * 2;
2023-10-03 22:57:50 +01:00
}
2019-12-27 18:00:03 +00:00
else
logicalSectorSize = 512;
if((ataId.PhysLogSectorSize & 0x2000) == 0x2000)
2023-10-03 22:57:50 +01:00
physicalSectorSize = (uint)(logicalSectorSize * (1 << ataId.PhysLogSectorSize & 0xF));
2019-12-27 18:00:03 +00:00
else
physicalSectorSize = logicalSectorSize;
}
else
{
2019-12-27 18:00:03 +00:00
logicalSectorSize = 512;
physicalSectorSize = 512;
}
2022-03-06 13:29:38 +00:00
mediaTest.BlockSize = logicalSectorSize;
2019-12-27 18:00:03 +00:00
if(physicalSectorSize != logicalSectorSize)
{
2022-03-06 13:29:38 +00:00
mediaTest.PhysicalBlockSize = physicalSectorSize;
if((ataId.LogicalAlignment & 0x8000) == 0x0000 && (ataId.LogicalAlignment & 0x4000) == 0x4000)
2022-03-06 13:29:38 +00:00
mediaTest.LogicalAlignment = (ushort)(ataId.LogicalAlignment & 0x3FFF);
}
if(ataId.EccBytes != 0x0000 && ataId.EccBytes != 0xFFFF)
2022-03-06 13:29:38 +00:00
mediaTest.LongBlockSize = logicalSectorSize + ataId.EccBytes;
2019-12-27 18:00:03 +00:00
if(ataId.UnformattedBPS > logicalSectorSize &&
2022-03-06 13:29:38 +00:00
(!(ataId.EccBytes != 0x0000 && ataId.EccBytes != 0xFFFF) || mediaTest.LongBlockSize == 516))
mediaTest.LongBlockSize = ataId.UnformattedBPS;
if(ataId.CommandSet3.HasFlag(Identify.CommandSetBit3.MustBeSet) &&
!ataId.CommandSet3.HasFlag(Identify.CommandSetBit3.MustBeClear) &&
ataId.EnabledCommandSet3.HasFlag(Identify.CommandSetBit3.MediaSerial))
{
2022-03-06 13:29:38 +00:00
mediaTest.CanReadMediaSerial = true;
2019-12-27 18:00:03 +00:00
if(!string.IsNullOrWhiteSpace(ataId.MediaManufacturer))
2022-03-06 13:29:38 +00:00
mediaTest.Manufacturer = ataId.MediaManufacturer;
}
2025-11-24 19:38:40 +00:00
var checkCorrectRead = BitConverter.ToUInt64(buffer, 0);
2021-09-13 18:08:44 +01:00
Spectre.ProgressSingleSpinner(ctx =>
{
ctx.AddTask(Localization.Core.Trying_READ_SECTORS_in_CHS_mode).IsIndeterminate();
2021-09-13 18:08:44 +01:00
sense = _dev.Read(out readBuf, out errorChs, false, 0, 0, 1, 1, _dev.Timeout, out _);
});
2019-12-27 18:00:03 +00:00
mediaTest.SupportsReadSectors =
!sense && (errorChs.Status & 0x01) != 0x01 && errorChs.Error == 0 && readBuf.Length > 0;
2019-12-27 18:00:03 +00:00
2025-08-17 06:11:22 +01:00
AaruLogging.Debug(ATA_MODULE_NAME,
2025-11-24 19:38:40 +00:00
Localization.Core.Sense_0_Status_1_Error_2_Length_3,
sense,
errorChs.Status,
errorChs.Error,
readBuf.Length);
2019-12-27 18:00:03 +00:00
2022-03-06 13:29:38 +00:00
mediaTest.ReadSectorsData = readBuf;
2021-09-13 18:08:44 +01:00
Spectre.ProgressSingleSpinner(ctx =>
{
ctx.AddTask(Localization.Core.Trying_READ_SECTORS_RETRY_in_CHS_mode).IsIndeterminate();
2021-09-13 18:08:44 +01:00
sense = _dev.Read(out readBuf, out errorChs, true, 0, 0, 1, 1, _dev.Timeout, out _);
});
2019-12-27 18:00:03 +00:00
mediaTest.SupportsReadRetry =
!sense && (errorChs.Status & 0x01) != 0x01 && errorChs.Error == 0 && readBuf.Length > 0;
2019-12-27 18:00:03 +00:00
2025-08-17 06:11:22 +01:00
AaruLogging.Debug(ATA_MODULE_NAME,
2025-11-24 19:38:40 +00:00
Localization.Core.Sense_0_Status_1_Error_2_Length_3,
sense,
errorChs.Status,
errorChs.Error,
readBuf.Length);
2019-12-27 18:00:03 +00:00
2022-03-06 13:29:38 +00:00
mediaTest.ReadSectorsRetryData = readBuf;
2021-09-13 18:08:44 +01:00
Spectre.ProgressSingleSpinner(ctx =>
{
ctx.AddTask(Localization.Core.Trying_READ_DMA_in_CHS_mode).IsIndeterminate();
2021-09-13 18:08:44 +01:00
sense = _dev.ReadDma(out readBuf, out errorChs, false, 0, 0, 1, 1, _dev.Timeout, out _);
});
2019-12-27 18:00:03 +00:00
mediaTest.SupportsReadDma =
!sense && (errorChs.Status & 0x01) != 0x01 && errorChs.Error == 0 && readBuf.Length > 0;
2019-12-27 18:00:03 +00:00
2025-08-17 06:11:22 +01:00
AaruLogging.Debug(ATA_MODULE_NAME,
2025-11-24 19:38:40 +00:00
Localization.Core.Sense_0_Status_1_Error_2_Length_3,
sense,
errorChs.Status,
errorChs.Error,
readBuf.Length);
2019-12-27 18:00:03 +00:00
2022-03-06 13:29:38 +00:00
mediaTest.ReadDmaData = readBuf;
2021-09-13 18:08:44 +01:00
Spectre.ProgressSingleSpinner(ctx =>
{
ctx.AddTask(Localization.Core.Trying_READ_DMA_RETRY_in_CHS_mode).IsIndeterminate();
2021-09-13 18:08:44 +01:00
sense = _dev.ReadDma(out readBuf, out errorChs, true, 0, 0, 1, 1, _dev.Timeout, out _);
});
2019-12-27 18:00:03 +00:00
mediaTest.SupportsReadDmaRetry =
!sense && (errorChs.Status & 0x01) != 0x01 && errorChs.Error == 0 && readBuf.Length > 0;
2019-12-27 18:00:03 +00:00
2025-08-17 06:11:22 +01:00
AaruLogging.Debug(ATA_MODULE_NAME,
2025-11-24 19:38:40 +00:00
Localization.Core.Sense_0_Status_1_Error_2_Length_3,
sense,
errorChs.Status,
errorChs.Error,
readBuf.Length);
2019-12-27 18:00:03 +00:00
2022-03-06 13:29:38 +00:00
mediaTest.ReadDmaRetryData = readBuf;
2021-09-13 18:08:44 +01:00
Spectre.ProgressSingleSpinner(ctx =>
{
ctx.AddTask(Localization.Core.Trying_SEEK_in_CHS_mode).IsIndeterminate();
2021-09-13 18:08:44 +01:00
sense = _dev.Seek(out errorChs, 0, 0, 1, _dev.Timeout, out _);
});
2022-03-06 13:29:38 +00:00
mediaTest.SupportsSeek = !sense && (errorChs.Status & 0x01) != 0x01 && errorChs.Error == 0;
2019-12-27 18:00:03 +00:00
2025-08-17 06:11:22 +01:00
AaruLogging.Debug(ATA_MODULE_NAME,
2025-11-24 19:38:40 +00:00
Localization.Core.Sense_0_Status_1_Error_2,
sense,
errorChs.Status,
errorChs.Error);
2021-09-13 18:08:44 +01:00
Spectre.ProgressSingleSpinner(ctx =>
{
ctx.AddTask(Localization.Core.Trying_READ_SECTORS_in_LBA_mode).IsIndeterminate();
2021-09-13 18:08:44 +01:00
sense = _dev.Read(out readBuf, out errorLba, false, 0, 1, _dev.Timeout, out _);
});
2019-12-27 18:00:03 +00:00
mediaTest.SupportsReadLba =
!sense && (errorLba.Status & 0x01) != 0x01 && errorLba.Error == 0 && readBuf.Length > 0;
2019-12-27 18:00:03 +00:00
2025-08-17 06:11:22 +01:00
AaruLogging.Debug(ATA_MODULE_NAME,
2025-11-24 19:38:40 +00:00
Localization.Core.Sense_0_Status_1_Error_2_Length_3,
sense,
errorChs.Status,
errorChs.Error,
readBuf.Length);
2019-12-27 18:00:03 +00:00
2022-03-06 13:29:38 +00:00
mediaTest.ReadLbaData = readBuf;
2021-09-13 18:08:44 +01:00
Spectre.ProgressSingleSpinner(ctx =>
{
ctx.AddTask(Localization.Core.Trying_READ_SECTORS_RETRY_in_LBA_mode).IsIndeterminate();
2021-09-13 18:08:44 +01:00
sense = _dev.Read(out readBuf, out errorLba, true, 0, 1, _dev.Timeout, out _);
});
2019-12-27 18:00:03 +00:00
mediaTest.SupportsReadRetryLba =
!sense && (errorLba.Status & 0x01) != 0x01 && errorLba.Error == 0 && readBuf.Length > 0;
2019-12-27 18:00:03 +00:00
2025-08-17 06:11:22 +01:00
AaruLogging.Debug(ATA_MODULE_NAME,
2025-11-24 19:38:40 +00:00
Localization.Core.Sense_0_Status_1_Error_2_Length_3,
sense,
errorChs.Status,
errorChs.Error,
readBuf.Length);
2019-12-27 18:00:03 +00:00
2022-03-06 13:29:38 +00:00
mediaTest.ReadRetryLbaData = readBuf;
2021-09-13 18:08:44 +01:00
Spectre.ProgressSingleSpinner(ctx =>
{
ctx.AddTask(Localization.Core.Trying_READ_DMA_in_LBA_mode).IsIndeterminate();
2021-09-13 18:08:44 +01:00
sense = _dev.ReadDma(out readBuf, out errorLba, false, 0, 1, _dev.Timeout, out _);
});
2019-12-27 18:00:03 +00:00
mediaTest.SupportsReadDmaLba =
!sense && (errorLba.Status & 0x01) != 0x01 && errorLba.Error == 0 && readBuf.Length > 0;
2019-12-27 18:00:03 +00:00
2025-08-17 06:11:22 +01:00
AaruLogging.Debug(ATA_MODULE_NAME,
2025-11-24 19:38:40 +00:00
Localization.Core.Sense_0_Status_1_Error_2_Length_3,
sense,
errorChs.Status,
errorChs.Error,
readBuf.Length);
2019-12-27 18:00:03 +00:00
2022-03-06 13:29:38 +00:00
mediaTest.ReadDmaLbaData = readBuf;
2021-09-13 18:08:44 +01:00
Spectre.ProgressSingleSpinner(ctx =>
{
ctx.AddTask(Localization.Core.Trying_READ_DMA_RETRY_in_LBA_mode).IsIndeterminate();
2021-09-13 18:08:44 +01:00
sense = _dev.ReadDma(out readBuf, out errorLba, true, 0, 1, _dev.Timeout, out _);
});
2019-12-27 18:00:03 +00:00
mediaTest.SupportsReadDmaRetryLba =
!sense && (errorLba.Status & 0x01) != 0x01 && errorLba.Error == 0 && readBuf.Length > 0;
2019-12-27 18:00:03 +00:00
2025-08-17 06:11:22 +01:00
AaruLogging.Debug(ATA_MODULE_NAME,
2025-11-24 19:38:40 +00:00
Localization.Core.Sense_0_Status_1_Error_2_Length_3,
sense,
errorChs.Status,
errorChs.Error,
readBuf.Length);
2019-12-27 18:00:03 +00:00
2022-03-06 13:29:38 +00:00
mediaTest.ReadDmaRetryLbaData = readBuf;
2021-09-13 18:08:44 +01:00
Spectre.ProgressSingleSpinner(ctx =>
{
ctx.AddTask(Localization.Core.Trying_SEEK_in_LBA_mode).IsIndeterminate();
2021-09-13 18:08:44 +01:00
sense = _dev.Seek(out errorLba, 0, _dev.Timeout, out _);
});
2022-03-06 13:29:38 +00:00
mediaTest.SupportsSeekLba = !sense && (errorLba.Status & 0x01) != 0x01 && errorLba.Error == 0;
2019-12-27 18:00:03 +00:00
2025-08-17 06:11:22 +01:00
AaruLogging.Debug(ATA_MODULE_NAME,
2025-11-24 19:38:40 +00:00
Localization.Core.Sense_0_Status_1_Error_2,
sense,
errorChs.Status,
errorChs.Error);
2021-09-13 18:08:44 +01:00
Spectre.ProgressSingleSpinner(ctx =>
{
ctx.AddTask(Localization.Core.Trying_READ_SECTORS_in_LBA48_mode).IsIndeterminate();
2022-03-17 23:54:41 +00:00
sense = _dev.Read(out readBuf, out AtaErrorRegistersLba28 _, 0, 1, _dev.Timeout, out _);
2021-09-13 18:08:44 +01:00
});
2019-12-27 18:00:03 +00:00
mediaTest.SupportsReadLba48 =
!sense && (errorLba48.Status & 0x01) != 0x01 && errorLba48.Error == 0 && readBuf.Length > 0;
2019-12-27 18:00:03 +00:00
2025-08-17 06:11:22 +01:00
AaruLogging.Debug(ATA_MODULE_NAME,
2025-11-24 19:38:40 +00:00
Localization.Core.Sense_0_Status_1_Error_2_Length_3,
sense,
errorChs.Status,
errorChs.Error,
readBuf.Length);
2019-12-27 18:00:03 +00:00
2022-03-06 13:29:38 +00:00
mediaTest.ReadLba48Data = readBuf;
2021-09-13 18:08:44 +01:00
Spectre.ProgressSingleSpinner(ctx =>
{
ctx.AddTask(Localization.Core.Trying_READ_DMA_in_LBA48_mode).IsIndeterminate();
2021-09-13 18:08:44 +01:00
sense = _dev.ReadDma(out readBuf, out errorLba48, 0, 1, _dev.Timeout, out _);
});
2019-12-27 18:00:03 +00:00
mediaTest.SupportsReadDmaLba48 =
!sense && (errorLba48.Status & 0x01) != 0x01 && errorLba48.Error == 0 && readBuf.Length > 0;
2019-12-27 18:00:03 +00:00
2025-08-17 06:11:22 +01:00
AaruLogging.Debug(ATA_MODULE_NAME,
2025-11-24 19:38:40 +00:00
Localization.Core.Sense_0_Status_1_Error_2_Length_3,
sense,
errorChs.Status,
errorChs.Error,
readBuf.Length);
2019-12-27 18:00:03 +00:00
2022-03-06 13:29:38 +00:00
mediaTest.ReadDmaLba48Data = readBuf;
// Send SET FEATURES before sending READ LONG commands, retrieve IDENTIFY again and
// check if ECC size changed. Sector is set to 1 because without it most drives just return
// CORRECTABLE ERROR for this command.
_dev.SetFeatures(out _, AtaFeatures.EnableReadLongVendorLength, 0, 0, 1, 0, _dev.Timeout, out _);
2022-03-06 13:29:38 +00:00
_dev.AtaIdentify(out buffer, out _, _dev.Timeout, out _);
2019-12-27 18:00:03 +00:00
if(Identify.Decode(buffer).HasValue)
{
ataId = Identify.Decode(buffer).Value;
if(ataId.EccBytes != 0x0000 && ataId.EccBytes != 0xFFFF)
2022-03-06 13:29:38 +00:00
mediaTest.LongBlockSize = logicalSectorSize + ataId.EccBytes;
2019-12-27 18:00:03 +00:00
if(ataId.UnformattedBPS > logicalSectorSize &&
2022-03-06 13:29:38 +00:00
(!(ataId.EccBytes != 0x0000 && ataId.EccBytes != 0xFFFF) || mediaTest.LongBlockSize == 516))
mediaTest.LongBlockSize = ataId.UnformattedBPS;
}
2021-09-13 18:08:44 +01:00
Spectre.ProgressSingleSpinner(ctx =>
{
ctx.AddTask(Localization.Core.Trying_READ_LONG_in_CHS_mode).IsIndeterminate();
2019-12-27 18:00:03 +00:00
2024-05-01 04:05:22 +01:00
sense = _dev.ReadLong(out readBuf,
out errorChs,
false,
0,
0,
1,
mediaTest.LongBlockSize ?? 0,
_dev.Timeout,
out _);
2021-09-13 18:08:44 +01:00
});
2019-12-27 18:00:03 +00:00
mediaTest.SupportsReadLong = !sense &&
(errorChs.Status & 0x01) != 0x01 &&
errorChs.Error == 0 &&
readBuf.Length > 0 &&
BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead;
2019-12-27 18:00:03 +00:00
2025-08-17 06:11:22 +01:00
AaruLogging.Debug(ATA_MODULE_NAME,
2025-11-24 19:38:40 +00:00
Localization.Core.Sense_0_Status_1_Error_2_Length_3,
sense,
errorChs.Status,
errorChs.Error,
readBuf.Length);
2019-12-27 18:00:03 +00:00
2022-03-06 13:29:38 +00:00
mediaTest.ReadLongData = readBuf;
2021-09-13 18:08:44 +01:00
Spectre.ProgressSingleSpinner(ctx =>
{
ctx.AddTask(Localization.Core.Trying_READ_LONG_RETRY_in_CHS_mode).IsIndeterminate();
2019-12-27 18:00:03 +00:00
2024-05-01 04:05:22 +01:00
sense = _dev.ReadLong(out readBuf,
out errorChs,
true,
0,
0,
1,
mediaTest.LongBlockSize ?? 0,
_dev.Timeout,
out _);
2021-09-13 18:08:44 +01:00
});
2019-12-27 18:00:03 +00:00
mediaTest.SupportsReadLongRetry = !sense &&
(errorChs.Status & 0x01) != 0x01 &&
errorChs.Error == 0 &&
readBuf.Length > 0 &&
BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead;
2019-12-27 18:00:03 +00:00
2025-08-17 06:11:22 +01:00
AaruLogging.Debug(ATA_MODULE_NAME,
2025-11-24 19:38:40 +00:00
Localization.Core.Sense_0_Status_1_Error_2_Length_3,
sense,
errorChs.Status,
errorChs.Error,
readBuf.Length);
2019-12-27 18:00:03 +00:00
2022-03-06 13:29:38 +00:00
mediaTest.ReadLongRetryData = readBuf;
2021-09-13 18:08:44 +01:00
Spectre.ProgressSingleSpinner(ctx =>
{
ctx.AddTask(Localization.Core.Trying_READ_LONG_in_LBA_mode).IsIndeterminate();
2019-12-27 18:00:03 +00:00
2024-05-01 04:05:22 +01:00
sense = _dev.ReadLong(out readBuf,
out errorLba,
false,
0,
mediaTest.LongBlockSize ?? 0,
_dev.Timeout,
2022-03-07 07:36:44 +00:00
out _);
2021-09-13 18:08:44 +01:00
});
2019-12-27 18:00:03 +00:00
mediaTest.SupportsReadLongLba = !sense &&
(errorLba.Status & 0x01) != 0x01 &&
errorLba.Error == 0 &&
readBuf.Length > 0 &&
BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead;
2019-12-27 18:00:03 +00:00
2025-08-17 06:11:22 +01:00
AaruLogging.Debug(ATA_MODULE_NAME,
2025-11-24 19:38:40 +00:00
Localization.Core.Sense_0_Status_1_Error_2_Length_3,
sense,
errorChs.Status,
errorChs.Error,
readBuf.Length);
2019-12-27 18:00:03 +00:00
2022-03-06 13:29:38 +00:00
mediaTest.ReadLongLbaData = readBuf;
2021-09-13 18:08:44 +01:00
Spectre.ProgressSingleSpinner(ctx =>
{
ctx.AddTask(Localization.Core.Trying_READ_LONG_RETRY_in_LBA_mode).IsIndeterminate();
2019-12-27 18:00:03 +00:00
2024-05-01 04:05:22 +01:00
sense = _dev.ReadLong(out readBuf,
out errorLba,
true,
0,
mediaTest.LongBlockSize ?? 0,
_dev.Timeout,
2022-03-07 07:36:44 +00:00
out _);
2021-09-13 18:08:44 +01:00
});
2019-12-27 18:00:03 +00:00
mediaTest.SupportsReadLongRetryLba = !sense &&
(errorLba.Status & 0x01) != 0x01 &&
errorLba.Error == 0 &&
readBuf.Length > 0 &&
BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead;
2022-03-06 13:29:38 +00:00
2025-08-17 06:11:22 +01:00
AaruLogging.Debug(ATA_MODULE_NAME,
2025-11-24 19:38:40 +00:00
Localization.Core.Sense_0_Status_1_Error_2_Length_3,
sense,
errorChs.Status,
errorChs.Error,
readBuf.Length);
2022-03-06 13:29:38 +00:00
mediaTest.ReadLongRetryLbaData = readBuf;
}
else
mediaTest.MediaIsRecognized = false;
2019-12-27 18:00:03 +00:00
2022-03-06 13:29:38 +00:00
return mediaTest;
}
2019-12-27 18:00:03 +00:00
2022-03-06 13:29:38 +00:00
/// <summary>Creates a report of an ATA device</summary>
public TestedMedia ReportAta(Identify.IdentifyDevice ataId)
{
2025-11-24 19:38:40 +00:00
var sense = true;
2024-05-01 04:39:38 +01:00
byte[] readBuf = [];
2022-03-06 13:29:38 +00:00
AtaErrorRegistersChs errorChs = new();
AtaErrorRegistersLba28 errorLba = new();
AtaErrorRegistersLba48 errorLba48 = new();
var capabilities = new TestedMedia();
2024-05-01 04:05:22 +01:00
if(ataId.UnformattedBPT != 0) capabilities.UnformattedBPT = ataId.UnformattedBPT;
2022-03-06 13:29:38 +00:00
2024-05-01 04:05:22 +01:00
if(ataId.UnformattedBPS != 0) capabilities.UnformattedBPS = ataId.UnformattedBPS;
2022-03-06 13:29:38 +00:00
if(ataId.Cylinders > 0 && ataId is { Heads: > 0, SectorsPerTrack: > 0 })
2022-03-06 13:29:38 +00:00
{
capabilities.CHS = new Chs
{
Cylinders = ataId.Cylinders,
Heads = ataId.Heads,
Sectors = ataId.SectorsPerTrack
};
2022-03-06 13:29:38 +00:00
capabilities.Blocks = (ulong)(ataId.Cylinders * ataId.Heads * ataId.SectorsPerTrack);
}
2018-12-25 14:46:02 +00:00
if(ataId.CurrentCylinders > 0 && ataId is { CurrentHeads: > 0, CurrentSectorsPerTrack: > 0 })
2018-12-25 14:46:02 +00:00
{
2022-03-06 13:29:38 +00:00
capabilities.CurrentCHS = new Chs
{
Cylinders = ataId.CurrentCylinders,
Heads = ataId.CurrentHeads,
Sectors = ataId.CurrentSectorsPerTrack
};
2018-12-25 14:46:02 +00:00
2022-03-07 07:36:44 +00:00
capabilities.Blocks = (ulong)(ataId.CurrentCylinders * ataId.CurrentHeads * ataId.CurrentSectorsPerTrack);
2022-03-06 13:29:38 +00:00
}
2018-12-25 14:46:02 +00:00
2022-03-06 13:29:38 +00:00
if(ataId.Capabilities.HasFlag(Identify.CapabilitiesBit.LBASupport))
{
capabilities.LBASectors = ataId.LBASectors;
capabilities.Blocks = ataId.LBASectors;
2018-12-25 14:46:02 +00:00
}
2022-03-06 13:29:38 +00:00
if(ataId.CommandSet2.HasFlag(Identify.CommandSetBit2.LBA48))
{
capabilities.LBA48Sectors = ataId.LBA48Sectors;
capabilities.Blocks = ataId.LBA48Sectors;
}
if(ataId.NominalRotationRate != 0x0000 && ataId.NominalRotationRate != 0xFFFF)
2023-10-03 22:57:50 +01:00
{
2022-03-06 13:29:38 +00:00
if(ataId.NominalRotationRate == 0x0001)
capabilities.SolidStateDevice = true;
else
{
capabilities.SolidStateDevice = false;
capabilities.NominalRotationRate = ataId.NominalRotationRate;
}
2023-10-03 22:57:50 +01:00
}
2022-03-06 13:29:38 +00:00
uint logicalSectorSize;
uint physicalSectorSize;
if((ataId.PhysLogSectorSize & 0x8000) == 0x0000 && (ataId.PhysLogSectorSize & 0x4000) == 0x4000)
2022-03-06 13:29:38 +00:00
{
if((ataId.PhysLogSectorSize & 0x1000) == 0x1000)
2023-10-03 22:57:50 +01:00
{
if(ataId.LogicalSectorWords <= 255 || ataId.LogicalAlignment == 0xFFFF)
2022-03-06 13:29:38 +00:00
logicalSectorSize = 512;
else
logicalSectorSize = ataId.LogicalSectorWords * 2;
2023-10-03 22:57:50 +01:00
}
2022-03-06 13:29:38 +00:00
else
logicalSectorSize = 512;
if((ataId.PhysLogSectorSize & 0x2000) == 0x2000)
physicalSectorSize = logicalSectorSize * (uint)Math.Pow(2, ataId.PhysLogSectorSize & 0xF);
else
physicalSectorSize = logicalSectorSize;
}
else
{
logicalSectorSize = 512;
physicalSectorSize = 512;
}
capabilities.BlockSize = logicalSectorSize;
if(physicalSectorSize != logicalSectorSize)
{
capabilities.PhysicalBlockSize = physicalSectorSize;
if((ataId.LogicalAlignment & 0x8000) == 0x0000 && (ataId.LogicalAlignment & 0x4000) == 0x4000)
2022-03-06 13:29:38 +00:00
capabilities.LogicalAlignment = (ushort)(ataId.LogicalAlignment & 0x3FFF);
}
if(ataId.EccBytes != 0x0000 && ataId.EccBytes != 0xFFFF)
2022-03-06 13:29:38 +00:00
capabilities.LongBlockSize = logicalSectorSize + ataId.EccBytes;
if(ataId.UnformattedBPS > logicalSectorSize &&
(!(ataId.EccBytes != 0x0000 && ataId.EccBytes != 0xFFFF) || capabilities.LongBlockSize == 516))
capabilities.LongBlockSize = ataId.UnformattedBPS;
if(ataId.CommandSet3.HasFlag(Identify.CommandSetBit3.MustBeSet) &&
!ataId.CommandSet3.HasFlag(Identify.CommandSetBit3.MustBeClear) &&
ataId.EnabledCommandSet3.HasFlag(Identify.CommandSetBit3.MediaSerial))
{
capabilities.CanReadMediaSerial = true;
2024-05-01 04:05:22 +01:00
if(!string.IsNullOrWhiteSpace(ataId.MediaManufacturer)) capabilities.Manufacturer = ataId.MediaManufacturer;
2022-03-06 13:29:38 +00:00
}
const ulong checkCorrectRead = 0;
2022-03-06 13:29:38 +00:00
Spectre.ProgressSingleSpinner(ctx =>
{
ctx.AddTask(Localization.Core.Trying_READ_SECTORS_in_CHS_mode).IsIndeterminate();
2022-03-06 13:29:38 +00:00
sense = _dev.Read(out readBuf, out errorChs, false, 0, 0, 1, 1, _dev.Timeout, out _);
});
capabilities.SupportsReadSectors =
!sense && (errorChs.Status & 0x01) != 0x01 && errorChs.Error == 0 && readBuf.Length > 0;
2022-03-06 13:29:38 +00:00
2025-08-17 06:11:22 +01:00
AaruLogging.Debug(ATA_MODULE_NAME,
2025-11-24 19:38:40 +00:00
Localization.Core.Sense_0_Status_1_Error_2_Length_3,
sense,
errorChs.Status,
errorChs.Error,
readBuf.Length);
2022-03-06 13:29:38 +00:00
capabilities.ReadSectorsData = readBuf;
Spectre.ProgressSingleSpinner(ctx =>
{
ctx.AddTask(Localization.Core.Trying_READ_SECTORS_RETRY_in_CHS_mode).IsIndeterminate();
2022-03-06 13:29:38 +00:00
sense = _dev.Read(out readBuf, out errorChs, true, 0, 0, 1, 1, _dev.Timeout, out _);
});
capabilities.SupportsReadRetry =
!sense && (errorChs.Status & 0x01) != 0x01 && errorChs.Error == 0 && readBuf.Length > 0;
2025-08-17 06:11:22 +01:00
AaruLogging.Debug(ATA_MODULE_NAME,
2025-11-24 19:38:40 +00:00
Localization.Core.Sense_0_Status_1_Error_2_Length_3,
sense,
errorChs.Status,
errorChs.Error,
readBuf.Length);
2022-03-06 13:29:38 +00:00
capabilities.ReadSectorsRetryData = readBuf;
Spectre.ProgressSingleSpinner(ctx =>
{
ctx.AddTask(Localization.Core.Trying_READ_DMA_in_CHS_mode).IsIndeterminate();
2022-03-06 13:29:38 +00:00
sense = _dev.ReadDma(out readBuf, out errorChs, false, 0, 0, 1, 1, _dev.Timeout, out _);
});
capabilities.SupportsReadDma =
!sense && (errorChs.Status & 0x01) != 0x01 && errorChs.Error == 0 && readBuf.Length > 0;
2025-08-17 06:11:22 +01:00
AaruLogging.Debug(ATA_MODULE_NAME,
2025-11-24 19:38:40 +00:00
Localization.Core.Sense_0_Status_1_Error_2_Length_3,
sense,
errorChs.Status,
errorChs.Error,
readBuf.Length);
2022-03-06 13:29:38 +00:00
capabilities.ReadDmaData = readBuf;
Spectre.ProgressSingleSpinner(ctx =>
{
ctx.AddTask(Localization.Core.Trying_READ_DMA_RETRY_in_CHS_mode).IsIndeterminate();
2022-03-06 13:29:38 +00:00
sense = _dev.ReadDma(out readBuf, out errorChs, true, 0, 0, 1, 1, _dev.Timeout, out _);
});
capabilities.SupportsReadDmaRetry =
!sense && (errorChs.Status & 0x01) != 0x01 && errorChs.Error == 0 && readBuf.Length > 0;
2022-03-06 13:29:38 +00:00
2025-08-17 06:11:22 +01:00
AaruLogging.Debug(ATA_MODULE_NAME,
2025-11-24 19:38:40 +00:00
Localization.Core.Sense_0_Status_1_Error_2_Length_3,
sense,
errorChs.Status,
errorChs.Error,
readBuf.Length);
2022-03-06 13:29:38 +00:00
capabilities.ReadDmaRetryData = readBuf;
Spectre.ProgressSingleSpinner(ctx =>
{
ctx.AddTask(Localization.Core.Trying_SEEK_in_CHS_mode).IsIndeterminate();
2022-03-06 13:29:38 +00:00
sense = _dev.Seek(out errorChs, 0, 0, 1, _dev.Timeout, out _);
});
capabilities.SupportsSeek = !sense && (errorChs.Status & 0x01) != 0x01 && errorChs.Error == 0;
2025-08-17 06:11:22 +01:00
AaruLogging.Debug(ATA_MODULE_NAME,
2025-11-24 19:38:40 +00:00
Localization.Core.Sense_0_Status_1_Error_2,
sense,
errorChs.Status,
errorChs.Error);
2022-03-06 13:29:38 +00:00
Spectre.ProgressSingleSpinner(ctx =>
{
ctx.AddTask(Localization.Core.Trying_READ_SECTORS_in_LBA_mode).IsIndeterminate();
2022-03-06 13:29:38 +00:00
sense = _dev.Read(out readBuf, out errorLba, false, 0, 1, _dev.Timeout, out _);
});
capabilities.SupportsReadLba =
!sense && (errorLba.Status & 0x01) != 0x01 && errorLba.Error == 0 && readBuf.Length > 0;
2025-08-17 06:11:22 +01:00
AaruLogging.Debug(ATA_MODULE_NAME,
2025-11-24 19:38:40 +00:00
Localization.Core.Sense_0_Status_1_Error_2_Length_3,
sense,
errorLba.Status,
errorLba.Error,
readBuf.Length);
2022-03-06 13:29:38 +00:00
capabilities.ReadLbaData = readBuf;
Spectre.ProgressSingleSpinner(ctx =>
{
ctx.AddTask(Localization.Core.Trying_READ_SECTORS_RETRY_in_LBA_mode).IsIndeterminate();
2022-03-06 13:29:38 +00:00
sense = _dev.Read(out readBuf, out errorLba, true, 0, 1, _dev.Timeout, out _);
});
capabilities.SupportsReadRetryLba =
!sense && (errorLba.Status & 0x01) != 0x01 && errorLba.Error == 0 && readBuf.Length > 0;
2022-03-06 13:29:38 +00:00
2025-08-17 06:11:22 +01:00
AaruLogging.Debug(ATA_MODULE_NAME,
2025-11-24 19:38:40 +00:00
Localization.Core.Sense_0_Status_1_Error_2_Length_3,
sense,
errorLba.Status,
errorLba.Error,
readBuf.Length);
2022-03-06 13:29:38 +00:00
capabilities.ReadRetryLbaData = readBuf;
Spectre.ProgressSingleSpinner(ctx =>
{
ctx.AddTask(Localization.Core.Trying_READ_DMA_in_LBA_mode).IsIndeterminate();
2022-03-06 13:29:38 +00:00
sense = _dev.ReadDma(out readBuf, out errorLba, false, 0, 1, _dev.Timeout, out _);
});
capabilities.SupportsReadDmaLba =
!sense && (errorLba.Status & 0x01) != 0x01 && errorLba.Error == 0 && readBuf.Length > 0;
2022-03-06 13:29:38 +00:00
2025-08-17 06:11:22 +01:00
AaruLogging.Debug(ATA_MODULE_NAME,
2025-11-24 19:38:40 +00:00
Localization.Core.Sense_0_Status_1_Error_2_Length_3,
sense,
errorLba.Status,
errorLba.Error,
readBuf.Length);
2022-03-06 13:29:38 +00:00
capabilities.ReadDmaLbaData = readBuf;
Spectre.ProgressSingleSpinner(ctx =>
{
ctx.AddTask(Localization.Core.Trying_READ_DMA_RETRY_in_LBA_mode).IsIndeterminate();
2022-03-06 13:29:38 +00:00
sense = _dev.ReadDma(out readBuf, out errorLba, true, 0, 1, _dev.Timeout, out _);
});
capabilities.SupportsReadDmaRetryLba =
!sense && (errorLba.Status & 0x01) != 0x01 && errorLba.Error == 0 && readBuf.Length > 0;
2025-08-17 06:11:22 +01:00
AaruLogging.Debug(ATA_MODULE_NAME,
2025-11-24 19:38:40 +00:00
Localization.Core.Sense_0_Status_1_Error_2_Length_3,
sense,
errorLba.Status,
errorLba.Error,
readBuf.Length);
2022-03-06 13:29:38 +00:00
capabilities.ReadDmaRetryLbaData = readBuf;
Spectre.ProgressSingleSpinner(ctx =>
{
ctx.AddTask(Localization.Core.Trying_SEEK_in_LBA_mode).IsIndeterminate();
2022-03-06 13:29:38 +00:00
sense = _dev.Seek(out errorLba, 0, _dev.Timeout, out _);
});
capabilities.SupportsSeekLba = !sense && (errorLba.Status & 0x01) != 0x01 && errorLba.Error == 0;
2025-08-17 06:11:22 +01:00
AaruLogging.Debug(ATA_MODULE_NAME,
2025-11-24 19:38:40 +00:00
Localization.Core.Sense_0_Status_1_Error_2,
sense,
errorLba.Status,
errorLba.Error);
2022-03-06 13:29:38 +00:00
Spectre.ProgressSingleSpinner(ctx =>
{
ctx.AddTask(Localization.Core.Trying_READ_SECTORS_in_LBA48_mode).IsIndeterminate();
2022-03-06 13:29:38 +00:00
sense = _dev.Read(out readBuf, out errorLba48, 0, 1, _dev.Timeout, out _);
});
capabilities.SupportsReadLba48 =
!sense && (errorLba48.Status & 0x01) != 0x01 && errorLba48.Error == 0 && readBuf.Length > 0;
2022-03-06 13:29:38 +00:00
2025-08-17 06:11:22 +01:00
AaruLogging.Debug(ATA_MODULE_NAME,
2025-11-24 19:38:40 +00:00
Localization.Core.Sense_0_Status_1_Error_2_Length_3,
sense,
errorLba48.Status,
errorLba48.Error,
readBuf.Length);
2022-03-06 13:29:38 +00:00
capabilities.ReadLba48Data = readBuf;
Spectre.ProgressSingleSpinner(ctx =>
{
ctx.AddTask(Localization.Core.Trying_READ_DMA_in_LBA48_mode).IsIndeterminate();
2022-03-06 13:29:38 +00:00
sense = _dev.ReadDma(out readBuf, out errorLba48, 0, 1, _dev.Timeout, out _);
});
capabilities.SupportsReadDmaLba48 =
!sense && (errorLba48.Status & 0x01) != 0x01 && errorLba48.Error == 0 && readBuf.Length > 0;
2022-03-06 13:29:38 +00:00
2025-08-17 06:11:22 +01:00
AaruLogging.Debug(ATA_MODULE_NAME,
2025-11-24 19:38:40 +00:00
Localization.Core.Sense_0_Status_1_Error_2_Length_3,
sense,
errorLba48.Status,
errorLba48.Error,
readBuf.Length);
2022-03-06 13:29:38 +00:00
capabilities.ReadDmaLba48Data = readBuf;
// Send SET FEATURES before sending READ LONG commands, retrieve IDENTIFY again and
// check if ECC size changed. Sector is set to 1 because without it most drives just return
// CORRECTABLE ERROR for this command.
_dev.SetFeatures(out _, AtaFeatures.EnableReadLongVendorLength, 0, 0, 1, 0, _dev.Timeout, out _);
_dev.AtaIdentify(out byte[] buffer, out _, _dev.Timeout, out _);
if(Identify.Decode(buffer).HasValue)
{
ataId = Identify.Decode(buffer).Value;
if(ataId.EccBytes != 0x0000 && ataId.EccBytes != 0xFFFF)
2022-03-06 13:29:38 +00:00
capabilities.LongBlockSize = logicalSectorSize + ataId.EccBytes;
if(ataId.UnformattedBPS > logicalSectorSize &&
(!(ataId.EccBytes != 0x0000 && ataId.EccBytes != 0xFFFF) || capabilities.LongBlockSize == 516))
capabilities.LongBlockSize = ataId.UnformattedBPS;
}
Spectre.ProgressSingleSpinner(ctx =>
{
ctx.AddTask(Localization.Core.Trying_READ_LONG_in_CHS_mode).IsIndeterminate();
2022-03-06 13:29:38 +00:00
2024-05-01 04:05:22 +01:00
sense = _dev.ReadLong(out readBuf,
out errorChs,
false,
0,
0,
1,
capabilities.LongBlockSize ?? 0,
_dev.Timeout,
out _);
2022-03-06 13:29:38 +00:00
});
capabilities.SupportsReadLong = !sense &&
(errorChs.Status & 0x01) != 0x01 &&
errorChs.Error == 0 &&
readBuf.Length > 0 &&
BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead;
2022-03-06 13:29:38 +00:00
2025-08-17 06:11:22 +01:00
AaruLogging.Debug(ATA_MODULE_NAME,
2025-11-24 19:38:40 +00:00
Localization.Core.Sense_0_Status_1_Error_2_Length_3,
sense,
errorChs.Status,
errorChs.Error,
readBuf.Length);
2022-03-06 13:29:38 +00:00
capabilities.ReadLongData = readBuf;
Spectre.ProgressSingleSpinner(ctx =>
{
ctx.AddTask(Localization.Core.Trying_READ_LONG_RETRY_in_CHS_mode).IsIndeterminate();
2022-03-06 13:29:38 +00:00
2024-05-01 04:05:22 +01:00
sense = _dev.ReadLong(out readBuf,
out errorChs,
true,
0,
0,
1,
capabilities.LongBlockSize ?? 0,
_dev.Timeout,
out _);
2022-03-06 13:29:38 +00:00
});
capabilities.SupportsReadLongRetry = !sense &&
(errorChs.Status & 0x01) != 0x01 &&
errorChs.Error == 0 &&
readBuf.Length > 0 &&
BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead;
2022-03-06 13:29:38 +00:00
2025-08-17 06:11:22 +01:00
AaruLogging.Debug(ATA_MODULE_NAME,
2025-11-24 19:38:40 +00:00
Localization.Core.Sense_0_Status_1_Error_2_Length_3,
sense,
errorChs.Status,
errorChs.Error,
readBuf.Length);
2022-03-06 13:29:38 +00:00
capabilities.ReadLongRetryData = readBuf;
Spectre.ProgressSingleSpinner(ctx =>
{
ctx.AddTask(Localization.Core.Trying_READ_LONG_in_LBA_mode).IsIndeterminate();
2022-03-06 13:29:38 +00:00
2024-05-01 04:05:22 +01:00
sense = _dev.ReadLong(out readBuf,
out errorLba,
false,
0,
capabilities.LongBlockSize ?? 0,
_dev.Timeout,
2022-03-07 07:36:44 +00:00
out _);
2022-03-06 13:29:38 +00:00
});
capabilities.SupportsReadLongLba = !sense &&
(errorLba.Status & 0x01) != 0x01 &&
errorLba.Error == 0 &&
readBuf.Length > 0 &&
BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead;
2022-03-06 13:29:38 +00:00
2025-08-17 06:11:22 +01:00
AaruLogging.Debug(ATA_MODULE_NAME,
2025-11-24 19:38:40 +00:00
Localization.Core.Sense_0_Status_1_Error_2_Length_3,
sense,
errorLba.Status,
errorLba.Error,
readBuf.Length);
2022-03-06 13:29:38 +00:00
capabilities.ReadLongLbaData = readBuf;
Spectre.ProgressSingleSpinner(ctx =>
{
ctx.AddTask(Localization.Core.Trying_READ_LONG_RETRY_in_LBA_mode).IsIndeterminate();
2022-03-06 13:29:38 +00:00
2024-05-01 04:05:22 +01:00
sense = _dev.ReadLong(out readBuf,
out errorLba,
true,
0,
capabilities.LongBlockSize ?? 0,
_dev.Timeout,
2022-03-06 13:29:38 +00:00
out _);
});
capabilities.SupportsReadLongRetryLba = !sense &&
(errorLba.Status & 0x01) != 0x01 &&
errorLba.Error == 0 &&
readBuf.Length > 0 &&
BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead;
2022-03-06 13:29:38 +00:00
2025-08-17 06:11:22 +01:00
AaruLogging.Debug(ATA_MODULE_NAME,
2025-11-24 19:38:40 +00:00
Localization.Core.Sense_0_Status_1_Error_2_Length_3,
sense,
errorLba.Status,
errorLba.Error,
readBuf.Length);
2022-03-06 13:29:38 +00:00
capabilities.ReadLongRetryLbaData = readBuf;
return capabilities;
}
/// <summary>Clear serial numbers and other private fields from an IDENTIFY ATA DEVICE response</summary>
/// <param name="buffer">IDENTIFY ATA DEVICE response</param>
/// <returns>IDENTIFY ATA DEVICE response without the private fields</returns>
public static byte[] ClearIdentify(byte[] buffer)
{
2025-11-24 19:38:40 +00:00
var empty = new byte[512];
2022-03-06 13:29:38 +00:00
2023-10-03 22:57:50 +01:00
Array.Copy(empty, 0, buffer, 20, 20);
2022-03-06 13:29:38 +00:00
Array.Copy(empty, 0, buffer, 216, 8);
Array.Copy(empty, 0, buffer, 224, 8);
Array.Copy(empty, 0, buffer, 352, 40);
return buffer;
}
2017-12-19 20:33:03 +00:00
}