Files
Aaru/SCSI/Modes/0A.cs

447 lines
18 KiB
C#
Raw Normal View History

2017-12-21 02:03:21 +00:00
// /***************************************************************************
// The Disc Image Chef
// ----------------------------------------------------------------------------
//
// Filename : 0A.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : Device structures decoders.
//
// --[ Description ] ----------------------------------------------------------
//
// Decodes SCSI MODE PAGE 0Ah: Control mode page.
//
// --[ 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 <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
2018-12-29 17:34:38 +00:00
// Copyright © 2011-2019 Natalia Portillo
2017-12-21 02:03:21 +00:00
// ****************************************************************************/
using System.Diagnostics.CodeAnalysis;
2017-12-21 02:03:21 +00:00
using System.Text;
namespace DiscImageChef.Decoders.SCSI
{
2019-11-25 00:54:38 +00:00
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
2017-12-21 02:03:21 +00:00
public static partial class Modes
{
#region Mode Page 0x0A: Control mode page
2019-11-25 00:54:38 +00:00
/// <summary>Control mode page Page code 0x0A 8 bytes in SCSI-2 12 bytes in SPC-1, SPC-2, SPC-3, SPC-4, SPC-5</summary>
2017-12-21 02:03:21 +00:00
public struct ModePage_0A
{
2019-11-25 00:54:38 +00:00
/// <summary>Parameters can be saved</summary>
2017-12-21 02:03:21 +00:00
public bool PS;
2019-11-25 00:54:38 +00:00
/// <summary>If set, target shall report log exception conditions</summary>
2017-12-21 02:03:21 +00:00
public bool RLEC;
2019-11-25 00:54:38 +00:00
/// <summary>Queue algorithm modifier</summary>
2017-12-21 02:03:21 +00:00
public byte QueueAlgorithm;
/// <summary>
2019-11-25 00:54:38 +00:00
/// If set all remaining suspended I/O processes shall be aborted after the contingent allegiance condition or
/// extended contingent allegiance condition
2017-12-21 02:03:21 +00:00
/// </summary>
public byte QErr;
2019-11-25 00:54:38 +00:00
/// <summary>Tagged queuing is disabled</summary>
2017-12-21 02:03:21 +00:00
public bool DQue;
2019-11-25 00:54:38 +00:00
/// <summary>Extended Contingent Allegiance is enabled</summary>
2017-12-21 02:03:21 +00:00
public bool EECA;
2019-11-25 00:54:38 +00:00
/// <summary>Target may issue an asynchronous event notification upon completing its initialization</summary>
2017-12-21 02:03:21 +00:00
public bool RAENP;
2019-11-25 00:54:38 +00:00
/// <summary>Target may issue an asynchronous event notification instead of a unit attention condition</summary>
2017-12-21 02:03:21 +00:00
public bool UAAENP;
2019-11-25 00:54:38 +00:00
/// <summary>Target may issue an asynchronous event notification instead of a deferred error</summary>
2017-12-21 02:03:21 +00:00
public bool EAENP;
2019-11-25 00:54:38 +00:00
/// <summary>Minimum time in ms after initialization before attempting asynchronous event notifications</summary>
2017-12-21 02:03:21 +00:00
public ushort ReadyAENHoldOffPeriod;
2019-11-25 00:54:38 +00:00
/// <summary>Global logging target save disabled</summary>
2017-12-21 02:03:21 +00:00
public bool GLTSD;
2019-11-25 00:54:38 +00:00
/// <summary>CHECK CONDITION should be reported rather than a long busy condition</summary>
2017-12-21 02:03:21 +00:00
public bool RAC;
2019-11-25 00:54:38 +00:00
/// <summary>Software write protect is active</summary>
2017-12-21 02:03:21 +00:00
public bool SWP;
2019-11-25 00:54:38 +00:00
/// <summary>Maximum time in 100 ms units allowed to remain busy. 0xFFFF == unlimited.</summary>
2017-12-21 02:03:21 +00:00
public ushort BusyTimeoutPeriod;
2019-11-25 00:54:38 +00:00
/// <summary>Task set type</summary>
2017-12-21 02:03:21 +00:00
public byte TST;
2019-11-25 00:54:38 +00:00
/// <summary>Tasks aborted by other initiator's actions should be terminated with TASK ABORTED</summary>
2017-12-21 02:03:21 +00:00
public bool TAS;
2019-11-25 00:54:38 +00:00
/// <summary>Action to be taken when a medium is inserted</summary>
2017-12-21 02:03:21 +00:00
public byte AutoloadMode;
2019-11-25 00:54:38 +00:00
/// <summary>Time in seconds to complete an extended self-test</summary>
2017-12-21 02:03:21 +00:00
public byte ExtendedSelfTestCompletionTime;
2019-11-25 00:54:38 +00:00
/// <summary>All tasks received in nexus with ACA ACTIVE is set and an ACA condition is established shall terminate</summary>
2017-12-21 02:03:21 +00:00
public bool TMF_ONLY;
/// <summary>
/// Device shall return descriptor format sense data when returning sense data in the same transactions as a CHECK
/// CONDITION
2017-12-21 02:03:21 +00:00
/// </summary>
public bool D_SENSE;
2019-11-25 00:54:38 +00:00
/// <summary>Unit attention interlocks control</summary>
2017-12-21 02:03:21 +00:00
public byte UA_INTLCK_CTRL;
2019-11-25 00:54:38 +00:00
/// <summary>LOGICAL BLOCK APPLICATION TAG should not be modified</summary>
2017-12-21 02:03:21 +00:00
public bool ATO;
2019-11-25 00:54:38 +00:00
/// <summary>Protector information checking is disabled</summary>
2017-12-21 02:03:21 +00:00
public bool DPICZ;
2019-11-25 00:54:38 +00:00
/// <summary>No unit attention on release</summary>
2017-12-21 02:03:21 +00:00
public bool NUAR;
2019-11-25 00:54:38 +00:00
/// <summary>Application Tag mode page is enabled</summary>
2017-12-21 02:03:21 +00:00
public bool ATMPE;
2019-11-25 00:54:38 +00:00
/// <summary>Abort any write command without protection information</summary>
2017-12-21 02:03:21 +00:00
public bool RWWP;
2019-11-25 00:54:38 +00:00
/// <summary>Supportes block lengths and protection information</summary>
2017-12-21 02:03:21 +00:00
public bool SBLP;
}
public static ModePage_0A? DecodeModePage_0A(byte[] pageResponse)
{
2019-11-25 00:54:38 +00:00
if((pageResponse?[0] & 0x40) == 0x40)
return null;
2017-12-21 02:03:21 +00:00
2019-11-25 00:54:38 +00:00
if((pageResponse?[0] & 0x3F) != 0x0A)
return null;
2017-12-21 02:03:21 +00:00
2019-11-25 00:54:38 +00:00
if(pageResponse[1] + 2 != pageResponse.Length)
return null;
2017-12-21 02:03:21 +00:00
2019-11-25 00:54:38 +00:00
if(pageResponse.Length < 8)
return null;
2017-12-21 02:03:21 +00:00
2019-11-25 00:54:38 +00:00
var decoded = new ModePage_0A();
2017-12-21 02:03:21 +00:00
2018-06-22 08:08:38 +01:00
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
2017-12-21 02:03:21 +00:00
decoded.RLEC |= (pageResponse[2] & 0x01) == 0x01;
decoded.QueueAlgorithm = (byte)((pageResponse[3] & 0xF0) >> 4);
2018-06-22 08:08:38 +01:00
decoded.QErr = (byte)((pageResponse[3] & 0x06) >> 1);
2017-12-21 02:03:21 +00:00
2018-06-22 08:08:38 +01:00
decoded.DQue |= (pageResponse[3] & 0x01) == 0x01;
decoded.EECA |= (pageResponse[4] & 0x80) == 0x80;
decoded.RAENP |= (pageResponse[4] & 0x04) == 0x04;
2017-12-21 02:03:21 +00:00
decoded.UAAENP |= (pageResponse[4] & 0x02) == 0x02;
2018-06-22 08:08:38 +01:00
decoded.EAENP |= (pageResponse[4] & 0x01) == 0x01;
2017-12-21 02:03:21 +00:00
decoded.ReadyAENHoldOffPeriod = (ushort)((pageResponse[6] << 8) + pageResponse[7]);
2019-11-25 00:54:38 +00:00
if(pageResponse.Length < 10)
return decoded;
2017-12-21 02:03:21 +00:00
// SPC-1
decoded.GLTSD |= (pageResponse[2] & 0x02) == 0x02;
2018-06-22 08:08:38 +01:00
decoded.RAC |= (pageResponse[4] & 0x40) == 0x40;
decoded.SWP |= (pageResponse[4] & 0x08) == 0x08;
2017-12-21 02:03:21 +00:00
decoded.BusyTimeoutPeriod = (ushort)((pageResponse[8] << 8) + pageResponse[9]);
// SPC-2
2018-06-22 08:08:38 +01:00
decoded.TST = (byte)((pageResponse[2] & 0xE0) >> 5);
decoded.TAS |= (pageResponse[4] & 0x80) == 0x80;
decoded.AutoloadMode = (byte)(pageResponse[5] & 0x07);
decoded.BusyTimeoutPeriod = (ushort)((pageResponse[10] << 8) + pageResponse[11]);
2017-12-21 02:03:21 +00:00
// SPC-3
2018-06-22 08:08:38 +01:00
decoded.TMF_ONLY |= (pageResponse[2] & 0x10) == 0x10;
decoded.D_SENSE |= (pageResponse[2] & 0x04) == 0x04;
decoded.UA_INTLCK_CTRL = (byte)((pageResponse[4] & 0x30) >> 4);
decoded.TAS |= (pageResponse[5] & 0x40) == 0x40;
decoded.ATO |= (pageResponse[5] & 0x80) == 0x80;
2017-12-21 02:03:21 +00:00
// SPC-5
decoded.DPICZ |= (pageResponse[2] & 0x08) == 0x08;
2018-06-22 08:08:38 +01:00
decoded.NUAR |= (pageResponse[3] & 0x08) == 0x08;
2017-12-21 02:03:21 +00:00
decoded.ATMPE |= (pageResponse[5] & 0x20) == 0x20;
2018-06-22 08:08:38 +01:00
decoded.RWWP |= (pageResponse[5] & 0x10) == 0x10;
decoded.SBLP |= (pageResponse[5] & 0x08) == 0x08;
2017-12-21 02:03:21 +00:00
return decoded;
}
2018-12-31 13:17:27 +00:00
public static string PrettifyModePage_0A(byte[] pageResponse) =>
PrettifyModePage_0A(DecodeModePage_0A(pageResponse));
2017-12-21 02:03:21 +00:00
public static string PrettifyModePage_0A(ModePage_0A? modePage)
{
2019-11-25 00:54:38 +00:00
if(!modePage.HasValue)
return null;
2017-12-21 02:03:21 +00:00
2019-11-25 00:54:38 +00:00
ModePage_0A page = modePage.Value;
var sb = new StringBuilder();
2017-12-21 02:03:21 +00:00
sb.AppendLine("SCSI Control mode page:");
2019-11-25 00:54:38 +00:00
if(page.PS)
sb.AppendLine("\tParameters can be saved");
if(page.RLEC)
sb.AppendLine("\tIf set, target shall report log exception conditions");
if(page.DQue)
sb.AppendLine("\tTagged queuing is disabled");
if(page.EECA)
sb.AppendLine("\tExtended Contingent Allegiance is enabled");
2017-12-21 02:03:21 +00:00
if(page.RAENP)
sb.AppendLine("\tTarget may issue an asynchronous event notification upon completing its initialization");
2019-11-25 00:54:38 +00:00
2017-12-21 02:03:21 +00:00
if(page.UAAENP)
sb.AppendLine("\tTarget may issue an asynchronous event notification instead of a unit attention condition");
2019-11-25 00:54:38 +00:00
2017-12-21 02:03:21 +00:00
if(page.EAENP)
sb.AppendLine("\tTarget may issue an asynchronous event notification instead of a deferred error");
2019-11-25 00:54:38 +00:00
if(page.GLTSD)
sb.AppendLine("\tGlobal logging target save disabled");
if(page.RAC)
sb.AppendLine("\tCHECK CONDITION should be reported rather than a long busy condition");
if(page.SWP)
sb.AppendLine("\tSoftware write protect is active");
2017-12-21 02:03:21 +00:00
if(page.TAS)
sb.AppendLine("\tTasks aborted by other initiator's actions should be terminated with TASK ABORTED");
2019-11-25 00:54:38 +00:00
2017-12-21 02:03:21 +00:00
if(page.TMF_ONLY)
sb.AppendLine("\tAll tasks received in nexus with ACA ACTIVE is set and an ACA condition is established shall terminate");
2019-11-25 00:54:38 +00:00
2017-12-21 02:03:21 +00:00
if(page.D_SENSE)
sb.AppendLine("\tDevice shall return descriptor format sense data when returning sense data in the same transactions as a CHECK CONDITION");
2019-11-25 00:54:38 +00:00
if(page.ATO)
sb.AppendLine("\tLOGICAL BLOCK APPLICATION TAG should not be modified");
if(page.DPICZ)
sb.AppendLine("\tProtector information checking is disabled");
if(page.NUAR)
sb.AppendLine("\tNo unit attention on release");
if(page.ATMPE)
sb.AppendLine("\tApplication Tag mode page is enabled");
if(page.RWWP)
sb.AppendLine("\tAbort any write command without protection information");
if(page.SBLP)
sb.AppendLine("\tSupportes block lengths and protection information");
2017-12-21 02:03:21 +00:00
switch(page.TST)
{
case 0:
sb.AppendLine("\tThe logical unit maintains one task set for all nexuses");
2019-11-25 00:54:38 +00:00
2017-12-21 02:03:21 +00:00
break;
case 1:
sb.AppendLine("\tThe logical unit maintains separate task sets for each nexus");
2019-11-25 00:54:38 +00:00
2017-12-21 02:03:21 +00:00
break;
default:
sb.AppendFormat("\tUnknown Task set type {0}", page.TST).AppendLine();
2019-11-25 00:54:38 +00:00
2017-12-21 02:03:21 +00:00
break;
}
switch(page.QueueAlgorithm)
{
case 0:
sb.AppendLine("\tCommands should be sent strictly ordered");
2019-11-25 00:54:38 +00:00
2017-12-21 02:03:21 +00:00
break;
case 1:
sb.AppendLine("\tCommands can be reordered in any manner");
2019-11-25 00:54:38 +00:00
2017-12-21 02:03:21 +00:00
break;
default:
sb.AppendFormat("\tUnknown Queue Algorithm Modifier {0}", page.QueueAlgorithm).AppendLine();
2019-11-25 00:54:38 +00:00
2017-12-21 02:03:21 +00:00
break;
}
switch(page.QErr)
{
case 0:
sb.AppendLine("\tIf ACA is established, the task set commands shall resume after it is cleared, otherwise they shall terminate with CHECK CONDITION");
2019-11-25 00:54:38 +00:00
2017-12-21 02:03:21 +00:00
break;
case 1:
sb.AppendLine("\tAll the affected commands in the task set shall be aborted when CHECK CONDITION is returned");
2019-11-25 00:54:38 +00:00
2017-12-21 02:03:21 +00:00
break;
case 3:
sb.AppendLine("\tAffected commands in the task set belonging with the CHECK CONDITION nexus shall be aborted");
2019-11-25 00:54:38 +00:00
2017-12-21 02:03:21 +00:00
break;
default:
sb.AppendLine("\tReserved QErr value 2 is set");
2019-11-25 00:54:38 +00:00
2017-12-21 02:03:21 +00:00
break;
}
switch(page.UA_INTLCK_CTRL)
{
case 0:
sb.AppendLine("\tLUN shall clear unit attention condition reported in the same nexus");
2019-11-25 00:54:38 +00:00
2017-12-21 02:03:21 +00:00
break;
case 2:
sb.AppendLine("\tLUN shall not clear unit attention condition reported in the same nexus");
2019-11-25 00:54:38 +00:00
2017-12-21 02:03:21 +00:00
break;
case 3:
sb.AppendLine("\tLUN shall not clear unit attention condition reported in the same nexus and shall establish a unit attention condition for the initiator");
2019-11-25 00:54:38 +00:00
2017-12-21 02:03:21 +00:00
break;
default:
sb.AppendLine("\tReserved UA_INTLCK_CTRL value 1 is set");
2019-11-25 00:54:38 +00:00
2017-12-21 02:03:21 +00:00
break;
}
switch(page.AutoloadMode)
{
case 0:
sb.AppendLine("\tOn medium insertion, it shall be loaded for full access");
2019-11-25 00:54:38 +00:00
2017-12-21 02:03:21 +00:00
break;
case 1:
sb.AppendLine("\tOn medium insertion, it shall be loaded for auxiliary memory access only");
2019-11-25 00:54:38 +00:00
2017-12-21 02:03:21 +00:00
break;
case 2:
sb.AppendLine("\tOn medium insertion, it shall not be loaded");
2019-11-25 00:54:38 +00:00
2017-12-21 02:03:21 +00:00
break;
default:
sb.AppendFormat("\tReserved autoload mode {0} set", page.AutoloadMode).AppendLine();
2019-11-25 00:54:38 +00:00
2017-12-21 02:03:21 +00:00
break;
}
if(page.ReadyAENHoldOffPeriod > 0)
sb.AppendFormat("\t{0} ms before attempting asynchronous event notifications after initialization",
page.ReadyAENHoldOffPeriod).AppendLine();
if(page.BusyTimeoutPeriod > 0)
if(page.BusyTimeoutPeriod == 0xFFFF)
sb.AppendLine("\tThere is no limit on the maximum time that is allowed to remain busy");
else
2019-11-25 00:54:38 +00:00
sb.AppendFormat("\tA maximum of {0} ms are allowed to remain busy", page.BusyTimeoutPeriod * 100).
AppendLine();
2017-12-21 02:03:21 +00:00
if(page.ExtendedSelfTestCompletionTime > 0)
sb.AppendFormat("\t{0} seconds to complete extended self-test", page.ExtendedSelfTestCompletionTime);
return sb.ToString();
}
#endregion Mode Page 0x0A: Control mode page
#region Mode Page 0x0A subpage 0x01: Control Extension mode page
2019-11-25 00:54:38 +00:00
/// <summary>Control Extension mode page Page code 0x0A Subpage code 0x01 32 bytes in SPC-3, SPC-4, SPC-5</summary>
2017-12-21 02:03:21 +00:00
public struct ModePage_0A_S01
{
2019-11-25 00:54:38 +00:00
/// <summary>Parameters can be saved</summary>
2017-12-21 02:03:21 +00:00
public bool PS;
2019-11-25 00:54:38 +00:00
/// <summary>Timestamp outside this standard</summary>
2017-12-21 02:03:21 +00:00
public bool TCMOS;
2019-11-25 00:54:38 +00:00
/// <summary>SCSI precedence</summary>
2017-12-21 02:03:21 +00:00
public bool SCSIP;
2019-11-25 00:54:38 +00:00
/// <summary>Implicit Asymmetric Logical Unit Access Enabled</summary>
2017-12-21 02:03:21 +00:00
public bool IALUAE;
2019-11-25 00:54:38 +00:00
/// <summary>Initial task priority</summary>
2017-12-21 02:03:21 +00:00
public byte InitialPriority;
2019-11-25 00:54:38 +00:00
/// <summary>Device life control disabled</summary>
2017-12-21 02:03:21 +00:00
public bool DLC;
2019-11-25 00:54:38 +00:00
/// <summary>Maximum size of SENSE data in bytes</summary>
2017-12-21 02:03:21 +00:00
public byte MaximumSenseLength;
}
public static ModePage_0A_S01? DecodeModePage_0A_S01(byte[] pageResponse)
{
2019-11-25 00:54:38 +00:00
if((pageResponse?[0] & 0x40) != 0x40)
return null;
2017-12-21 02:03:21 +00:00
2019-11-25 00:54:38 +00:00
if((pageResponse[0] & 0x3F) != 0x0A)
return null;
2017-12-21 02:03:21 +00:00
2019-11-25 00:54:38 +00:00
if(pageResponse[1] != 0x01)
return null;
2017-12-21 02:03:21 +00:00
2019-11-25 00:54:38 +00:00
if((pageResponse[2] << 8) + pageResponse[3] + 4 != pageResponse.Length)
return null;
2017-12-21 02:03:21 +00:00
2019-11-25 00:54:38 +00:00
if(pageResponse.Length < 32)
return null;
2017-12-21 02:03:21 +00:00
2019-11-25 00:54:38 +00:00
var decoded = new ModePage_0A_S01();
2017-12-21 02:03:21 +00:00
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
decoded.IALUAE |= (pageResponse[4] & 0x01) == 0x01;
2018-06-22 08:08:38 +01:00
decoded.SCSIP |= (pageResponse[4] & 0x02) == 0x02;
decoded.TCMOS |= (pageResponse[4] & 0x04) == 0x04;
2017-12-21 02:03:21 +00:00
decoded.InitialPriority = (byte)(pageResponse[5] & 0x0F);
return decoded;
}
2018-12-31 13:17:27 +00:00
public static string PrettifyModePage_0A_S01(byte[] pageResponse) =>
PrettifyModePage_0A_S01(DecodeModePage_0A_S01(pageResponse));
2017-12-21 02:03:21 +00:00
public static string PrettifyModePage_0A_S01(ModePage_0A_S01? modePage)
{
2019-11-25 00:54:38 +00:00
if(!modePage.HasValue)
return null;
2017-12-21 02:03:21 +00:00
ModePage_0A_S01 page = modePage.Value;
2019-11-25 00:54:38 +00:00
var sb = new StringBuilder();
2017-12-21 02:03:21 +00:00
sb.AppendLine("SCSI Control extension page:");
2019-11-25 00:54:38 +00:00
if(page.PS)
sb.AppendLine("\tParameters can be saved");
2017-12-21 02:03:21 +00:00
if(page.TCMOS)
{
sb.Append("\tTimestamp can be initialized by methods outside of the SCSI standards");
2019-11-25 00:54:38 +00:00
if(page.SCSIP)
sb.Append(", but SCSI's SET TIMESTAMP shall take precedence over them");
2017-12-21 02:03:21 +00:00
sb.AppendLine();
}
2019-11-25 00:54:38 +00:00
if(page.IALUAE)
sb.AppendLine("\tImplicit Asymmetric Logical Unit Access is enabled");
2017-12-21 02:03:21 +00:00
sb.AppendFormat("\tInitial priority is {0}", page.InitialPriority).AppendLine();
2019-11-25 00:54:38 +00:00
if(page.DLC)
sb.AppendLine("\tDevice will not degrade performance to extend its life");
2017-12-21 02:03:21 +00:00
if(page.MaximumSenseLength > 0)
sb.AppendFormat("\tMaximum sense data would be {0} bytes", page.MaximumSenseLength).AppendLine();
return sb.ToString();
}
#endregion Mode Page 0x0A subpage 0x01: Control Extension mode page
}
2017-12-21 02:03:21 +00:00
}