diff --git a/DiscImageChef.Devices/ChangeLog b/DiscImageChef.Devices/ChangeLog index 09da064bb..1d5be10a7 100644 --- a/DiscImageChef.Devices/ChangeLog +++ b/DiscImageChef.Devices/ChangeLog @@ -1,3 +1,20 @@ +2016-02-08 Natalia Portillo + + * Device/AtaCommands/Cfa.cs: + * Device/AtaCommands/MCPT.cs: + * Device/AtaCommands/Ata28.cs: + * Device/AtaCommands/Ata48.cs: + * Device/AtaCommands/Smart.cs: + * Device/AtaCommands/AtaCHS.cs: + * DiscImageChef.Devices.csproj: + Implemented ATA commands. + + * Device/ScsiCommands/SPC.cs: + Make MODE SENSE (6) buffer big enought. + + * Enums.cs: + Added new command found in ACS-3 rev. 6 + 2016-02-07 Natalia Portillo * Device/AtaCommands/Ata28.cs: diff --git a/DiscImageChef.Devices/Device/AtaCommands/Ata28.cs b/DiscImageChef.Devices/Device/AtaCommands/Ata28.cs index f40966671..0ce3527c3 100644 --- a/DiscImageChef.Devices/Device/AtaCommands/Ata28.cs +++ b/DiscImageChef.Devices/Device/AtaCommands/Ata28.cs @@ -43,6 +43,215 @@ namespace DiscImageChef.Devices { public partial class Device { + public bool ReadBuffer(out byte[] buffer, out AtaErrorRegistersLBA28 statusRegisters, uint timeout, out double duration) + { + buffer = new byte[512]; + AtaRegistersLBA28 registers = new AtaRegistersLBA28(); + bool sense; + + registers.command = (byte)AtaCommands.ReadBuffer; + + lastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn, AtaTransferRegister.NoTransfer, + ref buffer, timeout, false, out duration, out sense); + error = lastError != 0; + + DicConsole.DebugWriteLine("ATA Device", "READ BUFFER took {0} ms.", duration); + + return sense; + } + + public bool ReadBufferDma(out byte[] buffer, out AtaErrorRegistersLBA28 statusRegisters, uint timeout, out double duration) + { + buffer = new byte[512]; + AtaRegistersLBA28 registers = new AtaRegistersLBA28(); + bool sense; + + registers.command = (byte)AtaCommands.ReadBufferDma; + + lastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.Dma, AtaTransferRegister.NoTransfer, + ref buffer, timeout, false, out duration, out sense); + error = lastError != 0; + + DicConsole.DebugWriteLine("ATA Device", "READ BUFFER DMA took {0} ms.", duration); + + return sense; + } + + public bool ReadDma(out byte[] buffer, out AtaErrorRegistersLBA28 statusRegisters, uint lba, byte count, uint timeout, out double duration) + { + return ReadDma(out buffer, out statusRegisters, true, lba, count, timeout, out duration); + } + + public bool ReadDma(out byte[] buffer, out AtaErrorRegistersLBA28 statusRegisters, bool retry, uint lba, byte count, uint timeout, out double duration) + { + if (count == 0) + buffer = new byte[512 * 256]; + else + buffer = new byte[512 * count]; + AtaRegistersLBA28 registers = new AtaRegistersLBA28(); + bool sense; + + if(retry) + registers.command = (byte)AtaCommands.ReadDmaRetry; + else + registers.command = (byte)AtaCommands.ReadDma; + registers.sectorCount = count; + registers.deviceHead = (byte)((lba & 0xF000000) / 0x1000000); + registers.lbaHigh = (byte)((lba & 0xFF0000) / 0x10000); + registers.lbaMid = (byte)((lba & 0xFF00) / 0x100); + registers.lbaLow = (byte)((lba & 0xFF) / 0x1); + registers.deviceHead += 0x40; + + lastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.Dma, AtaTransferRegister.SectorCount, + ref buffer, timeout, true, out duration, out sense); + error = lastError != 0; + + DicConsole.DebugWriteLine("ATA Device", "READ DMA took {0} ms.", duration); + + return sense; + } + + public bool ReadMultiple(out byte[] buffer, out AtaErrorRegistersLBA28 statusRegisters, uint lba, byte count, uint timeout, out double duration) + { + if (count == 0) + buffer = new byte[512 * 256]; + else + buffer = new byte[512 * count]; + AtaRegistersLBA28 registers = new AtaRegistersLBA28(); + bool sense; + + registers.command = (byte)AtaCommands.ReadMultiple; + registers.sectorCount = count; + registers.deviceHead = (byte)((lba & 0xF000000) / 0x1000000); + registers.lbaHigh = (byte)((lba & 0xFF0000) / 0x10000); + registers.lbaMid = (byte)((lba & 0xFF00) / 0x100); + registers.lbaLow = (byte)((lba & 0xFF) / 0x1); + registers.deviceHead += 0x40; + + lastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn, AtaTransferRegister.SectorCount, + ref buffer, timeout, true, out duration, out sense); + error = lastError != 0; + + DicConsole.DebugWriteLine("ATA Device", "READ MULTIPLE took {0} ms.", duration); + + return sense; + } + + public bool ReadNativeMaxAddress(out uint lba, out AtaErrorRegistersLBA28 statusRegisters, uint timeout, out double duration) + { + lba = 0; + byte[] buffer = new byte[0]; + AtaRegistersLBA28 registers = new AtaRegistersLBA28(); + bool sense; + + registers.command = (byte)AtaCommands.ReadNativeMaxAddress; + registers.deviceHead += 0x40; + + lastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.NonData, AtaTransferRegister.NoTransfer, + ref buffer, timeout, false, out duration, out sense); + error = lastError != 0; + + if ((statusRegisters.status & 0x23) == 0) + { + lba += (uint)(statusRegisters.deviceHead & 0xF); + lba *= 0x1000000; + lba += (uint)(statusRegisters.lbaHigh << 16); + lba += (uint)(statusRegisters.lbaMid << 8); + lba += statusRegisters.lbaLow; + } + + DicConsole.DebugWriteLine("ATA Device", "READ NATIVE MAX ADDRESS took {0} ms.", duration); + + return sense; + } + + public bool Read(out byte[] buffer, out AtaErrorRegistersLBA28 statusRegisters, uint lba, byte count, uint timeout, out double duration) + { + return Read(out buffer, out statusRegisters, true, lba, count, timeout, out duration); + } + + public bool Read(out byte[] buffer, out AtaErrorRegistersLBA28 statusRegisters, bool retry, uint lba, byte count, uint timeout, out double duration) + { + if (count == 0) + buffer = new byte[512 * 256]; + else + buffer = new byte[512 * count]; + AtaRegistersLBA28 registers = new AtaRegistersLBA28(); + bool sense; + + if(retry) + registers.command = (byte)AtaCommands.ReadRetry; + else + registers.command = (byte)AtaCommands.Read; + registers.sectorCount = count; + registers.deviceHead = (byte)((lba & 0xF000000) / 0x1000000); + registers.lbaHigh = (byte)((lba & 0xFF0000) / 0x10000); + registers.lbaMid = (byte)((lba & 0xFF00) / 0x100); + registers.lbaLow = (byte)((lba & 0xFF) / 0x1); + registers.deviceHead += 0x40; + + lastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn, AtaTransferRegister.SectorCount, + ref buffer, timeout, true, out duration, out sense); + error = lastError != 0; + + DicConsole.DebugWriteLine("ATA Device", "READ SECTORS took {0} ms.", duration); + + return sense; + } + + + public bool ReadLong(out byte[] buffer, out AtaErrorRegistersLBA28 statusRegisters, uint lba, uint blockSize, uint timeout, out double duration) + { + return ReadLong(out buffer, out statusRegisters, true, lba, blockSize, timeout, out duration); + } + + public bool ReadLong(out byte[] buffer, out AtaErrorRegistersLBA28 statusRegisters, bool retry, uint lba, uint blockSize, uint timeout, out double duration) + { + buffer = new byte[blockSize]; + AtaRegistersLBA28 registers = new AtaRegistersLBA28(); + bool sense; + + if(retry) + registers.command = (byte)AtaCommands.ReadLongRetry; + else + registers.command = (byte)AtaCommands.ReadLong; + registers.sectorCount = 1; + registers.deviceHead = (byte)((lba & 0xF000000) / 0x1000000); + registers.lbaHigh = (byte)((lba & 0xFF0000) / 0x10000); + registers.lbaMid = (byte)((lba & 0xFF00) / 0x100); + registers.lbaLow = (byte)((lba & 0xFF) / 0x1); + registers.deviceHead += 0x40; + + lastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn, AtaTransferRegister.SectorCount, + ref buffer, timeout, true, out duration, out sense); + error = lastError != 0; + + DicConsole.DebugWriteLine("ATA Device", "READ LONG took {0} ms.", duration); + + return sense; + } + + public bool Seek(out AtaErrorRegistersLBA28 statusRegisters, uint lba, uint timeout, out double duration) + { + byte[] buffer = new byte[0]; + AtaRegistersLBA28 registers = new AtaRegistersLBA28(); + bool sense; + + registers.command = (byte)AtaCommands.Seek; + registers.deviceHead = (byte)((lba & 0xF000000) / 0x1000000); + registers.lbaHigh = (byte)((lba & 0xFF0000) / 0x10000); + registers.lbaMid = (byte)((lba & 0xFF00) / 0x100); + registers.lbaLow = (byte)((lba & 0xFF) / 0x1); + registers.deviceHead += 0x40; + + lastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn, AtaTransferRegister.SectorCount, + ref buffer, timeout, true, out duration, out sense); + error = lastError != 0; + + DicConsole.DebugWriteLine("ATA Device", "SEEK took {0} ms.", duration); + + return sense; + } } } diff --git a/DiscImageChef.Devices/Device/AtaCommands/Ata48.cs b/DiscImageChef.Devices/Device/AtaCommands/Ata48.cs index 00575f611..d32fed57e 100644 --- a/DiscImageChef.Devices/Device/AtaCommands/Ata48.cs +++ b/DiscImageChef.Devices/Device/AtaCommands/Ata48.cs @@ -43,5 +43,175 @@ namespace DiscImageChef.Devices { public partial class Device { + public bool GetNativeMaxAddressExt(out ulong lba, out AtaErrorRegistersLBA48 statusRegisters, uint timeout, out double duration) + { + lba = 0; + AtaRegistersLBA48 registers = new AtaRegistersLBA48(); + bool sense; + byte[] buffer = new byte[0]; + + registers.command = (byte)AtaCommands.NativeMaxAddress; + registers.feature = 0x0000; + + lastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.NonData, AtaTransferRegister.NoTransfer, + ref buffer, timeout, false, out duration, out sense); + error = lastError != 0; + + if ((statusRegisters.status & 0x23) == 0) + { + lba = statusRegisters.lbaHigh; + lba *= 0x100000000; + lba += (ulong)(statusRegisters.lbaMid << 16); + lba += statusRegisters.lbaLow; + } + + DicConsole.DebugWriteLine("ATA Device", "GET NATIVE MAX ADDRESS EXT took {0} ms.", duration); + + return sense; + } + + public bool ReadDma(out byte[] buffer, out AtaErrorRegistersLBA48 statusRegisters, ulong lba, ushort count, uint timeout, out double duration) + { + if (count == 0) + buffer = new byte[512 * 65536]; + else + buffer = new byte[512 * count]; + AtaRegistersLBA48 registers = new AtaRegistersLBA48(); + bool sense; + + registers.command = (byte)AtaCommands.ReadDmaExt; + registers.sectorCount = count; + registers.lbaHigh = (ushort)((lba & 0xFFFF00000000) / 0x100000000); + registers.lbaMid = (ushort)((lba & 0xFFFF0000) / 0x10000); + registers.lbaLow = (ushort)((lba & 0xFFFF) / 0x1); + registers.deviceHead += 0x40; + + lastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.Dma, AtaTransferRegister.SectorCount, + ref buffer, timeout, true, out duration, out sense); + error = lastError != 0; + + DicConsole.DebugWriteLine("ATA Device", "READ DMA EXT took {0} ms.", duration); + + return sense; + } + + public bool ReadLog(out byte[] buffer, out AtaErrorRegistersLBA48 statusRegisters, byte logAddress, ushort pageNumber, ushort count, uint timeout, out double duration) + { + buffer = new byte[512 * count]; + AtaRegistersLBA48 registers = new AtaRegistersLBA48(); + bool sense; + + registers.command = (byte)AtaCommands.ReadLogExt; + registers.sectorCount = count; + registers.lbaLow = (ushort)((pageNumber & 0xFF) * 0x100); + registers.lbaLow += logAddress; + registers.lbaHigh = (ushort)((pageNumber & 0xFF00) / 0x100); + + lastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn, AtaTransferRegister.SectorCount, + ref buffer, timeout, true, out duration, out sense); + error = lastError != 0; + + DicConsole.DebugWriteLine("ATA Device", "READ LOG EXT took {0} ms.", duration); + + return sense; + } + + public bool ReadLogDma(out byte[] buffer, out AtaErrorRegistersLBA48 statusRegisters, byte logAddress, ushort pageNumber, ushort count, uint timeout, out double duration) + { + buffer = new byte[512 * count]; + AtaRegistersLBA48 registers = new AtaRegistersLBA48(); + bool sense; + + registers.command = (byte)AtaCommands.ReadLogDmaExt; + registers.sectorCount = count; + registers.lbaLow = (ushort)((pageNumber & 0xFF) * 0x100); + registers.lbaLow += logAddress; + registers.lbaHigh = (ushort)((pageNumber & 0xFF00) / 0x100); + + lastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.Dma, AtaTransferRegister.SectorCount, + ref buffer, timeout, true, out duration, out sense); + error = lastError != 0; + + DicConsole.DebugWriteLine("ATA Device", "READ LOG DMA EXT took {0} ms.", duration); + + return sense; + } + + public bool ReadMultiple(out byte[] buffer, out AtaErrorRegistersLBA48 statusRegisters, ulong lba, ushort count, uint timeout, out double duration) + { + if (count == 0) + buffer = new byte[512 * 65536]; + else + buffer = new byte[512 * count]; + AtaRegistersLBA48 registers = new AtaRegistersLBA48(); + bool sense; + + registers.command = (byte)AtaCommands.ReadMultipleExt; + registers.sectorCount = count; + registers.lbaHigh = (ushort)((lba & 0xFFFF00000000) / 0x100000000); + registers.lbaMid = (ushort)((lba & 0xFFFF0000) / 0x10000); + registers.lbaLow = (ushort)((lba & 0xFFFF) / 0x1); + registers.deviceHead += 0x40; + + lastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn, AtaTransferRegister.SectorCount, + ref buffer, timeout, true, out duration, out sense); + error = lastError != 0; + + DicConsole.DebugWriteLine("ATA Device", "READ MULTIPLE EXT took {0} ms.", duration); + + return sense; + } + + public bool ReadNativeMaxAddress(out ulong lba, out AtaErrorRegistersLBA48 statusRegisters, uint timeout, out double duration) + { + lba = 0; + byte[] buffer = new byte[0]; + AtaRegistersLBA48 registers = new AtaRegistersLBA48(); + bool sense; + + registers.command = (byte)AtaCommands.ReadNativeMaxAddressExt; + registers.deviceHead += 0x40; + + lastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.NonData, AtaTransferRegister.NoTransfer, + ref buffer, timeout, false, out duration, out sense); + error = lastError != 0; + + if ((statusRegisters.status & 0x23) == 0) + { + lba = statusRegisters.lbaHigh; + lba *= 0x100000000; + lba += (ulong)(statusRegisters.lbaMid << 16); + lba += statusRegisters.lbaLow; + } + + DicConsole.DebugWriteLine("ATA Device", "READ NATIVE MAX ADDRESS EXT took {0} ms.", duration); + + return sense; + } + + public bool Read(out byte[] buffer, out AtaErrorRegistersLBA48 statusRegisters, ulong lba, ushort count, uint timeout, out double duration) + { + if (count == 0) + buffer = new byte[512 * 65536]; + else + buffer = new byte[512 * count]; + AtaRegistersLBA48 registers = new AtaRegistersLBA48(); + bool sense; + + registers.command = (byte)AtaCommands.ReadExt; + registers.sectorCount = count; + registers.lbaHigh = (ushort)((lba & 0xFFFF00000000) / 0x100000000); + registers.lbaMid = (ushort)((lba & 0xFFFF0000) / 0x10000); + registers.lbaLow = (ushort)((lba & 0xFFFF) / 0x1); + registers.deviceHead += 0x40; + + lastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn, AtaTransferRegister.SectorCount, + ref buffer, timeout, true, out duration, out sense); + error = lastError != 0; + + DicConsole.DebugWriteLine("ATA Device", "READ SECTORS EXT took {0} ms.", duration); + + return sense; + } } } \ No newline at end of file diff --git a/DiscImageChef.Devices/Device/AtaCommands/AtaCHS.cs b/DiscImageChef.Devices/Device/AtaCommands/AtaCHS.cs index 433a25737..76c50f3a1 100644 --- a/DiscImageChef.Devices/Device/AtaCommands/AtaCHS.cs +++ b/DiscImageChef.Devices/Device/AtaCommands/AtaCHS.cs @@ -103,6 +103,141 @@ namespace DiscImageChef.Devices return sense; } + + public bool ReadDma(out byte[] buffer, out AtaErrorRegistersCHS statusRegisters, ushort cylinder, byte head, byte sector, byte count, uint timeout, out double duration) + { + return ReadDma(out buffer, out statusRegisters, true, cylinder, head, sector, count, timeout, out duration); + } + + public bool ReadDma(out byte[] buffer, out AtaErrorRegistersCHS statusRegisters, bool retry, ushort cylinder, byte head, byte sector, byte count, uint timeout, out double duration) + { + if (count == 0) + buffer = new byte[512 * 256]; + else + buffer = new byte[512 * count]; + AtaRegistersCHS registers = new AtaRegistersCHS(); + bool sense; + + if(retry) + registers.command = (byte)AtaCommands.ReadDmaRetry; + else + registers.command = (byte)AtaCommands.ReadDma; + registers.sectorCount = count; + registers.cylinderHigh = (byte)((cylinder & 0xFF00) / 0x100); + registers.cylinderLow = (byte)((cylinder & 0xFF) / 0x1); + registers.deviceHead = (byte)(head & 0x0F); + registers.sector = sector; + + lastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.Dma, AtaTransferRegister.SectorCount, + ref buffer, timeout, true, out duration, out sense); + error = lastError != 0; + + DicConsole.DebugWriteLine("ATA Device", "READ DMA took {0} ms.", duration); + + return sense; + } + + public bool ReadMultiple(out byte[] buffer, out AtaErrorRegistersCHS statusRegisters, ushort cylinder, byte head, byte sector, byte count, uint timeout, out double duration) + { + if (count == 0) + buffer = new byte[512 * 256]; + else + buffer = new byte[512 * count]; + AtaRegistersCHS registers = new AtaRegistersCHS(); + bool sense; + + registers.command = (byte)AtaCommands.ReadMultiple; + registers.sectorCount = count; + registers.cylinderHigh = (byte)((cylinder & 0xFF00) / 0x100); + registers.cylinderLow = (byte)((cylinder & 0xFF) / 0x1); + registers.deviceHead = (byte)(head & 0x0F); + registers.sector = sector; + + lastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn, AtaTransferRegister.SectorCount, + ref buffer, timeout, true, out duration, out sense); + error = lastError != 0; + + DicConsole.DebugWriteLine("ATA Device", "READ MULTIPLE took {0} ms.", duration); + + return sense; + } + + + public bool Read(out byte[] buffer, out AtaErrorRegistersCHS statusRegisters, ushort cylinder, byte head, byte sector, byte count, uint timeout, out double duration) + { + if (count == 0) + buffer = new byte[512 * 256]; + else + buffer = new byte[512 * count]; + AtaRegistersCHS registers = new AtaRegistersCHS(); + bool sense; + + registers.command = (byte)AtaCommands.ReadRetry; + registers.sectorCount = count; + registers.cylinderHigh = (byte)((cylinder & 0xFF00) / 0x100); + registers.cylinderLow = (byte)((cylinder & 0xFF) / 0x1); + registers.deviceHead = (byte)(head & 0x0F); + registers.sector = sector; + + lastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn, AtaTransferRegister.SectorCount, + ref buffer, timeout, true, out duration, out sense); + error = lastError != 0; + + DicConsole.DebugWriteLine("ATA Device", "READ SECTORS took {0} ms.", duration); + + return sense; + } + + public bool ReadLong(out byte[] buffer, out AtaErrorRegistersCHS statusRegisters, ushort cylinder, byte head, byte sector, int blockSize, uint timeout, out double duration) + { + return ReadLong(out buffer, out statusRegisters, true, cylinder, head, sector, blockSize, timeout, out duration); + } + + public bool ReadLong(out byte[] buffer, out AtaErrorRegistersCHS statusRegisters, bool retry, ushort cylinder, byte head, byte sector, int blockSize, uint timeout, out double duration) + { + buffer = new byte[blockSize]; + AtaRegistersCHS registers = new AtaRegistersCHS(); + bool sense; + + if(retry) + registers.command = (byte)AtaCommands.ReadLong; + else + registers.command = (byte)AtaCommands.ReadLongRetry; + registers.sectorCount = 1; + registers.cylinderHigh = (byte)((cylinder & 0xFF00) / 0x100); + registers.cylinderLow = (byte)((cylinder & 0xFF) / 0x1); + registers.deviceHead = (byte)(head & 0x0F); + registers.sector = sector; + + lastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn, AtaTransferRegister.SectorCount, + ref buffer, timeout, true, out duration, out sense); + error = lastError != 0; + + DicConsole.DebugWriteLine("ATA Device", "READ LONG took {0} ms.", duration); + + return sense; + } + + public bool Seek(out AtaErrorRegistersCHS statusRegisters, ushort cylinder, byte head, byte sector, uint timeout, out double duration) + { + byte[] buffer = new byte[0]; + AtaRegistersCHS registers = new AtaRegistersCHS(); + bool sense; + + registers.command = (byte)AtaCommands.Seek; + registers.cylinderHigh = (byte)((cylinder & 0xFF00) / 0x100); + registers.cylinderLow = (byte)((cylinder & 0xFF) / 0x1); + registers.deviceHead = (byte)(head & 0x0F); + registers.sector = sector; + + lastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn, AtaTransferRegister.SectorCount, + ref buffer, timeout, true, out duration, out sense); + error = lastError != 0; + + DicConsole.DebugWriteLine("ATA Device", "SEEK took {0} ms.", duration); + + return sense; + } } } diff --git a/DiscImageChef.Devices/Device/AtaCommands/Cfa.cs b/DiscImageChef.Devices/Device/AtaCommands/Cfa.cs new file mode 100644 index 000000000..ec4ec1466 --- /dev/null +++ b/DiscImageChef.Devices/Device/AtaCommands/Cfa.cs @@ -0,0 +1,109 @@ +// /*************************************************************************** +// The Disc Image Chef +// ---------------------------------------------------------------------------- +// +// Filename : Cfa.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 System; +using DiscImageChef.Console; +using DiscImageChef.Decoders.ATA; + +namespace DiscImageChef.Devices +{ + public partial class Device + { + public bool TranslateSector(out byte[] buffer, out AtaErrorRegistersLBA28 statusRegisters, uint lba, uint timeout, out double duration) + { + buffer = new byte[512]; + AtaRegistersLBA28 registers = new AtaRegistersLBA28(); + bool sense; + + registers.command = (byte)AtaCommands.TranslateSector; + registers.deviceHead = (byte)((lba & 0xF000000) / 0x1000000); + registers.lbaHigh = (byte)((lba & 0xFF0000) / 0x10000); + registers.lbaMid = (byte)((lba & 0xFF00) / 0x100); + registers.lbaLow = (byte)((lba & 0xFF) / 0x1); + registers.deviceHead += 0x40; + + lastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn, AtaTransferRegister.NoTransfer, + ref buffer, timeout, false, out duration, out sense); + error = lastError != 0; + + DicConsole.DebugWriteLine("ATA Device", "CFA TRANSLATE SECTOR took {0} ms.", duration); + + return sense; + } + + public bool TranslateSector(out byte[] buffer, out AtaErrorRegistersCHS statusRegisters, ushort cylinder, byte head, byte sector, uint timeout, out double duration) + { + buffer = new byte[512]; + AtaRegistersCHS registers = new AtaRegistersCHS(); + bool sense; + + registers.command = (byte)AtaCommands.TranslateSector; + registers.cylinderHigh = (byte)((cylinder & 0xFF00) / 0x100); + registers.cylinderLow = (byte)((cylinder & 0xFF) / 0x1); + registers.sector = sector; + registers.deviceHead = (byte)(head & 0x0F); + + lastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn, AtaTransferRegister.NoTransfer, + ref buffer, timeout, false, out duration, out sense); + error = lastError != 0; + + DicConsole.DebugWriteLine("ATA Device", "CFA TRANSLATE SECTOR took {0} ms.", duration); + + return sense; + } + + public bool RequestExtendedErrorCode(out byte errorCode, out AtaErrorRegistersLBA28 statusRegisters, uint timeout, out double duration) + { + byte[] buffer = new byte[0]; + AtaRegistersLBA28 registers = new AtaRegistersLBA28(); + bool sense; + + registers.command = (byte)AtaCommands.RequestSense; + + lastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn, AtaTransferRegister.NoTransfer, + ref buffer, timeout, false, out duration, out sense); + error = lastError != 0; + + errorCode = statusRegisters.error; + + DicConsole.DebugWriteLine("ATA Device", "CFA REQUEST EXTENDED ERROR CODE took {0} ms.", duration); + + return sense; + } + } +} + diff --git a/DiscImageChef.Devices/Device/AtaCommands/MCPT.cs b/DiscImageChef.Devices/Device/AtaCommands/MCPT.cs new file mode 100644 index 000000000..3c4cdd96a --- /dev/null +++ b/DiscImageChef.Devices/Device/AtaCommands/MCPT.cs @@ -0,0 +1,83 @@ +// /*************************************************************************** +// The Disc Image Chef +// ---------------------------------------------------------------------------- +// +// Filename : MCPT.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 System; +using DiscImageChef.Console; +using DiscImageChef.Decoders.ATA; + +namespace DiscImageChef.Devices +{ + public partial class Device + { + public bool EnableMediaCardPassThrough(out AtaErrorRegistersLBA28 statusRegisters, uint lba, uint timeout, out double duration) + { + byte[] buffer = new byte[0]; + AtaRegistersLBA28 registers = new AtaRegistersLBA28(); + bool sense; + + registers.command = (byte)AtaCommands.CheckMediaCardType; + registers.feature = 1; + + lastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.NonData, AtaTransferRegister.NoTransfer, + ref buffer, timeout, false, out duration, out sense); + error = lastError != 0; + + DicConsole.DebugWriteLine("ATA Device", "CHECK MEDIA CARD TYPE took {0} ms.", duration); + + return sense; + } + + public bool DisableMediaCardPassThrough(out AtaErrorRegistersLBA28 statusRegisters, uint lba, uint timeout, out double duration) + { + byte[] buffer = new byte[0]; + AtaRegistersLBA28 registers = new AtaRegistersLBA28(); + bool sense; + + registers.command = (byte)AtaCommands.CheckMediaCardType; + registers.feature = 0; + + lastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.NonData, AtaTransferRegister.NoTransfer, + ref buffer, timeout, false, out duration, out sense); + error = lastError != 0; + + DicConsole.DebugWriteLine("ATA Device", "CHECK MEDIA CARD TYPE took {0} ms.", duration); + + return sense; + } + } +} + diff --git a/DiscImageChef.Devices/Device/AtaCommands/Smart.cs b/DiscImageChef.Devices/Device/AtaCommands/Smart.cs index be5d92b0b..134a7d314 100644 --- a/DiscImageChef.Devices/Device/AtaCommands/Smart.cs +++ b/DiscImageChef.Devices/Device/AtaCommands/Smart.cs @@ -43,5 +43,147 @@ namespace DiscImageChef.Devices { public partial class Device { + public bool SmartDisable(out AtaErrorRegistersLBA28 statusRegisters, uint timeout, out double duration) + { + byte[] buffer = new byte[0]; + AtaRegistersLBA28 registers = new AtaRegistersLBA28(); + bool sense; + + registers.command = (byte)AtaCommands.Smart; + registers.feature = (byte)AtaSmartSubCommands.Disable; + registers.lbaHigh = 0xC2; + registers.lbaMid = 0x4F; + + lastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.NonData, AtaTransferRegister.NoTransfer, + ref buffer, timeout, false, out duration, out sense); + error = lastError != 0; + + DicConsole.DebugWriteLine("ATA Device", "SMART DISABLE OPERATIONS took {0} ms.", duration); + + return sense; + } + + public bool SmartEnableAttributeAutosave(out AtaErrorRegistersLBA28 statusRegisters, uint timeout, out double duration) + { + byte[] buffer = new byte[0]; + AtaRegistersLBA28 registers = new AtaRegistersLBA28(); + bool sense; + + registers.command = (byte)AtaCommands.Smart; + registers.feature = (byte)AtaSmartSubCommands.EnableDisableAttributeAutosave; + registers.lbaHigh = 0xC2; + registers.lbaMid = 0x4F; + registers.sectorCount = 0xF1; + + lastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.NonData, AtaTransferRegister.NoTransfer, + ref buffer, timeout, false, out duration, out sense); + error = lastError != 0; + + DicConsole.DebugWriteLine("ATA Device", "SMART ENABLE ATTRIBUTE AUTOSAVE took {0} ms.", duration); + + return sense; + } + + public bool SmartDisableAttributeAutosave(out AtaErrorRegistersLBA28 statusRegisters, uint timeout, out double duration) + { + byte[] buffer = new byte[0]; + AtaRegistersLBA28 registers = new AtaRegistersLBA28(); + bool sense; + + registers.command = (byte)AtaCommands.Smart; + registers.feature = (byte)AtaSmartSubCommands.Enable; + registers.lbaHigh = 0xC2; + registers.lbaMid = 0x4F; + + lastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.NonData, AtaTransferRegister.NoTransfer, + ref buffer, timeout, false, out duration, out sense); + error = lastError != 0; + + DicConsole.DebugWriteLine("ATA Device", "SMART ENABLE OPERATIONS took {0} ms.", duration); + + return sense; + } + + public bool SmartExecuteOffLineImmediate(out AtaErrorRegistersLBA28 statusRegisters, byte subcommand, uint timeout, out double duration) + { + byte[] buffer = new byte[0]; + AtaRegistersLBA28 registers = new AtaRegistersLBA28(); + bool sense; + + registers.command = (byte)AtaCommands.Smart; + registers.feature = (byte)AtaSmartSubCommands.ExecuteOfflineImmediate; + registers.lbaHigh = 0xC2; + registers.lbaMid = 0x4F; + registers.lbaLow = subcommand; + + lastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.NonData, AtaTransferRegister.NoTransfer, + ref buffer, timeout, false, out duration, out sense); + error = lastError != 0; + + DicConsole.DebugWriteLine("ATA Device", "SMART EXECUTE OFF-LINE IMMEDIATE took {0} ms.", duration); + + return sense; + } + + public bool SmartReadData(out byte[] buffer, out AtaErrorRegistersLBA28 statusRegisters, uint timeout, out double duration) + { + buffer = new byte[512]; + AtaRegistersLBA28 registers = new AtaRegistersLBA28(); + bool sense; + + registers.command = (byte)AtaCommands.Smart; + registers.feature = (byte)AtaSmartSubCommands.ReadData; + registers.lbaHigh = 0xC2; + registers.lbaMid = 0x4F; + + lastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn, AtaTransferRegister.NoTransfer, + ref buffer, timeout, false, out duration, out sense); + error = lastError != 0; + + DicConsole.DebugWriteLine("ATA Device", "SMART READ DATA took {0} ms.", duration); + + return sense; + } + + public bool SmartReadLog(out byte[] buffer, out AtaErrorRegistersLBA28 statusRegisters, byte logAddress, uint timeout, out double duration) + { + buffer = new byte[512]; + AtaRegistersLBA28 registers = new AtaRegistersLBA28(); + bool sense; + + registers.command = (byte)AtaCommands.Smart; + registers.feature = (byte)AtaSmartSubCommands.ReadLog; + registers.lbaHigh = 0xC2; + registers.lbaMid = 0x4F; + registers.lbaLow = logAddress; + + lastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn, AtaTransferRegister.NoTransfer, + ref buffer, timeout, false, out duration, out sense); + error = lastError != 0; + + DicConsole.DebugWriteLine("ATA Device", "SMART READ LOG took {0} ms.", duration); + + return sense; + } + + public bool SmartReturnStatus(out AtaErrorRegistersLBA28 statusRegisters, uint timeout, out double duration) + { + byte[] buffer = new byte[0]; + AtaRegistersLBA28 registers = new AtaRegistersLBA28(); + bool sense; + + registers.command = (byte)AtaCommands.Smart; + registers.feature = (byte)AtaSmartSubCommands.ReturnStatus; + registers.lbaHigh = 0xC2; + registers.lbaMid = 0x4F; + + lastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.NonData, AtaTransferRegister.NoTransfer, + ref buffer, timeout, false, out duration, out sense); + error = lastError != 0; + + DicConsole.DebugWriteLine("ATA Device", "SMART RETURN STATUS took {0} ms.", duration); + + return sense; + } } } \ No newline at end of file diff --git a/DiscImageChef.Devices/Device/ScsiCommands/SPC.cs b/DiscImageChef.Devices/Device/ScsiCommands/SPC.cs index bbbc95c2e..fed1e3681 100644 --- a/DiscImageChef.Devices/Device/ScsiCommands/SPC.cs +++ b/DiscImageChef.Devices/Device/ScsiCommands/SPC.cs @@ -259,7 +259,7 @@ namespace DiscImageChef.Devices { senseBuffer = new byte[32]; byte[] cdb = new byte[6]; - buffer = new byte[4]; + buffer = new byte[4096]; bool sense; cdb[0] = (byte)ScsiCommands.ModeSense; diff --git a/DiscImageChef.Devices/DiscImageChef.Devices.csproj b/DiscImageChef.Devices/DiscImageChef.Devices.csproj index 0958fb49d..cd00ea882 100644 --- a/DiscImageChef.Devices/DiscImageChef.Devices.csproj +++ b/DiscImageChef.Devices/DiscImageChef.Devices.csproj @@ -70,6 +70,8 @@ + + diff --git a/DiscImageChef.Devices/Enums.cs b/DiscImageChef.Devices/Enums.cs index 197996c20..9fa3d8dd8 100644 --- a/DiscImageChef.Devices/Enums.cs +++ b/DiscImageChef.Devices/Enums.cs @@ -674,9 +674,13 @@ namespace DiscImageChef.Devices /// /// Sets the device date and time /// - SetDateAndTimeExt = 0x77 + SetDateAndTimeExt = 0x77, #endregion Commands defined on ATA/ATAPI Command Set 3 (ACS-3) rev. 5 + + #region Commands defined on ATA/ATAPI Command Set 3 (ACS-3) rev. 6 + NativeMaxAddress = 0x78 + #endregion Commands defined on ATA/ATAPI Command Set 3 (ACS-3) rev. 6 } #endregion ATA Commands