2015-10-12 06:39:31 +01:00
|
|
|
|
// /***************************************************************************
|
|
|
|
|
|
// The Disc Image Chef
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
|
//
|
|
|
|
|
|
// Filename : Command.cs
|
2016-07-28 18:13:49 +01:00
|
|
|
|
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
2015-10-12 06:39:31 +01:00
|
|
|
|
//
|
2016-07-28 18:13:49 +01:00
|
|
|
|
// Component : Linux direct device access.
|
2015-10-12 06:39:31 +01:00
|
|
|
|
//
|
|
|
|
|
|
// --[ Description ] ----------------------------------------------------------
|
|
|
|
|
|
//
|
2016-07-28 18:13:49 +01:00
|
|
|
|
// Contains a high level representation of the Linux syscalls used to
|
|
|
|
|
|
// directly interface devices.
|
2015-10-12 06:39:31 +01: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
|
2015-10-12 06:39:31 +01: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.
|
2015-10-12 06:39:31 +01: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/>.
|
2015-10-12 06:39:31 +01:00
|
|
|
|
//
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
2016-07-28 18:13:49 +01:00
|
|
|
|
// Copyright © 2011-2016 Natalia Portillo
|
2015-10-12 06:39:31 +01:00
|
|
|
|
// ****************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
using System;
|
2015-10-12 06:25:49 +01:00
|
|
|
|
using System.Runtime.InteropServices;
|
2015-11-23 04:26:53 +00:00
|
|
|
|
using DiscImageChef.Decoders.ATA;
|
2015-10-12 06:25:49 +01:00
|
|
|
|
|
|
|
|
|
|
namespace DiscImageChef.Devices.Linux
|
|
|
|
|
|
{
|
|
|
|
|
|
static class Command
|
|
|
|
|
|
{
|
2015-10-12 20:08:56 +01:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Sends a SCSI command
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns>0 if no error occurred, otherwise, errno</returns>
|
|
|
|
|
|
/// <param name="fd">File handle</param>
|
|
|
|
|
|
/// <param name="cdb">SCSI CDB</param>
|
|
|
|
|
|
/// <param name="buffer">Buffer for SCSI command response</param>
|
|
|
|
|
|
/// <param name="senseBuffer">Buffer with the SCSI sense</param>
|
|
|
|
|
|
/// <param name="timeout">Timeout in seconds</param>
|
|
|
|
|
|
/// <param name="direction">SCSI command transfer direction</param>
|
|
|
|
|
|
/// <param name="duration">Time it took to execute the command in milliseconds</param>
|
|
|
|
|
|
/// <param name="sense"><c>True</c> if SCSI error returned non-OK status and <paramref name="senseBuffer"/> contains SCSI sense</param>
|
2015-10-12 06:25:49 +01:00
|
|
|
|
internal static int SendScsiCommand(int fd, byte[] cdb, ref byte[] buffer, out byte[] senseBuffer, uint timeout, ScsiIoctlDirection direction, out double duration, out bool sense)
|
|
|
|
|
|
{
|
|
|
|
|
|
senseBuffer = null;
|
|
|
|
|
|
duration = 0;
|
|
|
|
|
|
sense = false;
|
|
|
|
|
|
|
2016-04-19 02:11:47 +01:00
|
|
|
|
if(buffer == null)
|
2015-10-12 06:25:49 +01:00
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
|
|
sg_io_hdr_t io_hdr = new sg_io_hdr_t();
|
|
|
|
|
|
|
|
|
|
|
|
senseBuffer = new byte[32];
|
|
|
|
|
|
|
|
|
|
|
|
io_hdr.interface_id = 'S';
|
|
|
|
|
|
io_hdr.cmd_len = (byte)cdb.Length;
|
|
|
|
|
|
io_hdr.mx_sb_len = (byte)senseBuffer.Length;
|
|
|
|
|
|
io_hdr.dxfer_direction = direction;
|
|
|
|
|
|
io_hdr.dxfer_len = (uint)buffer.Length;
|
|
|
|
|
|
io_hdr.dxferp = Marshal.AllocHGlobal(buffer.Length);
|
|
|
|
|
|
io_hdr.cmdp = Marshal.AllocHGlobal(cdb.Length);
|
|
|
|
|
|
io_hdr.sbp = Marshal.AllocHGlobal(senseBuffer.Length);
|
|
|
|
|
|
io_hdr.timeout = timeout * 1000;
|
|
|
|
|
|
|
|
|
|
|
|
Marshal.Copy(buffer, 0, io_hdr.dxferp, buffer.Length);
|
|
|
|
|
|
Marshal.Copy(cdb, 0, io_hdr.cmdp, cdb.Length);
|
|
|
|
|
|
Marshal.Copy(senseBuffer, 0, io_hdr.sbp, senseBuffer.Length);
|
|
|
|
|
|
|
2016-02-10 03:00:39 +00:00
|
|
|
|
DateTime start = DateTime.UtcNow;
|
2015-10-12 06:25:49 +01:00
|
|
|
|
int error = Extern.ioctlSg(fd, LinuxIoctl.SG_IO, ref io_hdr);
|
2016-02-10 03:00:39 +00:00
|
|
|
|
DateTime end = DateTime.UtcNow;
|
2015-10-12 06:25:49 +01:00
|
|
|
|
|
2016-04-19 02:11:47 +01:00
|
|
|
|
if(error < 0)
|
2015-10-12 06:25:49 +01:00
|
|
|
|
error = Marshal.GetLastWin32Error();
|
|
|
|
|
|
|
|
|
|
|
|
Marshal.Copy(io_hdr.dxferp, buffer, 0, buffer.Length);
|
|
|
|
|
|
Marshal.Copy(io_hdr.cmdp, cdb, 0, cdb.Length);
|
|
|
|
|
|
Marshal.Copy(io_hdr.sbp, senseBuffer, 0, senseBuffer.Length);
|
|
|
|
|
|
|
|
|
|
|
|
sense |= (io_hdr.info & SgInfo.OkMask) != SgInfo.Ok;
|
|
|
|
|
|
|
2016-04-19 02:11:47 +01:00
|
|
|
|
if(io_hdr.duration > 0)
|
2016-02-10 03:00:39 +00:00
|
|
|
|
duration = (double)io_hdr.duration;
|
|
|
|
|
|
else
|
|
|
|
|
|
duration = (end - start).TotalMilliseconds;
|
2015-10-12 06:25:49 +01:00
|
|
|
|
|
2015-12-30 11:45:27 +00:00
|
|
|
|
Marshal.FreeHGlobal(io_hdr.dxferp);
|
|
|
|
|
|
Marshal.FreeHGlobal(io_hdr.cmdp);
|
|
|
|
|
|
Marshal.FreeHGlobal(io_hdr.sbp);
|
|
|
|
|
|
|
2015-10-12 06:25:49 +01:00
|
|
|
|
return error;
|
|
|
|
|
|
}
|
2015-10-14 02:53:46 +01:00
|
|
|
|
|
2015-10-19 04:39:39 +01:00
|
|
|
|
static ScsiIoctlDirection AtaProtocolToScsiDirection(AtaProtocol protocol)
|
2015-10-14 02:53:46 +01:00
|
|
|
|
{
|
2016-04-19 02:11:47 +01:00
|
|
|
|
switch(protocol)
|
2015-10-14 02:53:46 +01:00
|
|
|
|
{
|
2015-10-19 04:39:39 +01:00
|
|
|
|
case AtaProtocol.DeviceDiagnostic:
|
|
|
|
|
|
case AtaProtocol.DeviceReset:
|
|
|
|
|
|
case AtaProtocol.HardReset:
|
|
|
|
|
|
case AtaProtocol.NonData:
|
|
|
|
|
|
case AtaProtocol.SoftReset:
|
|
|
|
|
|
case AtaProtocol.ReturnResponse:
|
2015-10-14 02:53:46 +01:00
|
|
|
|
return ScsiIoctlDirection.None;
|
2015-10-19 04:39:39 +01:00
|
|
|
|
case AtaProtocol.PioIn:
|
|
|
|
|
|
case AtaProtocol.UDmaIn:
|
2015-10-15 01:46:31 +01:00
|
|
|
|
return ScsiIoctlDirection.In;
|
2015-10-19 04:39:39 +01:00
|
|
|
|
case AtaProtocol.PioOut:
|
|
|
|
|
|
case AtaProtocol.UDmaOut:
|
2015-10-15 01:46:31 +01:00
|
|
|
|
return ScsiIoctlDirection.Out;
|
2015-10-14 02:53:46 +01:00
|
|
|
|
default:
|
|
|
|
|
|
return ScsiIoctlDirection.Unspecified;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2015-10-19 04:39:39 +01:00
|
|
|
|
internal static int SendAtaCommand(int fd, AtaRegistersCHS registers,
|
|
|
|
|
|
out AtaErrorRegistersCHS errorRegisters, AtaProtocol protocol,
|
|
|
|
|
|
AtaTransferRegister transferRegister, ref byte[] buffer, uint timeout,
|
2015-10-14 02:53:46 +01:00
|
|
|
|
bool transferBlocks, out double duration, out bool sense)
|
|
|
|
|
|
{
|
|
|
|
|
|
duration = 0;
|
|
|
|
|
|
sense = false;
|
2015-10-19 04:39:39 +01:00
|
|
|
|
errorRegisters = new AtaErrorRegistersCHS();
|
2015-10-14 02:53:46 +01:00
|
|
|
|
|
2016-04-19 02:11:47 +01:00
|
|
|
|
if(buffer == null)
|
2015-10-14 02:53:46 +01:00
|
|
|
|
return -1;
|
|
|
|
|
|
|
2015-10-15 01:46:31 +01:00
|
|
|
|
byte[] cdb = new byte[16];
|
2015-10-19 04:39:39 +01:00
|
|
|
|
cdb[0] = (byte)ScsiCommands.AtaPassThrough16;
|
2015-10-14 02:53:46 +01:00
|
|
|
|
cdb[1] = (byte)(((byte)protocol << 1) & 0x1E);
|
2016-04-19 02:11:47 +01:00
|
|
|
|
if(transferRegister != AtaTransferRegister.NoTransfer &&
|
2015-10-19 04:39:39 +01:00
|
|
|
|
protocol != AtaProtocol.NonData)
|
2015-10-14 02:53:46 +01:00
|
|
|
|
{
|
2016-04-19 02:11:47 +01:00
|
|
|
|
switch(protocol)
|
2015-10-14 02:53:46 +01:00
|
|
|
|
{
|
2015-10-19 04:39:39 +01:00
|
|
|
|
case AtaProtocol.PioIn:
|
|
|
|
|
|
case AtaProtocol.UDmaIn:
|
2015-10-14 02:53:46 +01:00
|
|
|
|
cdb[2] = 0x08;
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
cdb[2] = 0x00;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-04-19 02:11:47 +01:00
|
|
|
|
if(transferBlocks)
|
2015-10-14 02:53:46 +01:00
|
|
|
|
cdb[2] |= 0x04;
|
|
|
|
|
|
|
|
|
|
|
|
cdb[2] |= (byte)((int)transferRegister & 0x03);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2015-10-15 01:46:31 +01:00
|
|
|
|
cdb[2] |= 0x20;
|
|
|
|
|
|
|
|
|
|
|
|
cdb[4] = registers.feature;
|
|
|
|
|
|
cdb[6] = registers.sectorCount;
|
|
|
|
|
|
cdb[8] = registers.sector;
|
|
|
|
|
|
cdb[10] = registers.cylinderLow;
|
|
|
|
|
|
cdb[12] = registers.cylinderHigh;
|
|
|
|
|
|
cdb[13] = registers.deviceHead;
|
|
|
|
|
|
cdb[14] = registers.command;
|
2015-10-14 02:53:46 +01:00
|
|
|
|
|
|
|
|
|
|
byte[] senseBuffer;
|
|
|
|
|
|
int error = SendScsiCommand(fd, cdb, ref buffer, out senseBuffer, timeout, AtaProtocolToScsiDirection(protocol), out duration, out sense);
|
|
|
|
|
|
|
2016-04-19 02:11:47 +01:00
|
|
|
|
if(senseBuffer.Length < 22 || (senseBuffer[8] != 0x09 && senseBuffer[9] != 0x0C))
|
2015-10-14 02:53:46 +01:00
|
|
|
|
return error;
|
|
|
|
|
|
|
2015-10-15 01:46:31 +01:00
|
|
|
|
errorRegisters.error = senseBuffer[11];
|
2015-10-14 02:53:46 +01:00
|
|
|
|
|
2015-10-15 01:46:31 +01:00
|
|
|
|
errorRegisters.sectorCount = senseBuffer[13];
|
|
|
|
|
|
errorRegisters.sector = senseBuffer[15];
|
|
|
|
|
|
errorRegisters.cylinderLow = senseBuffer[17];
|
|
|
|
|
|
errorRegisters.cylinderHigh = senseBuffer[19];
|
|
|
|
|
|
errorRegisters.deviceHead = senseBuffer[20];
|
|
|
|
|
|
errorRegisters.status = senseBuffer[21];
|
|
|
|
|
|
|
|
|
|
|
|
sense = errorRegisters.error != 0 || (errorRegisters.status & 0xA5) != 0;
|
2015-10-14 02:53:46 +01:00
|
|
|
|
|
|
|
|
|
|
return error;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2015-10-19 04:39:39 +01:00
|
|
|
|
internal static int SendAtaCommand(int fd, AtaRegistersLBA28 registers,
|
|
|
|
|
|
out AtaErrorRegistersLBA28 errorRegisters, AtaProtocol protocol,
|
|
|
|
|
|
AtaTransferRegister transferRegister, ref byte[] buffer, uint timeout,
|
2015-10-14 02:53:46 +01:00
|
|
|
|
bool transferBlocks, out double duration, out bool sense)
|
|
|
|
|
|
{
|
|
|
|
|
|
duration = 0;
|
|
|
|
|
|
sense = false;
|
2015-10-19 04:39:39 +01:00
|
|
|
|
errorRegisters = new AtaErrorRegistersLBA28();
|
2015-10-14 02:53:46 +01:00
|
|
|
|
|
2016-04-19 02:11:47 +01:00
|
|
|
|
if(buffer == null)
|
2015-10-14 02:53:46 +01:00
|
|
|
|
return -1;
|
|
|
|
|
|
|
2015-10-15 01:46:31 +01:00
|
|
|
|
byte[] cdb = new byte[16];
|
2015-10-19 04:39:39 +01:00
|
|
|
|
cdb[0] = (byte)ScsiCommands.AtaPassThrough16;
|
2015-10-14 02:53:46 +01:00
|
|
|
|
cdb[1] = (byte)(((byte)protocol << 1) & 0x1E);
|
2016-04-19 02:11:47 +01:00
|
|
|
|
if(transferRegister != AtaTransferRegister.NoTransfer &&
|
2015-10-19 04:39:39 +01:00
|
|
|
|
protocol != AtaProtocol.NonData)
|
2015-10-14 02:53:46 +01:00
|
|
|
|
{
|
2016-04-19 02:11:47 +01:00
|
|
|
|
switch(protocol)
|
2015-10-14 02:53:46 +01:00
|
|
|
|
{
|
2015-10-19 04:39:39 +01:00
|
|
|
|
case AtaProtocol.PioIn:
|
|
|
|
|
|
case AtaProtocol.UDmaIn:
|
2015-10-14 02:53:46 +01:00
|
|
|
|
cdb[2] = 0x08;
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
cdb[2] = 0x00;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-04-19 02:11:47 +01:00
|
|
|
|
if(transferBlocks)
|
2015-10-14 02:53:46 +01:00
|
|
|
|
cdb[2] |= 0x04;
|
|
|
|
|
|
|
|
|
|
|
|
cdb[2] |= (byte)((int)transferRegister & 0x03);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2015-10-15 01:46:31 +01:00
|
|
|
|
cdb[2] |= 0x20;
|
|
|
|
|
|
|
|
|
|
|
|
cdb[4] = registers.feature;
|
|
|
|
|
|
cdb[6] = registers.sectorCount;
|
|
|
|
|
|
cdb[8] = registers.lbaLow;
|
|
|
|
|
|
cdb[10] = registers.lbaMid;
|
|
|
|
|
|
cdb[12] = registers.lbaHigh;
|
|
|
|
|
|
cdb[13] = registers.deviceHead;
|
|
|
|
|
|
cdb[14] = registers.command;
|
2015-10-14 02:53:46 +01:00
|
|
|
|
|
|
|
|
|
|
byte[] senseBuffer;
|
|
|
|
|
|
int error = SendScsiCommand(fd, cdb, ref buffer, out senseBuffer, timeout, AtaProtocolToScsiDirection(protocol), out duration, out sense);
|
|
|
|
|
|
|
2016-04-19 02:11:47 +01:00
|
|
|
|
if(senseBuffer.Length < 22 || (senseBuffer[8] != 0x09 && senseBuffer[9] != 0x0C))
|
2015-10-14 02:53:46 +01:00
|
|
|
|
return error;
|
|
|
|
|
|
|
2015-10-15 01:46:31 +01:00
|
|
|
|
errorRegisters.error = senseBuffer[11];
|
2015-10-14 02:53:46 +01:00
|
|
|
|
|
2015-10-15 01:46:31 +01:00
|
|
|
|
errorRegisters.sectorCount = senseBuffer[13];
|
|
|
|
|
|
errorRegisters.lbaLow = senseBuffer[15];
|
|
|
|
|
|
errorRegisters.lbaMid = senseBuffer[17];
|
|
|
|
|
|
errorRegisters.lbaHigh = senseBuffer[19];
|
|
|
|
|
|
errorRegisters.deviceHead = senseBuffer[20];
|
|
|
|
|
|
errorRegisters.status = senseBuffer[21];
|
|
|
|
|
|
|
|
|
|
|
|
sense = errorRegisters.error != 0 || (errorRegisters.status & 0xA5) != 0;
|
2015-10-14 02:53:46 +01:00
|
|
|
|
|
|
|
|
|
|
return error;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2015-10-19 04:39:39 +01:00
|
|
|
|
internal static int SendAtaCommand(int fd, AtaRegistersLBA48 registers,
|
|
|
|
|
|
out AtaErrorRegistersLBA48 errorRegisters, AtaProtocol protocol,
|
|
|
|
|
|
AtaTransferRegister transferRegister, ref byte[] buffer, uint timeout,
|
2015-10-14 02:53:46 +01:00
|
|
|
|
bool transferBlocks, out double duration, out bool sense)
|
|
|
|
|
|
{
|
|
|
|
|
|
duration = 0;
|
|
|
|
|
|
sense = false;
|
2015-10-19 04:39:39 +01:00
|
|
|
|
errorRegisters = new AtaErrorRegistersLBA48();
|
2015-10-14 02:53:46 +01:00
|
|
|
|
|
2016-04-19 02:11:47 +01:00
|
|
|
|
if(buffer == null)
|
2015-10-14 02:53:46 +01:00
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
|
|
byte[] cdb = new byte[16];
|
2015-10-19 04:39:39 +01:00
|
|
|
|
cdb[0] = (byte)ScsiCommands.AtaPassThrough16;
|
2015-10-14 02:53:46 +01:00
|
|
|
|
cdb[1] |= 0x01;
|
|
|
|
|
|
cdb[1] = (byte)(((byte)protocol << 1) & 0x1E);
|
2016-04-19 02:11:47 +01:00
|
|
|
|
if(transferRegister != AtaTransferRegister.NoTransfer &&
|
2015-10-19 04:39:39 +01:00
|
|
|
|
protocol != AtaProtocol.NonData)
|
2015-10-14 02:53:46 +01:00
|
|
|
|
{
|
2016-04-19 02:11:47 +01:00
|
|
|
|
switch(protocol)
|
2015-10-14 02:53:46 +01:00
|
|
|
|
{
|
2015-10-19 04:39:39 +01:00
|
|
|
|
case AtaProtocol.PioIn:
|
|
|
|
|
|
case AtaProtocol.UDmaIn:
|
2015-10-14 02:53:46 +01:00
|
|
|
|
cdb[2] = 0x08;
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
cdb[2] = 0x00;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-04-19 02:11:47 +01:00
|
|
|
|
if(transferBlocks)
|
2015-10-14 02:53:46 +01:00
|
|
|
|
cdb[2] |= 0x04;
|
|
|
|
|
|
|
|
|
|
|
|
cdb[2] |= (byte)((int)transferRegister & 0x03);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2015-10-15 01:46:31 +01:00
|
|
|
|
cdb[2] |= 0x20;
|
|
|
|
|
|
|
2015-10-14 02:53:46 +01:00
|
|
|
|
cdb[3] = (byte)((registers.feature & 0xFF00) >> 8);
|
|
|
|
|
|
cdb[4] = (byte)(registers.feature & 0xFF);
|
|
|
|
|
|
cdb[5] = (byte)((registers.sectorCount & 0xFF00) >> 8);
|
|
|
|
|
|
cdb[6] = (byte)(registers.sectorCount & 0xFF);
|
|
|
|
|
|
cdb[7] = (byte)((registers.lbaLow & 0xFF00) >> 8);
|
|
|
|
|
|
cdb[8] = (byte)(registers.lbaLow & 0xFF);
|
|
|
|
|
|
cdb[9] = (byte)((registers.lbaMid & 0xFF00) >> 8);
|
|
|
|
|
|
cdb[10] = (byte)(registers.lbaMid & 0xFF);
|
|
|
|
|
|
cdb[11] = (byte)((registers.lbaHigh & 0xFF00) >> 8);
|
|
|
|
|
|
cdb[12] = (byte)(registers.lbaHigh & 0xFF);
|
|
|
|
|
|
cdb[13] = registers.deviceHead;
|
|
|
|
|
|
cdb[14] = registers.command;
|
|
|
|
|
|
|
|
|
|
|
|
byte[] senseBuffer;
|
|
|
|
|
|
int error = SendScsiCommand(fd, cdb, ref buffer, out senseBuffer, timeout, AtaProtocolToScsiDirection(protocol), out duration, out sense);
|
|
|
|
|
|
|
2016-04-19 02:11:47 +01:00
|
|
|
|
if(senseBuffer.Length < 22 || (senseBuffer[8] != 0x09 && senseBuffer[9] != 0x0C))
|
2015-10-14 02:53:46 +01:00
|
|
|
|
return error;
|
|
|
|
|
|
|
2015-10-15 01:46:31 +01:00
|
|
|
|
errorRegisters.error = senseBuffer[11];
|
|
|
|
|
|
|
|
|
|
|
|
errorRegisters.sectorCount = (ushort)((senseBuffer[12] << 8) + senseBuffer[13]);
|
|
|
|
|
|
errorRegisters.lbaLow = (ushort)((senseBuffer[14] << 8) + senseBuffer[15]);
|
|
|
|
|
|
errorRegisters.lbaMid = (ushort)((senseBuffer[16] << 8) + senseBuffer[17]);
|
|
|
|
|
|
errorRegisters.lbaHigh = (ushort)((senseBuffer[18] << 8) + senseBuffer[19]);
|
|
|
|
|
|
errorRegisters.deviceHead = senseBuffer[20];
|
|
|
|
|
|
errorRegisters.status = senseBuffer[21];
|
2015-10-14 02:53:46 +01:00
|
|
|
|
|
2015-10-15 01:46:31 +01:00
|
|
|
|
sense = errorRegisters.error != 0 || (errorRegisters.status & 0xA5) != 0;
|
2015-10-14 02:53:46 +01:00
|
|
|
|
|
|
|
|
|
|
sense |= error != 0;
|
|
|
|
|
|
|
|
|
|
|
|
return error;
|
|
|
|
|
|
}
|
2015-12-31 16:12:22 +00:00
|
|
|
|
|
|
|
|
|
|
public static string ReadLink(string path)
|
|
|
|
|
|
{
|
* 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
|
|
|
|
IntPtr buf = Marshal.AllocHGlobal(4096);
|
2015-12-31 16:12:22 +00:00
|
|
|
|
int resultSize;
|
|
|
|
|
|
|
2016-04-19 02:11:47 +01:00
|
|
|
|
if(Interop.DetectOS.Is64Bit())
|
2015-12-31 16:12:22 +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
|
|
|
|
long result64 = Extern.readlink64(path, buf, (long)4096);
|
2016-04-19 02:11:47 +01:00
|
|
|
|
if(result64 <= 0)
|
2015-12-31 16:12:22 +00:00
|
|
|
|
return null;
|
2016-04-19 02:11:47 +01:00
|
|
|
|
|
2015-12-31 16:12:22 +00:00
|
|
|
|
resultSize = (int)result64;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
* 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
|
|
|
|
int result = Extern.readlink(path, buf, 4096);
|
2016-04-19 02:11:47 +01:00
|
|
|
|
if(result <= 0)
|
2015-12-31 16:12:22 +00:00
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
|
|
resultSize = result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
byte[] resultString = new byte[resultSize];
|
|
|
|
|
|
Marshal.Copy(buf, resultString, 0, resultSize);
|
|
|
|
|
|
Marshal.FreeHGlobal(buf);
|
|
|
|
|
|
return System.Text.Encoding.ASCII.GetString(resultString);
|
|
|
|
|
|
}
|
2015-10-12 06:25:49 +01:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|