diff --git a/Aaru.Server.New/Components/Pages/Report/View.razor b/Aaru.Server.New/Components/Pages/Report/View.razor
index 5a2c92e6..0e6983af 100644
--- a/Aaru.Server.New/Components/Pages/Report/View.razor
+++ b/Aaru.Server.New/Components/Pages/Report/View.razor
@@ -35,7 +35,7 @@
- @lblDeviceType
+ @DeviceType
@if(UsbItem is not null)
@@ -835,4 +835,45 @@
}
-
\ No newline at end of file
+
+
+@if(MediaInformation?.Count > 0)
+{
+
+
+ Tested media information
+
+
+
+ @foreach(KeyValuePair Table, List List)> mediaInfo in MediaInformation)
+ {
+
+
+
+ @mediaInfo.Key
+
+
+
+
+
+ @foreach(KeyValuePair kvp in mediaInfo.Value.Table)
+ {
+
+ @kvp.Key
+ @kvp.Value
+
+ }
+
+
+
+ @foreach(string cap in mediaInfo.Value.List)
+ {
+ @cap
+ }
+
+
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/Aaru.Server.New/Components/Pages/Report/View.razor.cs b/Aaru.Server.New/Components/Pages/Report/View.razor.cs
index 00b70d26..a8f09d22 100644
--- a/Aaru.Server.New/Components/Pages/Report/View.razor.cs
+++ b/Aaru.Server.New/Components/Pages/Report/View.razor.cs
@@ -10,6 +10,7 @@ using Microsoft.EntityFrameworkCore;
using Ata = Aaru.CommonTypes.Metadata.Ata;
using DbContext = Aaru.Server.Database.DbContext;
using Inquiry = Aaru.CommonTypes.Structs.Devices.SCSI.Inquiry;
+using TestedMedia = Aaru.CommonTypes.Metadata.TestedMedia;
using Tuple = Aaru.Decoders.PCMCIA.Tuple;
namespace Aaru.Server.New.Components.Pages.Report;
@@ -18,7 +19,6 @@ public partial class View
{
bool _initialized;
bool _notFound;
- bool accordionItem1Visible;
string _pageTitle { get; set; } = "Aaru Device Report";
[CascadingParameter]
HttpContext HttpContext { get; set; } = default!;
@@ -28,7 +28,7 @@ public partial class View
public Item? FireWireItem { get; set; }
public Dictionary? PcmciaTuples { get; set; }
public PcmciaItem? PcmciaItem { get; set; }
- public string? lblDeviceType { get; set; }
+ public string? DeviceType { get; set; }
public string? AtaItem { get; set; }
public string? MaximumAtaRevision { get; set; }
public List? SupportedAtaVersions { get; set; }
@@ -58,16 +58,18 @@ public partial class View
public List? InquiryCapabilities { get; set; }
public List? ModeSenseCapabilities { get; set; }
public Dictionary>? ModeSensePages { get; set; }
- public List? BlockDescriptors { get; set; }
- public List? ScsiSscMedias { get; set; }
- public List? ScsiSscDensities { get; set; }
- public string? ScsiSscMinBlock { get; set; }
- public string? ScsiSscMaxBlock { get; set; }
- public string? ScsiSscGranularity { get; set; }
- public bool ScsiSscVisible { get; set; }
- public List? MmcFeaturesList { get; set; }
- public List? MmcModeList { get; set; }
- public Dictionary>? EvpdPages { get; set; }
+ public List? BlockDescriptors { get; set; }
+ public List? ScsiSscMedias { get; set; }
+ public List? ScsiSscDensities { get; set; }
+ public string? ScsiSscMinBlock { get; set; }
+ public string? ScsiSscMaxBlock { get; set; }
+ public string? ScsiSscGranularity { get; set; }
+ public bool ScsiSscVisible { get; set; }
+ public List? MmcFeaturesList { get; set; }
+ public List? MmcModeList { get; set; }
+ public Dictionary>? EvpdPages { get; set; }
+
+ public Dictionary Table, List List)>? MediaInformation { get; set; }
///
protected override async Task OnInitializedAsync()
@@ -112,6 +114,14 @@ public partial class View
.ThenInclude(static ssc => ssc.SupportedMediaTypes)
.Include(static deviceReportV2 => deviceReportV2.SCSI)
.ThenInclude(static scsi => scsi.ReadCapabilities)
+ .Include(static deviceReportV2 => deviceReportV2.SCSI)
+ .ThenInclude(static scsi => scsi.SequentialDevice)
+ .ThenInclude(static ssc => ssc.TestedMedia)
+ .Include(static deviceReportV2 => deviceReportV2.SCSI)
+ .ThenInclude(static scsi => scsi.RemovableMedias)
+ .Include(static deviceReportV2 => deviceReportV2.SCSI)
+ .ThenInclude(static scsi => scsi.MultiMediaDevice)
+ .ThenInclude(static mmc => mmc.TestedMedia)
.FirstOrDefaultAsync(d => d.Id == Id);
if(report is null)
@@ -269,9 +279,10 @@ public partial class View
}
}
- var removable = true;
- List? testedMedia;
- var atapi = false;
+ var removable = true;
+ List? testedMedia = null;
+ var atapi = false;
+ var sscMedia = false;
if(report.ATA != null || report.ATAPI != null)
{
@@ -291,12 +302,12 @@ public partial class View
bool cfa = report.CompactFlash;
- lblDeviceType = atapi switch
- {
- true when !cfa => "ATAPI device",
- false when cfa => "CompactFlash device",
- _ => "ATA device"
- };
+ DeviceType = atapi switch
+ {
+ true when !cfa => "ATAPI device",
+ false when cfa => "CompactFlash device",
+ _ => "ATA device"
+ };
Core.Ata.Report(ataReport!,
cfa,
@@ -346,7 +357,7 @@ public partial class View
if(report.MultiMediaCard != null)
{
- lblDeviceType = "MultiMediaCard";
+ DeviceType = "MultiMediaCard";
if(report.MultiMediaCard.CID != null)
Cid = Decoders.MMC.Decoders.PrettifyCID(report.MultiMediaCard.CID).Replace("\n", "
");
@@ -366,7 +377,7 @@ public partial class View
if(report.SecureDigital != null)
{
- lblDeviceType = "SecureDigital";
+ DeviceType = "SecureDigital";
if(report.SecureDigital.CID != null)
Cid = Decoders.SecureDigital.Decoders.PrettifyCID(report.SecureDigital.CID).Replace("\n", "
");
@@ -381,6 +392,7 @@ public partial class View
Ocr = Decoders.SecureDigital.Decoders.PrettifyCSD(report.SecureDigital.OCR).Replace("\n", "
");
}
+
if(report.SCSI != null)
{
var vendorId = "";
@@ -388,16 +400,23 @@ public partial class View
if(report.SCSI.Inquiry != null)
{
Inquiry inq = report.SCSI.Inquiry.Value;
- vendorId = StringHandlers.CToString(report.SCSI.Inquiry?.VendorIdentification);
- DeviceInquiry = new Dictionary();
+ vendorId = StringHandlers.CToString(report.SCSI.Inquiry?.VendorIdentification);
- DeviceInquiry.Add("Vendor:",
- VendorString.Prettify(vendorId) != vendorId
- ? $"{vendorId} ({VendorString.Prettify(vendorId)})"
- : vendorId);
-
- DeviceInquiry.Add("Product:", StringHandlers.CToString(inq.ProductIdentification));
- DeviceInquiry.Add("Revision:", StringHandlers.CToString(inq.ProductRevisionLevel));
+ DeviceInquiry = new Dictionary
+ {
+ {
+ "Vendor:",
+ VendorString.Prettify(vendorId) != vendorId
+ ? $"{vendorId} ({VendorString.Prettify(vendorId)})"
+ : vendorId
+ },
+ {
+ "Product:", StringHandlers.CToString(inq.ProductIdentification)
+ },
+ {
+ "Revision:", StringHandlers.CToString(inq.ProductRevisionLevel)
+ }
+ };
}
List inquiryCapabilities = ScsiInquiry.Report(report.SCSI.Inquiry);
@@ -439,7 +458,7 @@ public partial class View
if(modeSenseCapabilities is not null)
{
- ModeSenseCapabilities ??= new List();
+ ModeSenseCapabilities ??= [];
ModeSenseCapabilities.AddRange(modeSenseCapabilities);
}
@@ -455,7 +474,7 @@ public partial class View
if(report.SCSI.MultiMediaDevice is not null)
{
- // testedMedia = report.SCSI.MultiMediaDevice.TestedMedia;
+ testedMedia = report.SCSI.MultiMediaDevice.TestedMedia;
if(report.SCSI.MultiMediaDevice.ModeSense2A != null)
{
@@ -487,20 +506,20 @@ public partial class View
if(report.SCSI.SequentialDevice.SupportedMediaTypes != null)
ScsiSscMedias = report.SCSI.SequentialDevice.SupportedMediaTypes;
-/* if(report.SCSI.SequentialDevice.TestedMedia != null)
- {
- List mediaOneValue = new();
- SscTestedMedia.Report(report.SCSI.SequentialDevice.TestedMedia, ref mediaOneValue);
+ if(report.SCSI.SequentialDevice.TestedMedia != null)
+ {
+ sscMedia = true;
- if(mediaOneValue.Count > 0)
- {
- sscMedia = true;
- ViewBag.repTestedMedia = mediaOneValue;
- }
- }*/
+ SscTestedMedia.Report(report.SCSI.SequentialDevice.TestedMedia,
+ out Dictionary Table, List List)>
+ mediaInformation);
+
+ if(mediaInformation.Count > 0) MediaInformation = mediaInformation;
+ }
}
else if(report.SCSI.ReadCapabilities != null)
{
+ removable = false;
List readCapabilitiesList = [];
var readCapabilitiesDictionary = new Dictionary();
@@ -530,8 +549,10 @@ public partial class View
}
if(report.SCSI.ReadCapabilities.MediumType.HasValue)
+ {
readCapabilitiesDictionary.Add("Medium type code",
$"{report.SCSI.ReadCapabilities.MediumType:X2}h");
+ }
if(report.SCSI.ReadCapabilities.Density.HasValue)
readCapabilitiesDictionary.Add("Density code", $"{report.SCSI.ReadCapabilities.Density:X2}h");
@@ -539,8 +560,10 @@ public partial class View
if((report.SCSI.ReadCapabilities.SupportsReadLong == true ||
report.SCSI.ReadCapabilities.SupportsReadLong16 == true) &&
report.SCSI.ReadCapabilities.LongBlockSize.HasValue)
+ {
readCapabilitiesDictionary.Add("Long block size",
$"{report.SCSI.ReadCapabilities.LongBlockSize} bytes");
+ }
if(report.SCSI.ReadCapabilities.SupportsReadCapacity == true)
readCapabilitiesList.Add("Device supports READ CAPACITY (10) command.");
@@ -569,9 +592,17 @@ public partial class View
if(readCapabilitiesList.Count > 0) ReadCapabilitiesList = readCapabilitiesList;
if(readCapabilitiesDictionary.Count > 0) ReadCapabilitiesDictionary = readCapabilitiesDictionary;
}
- /* else
- testedMedia = report.SCSI.RemovableMedias;
- */
+ else
+ testedMedia = report.SCSI.RemovableMedias;
+ }
+
+ if(removable && !sscMedia && testedMedia != null)
+ {
+ Core.TestedMedia.Report(testedMedia,
+ out Dictionary Table, List List)>
+ mediaInformation);
+
+ if(mediaInformation.Count > 0) MediaInformation = mediaInformation;
}
_initialized = true;
diff --git a/Aaru.Server.New/Core/Ata.cs b/Aaru.Server.New/Core/Ata.cs
index e8a18d84..4e361e4f 100644
--- a/Aaru.Server.New/Core/Ata.cs
+++ b/Aaru.Server.New/Core/Ata.cs
@@ -30,7 +30,6 @@
// Copyright © 2011-2024 Natalia Portillo
// ****************************************************************************/
-using Aaru.CommonTypes.Metadata;
using Aaru.CommonTypes.Structs.Devices.ATA;
using Aaru.CommonTypes.Structs.Devices.SCSI;
@@ -68,7 +67,8 @@ public static class Ata
/// Dictionary of read capabilities for non-removable media
/// List of read capabilities for non-removable media
public static void Report(CommonTypes.Metadata.Ata ataReport, bool cfa, bool atapi, ref bool removable,
- out List? testedMedia, out Dictionary? deviceIdentification,
+ out List? testedMedia,
+ out Dictionary? deviceIdentification,
out List supportedAtaVersions, out string? maximumAtaRevision,
out string? transport, out List? transportVersions,
out List generalConfiguration, out List? specificConfiguration,
@@ -1672,12 +1672,14 @@ public static class Ata
!ataIdentify.CommandSet3.HasFlag(Identify.CommandSetBit3.MustBeClear) &&
ataIdentify.CommandSet3.HasFlag(Identify.CommandSetBit3.Streaming))
{
- streaming = [];
- streaming.Add($"Minimum request size is {ataIdentify.StreamMinReqSize}");
- streaming.Add($"Streaming transfer time in PIO is {ataIdentify.StreamTransferTimePIO}");
- streaming.Add($"Streaming transfer time in DMA is {ataIdentify.StreamTransferTimeDMA}");
- streaming.Add($"Streaming access latency is {ataIdentify.StreamAccessLatency}");
- streaming.Add($"Streaming performance granularity is {ataIdentify.StreamPerformanceGranularity}");
+ streaming =
+ [
+ $"Minimum request size is {ataIdentify.StreamMinReqSize}",
+ $"Streaming transfer time in PIO is {ataIdentify.StreamTransferTimePIO}",
+ $"Streaming transfer time in DMA is {ataIdentify.StreamTransferTimeDMA}",
+ $"Streaming access latency is {ataIdentify.StreamAccessLatency}",
+ $"Streaming performance granularity is {ataIdentify.StreamPerformanceGranularity}"
+ ];
}
if(ataIdentify.SCTCommandTransport.HasFlag(Identify.SCTCommandTransportBit.Supported))
@@ -1702,8 +1704,7 @@ public static class Ata
if((ataIdentify.NVCacheCaps & 0x0010) == 0x0010)
{
- nvCache = [];
- nvCache.Add($"Version {(ataIdentify.NVCacheCaps & 0xF000) >> 12}");
+ nvCache = [$"Version {(ataIdentify.NVCacheCaps & 0xF000) >> 12}"];
if((ataIdentify.NVCacheCaps & 0x0001) == 0x0001)
{
@@ -1741,12 +1742,16 @@ public static class Ata
}
if(ataReport.ReadCapabilities.PhysicalBlockSize != null)
+ {
readCapabilitiesDictionary.Add("Physical sector size",
$"{ataReport.ReadCapabilities.PhysicalBlockSize} bytes");
+ }
if(ataReport.ReadCapabilities.LongBlockSize != null)
+ {
readCapabilitiesDictionary.Add("READ LONG sector size",
$"{ataReport.ReadCapabilities.LongBlockSize} bytes");
+ }
if(ataReport.ReadCapabilities.BlockSize != null &&
ataReport.ReadCapabilities.PhysicalBlockSize != null &&
@@ -1847,12 +1852,16 @@ public static class Ata
if(ata1 || cfa)
{
if(ataReport.ReadCapabilities.UnformattedBPT > 0)
+ {
readCapabilitiesDictionary.Add("Bytes per unformatted track",
$"{ataReport.ReadCapabilities.UnformattedBPT}");
+ }
if(ataReport.ReadCapabilities.UnformattedBPS > 0)
+ {
readCapabilitiesDictionary.Add("Bytes per unformatted sector",
$"{ataReport.ReadCapabilities.UnformattedBPS}");
+ }
}
}
diff --git a/Aaru.Server.New/Core/ScsiInquiry.cs b/Aaru.Server.New/Core/ScsiInquiry.cs
index 0a16c4a3..1f8d29ff 100644
--- a/Aaru.Server.New/Core/ScsiInquiry.cs
+++ b/Aaru.Server.New/Core/ScsiInquiry.cs
@@ -44,7 +44,7 @@ static class ScsiInquiry
/// List of values
internal static List Report(Inquiry? inquiryNullable)
{
- List scsiOneValue = new();
+ List scsiOneValue = [];
if(!inquiryNullable.HasValue) return scsiOneValue;
diff --git a/Aaru.Server.New/Core/SscTestedMedia.cs b/Aaru.Server.New/Core/SscTestedMedia.cs
new file mode 100644
index 00000000..f1b6ce39
--- /dev/null
+++ b/Aaru.Server.New/Core/SscTestedMedia.cs
@@ -0,0 +1,79 @@
+// /***************************************************************************
+// Aaru Data Preservation Suite
+// ----------------------------------------------------------------------------
+//
+// Filename : SscTestedMedia.cs
+// Author(s) : Natalia Portillo
+//
+// Component : Aaru Server.
+//
+// --[ Description ] ----------------------------------------------------------
+//
+// Decodes SCSI Streaming media tests from reports.
+//
+// --[ License ] --------------------------------------------------------------
+//
+// This library is free software; you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 2.1 of the
+// License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, see .
+//
+// ----------------------------------------------------------------------------
+// Copyright © 2011-2024 Natalia Portillo
+// ****************************************************************************/
+
+using Aaru.CommonTypes.Metadata;
+
+namespace Aaru.Server.New.Core;
+
+public static class SscTestedMedia
+{
+ /// Takes the tested media from SCSI Streaming devices of a device report and prints it as a list of values
+ /// List to put values on
+ /// List of tested media
+ public static void Report(IEnumerable testedMedia,
+ out Dictionary Table, List List)>
+ mediaInformation)
+ {
+ mediaInformation = new Dictionary, List)>();
+
+ foreach(TestedSequentialMedia media in testedMedia)
+ {
+ Dictionary table = new();
+ List list = [];
+ string header;
+
+ if(!string.IsNullOrWhiteSpace(media.MediumTypeName))
+ {
+ header = $"Information for medium named \"{media.MediumTypeName}\"";
+
+ if(media.MediumType.HasValue) table.Add("Medium type code", $"{media.MediumType:X2}h");
+ }
+ else if(media.MediumType.HasValue)
+ header = $"Information for medium type {media.MediumType:X2}h";
+ else
+ header = "Information for unknown medium type";
+
+ if(!string.IsNullOrWhiteSpace(media.Manufacturer))
+ table.Add("Medium manufacturer", $"{media.Manufacturer}");
+
+ if(!string.IsNullOrWhiteSpace(media.Model)) table.Add("Medium model", $"{media.Model}");
+
+ if(media.Density.HasValue) list.Add($"Medium has density code {media.Density:X2}h");
+
+ if(media.CanReadMediaSerial == true) list.Add("Drive can read medium serial number.");
+
+ if(media.MediaIsRecognized) list.Add("Drive recognizes this medium.");
+
+ mediaInformation.Add(header, (table, list));
+ }
+ }
+}
\ No newline at end of file
diff --git a/Aaru.Server.New/Core/TestedMedia.cs b/Aaru.Server.New/Core/TestedMedia.cs
new file mode 100644
index 00000000..d3a2aef7
--- /dev/null
+++ b/Aaru.Server.New/Core/TestedMedia.cs
@@ -0,0 +1,390 @@
+// /***************************************************************************
+// Aaru Data Preservation Suite
+// ----------------------------------------------------------------------------
+//
+// Filename : TestedMedia.cs
+// Author(s) : Natalia Portillo
+//
+// Component : Aaru Server.
+//
+// --[ Description ] ----------------------------------------------------------
+//
+// Decodes media tests from reports.
+//
+// --[ License ] --------------------------------------------------------------
+//
+// This library is free software; you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 2.1 of the
+// License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, see .
+//
+// ----------------------------------------------------------------------------
+// Copyright © 2011-2024 Natalia Portillo
+// ****************************************************************************/
+
+namespace Aaru.Server.New.Core;
+
+public static class TestedMedia
+{
+ /// Takes the tested media from a device report and prints it as a list of values
+ /// List to put values on
+ /// List of tested media
+ public static void Report(List testedMedias,
+ out Dictionary, List)> mediaInformation)
+ {
+ mediaInformation = new Dictionary, List)>();
+
+ foreach(CommonTypes.Metadata.TestedMedia testedMedia in testedMedias)
+ {
+ Dictionary table = new();
+ List list = [];
+ string header;
+
+ if(!string.IsNullOrWhiteSpace(testedMedia.MediumTypeName))
+ {
+ header = $"Information for medium named \"{testedMedia.MediumTypeName}\"";
+
+ if(testedMedia.MediumType != null) table.Add("Medium type code", $"{testedMedia.MediumType:X2}h");
+ }
+ else if(testedMedia.MediumType != null)
+ header = $"Information for medium type {testedMedia.MediumType:X2}h";
+ else
+ header = "Information for unknown medium type";
+
+ list.Add(testedMedia.MediaIsRecognized
+ ? "Drive recognizes this medium."
+ : "Drive does not recognize this medium.");
+
+ if(!string.IsNullOrWhiteSpace(testedMedia.Manufacturer))
+ table.Add("Medium manufacturer", $"{testedMedia.Manufacturer}");
+
+ if(!string.IsNullOrWhiteSpace(testedMedia.Model)) table.Add("Medium model", $"{testedMedia.Model}");
+
+ if(testedMedia.Density != null) table.Add("Density code", $"{testedMedia.Density:X2}h");
+
+ if(testedMedia.BlockSize != null) table.Add("Logical sector size", $"{testedMedia.BlockSize} bytes");
+
+ if(testedMedia.PhysicalBlockSize != null)
+ table.Add("Physical sector size", $"{testedMedia.PhysicalBlockSize} bytes");
+
+ if(testedMedia.LongBlockSize != null)
+ table.Add("READ LONG sector size", $"{testedMedia.LongBlockSize} bytes");
+
+ if(testedMedia is { Blocks: not null, BlockSize: not null })
+ {
+ table.Add("Blocks", $"{testedMedia.Blocks}");
+ table.Add("Block size", $"{testedMedia.BlockSize} bytes per block");
+
+ if(testedMedia.Blocks * testedMedia.BlockSize / 1024 / 1024 > 1000000)
+ {
+ table.Add("Medium size",
+ $"{testedMedia.Blocks * testedMedia.BlockSize} bytes, {testedMedia.Blocks * testedMedia.BlockSize / 1000 / 1000 / 1000 / 1000} Tb, {(double)(testedMedia.Blocks * testedMedia.BlockSize) / 1024 / 1024 / 1024 / 1024:F2} TiB");
+ }
+ else if(testedMedia.Blocks * testedMedia.BlockSize / 1024 / 1024 > 1000)
+ {
+ table.Add("Medium size",
+ $"{testedMedia.Blocks * testedMedia.BlockSize} bytes, {testedMedia.Blocks * testedMedia.BlockSize / 1000 / 1000 / 1000} Gb, {(double)(testedMedia.Blocks * testedMedia.BlockSize) / 1024 / 1024 / 1024:F2} GiB");
+ }
+ else
+ {
+ table.Add("Medium size",
+ $"{testedMedia.Blocks * testedMedia.BlockSize} bytes, {testedMedia.Blocks * testedMedia.BlockSize / 1000 / 1000} Mb, {(double)(testedMedia.Blocks * testedMedia.BlockSize) / 1024 / 1024:F2} MiB");
+ }
+ }
+
+ if(testedMedia is { CHS: not null, CurrentCHS: not null })
+ {
+ int currentSectors = testedMedia.CurrentCHS.Cylinders *
+ testedMedia.CurrentCHS.Heads *
+ testedMedia.CurrentCHS.Sectors;
+
+ table.Add("Cylinders", $"{testedMedia.CHS.Cylinders} max., {testedMedia.CurrentCHS.Cylinders} current");
+
+ table.Add("Heads", $"{testedMedia.CHS.Heads} max., {testedMedia.CurrentCHS.Heads} current");
+
+ table.Add("Sectors per track",
+ $"{testedMedia.CHS.Sectors} max., {testedMedia.CurrentCHS.Sectors} current");
+
+ table.Add("Sectors addressable in CHS mode",
+ $"{testedMedia.CHS.Cylinders * testedMedia.CHS.Heads * testedMedia.CHS.Sectors} max., {currentSectors} current");
+
+ table.Add("Medium size in CHS mode",
+ $"{(ulong)currentSectors * testedMedia.BlockSize} bytes, {(ulong)currentSectors * testedMedia.BlockSize / 1000 / 1000} Mb, {(double)((ulong)currentSectors * testedMedia.BlockSize) / 1024 / 1024:F2} MiB");
+ }
+ else if(testedMedia.CHS != null)
+ {
+ int currentSectors = testedMedia.CHS.Cylinders * testedMedia.CHS.Heads * testedMedia.CHS.Sectors;
+ table.Add("Cylinders", $"{testedMedia.CHS.Cylinders}");
+ table.Add("Heads", $"{testedMedia.CHS.Heads}");
+ table.Add("Sectors per track", $"{testedMedia.CHS.Sectors}");
+ table.Add("Sectors addressable in CHS mode", $"{currentSectors}");
+
+ table.Add("Medium size in CHS mode",
+ $"{(ulong)currentSectors * testedMedia.BlockSize} bytes, {(ulong)currentSectors * testedMedia.BlockSize / 1000 / 1000} Mb, {(double)((ulong)currentSectors * testedMedia.BlockSize) / 1024 / 1024:F2} MiB");
+ }
+
+ if(testedMedia.LBASectors != null)
+ {
+ table.Add("Sectors addressable in sectors in 28-bit LBA mode", $"{testedMedia.LBASectors}");
+
+ if((ulong)testedMedia.LBASectors * testedMedia.BlockSize / 1024 / 1024 > 1000000)
+ {
+ table.Add("Medium size in 28-bit LBA mode",
+ $"{(ulong)testedMedia.LBASectors * testedMedia.BlockSize} bytes, {(ulong)testedMedia.LBASectors * testedMedia.BlockSize / 1000 / 1000 / 1000 / 1000} Tb, {(double)((ulong)testedMedia.LBASectors * testedMedia.BlockSize) / 1024 / 1024 / 1024 / 1024:F2} TiB");
+ }
+ else if((ulong)testedMedia.LBASectors * testedMedia.BlockSize / 1024 / 1024 > 1000)
+ {
+ table.Add("Medium size in 28-bit LBA mode",
+ $"{(ulong)testedMedia.LBASectors * testedMedia.BlockSize} bytes, {(ulong)testedMedia.LBASectors * testedMedia.BlockSize / 1000 / 1000 / 1000} Gb, {(double)((ulong)testedMedia.LBASectors * testedMedia.BlockSize) / 1024 / 1024 / 1024:F2} GiB");
+ }
+ else
+ {
+ table.Add("Medium size in 28-bit LBA mode",
+ $"{(ulong)testedMedia.LBASectors * testedMedia.BlockSize} bytes, {(ulong)testedMedia.LBASectors * testedMedia.BlockSize / 1000 / 1000} Mb, {(double)((ulong)testedMedia.LBASectors * testedMedia.BlockSize) / 1024 / 1024:F2} MiB");
+ }
+ }
+
+ if(testedMedia.LBA48Sectors != null)
+ {
+ table.Add("Sectors addressable in sectors in 48-bit LBA mode", $"{testedMedia.LBA48Sectors}");
+
+ if(testedMedia.LBA48Sectors * testedMedia.BlockSize / 1024 / 1024 > 1000000)
+ {
+ table.Add("Medium size in 48-bit LBA mode",
+ $"{testedMedia.LBA48Sectors * testedMedia.BlockSize} bytes, {testedMedia.LBA48Sectors * testedMedia.BlockSize / 1000 / 1000 / 1000 / 1000} Tb, {(double)(testedMedia.LBA48Sectors * testedMedia.BlockSize) / 1024 / 1024 / 1024 / 1024:F2} TiB");
+ }
+ else if(testedMedia.LBA48Sectors * testedMedia.BlockSize / 1024 / 1024 > 1000)
+ {
+ table.Add("Medium size in 48-bit LBA mode",
+ $"{testedMedia.LBA48Sectors * testedMedia.BlockSize} bytes, {testedMedia.LBA48Sectors * testedMedia.BlockSize / 1000 / 1000 / 1000} Gb, {(double)(testedMedia.LBA48Sectors * testedMedia.BlockSize) / 1024 / 1024 / 1024:F2} GiB");
+ }
+ else
+ {
+ table.Add("Medium size in 48-bit LBA mode",
+ $"{testedMedia.LBA48Sectors * testedMedia.BlockSize} bytes, {testedMedia.LBA48Sectors * testedMedia.BlockSize / 1000 / 1000} Mb, {(double)(testedMedia.LBA48Sectors * testedMedia.BlockSize) / 1024 / 1024:F2} MiB");
+ }
+ }
+
+ if(testedMedia.NominalRotationRate != null &&
+ testedMedia.NominalRotationRate != 0x0000 &&
+ testedMedia.NominalRotationRate != 0xFFFF)
+ {
+ list.Add(testedMedia.NominalRotationRate == 0x0001
+ ? "Medium does not rotate."
+ : $"Medium rotates at {testedMedia.NominalRotationRate} rpm");
+ }
+
+ if(testedMedia.BlockSize != null &&
+ testedMedia.PhysicalBlockSize != null &&
+ testedMedia.BlockSize.Value != testedMedia.PhysicalBlockSize.Value &&
+ (testedMedia.LogicalAlignment & 0x8000) == 0x0000 &&
+ (testedMedia.LogicalAlignment & 0x4000) == 0x4000)
+ list.Add($"Logical sector starts at offset {testedMedia.LogicalAlignment & 0x3FFF} from physical sector");
+
+ if(testedMedia.SupportsReadSectors == true)
+ list.Add("Device can use the READ SECTOR(S) command in CHS mode with this medium");
+
+ if(testedMedia.SupportsReadRetry == true)
+ list.Add("Device can use the READ SECTOR(S) RETRY command in CHS mode with this medium");
+
+ if(testedMedia.SupportsReadDma == true)
+ list.Add("Device can use the READ DMA command in CHS mode with this medium");
+
+ if(testedMedia.SupportsReadDmaRetry == true)
+ list.Add("Device can use the READ DMA RETRY command in CHS mode with this medium");
+
+ if(testedMedia.SupportsReadLong == true)
+ list.Add("Device can use the READ LONG command in CHS mode with this medium");
+
+ if(testedMedia.SupportsReadLongRetry == true)
+ list.Add("Device can use the READ LONG RETRY command in CHS mode with this medium");
+
+ if(testedMedia.SupportsReadLba == true)
+ list.Add("Device can use the READ SECTOR(S) command in 28-bit LBA mode with this medium");
+
+ if(testedMedia.SupportsReadRetryLba == true)
+ list.Add("Device can use the READ SECTOR(S) RETRY command in 28-bit LBA mode with this medium");
+
+ if(testedMedia.SupportsReadDmaLba == true)
+ list.Add("Device can use the READ DMA command in 28-bit LBA mode with this medium");
+
+ if(testedMedia.SupportsReadDmaRetryLba == true)
+ list.Add("Device can use the READ DMA RETRY command in 28-bit LBA mode with this medium");
+
+ if(testedMedia.SupportsReadLongLba == true)
+ list.Add("Device can use the READ LONG command in 28-bit LBA mode with this medium");
+
+ if(testedMedia.SupportsReadLongRetryLba == true)
+ list.Add("Device can use the READ LONG RETRY command in 28-bit LBA mode with this medium");
+
+ if(testedMedia.SupportsReadLba48 == true)
+ list.Add("Device can use the READ SECTOR(S) command in 48-bit LBA mode with this medium");
+
+ if(testedMedia.SupportsReadDmaLba48 == true)
+ list.Add("Device can use the READ DMA command in 48-bit LBA mode with this medium");
+
+ if(testedMedia.SupportsSeek == true)
+ list.Add("Device can use the SEEK command in CHS mode with this medium");
+
+ if(testedMedia.SupportsSeekLba == true)
+ list.Add("Device can use the SEEK command in 28-bit LBA mode with this medium");
+
+ if(testedMedia.SupportsReadCapacity == true)
+ list.Add("Device can use the READ CAPACITY (10) command with this medium");
+
+ if(testedMedia.SupportsReadCapacity16 == true)
+ list.Add("Device can use the READ CAPACITY (16) command with this medium");
+
+ if(testedMedia.SupportsRead6 == true) list.Add("Device can use the READ (6) command with this medium");
+
+ if(testedMedia.SupportsRead10 == true) list.Add("Device can use the READ (10) command with this medium");
+
+ if(testedMedia.SupportsRead12 == true) list.Add("Device can use the READ (12) command with this medium");
+
+ if(testedMedia.SupportsRead16 == true) list.Add("Device can use the READ (16) command with this medium");
+
+ if(testedMedia.SupportsReadLong == true)
+ list.Add("Device can use the READ LONG (10) command with this medium");
+
+ if(testedMedia.SupportsReadLong16 == true)
+ list.Add("Device can use the READ LONG (16) command with this medium");
+
+ if(testedMedia.SupportsReadCd == true)
+ list.Add("Device can use the READ CD command with LBA addressing with this medium");
+
+ if(testedMedia.SupportsReadCdMsf == true)
+ list.Add("Device can use the READ CD command with MM:SS:FF addressing with this medium");
+
+ if(testedMedia.SupportsReadCdRaw == true)
+ list.Add("Device can use the READ CD command with LBA addressing with this medium to read raw sector");
+
+ if(testedMedia.SupportsReadCdMsfRaw == true)
+ list.Add("Device can use the READ CD command with MM:SS:FF addressing with this medium read raw sector");
+
+ if(testedMedia.SupportsHLDTSTReadRawDVD == true)
+ list.Add("Device can use the HL-DT-ST vendor READ DVD (RAW) command with this medium");
+
+ if(testedMedia.SupportsNECReadCDDA == true)
+ list.Add("Device can use the NEC vendor READ CD-DA command with this medium");
+
+ if(testedMedia.SupportsPioneerReadCDDA == true)
+ list.Add("Device can use the PIONEER vendor READ CD-DA command with this medium");
+
+ if(testedMedia.SupportsPioneerReadCDDAMSF == true)
+ list.Add("Device can use the PIONEER vendor READ CD-DA MSF command with this medium");
+
+ if(testedMedia.SupportsPlextorReadCDDA == true)
+ list.Add("Device can use the PLEXTOR vendor READ CD-DA command with this medium");
+
+ if(testedMedia.SupportsPlextorReadRawDVD == true)
+ list.Add("Device can use the PLEXTOR vendor READ DVD (RAW) command with this medium");
+
+ if(testedMedia.CanReadAACS == true)
+ list.Add("Device can read the Advanced Access Content System from this medium");
+
+ if(testedMedia.CanReadADIP == true)
+ list.Add("Device can read the DVD ADress-In-Pregroove from this medium");
+
+ if(testedMedia.CanReadATIP == true)
+ list.Add("Device can read the CD Absolute-Time-In-Pregroove from this medium");
+
+ if(testedMedia.CanReadBCA == true) list.Add("Device can read the Burst Cutting Area from this medium");
+
+ if(testedMedia.CanReadC2Pointers == true)
+ list.Add("Device can report the C2 pointers when reading from this medium");
+
+ if(testedMedia.CanReadCMI == true)
+ list.Add("Device can read the Copyright Management Information from this medium");
+
+ if(testedMedia.CanReadCorrectedSubchannel == true)
+ list.Add("Device can correct subchannels when reading from this medium");
+
+ if(testedMedia.CanReadCorrectedSubchannelWithC2 == true)
+ list.Add("Device can correct subchannels and report the C2 pointers when reading from this medium");
+
+ if(testedMedia.CanReadDCB == true) list.Add("Device can read the Disc Control Blocks from this medium");
+
+ if(testedMedia.CanReadDDS == true)
+ list.Add("Device can read the Disc Definition Structure from this medium");
+
+ if(testedMedia.CanReadDMI == true)
+ list.Add("Device can read the Disc Manufacturer Information from this medium");
+
+ if(testedMedia.CanReadDiscInformation == true)
+ list.Add("Device can read the Disc Information from this medium");
+
+ if(testedMedia.CanReadFullTOC == true)
+ list.Add("Device can read the Table of Contents from this medium, without processing it");
+
+ if(testedMedia.CanReadHDCMI == true)
+ list.Add("Device can read the HD DVD Copyright Management Information from this medium");
+
+ if(testedMedia.CanReadLayerCapacity == true)
+ list.Add("Device can read the layer capacity from this medium");
+
+ if(testedMedia.CanReadFirstTrackPreGap == true) list.Add("Device can read the first track's pregap data");
+
+ if(testedMedia.CanReadLeadIn == true) list.Add("Device can read the Lead-In from this medium");
+
+ if(testedMedia.CanReadLeadOut == true) list.Add("Device can read the Lead-Out from this medium");
+
+ if(testedMedia.CanReadMediaID == true) list.Add("Device can read the Media ID from this medium");
+
+ if(testedMedia.CanReadMediaSerial == true)
+ list.Add("Device can read the Media Serial Number from this medium");
+
+ if(testedMedia.CanReadPAC == true) list.Add("Device can read the PAC from this medium");
+
+ if(testedMedia.CanReadPFI == true)
+ list.Add("Device can read the Physical Format Information from this medium");
+
+ if(testedMedia.CanReadPMA == true) list.Add("Device can read the Power Management Area from this medium");
+
+ if(testedMedia.CanReadPQSubchannel == true)
+ list.Add("Device can read the P to Q subchannels from this medium");
+
+ if(testedMedia.CanReadPQSubchannelWithC2 == true)
+ list.Add("Device can read the P to Q subchannels from this medium reporting the C2 pointers");
+
+ if(testedMedia.CanReadPRI == true)
+ list.Add("Device can read the Pre-Recorded Information from this medium");
+
+ if(testedMedia.CanReadRWSubchannel == true)
+ list.Add("Device can read the R to W subchannels from this medium");
+
+ if(testedMedia.CanReadRWSubchannelWithC2 == true)
+ list.Add("Device can read the R to W subchannels from this medium reporting the C2 pointers");
+
+ if(testedMedia.CanReadRecordablePFI == true)
+ list.Add("Device can read the Physical Format Information from Lead-In from this medium");
+
+ if(testedMedia.CanReadSpareAreaInformation == true)
+ list.Add("Device can read the Spare Area Information from this medium");
+
+ if(testedMedia.CanReadTOC == true) list.Add("Device can read the Table of Contents from this medium");
+
+ if(testedMedia.CanReadingIntersessionLeadIn == true) list.Add("Device can read Lead-In between sessions");
+
+ if(testedMedia.CanReadingIntersessionLeadOut == true) list.Add("Device can read Lead-Out between sessions");
+
+ if(testedMedia.CanReadCdScrambled == true)
+ list.Add("Device can read scrambled sectors using standard READ CD command");
+
+ if(testedMedia.CanReadF1_06 == true)
+ list.Add("Device can read from cache using F1h command with subcommand 06h");
+
+ if(testedMedia.CanReadF1_06LeadOut == true)
+ list.Add("Device can read Lead-Out from cache using F1h command with subcommand 06h");
+
+ mediaInformation.Add(header, (table, list));
+ }
+ }
+}
\ No newline at end of file