public bool ReadMultiple(out byte[] buffer, out AtaErrorRegistersChs statusRegisters, ushort cylinder, byte head, byte sector, byte count, uint timeout, out double duration) { buffer = count == 0 ? new byte[512 * 256] : new byte[512 * count]; var registers = new AtaRegistersChs { Command = (byte)AtaCommands.ReadMultiple, SectorCount = count, CylinderHigh = (byte)((cylinder & 0xFF00) / 0x100), CylinderLow = (byte)((cylinder & 0xFF) / 0x1), DeviceHead = (byte)(head & 0x0F), Sector = sector }; LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn, AtaTransferRegister.SectorCount, ref buffer, timeout, true, out duration, out bool sense); Error = LastError != 0; AaruConsole.DebugWriteLine("ATA Device", "READ MULTIPLE took {0} ms.", duration); 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 ReadLong(out byte[] buffer, out AtaErrorRegistersChs statusRegisters, bool retry, ushort cylinder, byte head, byte sector, uint blockSize, uint timeout, out double duration) { buffer = new byte[blockSize]; var registers = new AtaRegistersChs { Command = retry ? (byte)AtaCommands.ReadLongRetry : (byte)AtaCommands.ReadLong, SectorCount = 1, CylinderHigh = (byte)((cylinder & 0xFF00) / 0x100), CylinderLow = (byte)((cylinder & 0xFF) / 0x1), DeviceHead = (byte)(head & 0x0F), Sector = sector }; LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn, AtaTransferRegister.SectorCount, ref buffer, timeout, true, out duration, out bool sense); Error = LastError != 0; AaruConsole.DebugWriteLine("ATA Device", "READ LONG took {0} ms.", duration); return(sense); }
public bool SetFeatures(out AtaErrorRegistersChs statusRegisters, AtaFeatures feature, ushort cylinder, byte head, byte sector, byte sectorCount, uint timeout, out double duration) { byte[] buffer = new byte[0]; var registers = new AtaRegistersChs { Command = (byte)AtaCommands.SetFeatures, CylinderHigh = (byte)((cylinder & 0xFF00) / 0x100), CylinderLow = (byte)((cylinder & 0xFF) / 0x1), DeviceHead = (byte)(head & 0x0F), Sector = sector, SectorCount = sectorCount, Feature = (byte)feature }; LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.NonData, AtaTransferRegister.NoTransfer, ref buffer, timeout, true, out duration, out bool sense); Error = LastError != 0; AaruConsole.DebugWriteLine("ATA Device", "SET FEATURES took {0} ms.", duration); return(sense); }
/// <summary> /// Sends an ATA/ATAPI command to this device using CHS addressing /// </summary> /// <returns>0 if no error occurred, otherwise, errno</returns> /// <param name="registers">ATA registers.</param> /// <param name="errorRegisters">Status/error registers.</param> /// <param name="protocol">ATA Protocol.</param> /// <param name="transferRegister">Indicates which register indicates the transfer length</param> /// <param name="buffer">Buffer for ATA/ATAPI command response</param> /// <param name="timeout">Timeout in seconds</param> /// <param name="transferBlocks"> /// If set to <c>true</c>, transfer is indicated in blocks, otherwise, it is indicated in /// bytes. /// </param> /// <param name="duration">Time it took to execute the command in milliseconds</param> /// <param name="sense"><c>True</c> if ATA/ATAPI command returned non-OK status</param> public int SendAtaCommand(AtaRegistersChs registers, out AtaErrorRegistersChs errorRegisters, AtaProtocol protocol, AtaTransferRegister transferRegister, ref byte[] buffer, uint timeout, bool transferBlocks, out double duration, out bool sense) => Command.SendAtaCommand(PlatformId, FileHandle, registers, out errorRegisters, protocol, transferRegister, ref buffer, timeout, transferBlocks, out duration, out sense);
/// <summary>Sends an ATA command in CHS format</summary> /// <returns>0 if no error occurred, otherwise, errno</returns> /// <param name="fd">File handle</param> /// <param name="buffer">Buffer for SCSI command response</param> /// <param name="timeout">Timeout in seconds</param> /// <param name="duration">Time it took to execute the command in milliseconds</param> /// <param name="sense"><c>True</c> if ATA returned non-OK status</param> /// <param name="registers">Registers to send to the device</param> /// <param name="errorRegisters">Registers returned by the device</param> /// <param name="protocol">ATA protocol to use</param> /// <param name="transferRegister">What register contains the transfer length</param> /// <param name="transferBlocks">Set to <c>true</c> if the transfer length is in block, otherwise it is in bytes</param> /// <exception cref="InvalidOperationException">If the specified platform is not supported</exception> internal static int SendAtaCommand(object fd, AtaRegistersChs registers, out AtaErrorRegistersChs errorRegisters, AtaProtocol protocol, AtaTransferRegister transferRegister, ref byte[] buffer, uint timeout, bool transferBlocks, out double duration, out bool sense) { PlatformID ptId = DetectOS.GetRealPlatformID(); return(SendAtaCommand(ptId, fd, registers, out errorRegisters, protocol, transferRegister, ref buffer, timeout, transferBlocks, out duration, out sense)); }
/// <summary>Sends an ATA/ATAPI command to this device using CHS addressing</summary> /// <returns>0 if no error occurred, otherwise, errno</returns> /// <param name="registers">ATA registers.</param> /// <param name="errorRegisters">Status/error registers.</param> /// <param name="protocol">ATA Protocol.</param> /// <param name="transferRegister">Indicates which register indicates the transfer length</param> /// <param name="buffer">Buffer for ATA/ATAPI command response</param> /// <param name="timeout">Timeout in seconds</param> /// <param name="transferBlocks"> /// If set to <c>true</c>, transfer is indicated in blocks, otherwise, it is indicated in /// bytes. /// </param> /// <param name="duration">Time it took to execute the command in milliseconds</param> /// <param name="sense"><c>True</c> if ATA/ATAPI command returned non-OK status</param> public int SendAtaCommand(AtaRegistersChs registers, out AtaErrorRegistersChs errorRegisters, AtaProtocol protocol, AtaTransferRegister transferRegister, ref byte[] buffer, uint timeout, bool transferBlocks, out double duration, out bool sense) { if (!(_remote is null)) { return(_remote.SendAtaCommand(registers, out errorRegisters, protocol, transferRegister, ref buffer, timeout, transferBlocks, out duration, out sense)); } return(Command.SendAtaCommand(PlatformId, FileHandle, registers, out errorRegisters, protocol, transferRegister, ref buffer, timeout, transferBlocks, out duration, out sense)); }
public static string DecodeAtaRegisters(AtaErrorRegistersChs registers) { StringBuilder sb = new StringBuilder(); sb.AppendFormat("Status: {0}", DecodeAtaStatus(registers.Status)).AppendLine(); sb.AppendFormat("Error: {0}", DecodeAtaStatus(registers.Error)).AppendLine(); sb.AppendFormat("Device: {0}", (registers.DeviceHead >> 4) & 0x01).AppendLine(); sb.AppendFormat("Cylinder: {0}", registers.CylinderHigh << (8 + registers.CylinderLow)).AppendLine(); sb.AppendFormat("Head: {0}", registers.DeviceHead & 0xF).AppendLine(); sb.AppendFormat("Sector: {0}", registers.Sector).AppendLine(); sb.AppendFormat("Count: {0}", registers.SectorCount).AppendLine(); sb.AppendFormat("LBA?: {0}", Convert.ToBoolean(registers.DeviceHead & 0x40)).AppendLine(); sb.AppendFormat("Bit 7 set?: {0}", Convert.ToBoolean(registers.DeviceHead & 0x80)).AppendLine(); sb.AppendFormat("Bit 5 set?: {0}", Convert.ToBoolean(registers.DeviceHead & 0x20)).AppendLine(); return(sb.ToString()); }
/// <summary> /// Sends an ATA command in CHS format /// </summary> /// <returns>0 if no error occurred, otherwise, errno</returns> /// <param name="ptId">Platform ID for executing the command</param> /// <param name="fd">File handle</param> /// <param name="buffer">Buffer for SCSI command response</param> /// <param name="timeout">Timeout in seconds</param> /// <param name="duration">Time it took to execute the command in milliseconds</param> /// <param name="sense"><c>True</c> if ATA returned non-OK status</param> /// <param name="registers">Registers to send to the device</param> /// <param name="errorRegisters">Registers returned by the device</param> /// <param name="protocol">ATA protocol to use</param> /// <param name="transferRegister">What register contains the transfer length</param> /// <param name="transferBlocks">Set to <c>true</c> if the transfer length is in block, otherwise it is in bytes</param> /// <exception cref="InvalidOperationException">If the specified platform is not supported</exception> internal static int SendAtaCommand(PlatformID ptId, object fd, AtaRegistersChs registers, out AtaErrorRegistersChs errorRegisters, AtaProtocol protocol, AtaTransferRegister transferRegister, ref byte[] buffer, uint timeout, bool transferBlocks, out double duration, out bool sense) { switch (ptId) { case PlatformID.Win32NT: { if (Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor == 1 && (Environment.OSVersion.ServicePack == "Service Pack 1" || Environment.OSVersion.ServicePack == "") || Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor == 0) { throw new InvalidOperationException("Windows XP or earlier is not supported."); } // Windows NT 4 or earlier, requires special ATA pass thru SCSI. But DiscImageChef cannot run there (or can it?) if (Environment.OSVersion.Version.Major <= 4) { throw new InvalidOperationException("Windows NT 4.0 or earlier is not supported."); } return(Windows.Command.SendAtaCommand((SafeFileHandle)fd, registers, out errorRegisters, protocol, ref buffer, timeout, out duration, out sense)); } case PlatformID.Linux: { return(Linux.Command.SendAtaCommand((int)fd, registers, out errorRegisters, protocol, transferRegister, ref buffer, timeout, transferBlocks, out duration, out sense)); } case PlatformID.FreeBSD: { return(FreeBSD.Command.SendAtaCommand((IntPtr)fd, registers, out errorRegisters, protocol, ref buffer, timeout, out duration, out sense)); } default: throw new InvalidOperationException($"Platform {ptId} not yet supported."); } }
/// <summary> /// Sends the ATA IDENTIFY PACKET DEVICE command to the device /// </summary> /// <returns><c>true</c> if the command failed and <paramref name="statusRegisters" /> contains the error registers.</returns> /// <param name="buffer">Buffer.</param> /// <param name="statusRegisters">Status registers.</param> /// <param name="timeout">Timeout.</param> /// <param name="duration">Duration.</param> public bool AtapiIdentify(out byte[] buffer, out AtaErrorRegistersChs statusRegisters, uint timeout, out double duration) { buffer = new byte[512]; AtaRegistersChs registers = new AtaRegistersChs { Command = (byte)AtaCommands.IdentifyPacketDevice }; LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn, AtaTransferRegister.NoTransfer, ref buffer, timeout, false, out duration, out bool sense); Error = LastError != 0; DicConsole.DebugWriteLine("ATA Device", "IDENTIFY PACKET DEVICE took {0} ms.", duration); return(sense); }
public bool CheckMediaCardType(byte feature, out AtaErrorRegistersChs statusRegisters, uint timeout, out double duration) { byte[] buffer = new byte[0]; AtaRegistersChs registers = new AtaRegistersChs { Command = (byte)AtaCommands.CheckMediaCardType, Feature = feature }; LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.NonData, AtaTransferRegister.NoTransfer, ref buffer, timeout, false, out duration, out bool sense); Error = LastError != 0; DicConsole.DebugWriteLine("ATA Device", "CHECK MEDIA CARD TYPE took {0} ms.", duration); return(sense); }
public bool MediaEject(out AtaErrorRegistersChs statusRegisters, uint timeout, out double duration) { byte[] buffer = new byte[0]; var registers = new AtaRegistersChs { Command = (byte)AtaCommands.MediaEject }; LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.NonData, AtaTransferRegister.NoTransfer, ref buffer, timeout, true, out duration, out bool sense); Error = LastError != 0; AaruConsole.DebugWriteLine("ATA Device", "MEDIA EJECT 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 { Command = (byte)AtaCommands.TranslateSector, CylinderHigh = (byte)((cylinder & 0xFF00) / 0x100), CylinderLow = (byte)((cylinder & 0xFF) / 0x1), Sector = sector, DeviceHead = (byte)(head & 0x0F) }; LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.PioIn, AtaTransferRegister.NoTransfer, ref buffer, timeout, false, out duration, out bool sense); Error = LastError != 0; DicConsole.DebugWriteLine("ATA Device", "CFA TRANSLATE SECTOR took {0} ms.", duration); return(sense); }
/// <summary>Sends the ATA IDENTIFY PACKET DEVICE command to the device, using default device timeout</summary> /// <returns><c>true</c> if the command failed and <paramref name="statusRegisters" /> contains the error registers.</returns> /// <param name="buffer">Buffer.</param> /// <param name="statusRegisters">Status registers.</param> public bool AtapiIdentify(out byte[] buffer, out AtaErrorRegistersChs statusRegisters) => AtapiIdentify(out buffer, out statusRegisters, Timeout);
/// <summary> /// Sends the ATA IDENTIFY DEVICE command to the device, using default device timeout /// </summary> /// <returns><c>true</c> if the command failed and <paramref name="statusRegisters" /> contains the error registers.</returns> /// <param name="buffer">Buffer.</param> /// <param name="statusRegisters">Status registers.</param> public bool AtaIdentify(out byte[] buffer, out AtaErrorRegistersChs statusRegisters) { return(AtaIdentify(out buffer, out statusRegisters, Timeout)); }
/// <summary>Sends the ATA IDENTIFY DEVICE command to the device</summary> /// <returns><c>true</c> if the command failed and <paramref name="statusRegisters" /> contains the error registers.</returns> /// <param name="buffer">Buffer.</param> /// <param name="statusRegisters">Status registers.</param> /// <param name="timeout">Timeout.</param> public bool AtaIdentify(out byte[] buffer, out AtaErrorRegistersChs statusRegisters, uint timeout) => AtaIdentify(out buffer, out statusRegisters, timeout, out _);
/// <summary>Sends the ATA IDENTIFY DEVICE command to the device, using default device timeout</summary> /// <returns><c>true</c> if the command failed and <paramref name="statusRegisters" /> contains the error registers.</returns> /// <param name="buffer">Buffer.</param> /// <param name="statusRegisters">Status registers.</param> /// <param name="duration">Duration.</param> public bool AtaIdentify(out byte[] buffer, out AtaErrorRegistersChs statusRegisters, out double duration) => AtaIdentify(out buffer, out statusRegisters, Timeout, out duration);
/// <summary> /// Sends an ATA command in CHS mode /// </summary> /// <returns>0 if no error occurred, otherwise, errno</returns> /// <param name="fd">File handle</param> /// <param name="buffer">Buffer for SCSI command response</param> /// <param name="timeout">Timeout in seconds</param> /// <param name="duration">Time it took to execute the command in milliseconds</param> /// <param name="sense"><c>True</c> if ATA error returned non-OK status</param> /// <param name="registers">Registers to send to drive</param> /// <param name="errorRegisters">Registers returned by drive</param> /// <param name="protocol">ATA protocol to use</param> internal static int SendAtaCommand(SafeFileHandle fd, AtaRegistersChs registers, out AtaErrorRegistersChs errorRegisters, AtaProtocol protocol, ref byte[] buffer, uint timeout, out double duration, out bool sense) { duration = 0; sense = false; errorRegisters = new AtaErrorRegistersChs(); if (buffer == null) { return(-1); } uint offsetForBuffer = (uint)(Marshal.SizeOf(typeof(AtaPassThroughDirect)) + Marshal.SizeOf(typeof(uint))); AtaPassThroughDirectWithBuffer aptdBuf = new AtaPassThroughDirectWithBuffer { aptd = new AtaPassThroughDirect { TimeOutValue = timeout, DataBuffer = (IntPtr)offsetForBuffer, Length = (ushort)Marshal.SizeOf(typeof(AtaPassThroughDirect)), DataTransferLength = (uint)buffer.Length, PreviousTaskFile = new AtaTaskFile(), CurrentTaskFile = new AtaTaskFile { Command = registers.Command, CylinderHigh = registers.CylinderHigh, CylinderLow = registers.CylinderLow, DeviceHead = registers.DeviceHead, Features = registers.Feature, SectorCount = registers.SectorCount, SectorNumber = registers.Sector } }, dataBuffer = new byte[64 * 512] }; switch (protocol) { case AtaProtocol.PioIn: case AtaProtocol.UDmaIn: case AtaProtocol.Dma: aptdBuf.aptd.AtaFlags = AtaFlags.DataIn; break; case AtaProtocol.PioOut: case AtaProtocol.UDmaOut: aptdBuf.aptd.AtaFlags = AtaFlags.DataOut; break; } switch (protocol) { case AtaProtocol.Dma: case AtaProtocol.DmaQueued: case AtaProtocol.FpDma: case AtaProtocol.UDmaIn: case AtaProtocol.UDmaOut: aptdBuf.aptd.AtaFlags |= AtaFlags.Dma; break; } // Unknown if needed aptdBuf.aptd.AtaFlags |= AtaFlags.DrdyRequired; uint k = 0; int error = 0; Array.Copy(buffer, 0, aptdBuf.dataBuffer, 0, buffer.Length); DateTime start = DateTime.Now; sense = !Extern.DeviceIoControlAta(fd, WindowsIoctl.IoctlAtaPassThrough, ref aptdBuf, (uint)Marshal.SizeOf(aptdBuf), ref aptdBuf, (uint)Marshal.SizeOf(aptdBuf), ref k, IntPtr.Zero); DateTime end = DateTime.Now; if (sense) { error = Marshal.GetLastWin32Error(); } Array.Copy(aptdBuf.dataBuffer, 0, buffer, 0, buffer.Length); duration = (end - start).TotalMilliseconds; errorRegisters.CylinderHigh = aptdBuf.aptd.CurrentTaskFile.CylinderHigh; errorRegisters.CylinderLow = aptdBuf.aptd.CurrentTaskFile.CylinderLow; errorRegisters.DeviceHead = aptdBuf.aptd.CurrentTaskFile.DeviceHead; errorRegisters.Error = aptdBuf.aptd.CurrentTaskFile.Error; errorRegisters.Sector = aptdBuf.aptd.CurrentTaskFile.SectorNumber; errorRegisters.SectorCount = aptdBuf.aptd.CurrentTaskFile.SectorCount; errorRegisters.Status = aptdBuf.aptd.CurrentTaskFile.Status; sense = errorRegisters.Error != 0 || (errorRegisters.Status & 0xA5) != 0; return(error); }
/// <summary> /// Sends the ATA IDENTIFY PACKET DEVICE command to the device /// </summary> /// <returns><c>true</c> if the command failed and <paramref name="statusRegisters" /> contains the error registers.</returns> /// <param name="buffer">Buffer.</param> /// <param name="statusRegisters">Status registers.</param> /// <param name="timeout">Timeout.</param> public bool AtapiIdentify(out byte[] buffer, out AtaErrorRegistersChs statusRegisters, uint timeout) { return(AtapiIdentify(out buffer, out statusRegisters, timeout, out _)); }
/// <summary>Sends an ATA command in CHS mode</summary> /// <returns>0 if no error occurred, otherwise, errno</returns> /// <param name="dev">CAM device</param> /// <param name="buffer">Buffer for SCSI command response</param> /// <param name="timeout">Timeout in seconds</param> /// <param name="duration">Time it took to execute the command in milliseconds</param> /// <param name="sense"><c>True</c> if ATA error returned non-OK status</param> /// <param name="registers">Registers to send to drive</param> /// <param name="errorRegisters">Registers returned by drive</param> /// <param name="protocol">ATA protocol to use</param> internal static int SendAtaCommand(IntPtr dev, AtaRegistersChs registers, out AtaErrorRegistersChs errorRegisters, AtaProtocol protocol, ref byte[] buffer, uint timeout, out double duration, out bool sense) { duration = 0; sense = false; errorRegisters = new AtaErrorRegistersChs(); if (buffer == null) { return(-1); } IntPtr ccbPtr = cam_getccb(dev); var ataio = (CcbAtaio)Marshal.PtrToStructure(ccbPtr, typeof(CcbAtaio)); ataio.ccb_h.func_code = XptOpcode.XptAtaIo; ataio.ccb_h.flags = AtaProtocolToCamFlags(protocol); ataio.ccb_h.xflags = 0; ataio.ccb_h.retry_count = 1; ataio.ccb_h.cbfcnp = IntPtr.Zero; ataio.ccb_h.timeout = timeout; ataio.data_ptr = Marshal.AllocHGlobal(buffer.Length); ataio.dxfer_len = (uint)buffer.Length; ataio.ccb_h.flags |= CcbFlags.CamDevQfrzdis; ataio.cmd.flags = CamAtaIoFlags.NeedResult; switch (protocol) { case AtaProtocol.Dma: case AtaProtocol.DmaQueued: case AtaProtocol.UDmaIn: case AtaProtocol.UDmaOut: ataio.cmd.flags |= CamAtaIoFlags.Dma; break; case AtaProtocol.FpDma: ataio.cmd.flags |= CamAtaIoFlags.Fpdma; break; } ataio.cmd.command = registers.Command; ataio.cmd.lba_high = registers.CylinderHigh; ataio.cmd.lba_mid = registers.CylinderLow; ataio.cmd.device = (byte)(0x40 | registers.DeviceHead); ataio.cmd.features = registers.Feature; ataio.cmd.sector_count = registers.SectorCount; ataio.cmd.lba_low = registers.Sector; Marshal.Copy(buffer, 0, ataio.data_ptr, buffer.Length); Marshal.StructureToPtr(ataio, ccbPtr, false); DateTime start = DateTime.UtcNow; int error = cam_send_ccb(dev, ccbPtr); DateTime end = DateTime.UtcNow; if (error < 0) { error = Marshal.GetLastWin32Error(); } ataio = (CcbAtaio)Marshal.PtrToStructure(ccbPtr, typeof(CcbAtaio)); if ((ataio.ccb_h.status & CamStatus.CamStatusMask) != CamStatus.CamReqCmp && (ataio.ccb_h.status & CamStatus.CamStatusMask) != CamStatus.CamScsiStatusError) { error = Marshal.GetLastWin32Error(); AaruConsole.DebugWriteLine("FreeBSD devices", "CAM status {0} error {1}", ataio.ccb_h.status, error); sense = true; } if ((ataio.ccb_h.status & CamStatus.CamStatusMask) == CamStatus.CamAtaStatusError) { sense = true; } errorRegisters.CylinderHigh = ataio.res.lba_high; errorRegisters.CylinderLow = ataio.res.lba_mid; errorRegisters.DeviceHead = ataio.res.device; errorRegisters.Error = ataio.res.error; errorRegisters.Sector = ataio.res.lba_low; errorRegisters.SectorCount = ataio.res.sector_count; errorRegisters.Status = ataio.res.status; buffer = new byte[ataio.dxfer_len]; Marshal.Copy(ataio.data_ptr, buffer, 0, buffer.Length); duration = (end - start).TotalMilliseconds; Marshal.FreeHGlobal(ataio.data_ptr); cam_freeccb(ccbPtr); sense = errorRegisters.Error != 0 || (errorRegisters.Status & 0xA5) != 0 || error != 0; return(error); }
public bool ReadLong(out byte[] buffer, out AtaErrorRegistersChs statusRegisters, ushort cylinder, byte head, byte sector, uint blockSize, uint timeout, out double duration) => ReadLong(out buffer, out statusRegisters, true, cylinder, head, sector, blockSize, timeout, out duration);
/// <summary>Register an ATA error after trying to read using CHS commands</summary> /// <param name="cylinder">Cylinder</param> /// <param name="head">Head</param> /// <param name="sector">Sector</param> /// <param name="osError"><c>true</c> if operating system returned an error status instead of the device</param> /// <param name="errno">Operating system error number</param> /// <param name="registers">Error registers</param> public void WriteLine(ushort cylinder, byte head, byte sector, bool osError, int errno, AtaErrorRegistersChs registers) { if (osError) { _logSw.WriteLine("ATA reading C/H/S {0}/{1}/{2} operating system error: {3}.", cylinder, head, sector, errno); _logSw.Flush(); } else { List <string> error = new List <string>(); List <string> status = new List <string>(); if ((registers.Status & 0x01) == 0x01) { status.Add("ERR"); } if ((registers.Status & 0x02) == 0x02) { status.Add("IDX"); } if ((registers.Status & 0x04) == 0x04) { status.Add("CORR"); } if ((registers.Status & 0x08) == 0x08) { status.Add("DRQ"); } if ((registers.Status & 0x10) == 0x10) { status.Add("SRV"); } if ((registers.Status & 0x20) == 0x20) { status.Add("DF"); } if ((registers.Status & 0x40) == 0x40) { status.Add("RDY"); } if ((registers.Status & 0x80) == 0x80) { status.Add("BSY"); } if ((registers.Error & 0x01) == 0x01) { error.Add("AMNF"); } if ((registers.Error & 0x02) == 0x02) { error.Add("T0NF"); } if ((registers.Error & 0x04) == 0x04) { error.Add("ABRT"); } if ((registers.Error & 0x08) == 0x08) { error.Add("MCR"); } if ((registers.Error & 0x10) == 0x10) { error.Add("IDNF"); } if ((registers.Error & 0x20) == 0x20) { error.Add("MC"); } if ((registers.Error & 0x40) == 0x40) { error.Add("UNC"); } if ((registers.Error & 0x80) == 0x80) { error.Add("BBK"); } _logSw.WriteLine("ATA reading C/H/S {0}/{1}/{2} error: status = {3}, error = {4}.", cylinder, head, sector, string.Join(' ', status), string.Join(' ', error)); _logSw.Flush(); } }
public bool DisableMediaCardPassThrough(out AtaErrorRegistersChs statusRegisters, uint timeout, out double duration) { return(CheckMediaCardType(0, out statusRegisters, timeout, out duration)); }
public bool EnableMediaCardPassThrough(out AtaErrorRegistersChs statusRegisters, uint timeout, out double duration) => CheckMediaCardType(1, out statusRegisters, timeout, out duration);
/// <summary> /// Sends an ATA command in CHS mode using undocumented Windows XP ioctl /// </summary> /// <returns>0 if no error occurred, otherwise, errno</returns> /// <param name="fd">File handle</param> /// <param name="buffer">Buffer for SCSI command response</param> /// <param name="timeout">Timeout in seconds</param> /// <param name="duration">Time it took to execute the command in milliseconds</param> /// <param name="sense"><c>True</c> if ATA error returned non-OK status</param> /// <param name="registers">Registers to send to drive</param> /// <param name="errorRegisters">Registers returned by drive</param> /// <param name="protocol">ATA protocol to use</param> internal static int SendIdeCommand(SafeFileHandle fd, AtaRegistersChs registers, out AtaErrorRegistersChs errorRegisters, AtaProtocol protocol, ref byte[] buffer, uint timeout, out double duration, out bool sense) { duration = 0; sense = false; errorRegisters = new AtaErrorRegistersChs(); if (buffer == null || buffer.Length > 512) { return(-1); } IdePassThroughDirect iptd = new IdePassThroughDirect { CurrentTaskFile = new AtaTaskFile { Command = registers.Command, CylinderHigh = registers.CylinderHigh, CylinderLow = registers.CylinderLow, DeviceHead = registers.DeviceHead, Features = registers.Feature, SectorCount = registers.SectorCount, SectorNumber = registers.Sector }, DataBufferSize = 512, DataBuffer = new byte[512] }; uint k = 0; int error = 0; Array.Copy(buffer, 0, iptd.DataBuffer, 0, buffer.Length); DateTime start = DateTime.Now; sense = !Extern.DeviceIoControlIde(fd, WindowsIoctl.IoctlIdePassThrough, ref iptd, (uint)Marshal.SizeOf(iptd), ref iptd, (uint)Marshal.SizeOf(iptd), ref k, IntPtr.Zero); DateTime end = DateTime.Now; if (sense) { error = Marshal.GetLastWin32Error(); } buffer = new byte[k - 12]; Array.Copy(iptd.DataBuffer, 0, buffer, 0, buffer.Length); duration = (end - start).TotalMilliseconds; errorRegisters.CylinderHigh = iptd.CurrentTaskFile.CylinderHigh; errorRegisters.CylinderLow = iptd.CurrentTaskFile.CylinderLow; errorRegisters.DeviceHead = iptd.CurrentTaskFile.DeviceHead; errorRegisters.Error = iptd.CurrentTaskFile.Error; errorRegisters.Sector = iptd.CurrentTaskFile.SectorNumber; errorRegisters.SectorCount = iptd.CurrentTaskFile.SectorCount; errorRegisters.Status = iptd.CurrentTaskFile.Status; sense = errorRegisters.Error != 0 || (errorRegisters.Status & 0xA5) != 0; return(error); }
public bool SetFeatures(out AtaErrorRegistersChs statusRegisters, AtaFeatures feature, uint timeout, out double duration) => SetFeatures(out statusRegisters, feature, 0, 0, 0, 0, timeout, out duration);
/// <summary> /// Sends the ATA IDENTIFY PACKET DEVICE command to the device, using default device timeout /// </summary> /// <returns><c>true</c> if the command failed and <paramref name="statusRegisters" /> contains the error registers.</returns> /// <param name="buffer">Buffer.</param> /// <param name="statusRegisters">Status registers.</param> /// <param name="duration">Duration.</param> public bool AtapiIdentify(out byte[] buffer, out AtaErrorRegistersChs statusRegisters, out double duration) { return(AtapiIdentify(out buffer, out statusRegisters, Timeout, out duration)); }
public int SendAtaCommand(AtaRegistersChs registers, out AtaErrorRegistersChs errorRegisters, AtaProtocol protocol, AtaTransferRegister transferRegister, ref byte[] buffer, uint timeout, bool transferBlocks, out double duration, out bool sense) { duration = 0; sense = true; errorRegisters = new AtaErrorRegistersChs(); var cmdPkt = new AaruPacketCmdAtaChs { hdr = new AaruPacketHeader { remote_id = Consts.RemoteId, packet_id = Consts.PacketId, version = Consts.PacketVersion, packetType = AaruPacketType.CommandAtaChs }, registers = registers, protocol = (byte)protocol, transferRegister = (byte)transferRegister, transferBlocks = transferBlocks, timeout = timeout * 1000 }; if (buffer != null) { cmdPkt.buf_len = (uint)buffer.Length; } cmdPkt.hdr.len = (uint)(Marshal.SizeOf <AaruPacketCmdAtaChs>() + cmdPkt.buf_len); byte[] pktBuf = Marshal.StructureToByteArrayLittleEndian(cmdPkt); byte[] buf = new byte[cmdPkt.hdr.len]; Array.Copy(pktBuf, 0, buf, 0, Marshal.SizeOf <AaruPacketCmdAtaChs>()); if (buffer != null) { Array.Copy(buffer, 0, buf, Marshal.SizeOf <AaruPacketCmdAtaChs>(), cmdPkt.buf_len); } int len = _socket.Send(buf, SocketFlags.None); if (len != buf.Length) { AaruConsole.ErrorWriteLine("Could not write to the network..."); return(-1); } byte[] hdrBuf = new byte[Marshal.SizeOf <AaruPacketHeader>()]; len = Receive(_socket, hdrBuf, hdrBuf.Length, SocketFlags.Peek); if (len < hdrBuf.Length) { AaruConsole.ErrorWriteLine("Could not read from the network..."); return(-1); } AaruPacketHeader hdr = Marshal.ByteArrayToStructureLittleEndian <AaruPacketHeader>(hdrBuf); if (hdr.remote_id != Consts.RemoteId || hdr.packet_id != Consts.PacketId) { AaruConsole.ErrorWriteLine("Received data is not an Aaru Remote Packet..."); return(-1); } if (hdr.packetType != AaruPacketType.ResponseAtaChs) { AaruConsole.ErrorWriteLine("Expected ATA CHS Response Packet, got packet type {0}...", hdr.packetType); return(-1); } buf = new byte[hdr.len]; len = Receive(_socket, buf, buf.Length, SocketFlags.None); if (len < buf.Length) { AaruConsole.ErrorWriteLine("Could not read from the network..."); return(-1); } AaruPacketResAtaChs res = Marshal.ByteArrayToStructureLittleEndian <AaruPacketResAtaChs>(buf); buffer = new byte[res.buf_len]; Array.Copy(buf, Marshal.SizeOf <AaruPacketResAtaChs>(), buffer, 0, res.buf_len); duration = res.duration; sense = res.sense != 0; errorRegisters = res.registers; return((int)res.error_no); }
/// <summary>Sends an ATA command in CHS mode</summary> /// <returns>0 if no error occurred, otherwise, errno</returns> /// <param name="fd">File handle</param> /// <param name="buffer">Buffer for SCSI command response</param> /// <param name="timeout">Timeout in seconds</param> /// <param name="duration">Time it took to execute the command in milliseconds</param> /// <param name="sense"><c>True</c> if ATA error returned non-OK status</param> /// <param name="registers">Registers to send to drive</param> /// <param name="errorRegisters">Registers returned by drive</param> /// <param name="protocol">ATA protocol to use</param> /// <param name="transferRegister">Which register contains the transfer count</param> /// <param name="transferBlocks">Set to <c>true</c> if the transfer count is in blocks, otherwise it is in bytes</param> internal static int SendAtaCommand(int fd, AtaRegistersChs registers, out AtaErrorRegistersChs errorRegisters, AtaProtocol protocol, AtaTransferRegister transferRegister, ref byte[] buffer, uint timeout, bool transferBlocks, out double duration, out bool sense) { duration = 0; sense = false; errorRegisters = new AtaErrorRegistersChs(); if (buffer == null) { return(-1); } byte[] cdb = new byte[16]; cdb[0] = (byte)ScsiCommands.AtaPassThrough16; cdb[1] = (byte)(((byte)protocol << 1) & 0x1E); if (transferRegister != AtaTransferRegister.NoTransfer && protocol != AtaProtocol.NonData) { switch (protocol) { case AtaProtocol.PioIn: case AtaProtocol.UDmaIn: cdb[2] = 0x08; break; default: cdb[2] = 0x00; break; } if (transferBlocks) { cdb[2] |= 0x04; } cdb[2] |= (byte)((int)transferRegister & 0x03); } //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; int error = SendScsiCommand(fd, cdb, ref buffer, out byte[] senseBuffer, timeout, AtaProtocolToScsiDirection(protocol), out duration, out sense); if (senseBuffer.Length < 22 || (senseBuffer[8] != 0x09 && senseBuffer[9] != 0x0C)) { return(error); } errorRegisters.Error = senseBuffer[11]; 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; return(error); }
/// <summary>Register an ATA error after sending a CHS command</summary> /// <param name="command">Command</param> /// <param name="osError"><c>true</c> if operating system returned an error status instead of the device</param> /// <param name="errno">Operating system error number</param> /// <param name="registers">Error registers</param> public void WriteLine(string command, bool osError, int errno, AtaErrorRegistersChs registers) { if (osError) { _logSw.WriteLine("ATA command {0} operating system error: {1}.", command, errno); _logSw.Flush(); } else { List <string> error = new List <string>(); List <string> status = new List <string>(); if ((registers.Status & 0x01) == 0x01) { status.Add("ERR"); } if ((registers.Status & 0x02) == 0x02) { status.Add("IDX"); } if ((registers.Status & 0x04) == 0x04) { status.Add("CORR"); } if ((registers.Status & 0x08) == 0x08) { status.Add("DRQ"); } if ((registers.Status & 0x10) == 0x10) { status.Add("SRV"); } if ((registers.Status & 0x20) == 0x20) { status.Add("DF"); } if ((registers.Status & 0x40) == 0x40) { status.Add("RDY"); } if ((registers.Status & 0x80) == 0x80) { status.Add("BSY"); } if ((registers.Error & 0x01) == 0x01) { error.Add("AMNF"); } if ((registers.Error & 0x02) == 0x02) { error.Add("T0NF"); } if ((registers.Error & 0x04) == 0x04) { error.Add("ABRT"); } if ((registers.Error & 0x08) == 0x08) { error.Add("MCR"); } if ((registers.Error & 0x10) == 0x10) { error.Add("IDNF"); } if ((registers.Error & 0x20) == 0x20) { error.Add("MC"); } if ((registers.Error & 0x40) == 0x40) { error.Add("UNC"); } if ((registers.Error & 0x80) == 0x80) { error.Add("BBK"); } _logSw.WriteLine("ATA command {0} error: status = {1}, error = {2}.", command, string.Join(' ', status), string.Join(' ', error)); _logSw.Flush(); } }