From afdcc5b7293c3d238fe814d1be6464e5ce1ee4cf Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Thu, 14 Jan 2016 20:40:45 +0000 Subject: [PATCH] Added SyQuest vendor commands. --- DiscImageChef.Devices/ChangeLog | 6 + .../Device/ScsiCommands/SyQuest.cs | 212 ++++++++++++++++++ .../DiscImageChef.Devices.csproj | 1 + 3 files changed, 219 insertions(+) create mode 100644 DiscImageChef.Devices/Device/ScsiCommands/SyQuest.cs diff --git a/DiscImageChef.Devices/ChangeLog b/DiscImageChef.Devices/ChangeLog index 99cee1c7..650d29cb 100644 --- a/DiscImageChef.Devices/ChangeLog +++ b/DiscImageChef.Devices/ChangeLog @@ -1,3 +1,9 @@ +2016-01-14 Natalia Portillo + + * DiscImageChef.Devices.csproj: + * Device/ScsiCommands/SyQuest.cs: + Added SyQuest vendor commands. + 2016-01-14 Natalia Portillo * Enums.cs: diff --git a/DiscImageChef.Devices/Device/ScsiCommands/SyQuest.cs b/DiscImageChef.Devices/Device/ScsiCommands/SyQuest.cs new file mode 100644 index 00000000..8e08fa6e --- /dev/null +++ b/DiscImageChef.Devices/Device/ScsiCommands/SyQuest.cs @@ -0,0 +1,212 @@ +// /*************************************************************************** +// The Disc Image Chef +// ---------------------------------------------------------------------------- +// +// Filename : SyQuest.cs +// Version : 1.0 +// Author(s) : Natalia Portillo +// +// Component : Component +// +// Revision : $Revision$ +// Last change by : $Author$ +// Date : $Date$ +// +// --[ Description ] ---------------------------------------------------------- +// +// Description +// +// --[ License ] -------------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// ---------------------------------------------------------------------------- +// Copyright (C) 2011-2015 Claunia.com +// ****************************************************************************/ +// //$Id$ +using DiscImageChef.Console; + +namespace DiscImageChef.Devices +{ + public partial class Device + { + /// + /// Sends the SyQuest READ (6) command + /// + /// true if the command failed and contains the sense buffer. + /// Buffer where the SCSI READ response will be stored + /// Sense buffer. + /// Timeout in seconds. + /// Duration in milliseconds it took for the device to execute the command. + /// Starting block. + /// Block size in bytes. + public bool SyQuestRead6(out byte[] buffer, out byte[] senseBuffer, uint lba, uint blockSize, uint timeout, out double duration) + { + return SyQuestRead6(out buffer, out senseBuffer, lba, blockSize, 1, false, false, timeout, out duration); + } + + /// + /// Sends the SyQuest READ LONG (6) command + /// + /// true if the command failed and contains the sense buffer. + /// Buffer where the SCSI READ response will be stored + /// Sense buffer. + /// Timeout in seconds. + /// Duration in milliseconds it took for the device to execute the command. + /// Starting block. + /// Block size in bytes. + public bool SyQuestReadLong6(out byte[] buffer, out byte[] senseBuffer, uint lba, uint blockSize, uint timeout, out double duration) + { + return SyQuestRead6(out buffer, out senseBuffer, lba, blockSize, 1, false, true, timeout, out duration); + } + + /// + /// Sends the SyQuest READ (6) command + /// + /// true if the command failed and contains the sense buffer. + /// Buffer where the SCSI READ response will be stored + /// Sense buffer. + /// Timeout in seconds. + /// Duration in milliseconds it took for the device to execute the command. + /// Starting block. + /// If set to true, block will not be transfer and will reside in the drive's buffer. + /// If set to true drive will return ECC bytes and disable error detection. + /// Block size in bytes. + /// How many blocks to read. + public bool SyQuestRead6(out byte[] buffer, out byte[] senseBuffer, uint lba, uint blockSize, byte transferLength, bool inhibitDma, bool readLong, uint timeout, out double duration) + { + senseBuffer = new byte[32]; + byte[] cdb = new byte[6]; + bool sense; + + cdb[0] = (byte)ScsiCommands.Read6; + cdb[1] = (byte)((lba & 0x1F0000) >> 16); + cdb[2] = (byte)((lba & 0xFF00) >> 8); + cdb[3] = (byte)(lba & 0xFF); + cdb[4] = transferLength; + if (inhibitDma) + cdb[5] += 0x80; + if (readLong) + cdb[5] += 0x40; + + if (!inhibitDma && !readLong) + { + if (transferLength == 0) + buffer = new byte[256 * blockSize]; + else + buffer = new byte[transferLength * blockSize]; + } + else if(readLong) + { + buffer = new byte[blockSize]; + cdb[4] = 1; + } + else + buffer = new byte[0]; + + if (!inhibitDma) + lastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration, out sense); + else + lastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.None, out duration, out sense); + + error = lastError != 0; + + DicConsole.DebugWriteLine("SCSI Device", "SYQUEST READ (6) took {0} ms.", duration); + + return sense; + } + + /// + /// Requests the usage, seek and error counters, and resets them + /// + /// Buffer. + /// Sense buffer. + /// Timeout. + /// Duration. + public bool SyQuestReadUsageCounter(out byte[] buffer, out byte[] senseBuffer, uint timeout, out double duration) + { + return AdaptecReadUsageCounter(out buffer, out senseBuffer, false, timeout, duration); + } + + /// + /// Sends the SyQuest READ LONG (10) command + /// + /// true if the command failed and contains the sense buffer. + /// Buffer where the SCSI READ response will be stored + /// Sense buffer. + /// Timeout in seconds. + /// Duration in milliseconds it took for the device to execute the command. + /// Starting block. + /// Block size in bytes. + public bool SyQuestReadLong10(out byte[] buffer, out byte[] senseBuffer, uint lba, uint blockSize, uint timeout, out double duration) + { + return SyQuestRead10(out buffer, out senseBuffer, lba, blockSize, 1, false, true, timeout, out duration); + } + + /// + /// Sends the SyQuest READ (10) command + /// + /// true if the command failed and contains the sense buffer. + /// Buffer where the SCSI READ response will be stored + /// Sense buffer. + /// Timeout in seconds. + /// Duration in milliseconds it took for the device to execute the command. + /// Starting block. + /// If set to true, block will not be transfer and will reside in the drive's buffer. + /// If set to true drive will return ECC bytes and disable error detection. + /// Block size in bytes. + /// How many blocks to read. + public bool SyQuestRead10(out byte[] buffer, out byte[] senseBuffer, uint lba, uint blockSize, ushort transferLength, bool inhibitDma, bool readLong, uint timeout, out double duration) + { + senseBuffer = new byte[32]; + byte[] cdb = new byte[10]; + bool sense; + + cdb[0] = (byte)ScsiCommands.Read10; + cdb[2] = (byte)((lba & 0xFF000000) >> 24); + cdb[3] = (byte)((lba & 0xFF0000) >> 16); + cdb[4] = (byte)((lba & 0xFF00) >> 8); + cdb[5] = (byte)(lba & 0xFF); + cdb[7] = (byte)((transferLength & 0xFF00) >> 8); + cdb[8] = (byte)(transferLength & 0xFF); + if (inhibitDma) + cdb[9] += 0x80; + if (readLong) + cdb[9] += 0x40; + + if (!inhibitDma && !readLong) + { + buffer = new byte[transferLength * blockSize]; + } + else if(readLong) + { + buffer = new byte[blockSize]; + cdb[4] = 1; + } + else + buffer = new byte[0]; + + if (!inhibitDma) + lastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration, out sense); + else + lastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.None, out duration, out sense); + error = lastError != 0; + + DicConsole.DebugWriteLine("SCSI Device", "SYQUEST READ (10) took {0} ms.", duration); + + return sense; + } + } +} + diff --git a/DiscImageChef.Devices/DiscImageChef.Devices.csproj b/DiscImageChef.Devices/DiscImageChef.Devices.csproj index c1e526ef..3a82c25a 100644 --- a/DiscImageChef.Devices/DiscImageChef.Devices.csproj +++ b/DiscImageChef.Devices/DiscImageChef.Devices.csproj @@ -65,6 +65,7 @@ +