2017-05-19 20:28:49 +01:00
|
|
|
// /***************************************************************************
|
2016-01-11 19:40:58 +00:00
|
|
|
// The Disc Image Chef
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
//
|
2016-01-13 03:47:25 +00:00
|
|
|
// Filename : SPC.cs
|
2016-07-28 18:13:49 +01:00
|
|
|
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
2016-01-11 19:40:58 +00:00
|
|
|
//
|
2016-07-28 18:13:49 +01:00
|
|
|
// Component : SCSI Primary Commands.
|
2016-01-11 19:40:58 +00:00
|
|
|
//
|
|
|
|
|
// --[ Description ] ----------------------------------------------------------
|
|
|
|
|
//
|
2016-07-28 18:13:49 +01:00
|
|
|
// Contains SCSI commands defined in SPC standards.
|
2016-01-11 19:40:58 +00:00
|
|
|
//
|
|
|
|
|
// --[ License ] --------------------------------------------------------------
|
|
|
|
|
//
|
2016-07-28 18:13:49 +01:00
|
|
|
// 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
|
2016-01-11 19:40:58 +00:00
|
|
|
// License, or (at your option) any later version.
|
|
|
|
|
//
|
2016-07-28 18:13:49 +01:00
|
|
|
// 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.
|
2016-01-11 19:40:58 +00:00
|
|
|
//
|
2016-07-28 18:13:49 +01:00
|
|
|
// 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/>.
|
2016-01-11 19:40:58 +00:00
|
|
|
//
|
|
|
|
|
// ----------------------------------------------------------------------------
|
2017-12-19 03:50:57 +00:00
|
|
|
// Copyright © 2011-2018 Natalia Portillo
|
2016-01-11 19:40:58 +00:00
|
|
|
// ****************************************************************************/
|
2016-07-28 18:13:49 +01:00
|
|
|
|
2016-01-11 19:40:58 +00:00
|
|
|
using System;
|
|
|
|
|
using DiscImageChef.Console;
|
2017-12-21 14:30:38 +00:00
|
|
|
using PlatformID = DiscImageChef.Interop.PlatformID;
|
2016-01-11 19:40:58 +00:00
|
|
|
|
|
|
|
|
namespace DiscImageChef.Devices
|
|
|
|
|
{
|
|
|
|
|
public partial class Device
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Sends the SPC INQUIRY command to the device using default device timeout.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer"/> contains the sense buffer.</returns>
|
|
|
|
|
/// <param name="buffer">Buffer where the SCSI INQUIRY response will be stored</param>
|
|
|
|
|
/// <param name="senseBuffer">Sense buffer.</param>
|
|
|
|
|
public bool ScsiInquiry(out byte[] buffer, out byte[] senseBuffer)
|
|
|
|
|
{
|
|
|
|
|
return ScsiInquiry(out buffer, out senseBuffer, Timeout);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Sends the SPC INQUIRY command to the device using default device timeout.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer"/> contains the sense buffer.</returns>
|
|
|
|
|
/// <param name="buffer">Buffer where the SCSI INQUIRY response will be stored</param>
|
|
|
|
|
/// <param name="senseBuffer">Sense buffer.</param>
|
|
|
|
|
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
|
|
|
|
|
public bool ScsiInquiry(out byte[] buffer, out byte[] senseBuffer, out double duration)
|
|
|
|
|
{
|
|
|
|
|
return ScsiInquiry(out buffer, out senseBuffer, Timeout, out duration);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Sends the SPC INQUIRY command to the device.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer"/> contains the sense buffer.</returns>
|
|
|
|
|
/// <param name="buffer">Buffer where the SCSI INQUIRY response will be stored</param>
|
|
|
|
|
/// <param name="senseBuffer">Sense buffer.</param>
|
|
|
|
|
/// <param name="timeout">Timeout in seconds.</param>
|
|
|
|
|
public bool ScsiInquiry(out byte[] buffer, out byte[] senseBuffer, uint timeout)
|
|
|
|
|
{
|
|
|
|
|
double duration;
|
|
|
|
|
return ScsiInquiry(out buffer, out senseBuffer, timeout, out duration);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Sends the SPC INQUIRY command to the device.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer"/> contains the sense buffer.</returns>
|
|
|
|
|
/// <param name="buffer">Buffer where the SCSI INQUIRY response will be stored</param>
|
|
|
|
|
/// <param name="senseBuffer">Sense buffer.</param>
|
|
|
|
|
/// <param name="timeout">Timeout in seconds.</param>
|
|
|
|
|
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
|
|
|
|
|
public bool ScsiInquiry(out byte[] buffer, out byte[] senseBuffer, uint timeout, out double duration)
|
|
|
|
|
{
|
|
|
|
|
buffer = new byte[36];
|
|
|
|
|
senseBuffer = new byte[32];
|
2017-12-19 20:33:03 +00:00
|
|
|
byte[] cdb = {(byte)ScsiCommands.Inquiry, 0, 0, 0, 36, 0};
|
2016-01-11 19:40:58 +00:00
|
|
|
bool sense;
|
|
|
|
|
|
2017-12-21 07:19:46 +00:00
|
|
|
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
2017-12-19 20:33:03 +00:00
|
|
|
out sense);
|
2017-12-21 07:19:46 +00:00
|
|
|
Error = LastError != 0;
|
2016-01-11 19:40:58 +00:00
|
|
|
|
2017-12-19 20:33:03 +00:00
|
|
|
if(sense) return true;
|
2016-01-11 19:40:58 +00:00
|
|
|
|
|
|
|
|
byte pagesLength = (byte)(buffer[4] + 5);
|
|
|
|
|
|
2017-12-19 20:33:03 +00:00
|
|
|
cdb = new byte[] {(byte)ScsiCommands.Inquiry, 0, 0, 0, pagesLength, 0};
|
2016-01-11 19:40:58 +00:00
|
|
|
buffer = new byte[pagesLength];
|
|
|
|
|
senseBuffer = new byte[32];
|
|
|
|
|
|
2017-12-21 07:19:46 +00:00
|
|
|
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
2017-12-19 20:33:03 +00:00
|
|
|
out sense);
|
2017-12-21 07:19:46 +00:00
|
|
|
Error = LastError != 0;
|
2016-01-11 19:40:58 +00:00
|
|
|
|
|
|
|
|
DicConsole.DebugWriteLine("SCSI Device", "INQUIRY took {0} ms.", duration);
|
|
|
|
|
|
|
|
|
|
return sense;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Sends the SPC INQUIRY command to the device with an Extended Vital Product Data page using default device timeout.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer"/> contains the sense buffer.</returns>
|
|
|
|
|
/// <param name="buffer">Buffer where the SCSI INQUIRY response will be stored</param>
|
|
|
|
|
/// <param name="senseBuffer">Sense buffer.</param>
|
|
|
|
|
/// <param name="page">The Extended Vital Product Data</param>
|
|
|
|
|
public bool ScsiInquiry(out byte[] buffer, out byte[] senseBuffer, byte page)
|
|
|
|
|
{
|
|
|
|
|
return ScsiInquiry(out buffer, out senseBuffer, page, Timeout);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Sends the SPC INQUIRY command to the device with an Extended Vital Product Data page using default device timeout.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer"/> contains the sense buffer.</returns>
|
|
|
|
|
/// <param name="buffer">Buffer where the SCSI INQUIRY response will be stored</param>
|
|
|
|
|
/// <param name="senseBuffer">Sense buffer.</param>
|
|
|
|
|
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
|
|
|
|
|
/// <param name="page">The Extended Vital Product Data</param>
|
|
|
|
|
public bool ScsiInquiry(out byte[] buffer, out byte[] senseBuffer, byte page, out double duration)
|
|
|
|
|
{
|
|
|
|
|
return ScsiInquiry(out buffer, out senseBuffer, page, Timeout, out duration);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Sends the SPC INQUIRY command to the device with an Extended Vital Product Data page.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer"/> contains the sense buffer.</returns>
|
|
|
|
|
/// <param name="buffer">Buffer where the SCSI INQUIRY response will be stored</param>
|
|
|
|
|
/// <param name="senseBuffer">Sense buffer.</param>
|
|
|
|
|
/// <param name="timeout">Timeout in seconds.</param>
|
|
|
|
|
/// <param name="page">The Extended Vital Product Data</param>
|
|
|
|
|
public bool ScsiInquiry(out byte[] buffer, out byte[] senseBuffer, byte page, uint timeout)
|
|
|
|
|
{
|
|
|
|
|
double duration;
|
|
|
|
|
return ScsiInquiry(out buffer, out senseBuffer, page, timeout, out duration);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Sends the SPC INQUIRY command to the device with an Extended Vital Product Data page.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer"/> contains the sense buffer.</returns>
|
|
|
|
|
/// <param name="buffer">Buffer where the SCSI INQUIRY response will be stored</param>
|
|
|
|
|
/// <param name="senseBuffer">Sense buffer.</param>
|
|
|
|
|
/// <param name="timeout">Timeout in seconds.</param>
|
|
|
|
|
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
|
|
|
|
|
/// <param name="page">The Extended Vital Product Data</param>
|
|
|
|
|
public bool ScsiInquiry(out byte[] buffer, out byte[] senseBuffer, byte page, uint timeout, out double duration)
|
|
|
|
|
{
|
|
|
|
|
buffer = new byte[36];
|
|
|
|
|
senseBuffer = new byte[32];
|
2017-12-19 20:33:03 +00:00
|
|
|
byte[] cdb = {(byte)ScsiCommands.Inquiry, 1, page, 0, 36, 0};
|
2016-01-11 19:40:58 +00:00
|
|
|
bool sense;
|
|
|
|
|
|
2017-12-21 07:19:46 +00:00
|
|
|
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
2017-12-19 20:33:03 +00:00
|
|
|
out sense);
|
2017-12-21 07:19:46 +00:00
|
|
|
Error = LastError != 0;
|
2016-01-11 19:40:58 +00:00
|
|
|
|
2017-12-19 20:33:03 +00:00
|
|
|
if(sense) return true;
|
2016-01-11 19:40:58 +00:00
|
|
|
|
|
|
|
|
// This is because INQ was returned instead of EVPD
|
2017-12-19 20:33:03 +00:00
|
|
|
if(buffer[1] != page) return true;
|
2016-01-11 19:40:58 +00:00
|
|
|
|
|
|
|
|
byte pagesLength = (byte)(buffer[3] + 4);
|
|
|
|
|
|
2017-12-19 20:33:03 +00:00
|
|
|
cdb = new byte[] {(byte)ScsiCommands.Inquiry, 1, page, 0, pagesLength, 0};
|
2016-01-11 19:40:58 +00:00
|
|
|
buffer = new byte[pagesLength];
|
|
|
|
|
senseBuffer = new byte[32];
|
|
|
|
|
|
2017-12-21 07:19:46 +00:00
|
|
|
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
2017-12-19 20:33:03 +00:00
|
|
|
out sense);
|
2017-12-21 07:19:46 +00:00
|
|
|
Error = LastError != 0;
|
2016-01-11 19:40:58 +00:00
|
|
|
|
|
|
|
|
DicConsole.DebugWriteLine("SCSI Device", "INQUIRY took {0} ms.", duration);
|
|
|
|
|
|
|
|
|
|
return sense;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Sends the SPC TEST UNIT READY command to the device
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns><c>true</c>, if unit is NOT ready, <c>false</c> otherwise.</returns>
|
|
|
|
|
/// <param name="senseBuffer">Sense buffer.</param>
|
|
|
|
|
/// <param name="timeout">Timeout in seconds.</param>
|
|
|
|
|
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
|
|
|
|
|
public bool ScsiTestUnitReady(out byte[] senseBuffer, uint timeout, out double duration)
|
|
|
|
|
{
|
|
|
|
|
senseBuffer = new byte[32];
|
2017-12-19 20:33:03 +00:00
|
|
|
byte[] cdb = {(byte)ScsiCommands.TestUnitReady, 0, 0, 0, 0, 0};
|
2016-01-11 19:40:58 +00:00
|
|
|
bool sense;
|
|
|
|
|
byte[] buffer = new byte[0];
|
|
|
|
|
|
2017-12-21 07:19:46 +00:00
|
|
|
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.None, out duration,
|
2017-12-19 20:33:03 +00:00
|
|
|
out sense);
|
2017-12-21 07:19:46 +00:00
|
|
|
Error = LastError != 0;
|
2016-01-11 19:40:58 +00:00
|
|
|
|
|
|
|
|
DicConsole.DebugWriteLine("SCSI Device", "TEST UNIT READY took {0} ms.", duration);
|
|
|
|
|
|
|
|
|
|
return sense;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Sends the SPC MODE SENSE(6) command to the device as introduced in SCSI-1
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer"/> contains the sense buffer.</returns>
|
|
|
|
|
/// <param name="buffer">Buffer where the SCSI MODE SENSE(6) response will be stored</param>
|
|
|
|
|
/// <param name="senseBuffer">Sense buffer.</param>
|
|
|
|
|
/// <param name="timeout">Timeout in seconds.</param>
|
|
|
|
|
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
|
|
|
|
|
public bool ModeSense(out byte[] buffer, out byte[] senseBuffer, uint timeout, out double duration)
|
|
|
|
|
{
|
2017-12-19 20:33:03 +00:00
|
|
|
return ModeSense6(out buffer, out senseBuffer, false, ScsiModeSensePageControl.Current, 0, 0, timeout,
|
|
|
|
|
out duration);
|
2016-01-11 19:40:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Sends the SPC MODE SENSE(6) command to the device as introduced in SCSI-2
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer"/> contains the sense buffer.</returns>
|
|
|
|
|
/// <param name="buffer">Buffer where the SCSI MODE SENSE(6) response will be stored</param>
|
|
|
|
|
/// <param name="senseBuffer">Sense buffer.</param>
|
|
|
|
|
/// <param name="timeout">Timeout in seconds.</param>
|
|
|
|
|
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
|
2017-12-20 17:15:26 +00:00
|
|
|
/// <param name="dbd">If set to <c>true</c> device MUST not return any block descriptor.</param>
|
2016-01-11 19:40:58 +00:00
|
|
|
/// <param name="pageControl">Page control.</param>
|
|
|
|
|
/// <param name="pageCode">Page code.</param>
|
2017-12-20 17:15:26 +00:00
|
|
|
public bool ModeSense6(out byte[] buffer, out byte[] senseBuffer, bool dbd,
|
2017-12-19 20:33:03 +00:00
|
|
|
ScsiModeSensePageControl pageControl, byte pageCode, uint timeout, out double duration)
|
2016-01-11 19:40:58 +00:00
|
|
|
{
|
2017-12-20 17:15:26 +00:00
|
|
|
return ModeSense6(out buffer, out senseBuffer, dbd, pageControl, pageCode, 0, timeout, out duration);
|
2016-01-11 19:40:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Sends the SPC MODE SENSE(6) command to the device as introduced in SCSI-3 SPC-3
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer"/> contains the sense buffer.</returns>
|
|
|
|
|
/// <param name="buffer">Buffer where the SCSI MODE SENSE(6) response will be stored</param>
|
|
|
|
|
/// <param name="senseBuffer">Sense buffer.</param>
|
|
|
|
|
/// <param name="timeout">Timeout in seconds.</param>
|
|
|
|
|
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
|
2017-12-20 17:15:26 +00:00
|
|
|
/// <param name="dbd">If set to <c>true</c> device MUST not return any block descriptor.</param>
|
2016-01-11 19:40:58 +00:00
|
|
|
/// <param name="pageControl">Page control.</param>
|
|
|
|
|
/// <param name="pageCode">Page code.</param>
|
|
|
|
|
/// <param name="subPageCode">Sub-page code.</param>
|
2017-12-20 17:15:26 +00:00
|
|
|
public bool ModeSense6(out byte[] buffer, out byte[] senseBuffer, bool dbd,
|
2017-12-19 20:33:03 +00:00
|
|
|
ScsiModeSensePageControl pageControl, byte pageCode, byte subPageCode, uint timeout,
|
|
|
|
|
out double duration)
|
2016-01-11 19:40:58 +00:00
|
|
|
{
|
|
|
|
|
senseBuffer = new byte[32];
|
|
|
|
|
byte[] cdb = new byte[6];
|
2016-10-10 23:58:35 +01:00
|
|
|
buffer = new byte[255];
|
2016-01-11 19:40:58 +00:00
|
|
|
bool sense;
|
|
|
|
|
|
|
|
|
|
cdb[0] = (byte)ScsiCommands.ModeSense;
|
2017-12-20 17:15:26 +00:00
|
|
|
if(dbd) cdb[1] = 0x08;
|
2016-01-11 19:40:58 +00:00
|
|
|
cdb[2] |= (byte)pageControl;
|
|
|
|
|
cdb[2] |= (byte)(pageCode & 0x3F);
|
|
|
|
|
cdb[3] = subPageCode;
|
|
|
|
|
cdb[4] = (byte)buffer.Length;
|
|
|
|
|
cdb[5] = 0;
|
|
|
|
|
|
2017-12-21 07:19:46 +00:00
|
|
|
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
2017-12-19 20:33:03 +00:00
|
|
|
out sense);
|
2017-12-21 07:19:46 +00:00
|
|
|
Error = LastError != 0;
|
2016-01-11 19:40:58 +00:00
|
|
|
|
2017-12-19 20:33:03 +00:00
|
|
|
if(sense) return true;
|
2016-01-11 19:40:58 +00:00
|
|
|
|
|
|
|
|
byte modeLength = (byte)(buffer[0] + 1);
|
|
|
|
|
buffer = new byte[modeLength];
|
|
|
|
|
cdb[4] = (byte)buffer.Length;
|
|
|
|
|
senseBuffer = new byte[32];
|
|
|
|
|
|
2017-12-21 07:19:46 +00:00
|
|
|
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
2017-12-19 20:33:03 +00:00
|
|
|
out sense);
|
2017-12-21 07:19:46 +00:00
|
|
|
Error = LastError != 0;
|
2016-01-11 19:40:58 +00:00
|
|
|
|
|
|
|
|
DicConsole.DebugWriteLine("SCSI Device", "MODE SENSE(6) took {0} ms.", duration);
|
|
|
|
|
|
|
|
|
|
return sense;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Sends the SPC MODE SENSE(10) command to the device as introduced in SCSI-2
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer"/> contains the sense buffer.</returns>
|
|
|
|
|
/// <param name="buffer">Buffer where the SCSI MODE SENSE(10) response will be stored</param>
|
|
|
|
|
/// <param name="senseBuffer">Sense buffer.</param>
|
|
|
|
|
/// <param name="timeout">Timeout in seconds.</param>
|
|
|
|
|
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
|
2017-12-20 17:15:26 +00:00
|
|
|
/// <param name="dbd">If set to <c>true</c> device MUST not return any block descriptor.</param>
|
2016-01-11 19:40:58 +00:00
|
|
|
/// <param name="pageControl">Page control.</param>
|
|
|
|
|
/// <param name="pageCode">Page code.</param>
|
2017-12-20 17:15:26 +00:00
|
|
|
public bool ModeSense10(out byte[] buffer, out byte[] senseBuffer, bool dbd,
|
2017-12-19 20:33:03 +00:00
|
|
|
ScsiModeSensePageControl pageControl, byte pageCode, uint timeout, out double duration)
|
2016-01-11 19:40:58 +00:00
|
|
|
{
|
2017-12-20 17:15:26 +00:00
|
|
|
return ModeSense10(out buffer, out senseBuffer, false, dbd, pageControl, pageCode, 0, timeout,
|
2017-12-19 20:33:03 +00:00
|
|
|
out duration);
|
2016-01-11 19:40:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Sends the SPC MODE SENSE(10) command to the device as introduced in SCSI-3 SPC-2
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer"/> contains the sense buffer.</returns>
|
|
|
|
|
/// <param name="buffer">Buffer where the SCSI MODE SENSE(10) response will be stored</param>
|
|
|
|
|
/// <param name="senseBuffer">Sense buffer.</param>
|
|
|
|
|
/// <param name="timeout">Timeout in seconds.</param>
|
|
|
|
|
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
|
2017-12-20 17:15:26 +00:00
|
|
|
/// <param name="dbd">If set to <c>true</c> device MUST not return any block descriptor.</param>
|
2016-01-11 19:40:58 +00:00
|
|
|
/// <param name="pageControl">Page control.</param>
|
|
|
|
|
/// <param name="pageCode">Page code.</param>
|
2017-12-20 17:15:26 +00:00
|
|
|
/// <param name="llbaa">If set means 64-bit LBAs are accepted by the caller.</param>
|
|
|
|
|
public bool ModeSense10(out byte[] buffer, out byte[] senseBuffer, bool llbaa, bool dbd,
|
2017-12-19 20:33:03 +00:00
|
|
|
ScsiModeSensePageControl pageControl, byte pageCode, uint timeout, out double duration)
|
2016-01-11 19:40:58 +00:00
|
|
|
{
|
2017-12-20 17:15:26 +00:00
|
|
|
return ModeSense10(out buffer, out senseBuffer, llbaa, dbd, pageControl, pageCode, 0, timeout,
|
2017-12-19 20:33:03 +00:00
|
|
|
out duration);
|
2016-01-11 19:40:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Sends the SPC MODE SENSE(10) command to the device as introduced in SCSI-3 SPC-3
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer"/> contains the sense buffer.</returns>
|
|
|
|
|
/// <param name="buffer">Buffer where the SCSI MODE SENSE(10) response will be stored</param>
|
|
|
|
|
/// <param name="senseBuffer">Sense buffer.</param>
|
|
|
|
|
/// <param name="timeout">Timeout in seconds.</param>
|
|
|
|
|
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
|
2017-12-20 17:15:26 +00:00
|
|
|
/// <param name="dbd">If set to <c>true</c> device MUST not return any block descriptor.</param>
|
2016-01-11 19:40:58 +00:00
|
|
|
/// <param name="pageControl">Page control.</param>
|
|
|
|
|
/// <param name="pageCode">Page code.</param>
|
|
|
|
|
/// <param name="subPageCode">Sub-page code.</param>
|
2017-12-20 17:15:26 +00:00
|
|
|
/// <param name="llbaa">If set means 64-bit LBAs are accepted by the caller.</param>
|
|
|
|
|
public bool ModeSense10(out byte[] buffer, out byte[] senseBuffer, bool llbaa, bool dbd,
|
2017-12-19 20:33:03 +00:00
|
|
|
ScsiModeSensePageControl pageControl, byte pageCode, byte subPageCode, uint timeout,
|
|
|
|
|
out double duration)
|
2016-01-11 19:40:58 +00:00
|
|
|
{
|
|
|
|
|
senseBuffer = new byte[32];
|
|
|
|
|
byte[] cdb = new byte[10];
|
|
|
|
|
buffer = new byte[4096];
|
|
|
|
|
bool sense;
|
|
|
|
|
|
|
|
|
|
cdb[0] = (byte)ScsiCommands.ModeSense10;
|
2017-12-20 17:15:26 +00:00
|
|
|
if(llbaa) cdb[1] |= 0x10;
|
|
|
|
|
if(dbd) cdb[1] |= 0x08;
|
2016-01-11 19:40:58 +00:00
|
|
|
cdb[2] |= (byte)pageControl;
|
|
|
|
|
cdb[2] |= (byte)(pageCode & 0x3F);
|
|
|
|
|
cdb[3] = subPageCode;
|
|
|
|
|
cdb[7] = (byte)((buffer.Length & 0xFF00) >> 8);
|
|
|
|
|
cdb[8] = (byte)(buffer.Length & 0xFF);
|
|
|
|
|
cdb[9] = 0;
|
|
|
|
|
|
2017-12-21 07:19:46 +00:00
|
|
|
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
2017-12-19 20:33:03 +00:00
|
|
|
out sense);
|
2017-12-21 07:19:46 +00:00
|
|
|
Error = LastError != 0;
|
2016-01-11 19:40:58 +00:00
|
|
|
|
2017-12-19 20:33:03 +00:00
|
|
|
if(sense) return true;
|
2016-01-11 19:40:58 +00:00
|
|
|
|
2017-12-21 14:30:38 +00:00
|
|
|
ushort modeLength = (ushort)((buffer[0] << 8) + buffer[1] + 2);
|
2016-01-11 19:40:58 +00:00
|
|
|
buffer = new byte[modeLength];
|
|
|
|
|
cdb[7] = (byte)((buffer.Length & 0xFF00) >> 8);
|
|
|
|
|
cdb[8] = (byte)(buffer.Length & 0xFF);
|
|
|
|
|
senseBuffer = new byte[32];
|
|
|
|
|
|
2017-12-21 07:19:46 +00:00
|
|
|
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
2017-12-19 20:33:03 +00:00
|
|
|
out sense);
|
2017-12-21 07:19:46 +00:00
|
|
|
Error = LastError != 0;
|
2016-01-11 19:40:58 +00:00
|
|
|
|
|
|
|
|
DicConsole.DebugWriteLine("SCSI Device", "MODE SENSE(10) took {0} ms.", duration);
|
|
|
|
|
|
|
|
|
|
return sense;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Sends the SPC PREVENT ALLOW MEDIUM REMOVAL command to prevent medium removal
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer"/> contains the sense buffer.</returns>
|
|
|
|
|
/// <param name="senseBuffer">Sense buffer.</param>
|
|
|
|
|
/// <param name="timeout">Timeout in seconds.</param>
|
|
|
|
|
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
|
* DiscImageChef.CommonTypes/MediaTypeFromSCSI.cs:
* DiscImageChef.CommonTypes/DiscImageChef.CommonTypes.csproj:
Added method to calculate MediaType from SCSI parameters
(mode, density, medium type, device type, etc).
* DiscImageChef.Metadata/DeviceReport.cs:
Added command to guess drive and media parameters and output
an XML report of them.
* DiscImageChef/Commands/DeviceReport.cs:
* DiscImageChef.Metadata/DiscImageChef.Metadata.csproj:
Added command to guess drive and media parameters and output
an XML report of them.
* DiscImageChef/Commands/DumpMedia.cs:
Added preliminary command to dump media. Only SCSI for now.
CDs and tapes are not supported. Errors are blalanty
ignored. Options are incomplete. Not yet usable.
* DiscImageChef/Core/Checksum.cs:
* DiscImageChef/Commands/CreateSidecar.cs:
Moved checksum generation to a separate class.
* CICMMetadata:
Added support for ADIP.
* DiscImageChef.CommonTypes/MediaType.cs:
Added parameters of UDO media.
Moved DataPlay outside of Iomega, as it's not from that
manufacturer.
Added missing Exatape media and corrected 160m XL one.
Added SyJet media.
Added all ECMA defined magneto-optical (sectors calculated
from specifications, unchecked).
Added PD media.
Added Imation 320Gb RDX.
Added generic USB flash drives.
* DiscImageChef.Decoders/SCSI/Enums.cs:
Make enumerations public.
* DiscImageChef.Decoders/SCSI/Inquiry.cs:
* DiscImageChef.Devices/Device/Constructor.cs:
Trim space padded strings on SCSI INQUIRY.
* DiscImageChef.Devices/Device/ScsiCommands/MMC.cs:
Added PREVENT ALLOW MEDIUM REMOVAL.
Added START STOP UNIT.
* DiscImageChef.Devices/Device/ScsiCommands/NEC.cs:
Rename NEC methods.
* DiscImageChef.Devices/Device/ScsiCommands/Pioneer.cs:
Corrected Pioneer transfer length calculation.
* DiscImageChef.Devices/Device/ScsiCommands/Plextor.cs:
Renamed Plextor methods.
* DiscImageChef.Devices/Device/ScsiCommands/SPC.cs:
Renamed SSC PREVENT ALLOW MEDIUM REMOVAL to uncollide with
MMC same name but different command.
* DiscImageChef.Devices/DiscImageChef.Devices.csproj:
Set platform target to x86 (does it really matter?).
* DiscImageChef.Devices/Linux/Command.cs:
Reduced allocation for readlink() to current kernel
MAX_PATH.
* DiscImageChef.Devices/Linux/Enums.cs:
Modified Linux ioctl to 32-bit. Works on 64-bit also. Solves
commands not working on 32-bit environments.
* DiscImageChef.DiscImages/ZZZRawImage.cs:
Changed ECMA-184 and ECMA-183 enums.
* DiscImageChef.Metadata/Dimensions.cs:
Added all ECMA defined magneto-opticals.
Added PD media.
Added 320Gb RDX.
Corrected Exatape 160m XL.
Added Exatape 22m and 28m.
* DiscImageChef.Metadata/MediaType.cs:
Added 356mm magneto-optical media.
Changed ECMA-184 and ECMA-183 enums.
Added USB generic flash drive.
* DiscImageChef/Commands/DeviceInfo.cs:
Corrected SCSI INQUIRY naming.
Corrected SCSI MODE SENSE (6) parameters.
Reduced SCSI MODE SENSE timeout, some devices just get stuck
with unsupported MODE SENSE commanda and must be left to
timeout.
Changed FUJITSU vendor string comparison.
* DiscImageChef/Commands/MediaInfo.cs:
Added method to calculate MediaType from SCSI parameters
(mode, density, medium type, device type, etc).
Changed some error WriteLine() to debug ones. Too much
verbosity.
Added DVD media type decoding from PFI.
Found a drive that dumps ADIP, enabling it again (not
decoded).
* DiscImageChef/Commands/MediaScan.cs:
Added option to generate ImgBurn compatible log to
media-scan command.
* DiscImageChef/DiscImageChef.csproj:
Moved checksum generation to a separate class.
Added command to guess drive and media parameters and output
an XML report of them.
Added preliminary command to dump media. Only SCSI for now.
CDs and tapes are not supported. Errors are blalanty
ignored. Options are incomplete. Not yet usable.
* DiscImageChef/Main.cs:
Added command to guess drive and media parameters and output
an XML report of them.
Added preliminary command to dump media. Only SCSI for now.
CDs and tapes are not supported. Errors are blalanty
ignored. Options are incomplete. Not yet usable.
* DiscImageChef/Options.cs:
Added command to guess drive and media parameters and output
an XML report of them.
Added preliminary command to dump media. Only SCSI for now.
CDs and tapes are not supported. Errors are blalanty
ignored. Options are incomplete. Not yet usable.
Added option to generate ImgBurn compatible log to media-scan
command.
2016-01-31 08:05:56 +00:00
|
|
|
public bool SpcPreventMediumRemoval(out byte[] senseBuffer, uint timeout, out double duration)
|
2016-01-11 19:40:58 +00:00
|
|
|
{
|
* DiscImageChef.CommonTypes/MediaTypeFromSCSI.cs:
* DiscImageChef.CommonTypes/DiscImageChef.CommonTypes.csproj:
Added method to calculate MediaType from SCSI parameters
(mode, density, medium type, device type, etc).
* DiscImageChef.Metadata/DeviceReport.cs:
Added command to guess drive and media parameters and output
an XML report of them.
* DiscImageChef/Commands/DeviceReport.cs:
* DiscImageChef.Metadata/DiscImageChef.Metadata.csproj:
Added command to guess drive and media parameters and output
an XML report of them.
* DiscImageChef/Commands/DumpMedia.cs:
Added preliminary command to dump media. Only SCSI for now.
CDs and tapes are not supported. Errors are blalanty
ignored. Options are incomplete. Not yet usable.
* DiscImageChef/Core/Checksum.cs:
* DiscImageChef/Commands/CreateSidecar.cs:
Moved checksum generation to a separate class.
* CICMMetadata:
Added support for ADIP.
* DiscImageChef.CommonTypes/MediaType.cs:
Added parameters of UDO media.
Moved DataPlay outside of Iomega, as it's not from that
manufacturer.
Added missing Exatape media and corrected 160m XL one.
Added SyJet media.
Added all ECMA defined magneto-optical (sectors calculated
from specifications, unchecked).
Added PD media.
Added Imation 320Gb RDX.
Added generic USB flash drives.
* DiscImageChef.Decoders/SCSI/Enums.cs:
Make enumerations public.
* DiscImageChef.Decoders/SCSI/Inquiry.cs:
* DiscImageChef.Devices/Device/Constructor.cs:
Trim space padded strings on SCSI INQUIRY.
* DiscImageChef.Devices/Device/ScsiCommands/MMC.cs:
Added PREVENT ALLOW MEDIUM REMOVAL.
Added START STOP UNIT.
* DiscImageChef.Devices/Device/ScsiCommands/NEC.cs:
Rename NEC methods.
* DiscImageChef.Devices/Device/ScsiCommands/Pioneer.cs:
Corrected Pioneer transfer length calculation.
* DiscImageChef.Devices/Device/ScsiCommands/Plextor.cs:
Renamed Plextor methods.
* DiscImageChef.Devices/Device/ScsiCommands/SPC.cs:
Renamed SSC PREVENT ALLOW MEDIUM REMOVAL to uncollide with
MMC same name but different command.
* DiscImageChef.Devices/DiscImageChef.Devices.csproj:
Set platform target to x86 (does it really matter?).
* DiscImageChef.Devices/Linux/Command.cs:
Reduced allocation for readlink() to current kernel
MAX_PATH.
* DiscImageChef.Devices/Linux/Enums.cs:
Modified Linux ioctl to 32-bit. Works on 64-bit also. Solves
commands not working on 32-bit environments.
* DiscImageChef.DiscImages/ZZZRawImage.cs:
Changed ECMA-184 and ECMA-183 enums.
* DiscImageChef.Metadata/Dimensions.cs:
Added all ECMA defined magneto-opticals.
Added PD media.
Added 320Gb RDX.
Corrected Exatape 160m XL.
Added Exatape 22m and 28m.
* DiscImageChef.Metadata/MediaType.cs:
Added 356mm magneto-optical media.
Changed ECMA-184 and ECMA-183 enums.
Added USB generic flash drive.
* DiscImageChef/Commands/DeviceInfo.cs:
Corrected SCSI INQUIRY naming.
Corrected SCSI MODE SENSE (6) parameters.
Reduced SCSI MODE SENSE timeout, some devices just get stuck
with unsupported MODE SENSE commanda and must be left to
timeout.
Changed FUJITSU vendor string comparison.
* DiscImageChef/Commands/MediaInfo.cs:
Added method to calculate MediaType from SCSI parameters
(mode, density, medium type, device type, etc).
Changed some error WriteLine() to debug ones. Too much
verbosity.
Added DVD media type decoding from PFI.
Found a drive that dumps ADIP, enabling it again (not
decoded).
* DiscImageChef/Commands/MediaScan.cs:
Added option to generate ImgBurn compatible log to
media-scan command.
* DiscImageChef/DiscImageChef.csproj:
Moved checksum generation to a separate class.
Added command to guess drive and media parameters and output
an XML report of them.
Added preliminary command to dump media. Only SCSI for now.
CDs and tapes are not supported. Errors are blalanty
ignored. Options are incomplete. Not yet usable.
* DiscImageChef/Main.cs:
Added command to guess drive and media parameters and output
an XML report of them.
Added preliminary command to dump media. Only SCSI for now.
CDs and tapes are not supported. Errors are blalanty
ignored. Options are incomplete. Not yet usable.
* DiscImageChef/Options.cs:
Added command to guess drive and media parameters and output
an XML report of them.
Added preliminary command to dump media. Only SCSI for now.
CDs and tapes are not supported. Errors are blalanty
ignored. Options are incomplete. Not yet usable.
Added option to generate ImgBurn compatible log to media-scan
command.
2016-01-31 08:05:56 +00:00
|
|
|
return SpcPreventAllowMediumRemoval(out senseBuffer, ScsiPreventAllowMode.Prevent, timeout, out duration);
|
2016-01-11 19:40:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Sends the SPC PREVENT ALLOW MEDIUM REMOVAL command to allow medium removal
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer"/> contains the sense buffer.</returns>
|
|
|
|
|
/// <param name="senseBuffer">Sense buffer.</param>
|
|
|
|
|
/// <param name="timeout">Timeout in seconds.</param>
|
|
|
|
|
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
|
* DiscImageChef.CommonTypes/MediaTypeFromSCSI.cs:
* DiscImageChef.CommonTypes/DiscImageChef.CommonTypes.csproj:
Added method to calculate MediaType from SCSI parameters
(mode, density, medium type, device type, etc).
* DiscImageChef.Metadata/DeviceReport.cs:
Added command to guess drive and media parameters and output
an XML report of them.
* DiscImageChef/Commands/DeviceReport.cs:
* DiscImageChef.Metadata/DiscImageChef.Metadata.csproj:
Added command to guess drive and media parameters and output
an XML report of them.
* DiscImageChef/Commands/DumpMedia.cs:
Added preliminary command to dump media. Only SCSI for now.
CDs and tapes are not supported. Errors are blalanty
ignored. Options are incomplete. Not yet usable.
* DiscImageChef/Core/Checksum.cs:
* DiscImageChef/Commands/CreateSidecar.cs:
Moved checksum generation to a separate class.
* CICMMetadata:
Added support for ADIP.
* DiscImageChef.CommonTypes/MediaType.cs:
Added parameters of UDO media.
Moved DataPlay outside of Iomega, as it's not from that
manufacturer.
Added missing Exatape media and corrected 160m XL one.
Added SyJet media.
Added all ECMA defined magneto-optical (sectors calculated
from specifications, unchecked).
Added PD media.
Added Imation 320Gb RDX.
Added generic USB flash drives.
* DiscImageChef.Decoders/SCSI/Enums.cs:
Make enumerations public.
* DiscImageChef.Decoders/SCSI/Inquiry.cs:
* DiscImageChef.Devices/Device/Constructor.cs:
Trim space padded strings on SCSI INQUIRY.
* DiscImageChef.Devices/Device/ScsiCommands/MMC.cs:
Added PREVENT ALLOW MEDIUM REMOVAL.
Added START STOP UNIT.
* DiscImageChef.Devices/Device/ScsiCommands/NEC.cs:
Rename NEC methods.
* DiscImageChef.Devices/Device/ScsiCommands/Pioneer.cs:
Corrected Pioneer transfer length calculation.
* DiscImageChef.Devices/Device/ScsiCommands/Plextor.cs:
Renamed Plextor methods.
* DiscImageChef.Devices/Device/ScsiCommands/SPC.cs:
Renamed SSC PREVENT ALLOW MEDIUM REMOVAL to uncollide with
MMC same name but different command.
* DiscImageChef.Devices/DiscImageChef.Devices.csproj:
Set platform target to x86 (does it really matter?).
* DiscImageChef.Devices/Linux/Command.cs:
Reduced allocation for readlink() to current kernel
MAX_PATH.
* DiscImageChef.Devices/Linux/Enums.cs:
Modified Linux ioctl to 32-bit. Works on 64-bit also. Solves
commands not working on 32-bit environments.
* DiscImageChef.DiscImages/ZZZRawImage.cs:
Changed ECMA-184 and ECMA-183 enums.
* DiscImageChef.Metadata/Dimensions.cs:
Added all ECMA defined magneto-opticals.
Added PD media.
Added 320Gb RDX.
Corrected Exatape 160m XL.
Added Exatape 22m and 28m.
* DiscImageChef.Metadata/MediaType.cs:
Added 356mm magneto-optical media.
Changed ECMA-184 and ECMA-183 enums.
Added USB generic flash drive.
* DiscImageChef/Commands/DeviceInfo.cs:
Corrected SCSI INQUIRY naming.
Corrected SCSI MODE SENSE (6) parameters.
Reduced SCSI MODE SENSE timeout, some devices just get stuck
with unsupported MODE SENSE commanda and must be left to
timeout.
Changed FUJITSU vendor string comparison.
* DiscImageChef/Commands/MediaInfo.cs:
Added method to calculate MediaType from SCSI parameters
(mode, density, medium type, device type, etc).
Changed some error WriteLine() to debug ones. Too much
verbosity.
Added DVD media type decoding from PFI.
Found a drive that dumps ADIP, enabling it again (not
decoded).
* DiscImageChef/Commands/MediaScan.cs:
Added option to generate ImgBurn compatible log to
media-scan command.
* DiscImageChef/DiscImageChef.csproj:
Moved checksum generation to a separate class.
Added command to guess drive and media parameters and output
an XML report of them.
Added preliminary command to dump media. Only SCSI for now.
CDs and tapes are not supported. Errors are blalanty
ignored. Options are incomplete. Not yet usable.
* DiscImageChef/Main.cs:
Added command to guess drive and media parameters and output
an XML report of them.
Added preliminary command to dump media. Only SCSI for now.
CDs and tapes are not supported. Errors are blalanty
ignored. Options are incomplete. Not yet usable.
* DiscImageChef/Options.cs:
Added command to guess drive and media parameters and output
an XML report of them.
Added preliminary command to dump media. Only SCSI for now.
CDs and tapes are not supported. Errors are blalanty
ignored. Options are incomplete. Not yet usable.
Added option to generate ImgBurn compatible log to media-scan
command.
2016-01-31 08:05:56 +00:00
|
|
|
public bool SpcAllowMediumRemoval(out byte[] senseBuffer, uint timeout, out double duration)
|
2016-01-11 19:40:58 +00:00
|
|
|
{
|
* DiscImageChef.CommonTypes/MediaTypeFromSCSI.cs:
* DiscImageChef.CommonTypes/DiscImageChef.CommonTypes.csproj:
Added method to calculate MediaType from SCSI parameters
(mode, density, medium type, device type, etc).
* DiscImageChef.Metadata/DeviceReport.cs:
Added command to guess drive and media parameters and output
an XML report of them.
* DiscImageChef/Commands/DeviceReport.cs:
* DiscImageChef.Metadata/DiscImageChef.Metadata.csproj:
Added command to guess drive and media parameters and output
an XML report of them.
* DiscImageChef/Commands/DumpMedia.cs:
Added preliminary command to dump media. Only SCSI for now.
CDs and tapes are not supported. Errors are blalanty
ignored. Options are incomplete. Not yet usable.
* DiscImageChef/Core/Checksum.cs:
* DiscImageChef/Commands/CreateSidecar.cs:
Moved checksum generation to a separate class.
* CICMMetadata:
Added support for ADIP.
* DiscImageChef.CommonTypes/MediaType.cs:
Added parameters of UDO media.
Moved DataPlay outside of Iomega, as it's not from that
manufacturer.
Added missing Exatape media and corrected 160m XL one.
Added SyJet media.
Added all ECMA defined magneto-optical (sectors calculated
from specifications, unchecked).
Added PD media.
Added Imation 320Gb RDX.
Added generic USB flash drives.
* DiscImageChef.Decoders/SCSI/Enums.cs:
Make enumerations public.
* DiscImageChef.Decoders/SCSI/Inquiry.cs:
* DiscImageChef.Devices/Device/Constructor.cs:
Trim space padded strings on SCSI INQUIRY.
* DiscImageChef.Devices/Device/ScsiCommands/MMC.cs:
Added PREVENT ALLOW MEDIUM REMOVAL.
Added START STOP UNIT.
* DiscImageChef.Devices/Device/ScsiCommands/NEC.cs:
Rename NEC methods.
* DiscImageChef.Devices/Device/ScsiCommands/Pioneer.cs:
Corrected Pioneer transfer length calculation.
* DiscImageChef.Devices/Device/ScsiCommands/Plextor.cs:
Renamed Plextor methods.
* DiscImageChef.Devices/Device/ScsiCommands/SPC.cs:
Renamed SSC PREVENT ALLOW MEDIUM REMOVAL to uncollide with
MMC same name but different command.
* DiscImageChef.Devices/DiscImageChef.Devices.csproj:
Set platform target to x86 (does it really matter?).
* DiscImageChef.Devices/Linux/Command.cs:
Reduced allocation for readlink() to current kernel
MAX_PATH.
* DiscImageChef.Devices/Linux/Enums.cs:
Modified Linux ioctl to 32-bit. Works on 64-bit also. Solves
commands not working on 32-bit environments.
* DiscImageChef.DiscImages/ZZZRawImage.cs:
Changed ECMA-184 and ECMA-183 enums.
* DiscImageChef.Metadata/Dimensions.cs:
Added all ECMA defined magneto-opticals.
Added PD media.
Added 320Gb RDX.
Corrected Exatape 160m XL.
Added Exatape 22m and 28m.
* DiscImageChef.Metadata/MediaType.cs:
Added 356mm magneto-optical media.
Changed ECMA-184 and ECMA-183 enums.
Added USB generic flash drive.
* DiscImageChef/Commands/DeviceInfo.cs:
Corrected SCSI INQUIRY naming.
Corrected SCSI MODE SENSE (6) parameters.
Reduced SCSI MODE SENSE timeout, some devices just get stuck
with unsupported MODE SENSE commanda and must be left to
timeout.
Changed FUJITSU vendor string comparison.
* DiscImageChef/Commands/MediaInfo.cs:
Added method to calculate MediaType from SCSI parameters
(mode, density, medium type, device type, etc).
Changed some error WriteLine() to debug ones. Too much
verbosity.
Added DVD media type decoding from PFI.
Found a drive that dumps ADIP, enabling it again (not
decoded).
* DiscImageChef/Commands/MediaScan.cs:
Added option to generate ImgBurn compatible log to
media-scan command.
* DiscImageChef/DiscImageChef.csproj:
Moved checksum generation to a separate class.
Added command to guess drive and media parameters and output
an XML report of them.
Added preliminary command to dump media. Only SCSI for now.
CDs and tapes are not supported. Errors are blalanty
ignored. Options are incomplete. Not yet usable.
* DiscImageChef/Main.cs:
Added command to guess drive and media parameters and output
an XML report of them.
Added preliminary command to dump media. Only SCSI for now.
CDs and tapes are not supported. Errors are blalanty
ignored. Options are incomplete. Not yet usable.
* DiscImageChef/Options.cs:
Added command to guess drive and media parameters and output
an XML report of them.
Added preliminary command to dump media. Only SCSI for now.
CDs and tapes are not supported. Errors are blalanty
ignored. Options are incomplete. Not yet usable.
Added option to generate ImgBurn compatible log to media-scan
command.
2016-01-31 08:05:56 +00:00
|
|
|
return SpcPreventAllowMediumRemoval(out senseBuffer, ScsiPreventAllowMode.Allow, timeout, out duration);
|
2016-01-11 19:40:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Sends the SPC PREVENT ALLOW MEDIUM REMOVAL command
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer"/> contains the sense buffer.</returns>
|
|
|
|
|
/// <param name="senseBuffer">Sense buffer.</param>
|
|
|
|
|
/// <param name="timeout">Timeout in seconds.</param>
|
|
|
|
|
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
|
|
|
|
|
/// <param name="prevent"><c>true</c> to prevent medium removal, <c>false</c> to allow it.</param>
|
2017-12-19 20:33:03 +00:00
|
|
|
public bool SpcPreventAllowMediumRemoval(out byte[] senseBuffer, bool prevent, uint timeout,
|
|
|
|
|
out double duration)
|
2016-01-11 19:40:58 +00:00
|
|
|
{
|
2016-04-19 02:11:47 +01:00
|
|
|
if(prevent)
|
2017-12-19 20:33:03 +00:00
|
|
|
return SpcPreventAllowMediumRemoval(out senseBuffer, ScsiPreventAllowMode.Prevent, timeout,
|
|
|
|
|
out duration);
|
2017-12-21 02:57:32 +00:00
|
|
|
|
|
|
|
|
return SpcPreventAllowMediumRemoval(out senseBuffer, ScsiPreventAllowMode.Allow, timeout, out duration);
|
2016-01-11 19:40:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Sends the SPC PREVENT ALLOW MEDIUM REMOVAL command
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer"/> contains the sense buffer.</returns>
|
|
|
|
|
/// <param name="senseBuffer">Sense buffer.</param>
|
|
|
|
|
/// <param name="timeout">Timeout in seconds.</param>
|
|
|
|
|
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
|
|
|
|
|
/// <param name="preventMode">Prevention mode.</param>
|
2017-12-19 20:33:03 +00:00
|
|
|
public bool SpcPreventAllowMediumRemoval(out byte[] senseBuffer, ScsiPreventAllowMode preventMode, uint timeout,
|
|
|
|
|
out double duration)
|
2016-01-11 19:40:58 +00:00
|
|
|
{
|
|
|
|
|
senseBuffer = new byte[32];
|
|
|
|
|
byte[] cdb = new byte[6];
|
|
|
|
|
bool sense;
|
|
|
|
|
byte[] buffer = new byte[0];
|
|
|
|
|
|
|
|
|
|
cdb[0] = (byte)ScsiCommands.PreventAllowMediumRemoval;
|
|
|
|
|
cdb[4] = (byte)((byte)preventMode & 0x03);
|
|
|
|
|
|
2017-12-21 07:19:46 +00:00
|
|
|
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.None, out duration,
|
2017-12-19 20:33:03 +00:00
|
|
|
out sense);
|
2017-12-21 07:19:46 +00:00
|
|
|
Error = LastError != 0;
|
2016-01-11 19:40:58 +00:00
|
|
|
|
|
|
|
|
DicConsole.DebugWriteLine("SCSI Device", "PREVENT ALLOW MEDIUM REMOVAL took {0} ms.", duration);
|
|
|
|
|
|
|
|
|
|
return sense;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Sends the SPC READ CAPACITY command
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer"/> contains the sense buffer.</returns>
|
|
|
|
|
/// <param name="buffer">Buffer where the SCSI READ CAPACITY response will be stored</param>
|
|
|
|
|
/// <param name="senseBuffer">Sense buffer.</param>
|
|
|
|
|
/// <param name="timeout">Timeout in seconds.</param>
|
|
|
|
|
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
|
|
|
|
|
public bool ReadCapacity(out byte[] buffer, out byte[] senseBuffer, uint timeout, out double duration)
|
|
|
|
|
{
|
|
|
|
|
return ReadCapacity(out buffer, out senseBuffer, false, 0, false, timeout, out duration);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Sends the SPC READ CAPACITY command
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer"/> contains the sense buffer.</returns>
|
|
|
|
|
/// <param name="buffer">Buffer where the SCSI READ CAPACITY response will be stored</param>
|
|
|
|
|
/// <param name="senseBuffer">Sense buffer.</param>
|
2017-12-20 17:15:26 +00:00
|
|
|
/// <param name="relAddr">Indicates that <paramref name="address"/> is relative to current medium position</param>
|
|
|
|
|
/// <param name="address">Address where information is requested from, only valid if <paramref name="pmi"/> is set</param>
|
|
|
|
|
/// <param name="pmi">If set, it is requesting partial media capacity</param>
|
2016-01-11 19:40:58 +00:00
|
|
|
/// <param name="timeout">Timeout in seconds.</param>
|
|
|
|
|
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
|
2017-12-20 17:15:26 +00:00
|
|
|
public bool ReadCapacity(out byte[] buffer, out byte[] senseBuffer, bool relAddr, uint address, bool pmi,
|
2017-12-19 20:33:03 +00:00
|
|
|
uint timeout, out double duration)
|
2016-01-11 19:40:58 +00:00
|
|
|
{
|
|
|
|
|
senseBuffer = new byte[32];
|
|
|
|
|
byte[] cdb = new byte[10];
|
|
|
|
|
buffer = new byte[8];
|
|
|
|
|
bool sense;
|
|
|
|
|
|
|
|
|
|
cdb[0] = (byte)ScsiCommands.ReadCapacity;
|
|
|
|
|
|
2017-12-20 17:15:26 +00:00
|
|
|
if(pmi)
|
2016-01-11 19:40:58 +00:00
|
|
|
{
|
|
|
|
|
cdb[8] = 0x01;
|
2017-12-20 17:15:26 +00:00
|
|
|
if(relAddr) cdb[1] = 0x01;
|
2016-01-11 19:40:58 +00:00
|
|
|
|
|
|
|
|
cdb[2] = (byte)((address & 0xFF000000) >> 24);
|
|
|
|
|
cdb[3] = (byte)((address & 0xFF0000) >> 16);
|
|
|
|
|
cdb[4] = (byte)((address & 0xFF00) >> 8);
|
|
|
|
|
cdb[5] = (byte)(address & 0xFF);
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-21 07:19:46 +00:00
|
|
|
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
2017-12-19 20:33:03 +00:00
|
|
|
out sense);
|
2017-12-21 07:19:46 +00:00
|
|
|
Error = LastError != 0;
|
2016-01-11 19:40:58 +00:00
|
|
|
|
|
|
|
|
DicConsole.DebugWriteLine("SCSI Device", "READ CAPACITY took {0} ms.", duration);
|
|
|
|
|
|
|
|
|
|
return sense;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Sends the SPC READ CAPACITY(16) command
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer"/> contains the sense buffer.</returns>
|
|
|
|
|
/// <param name="buffer">Buffer where the SCSI READ CAPACITY(16) response will be stored</param>
|
|
|
|
|
/// <param name="senseBuffer">Sense buffer.</param>
|
|
|
|
|
/// <param name="timeout">Timeout in seconds.</param>
|
|
|
|
|
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
|
|
|
|
|
public bool ReadCapacity16(out byte[] buffer, out byte[] senseBuffer, uint timeout, out double duration)
|
|
|
|
|
{
|
|
|
|
|
return ReadCapacity16(out buffer, out senseBuffer, 0, false, timeout, out duration);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Sends the SPC READ CAPACITY(16) command
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer"/> contains the sense buffer.</returns>
|
|
|
|
|
/// <param name="buffer">Buffer where the SCSI READ CAPACITY(16) response will be stored</param>
|
|
|
|
|
/// <param name="senseBuffer">Sense buffer.</param>
|
2017-12-20 17:15:26 +00:00
|
|
|
/// <param name="address">Address where information is requested from, only valid if <paramref name="pmi"/> is set</param>
|
|
|
|
|
/// <param name="pmi">If set, it is requesting partial media capacity</param>
|
2016-01-11 19:40:58 +00:00
|
|
|
/// <param name="timeout">Timeout in seconds.</param>
|
|
|
|
|
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
|
2017-12-20 17:15:26 +00:00
|
|
|
public bool ReadCapacity16(out byte[] buffer, out byte[] senseBuffer, ulong address, bool pmi, uint timeout,
|
2017-12-19 20:33:03 +00:00
|
|
|
out double duration)
|
2016-01-11 19:40:58 +00:00
|
|
|
{
|
|
|
|
|
senseBuffer = new byte[32];
|
|
|
|
|
byte[] cdb = new byte[16];
|
|
|
|
|
buffer = new byte[32];
|
|
|
|
|
bool sense;
|
|
|
|
|
|
|
|
|
|
cdb[0] = (byte)ScsiCommands.ServiceActionIn;
|
|
|
|
|
cdb[1] = (byte)ScsiServiceActions.ReadCapacity16;
|
|
|
|
|
|
2017-12-20 17:15:26 +00:00
|
|
|
if(pmi)
|
2016-01-11 19:40:58 +00:00
|
|
|
{
|
|
|
|
|
cdb[14] = 0x01;
|
|
|
|
|
byte[] temp = BitConverter.GetBytes(address);
|
|
|
|
|
cdb[2] = temp[7];
|
|
|
|
|
cdb[3] = temp[6];
|
|
|
|
|
cdb[4] = temp[5];
|
|
|
|
|
cdb[5] = temp[4];
|
|
|
|
|
cdb[6] = temp[3];
|
|
|
|
|
cdb[7] = temp[2];
|
|
|
|
|
cdb[8] = temp[1];
|
|
|
|
|
cdb[9] = temp[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cdb[10] = (byte)((buffer.Length & 0xFF000000) >> 24);
|
|
|
|
|
cdb[11] = (byte)((buffer.Length & 0xFF0000) >> 16);
|
|
|
|
|
cdb[12] = (byte)((buffer.Length & 0xFF00) >> 8);
|
|
|
|
|
cdb[13] = (byte)(buffer.Length & 0xFF);
|
|
|
|
|
|
2017-12-21 07:19:46 +00:00
|
|
|
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
2017-12-19 20:33:03 +00:00
|
|
|
out sense);
|
2017-12-21 07:19:46 +00:00
|
|
|
Error = LastError != 0;
|
2016-01-11 19:40:58 +00:00
|
|
|
|
|
|
|
|
DicConsole.DebugWriteLine("SCSI Device", "READ CAPACITY(16) took {0} ms.", duration);
|
|
|
|
|
|
|
|
|
|
return sense;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Sends the SPC READ MEDIA SERIAL NUMBER command
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer"/> contains the sense buffer.</returns>
|
|
|
|
|
/// <param name="buffer">Buffer where the SCSI READ MEDIA SERIAL NUMBER response will be stored</param>
|
|
|
|
|
/// <param name="senseBuffer">Sense buffer.</param>
|
|
|
|
|
/// <param name="timeout">Timeout in seconds.</param>
|
|
|
|
|
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
|
|
|
|
|
public bool ReadMediaSerialNumber(out byte[] buffer, out byte[] senseBuffer, uint timeout, out double duration)
|
|
|
|
|
{
|
|
|
|
|
senseBuffer = new byte[32];
|
|
|
|
|
byte[] cdb = new byte[12];
|
|
|
|
|
buffer = new byte[4];
|
|
|
|
|
bool sense;
|
|
|
|
|
|
|
|
|
|
cdb[0] = (byte)ScsiCommands.ReadSerialNumber;
|
|
|
|
|
cdb[1] = 0x01;
|
|
|
|
|
cdb[6] = (byte)((buffer.Length & 0xFF000000) >> 24);
|
|
|
|
|
cdb[7] = (byte)((buffer.Length & 0xFF0000) >> 16);
|
|
|
|
|
cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8);
|
|
|
|
|
cdb[9] = (byte)(buffer.Length & 0xFF);
|
|
|
|
|
|
2017-12-21 07:19:46 +00:00
|
|
|
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
2017-12-19 20:33:03 +00:00
|
|
|
out sense);
|
2017-12-21 07:19:46 +00:00
|
|
|
Error = LastError != 0;
|
2016-01-11 19:40:58 +00:00
|
|
|
|
2017-12-19 20:33:03 +00:00
|
|
|
if(sense) return true;
|
2016-01-11 19:40:58 +00:00
|
|
|
|
2017-12-21 14:30:38 +00:00
|
|
|
uint strctLength = (uint)((buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) +
|
2017-12-19 20:33:03 +00:00
|
|
|
buffer[3] + 4);
|
2016-01-13 03:47:25 +00:00
|
|
|
buffer = new byte[strctLength];
|
2016-01-11 19:40:58 +00:00
|
|
|
cdb[6] = (byte)((buffer.Length & 0xFF000000) >> 24);
|
|
|
|
|
cdb[7] = (byte)((buffer.Length & 0xFF0000) >> 16);
|
|
|
|
|
cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8);
|
|
|
|
|
cdb[9] = (byte)(buffer.Length & 0xFF);
|
|
|
|
|
senseBuffer = new byte[32];
|
|
|
|
|
|
2017-12-21 07:19:46 +00:00
|
|
|
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
2017-12-19 20:33:03 +00:00
|
|
|
out sense);
|
2017-12-21 07:19:46 +00:00
|
|
|
Error = LastError != 0;
|
2016-01-11 19:40:58 +00:00
|
|
|
|
|
|
|
|
DicConsole.DebugWriteLine("SCSI Device", "READ MEDIA SERIAL NUMBER took {0} ms.", duration);
|
|
|
|
|
|
|
|
|
|
return sense;
|
|
|
|
|
}
|
2016-01-13 03:47:25 +00:00
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Reads an attribute from the medium auxiliary memory
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="buffer">Buffer.</param>
|
|
|
|
|
/// <param name="senseBuffer">Sense buffer.</param>
|
|
|
|
|
/// <param name="action">What to do, <see cref="ScsiAttributeAction"/>.</param>
|
|
|
|
|
/// <param name="partition">Partition number.</param>
|
|
|
|
|
/// <param name="firstAttribute">First attribute identifier.</param>
|
|
|
|
|
/// <param name="cache">If set to <c>true</c> device can return cached data.</param>
|
|
|
|
|
/// <param name="timeout">Timeout.</param>
|
|
|
|
|
/// <param name="duration">Duration.</param>
|
2017-12-19 20:33:03 +00:00
|
|
|
public bool ReadAttribute(out byte[] buffer, out byte[] senseBuffer, ScsiAttributeAction action, byte partition,
|
|
|
|
|
ushort firstAttribute, bool cache, uint timeout, out double duration)
|
2016-01-13 03:47:25 +00:00
|
|
|
{
|
2017-12-19 20:33:03 +00:00
|
|
|
return ReadAttribute(out buffer, out senseBuffer, action, 0, 0, 0, partition, firstAttribute, cache,
|
|
|
|
|
timeout, out duration);
|
2016-01-13 03:47:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Reads an attribute from the medium auxiliary memory
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="buffer">Buffer.</param>
|
|
|
|
|
/// <param name="senseBuffer">Sense buffer.</param>
|
|
|
|
|
/// <param name="action">What to do, <see cref="ScsiAttributeAction"/>.</param>
|
|
|
|
|
/// <param name="firstAttribute">First attribute identifier.</param>
|
|
|
|
|
/// <param name="cache">If set to <c>true</c> device can return cached data.</param>
|
|
|
|
|
/// <param name="timeout">Timeout.</param>
|
|
|
|
|
/// <param name="duration">Duration.</param>
|
2017-12-19 20:33:03 +00:00
|
|
|
public bool ReadAttribute(out byte[] buffer, out byte[] senseBuffer, ScsiAttributeAction action,
|
|
|
|
|
ushort firstAttribute, bool cache, uint timeout, out double duration)
|
2016-01-13 03:47:25 +00:00
|
|
|
{
|
2017-12-19 20:33:03 +00:00
|
|
|
return ReadAttribute(out buffer, out senseBuffer, action, 0, 0, 0, 0, firstAttribute, cache, timeout,
|
|
|
|
|
out duration);
|
2016-01-13 03:47:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Reads an attribute from the medium auxiliary memory
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="buffer">Buffer.</param>
|
|
|
|
|
/// <param name="senseBuffer">Sense buffer.</param>
|
|
|
|
|
/// <param name="action">What to do, <see cref="ScsiAttributeAction"/>.</param>
|
|
|
|
|
/// <param name="partition">Partition number.</param>
|
|
|
|
|
/// <param name="firstAttribute">First attribute identifier.</param>
|
|
|
|
|
/// <param name="timeout">Timeout.</param>
|
|
|
|
|
/// <param name="duration">Duration.</param>
|
2017-12-19 20:33:03 +00:00
|
|
|
public bool ReadAttribute(out byte[] buffer, out byte[] senseBuffer, ScsiAttributeAction action, byte partition,
|
|
|
|
|
ushort firstAttribute, uint timeout, out double duration)
|
2016-01-13 03:47:25 +00:00
|
|
|
{
|
2017-12-19 20:33:03 +00:00
|
|
|
return ReadAttribute(out buffer, out senseBuffer, action, 0, 0, 0, partition, firstAttribute, false,
|
|
|
|
|
timeout, out duration);
|
2016-01-13 03:47:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Reads an attribute from the medium auxiliary memory
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="buffer">Buffer.</param>
|
|
|
|
|
/// <param name="senseBuffer">Sense buffer.</param>
|
|
|
|
|
/// <param name="action">What to do, <see cref="ScsiAttributeAction"/>.</param>
|
|
|
|
|
/// <param name="firstAttribute">First attribute identifier.</param>
|
|
|
|
|
/// <param name="timeout">Timeout.</param>
|
|
|
|
|
/// <param name="duration">Duration.</param>
|
2017-12-19 20:33:03 +00:00
|
|
|
public bool ReadAttribute(out byte[] buffer, out byte[] senseBuffer, ScsiAttributeAction action,
|
|
|
|
|
ushort firstAttribute, uint timeout, out double duration)
|
2016-01-13 03:47:25 +00:00
|
|
|
{
|
2017-12-19 20:33:03 +00:00
|
|
|
return ReadAttribute(out buffer, out senseBuffer, action, 0, 0, 0, 0, firstAttribute, false, timeout,
|
|
|
|
|
out duration);
|
2016-01-13 03:47:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Reads an attribute from the medium auxiliary memory
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="buffer">Buffer.</param>
|
|
|
|
|
/// <param name="senseBuffer">Sense buffer.</param>
|
|
|
|
|
/// <param name="action">What to do, <see cref="ScsiAttributeAction"/>.</param>
|
|
|
|
|
/// <param name="volume">Volume number.</param>
|
|
|
|
|
/// <param name="partition">Partition number.</param>
|
|
|
|
|
/// <param name="firstAttribute">First attribute identifier.</param>
|
|
|
|
|
/// <param name="timeout">Timeout.</param>
|
|
|
|
|
/// <param name="duration">Duration.</param>
|
2017-12-19 20:33:03 +00:00
|
|
|
public bool ReadAttribute(out byte[] buffer, out byte[] senseBuffer, ScsiAttributeAction action, byte volume,
|
|
|
|
|
byte partition, ushort firstAttribute, uint timeout, out double duration)
|
2016-01-13 03:47:25 +00:00
|
|
|
{
|
2017-12-19 20:33:03 +00:00
|
|
|
return ReadAttribute(out buffer, out senseBuffer, action, 0, 0, volume, partition, firstAttribute, false,
|
|
|
|
|
timeout, out duration);
|
2016-01-13 03:47:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Reads an attribute from the medium auxiliary memory
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="buffer">Buffer.</param>
|
|
|
|
|
/// <param name="senseBuffer">Sense buffer.</param>
|
|
|
|
|
/// <param name="action">What to do, <see cref="ScsiAttributeAction"/>.</param>
|
|
|
|
|
/// <param name="volume">Volume number.</param>
|
|
|
|
|
/// <param name="partition">Partition number.</param>
|
|
|
|
|
/// <param name="firstAttribute">First attribute identifier.</param>
|
|
|
|
|
/// <param name="cache">If set to <c>true</c> device can return cached data.</param>
|
|
|
|
|
/// <param name="timeout">Timeout.</param>
|
|
|
|
|
/// <param name="duration">Duration.</param>
|
2017-12-19 20:33:03 +00:00
|
|
|
public bool ReadAttribute(out byte[] buffer, out byte[] senseBuffer, ScsiAttributeAction action, byte volume,
|
|
|
|
|
byte partition, ushort firstAttribute, bool cache, uint timeout, out double duration)
|
2016-01-13 03:47:25 +00:00
|
|
|
{
|
2017-12-19 20:33:03 +00:00
|
|
|
return ReadAttribute(out buffer, out senseBuffer, action, 0, 0, volume, partition, firstAttribute, cache,
|
|
|
|
|
timeout, out duration);
|
2016-01-13 03:47:25 +00:00
|
|
|
}
|
2016-02-04 16:51:03 +00:00
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Sends the SPC MODE SELECT(6) command
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer"/> contains the sense buffer.</returns>
|
|
|
|
|
/// <param name="buffer">Buffer with the data to be sent to the device</param>
|
|
|
|
|
/// <param name="senseBuffer">Sense buffer.</param>
|
|
|
|
|
/// <param name="timeout">Timeout in seconds.</param>
|
|
|
|
|
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
|
2017-12-19 20:33:03 +00:00
|
|
|
public bool ModeSelect(byte[] buffer, out byte[] senseBuffer, bool pageFormat, bool savePages, uint timeout,
|
|
|
|
|
out double duration)
|
2016-02-04 16:51:03 +00:00
|
|
|
{
|
|
|
|
|
senseBuffer = new byte[32];
|
|
|
|
|
|
|
|
|
|
// Prevent overflows
|
2016-04-19 02:11:47 +01:00
|
|
|
if(buffer.Length > 255)
|
2016-02-04 16:51:03 +00:00
|
|
|
{
|
2017-12-21 14:30:38 +00:00
|
|
|
if(PlatformId != PlatformID.Win32NT && PlatformId != PlatformID.Win32S &&
|
|
|
|
|
PlatformId != PlatformID.Win32Windows && PlatformId != PlatformID.WinCE &&
|
|
|
|
|
PlatformId != PlatformID.WindowsPhone &&
|
|
|
|
|
PlatformId != PlatformID.Xbox) LastError = 75;
|
2017-12-21 07:19:46 +00:00
|
|
|
else LastError = 111;
|
|
|
|
|
Error = true;
|
2016-02-04 16:51:03 +00:00
|
|
|
duration = 0;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
byte[] cdb = new byte[6];
|
|
|
|
|
bool sense;
|
|
|
|
|
|
|
|
|
|
cdb[0] = (byte)ScsiCommands.ModeSelect;
|
2017-12-19 20:33:03 +00:00
|
|
|
if(pageFormat) cdb[1] += 0x10;
|
|
|
|
|
if(savePages) cdb[1] += 0x01;
|
2016-02-04 16:51:03 +00:00
|
|
|
cdb[4] = (byte)buffer.Length;
|
|
|
|
|
|
2017-12-21 07:19:46 +00:00
|
|
|
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.Out, out duration,
|
2017-12-19 20:33:03 +00:00
|
|
|
out sense);
|
2017-12-21 07:19:46 +00:00
|
|
|
Error = LastError != 0;
|
2016-02-04 16:51:03 +00:00
|
|
|
|
|
|
|
|
DicConsole.DebugWriteLine("SCSI Device", "MODE SELECT(6) took {0} ms.", duration);
|
|
|
|
|
|
|
|
|
|
return sense;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Sends the SPC MODE SELECT(10) command
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer"/> contains the sense buffer.</returns>
|
|
|
|
|
/// <param name="buffer">Buffer with the data to be sent to the device</param>
|
|
|
|
|
/// <param name="senseBuffer">Sense buffer.</param>
|
|
|
|
|
/// <param name="timeout">Timeout in seconds.</param>
|
|
|
|
|
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
|
2017-12-19 20:33:03 +00:00
|
|
|
public bool ModeSelect10(byte[] buffer, out byte[] senseBuffer, bool pageFormat, bool savePages, uint timeout,
|
|
|
|
|
out double duration)
|
2016-02-04 16:51:03 +00:00
|
|
|
{
|
|
|
|
|
senseBuffer = new byte[32];
|
|
|
|
|
|
|
|
|
|
// Prevent overflows
|
2016-04-19 02:11:47 +01:00
|
|
|
if(buffer.Length > 65535)
|
2016-02-04 16:51:03 +00:00
|
|
|
{
|
2017-12-21 14:30:38 +00:00
|
|
|
if(PlatformId != PlatformID.Win32NT && PlatformId != PlatformID.Win32S &&
|
|
|
|
|
PlatformId != PlatformID.Win32Windows && PlatformId != PlatformID.WinCE &&
|
|
|
|
|
PlatformId != PlatformID.WindowsPhone &&
|
|
|
|
|
PlatformId != PlatformID.Xbox) LastError = 75;
|
2017-12-21 07:19:46 +00:00
|
|
|
else LastError = 111;
|
|
|
|
|
Error = true;
|
2016-02-04 16:51:03 +00:00
|
|
|
duration = 0;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
byte[] cdb = new byte[10];
|
|
|
|
|
bool sense;
|
|
|
|
|
|
|
|
|
|
cdb[0] = (byte)ScsiCommands.ModeSelect10;
|
2017-12-19 20:33:03 +00:00
|
|
|
if(pageFormat) cdb[1] += 0x10;
|
|
|
|
|
if(savePages) cdb[1] += 0x01;
|
2016-02-04 16:51:03 +00:00
|
|
|
cdb[7] = (byte)((buffer.Length & 0xFF00) << 8);
|
|
|
|
|
cdb[8] = (byte)(buffer.Length & 0xFF);
|
|
|
|
|
|
2017-12-21 07:19:46 +00:00
|
|
|
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.Out, out duration,
|
2017-12-19 20:33:03 +00:00
|
|
|
out sense);
|
2017-12-21 07:19:46 +00:00
|
|
|
Error = LastError != 0;
|
2016-02-04 16:51:03 +00:00
|
|
|
|
|
|
|
|
DicConsole.DebugWriteLine("SCSI Device", "MODE SELECT(10) took {0} ms.", duration);
|
|
|
|
|
|
|
|
|
|
return sense;
|
|
|
|
|
}
|
2016-10-12 06:16:41 +01:00
|
|
|
|
|
|
|
|
public bool RequestSense(out byte[] buffer, uint timeout, out double duration)
|
|
|
|
|
{
|
|
|
|
|
return RequestSense(false, out buffer, timeout, out duration);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool RequestSense(bool descriptor, out byte[] buffer, uint timeout, out double duration)
|
|
|
|
|
{
|
|
|
|
|
byte[] senseBuffer = new byte[32];
|
|
|
|
|
byte[] cdb = new byte[6];
|
|
|
|
|
buffer = new byte[252];
|
|
|
|
|
bool sense;
|
|
|
|
|
|
|
|
|
|
cdb[0] = (byte)ScsiCommands.RequestSense;
|
2017-12-19 20:33:03 +00:00
|
|
|
if(descriptor) cdb[1] = 0x01;
|
2016-10-12 06:16:41 +01:00
|
|
|
cdb[2] = 0;
|
|
|
|
|
cdb[3] = 0;
|
|
|
|
|
cdb[4] = (byte)buffer.Length;
|
|
|
|
|
cdb[5] = 0;
|
|
|
|
|
|
2017-12-21 07:19:46 +00:00
|
|
|
LastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
|
2017-12-19 20:33:03 +00:00
|
|
|
out sense);
|
2017-12-21 07:19:46 +00:00
|
|
|
Error = LastError != 0;
|
2016-10-12 06:16:41 +01:00
|
|
|
|
|
|
|
|
DicConsole.DebugWriteLine("SCSI Device", "REQUEST SENSE took {0} ms.", duration);
|
|
|
|
|
|
|
|
|
|
return sense;
|
|
|
|
|
}
|
2016-01-11 19:40:58 +00:00
|
|
|
}
|
2017-12-19 20:33:03 +00:00
|
|
|
}
|