public bool Seek(out AtaErrorRegistersChs statusRegisters, ushort cylinder, byte head, byte sector, uint timeout, out double duration) { byte[] buffer = new byte[0]; var registers = new AtaRegistersChs { Command = (byte)AtaCommands.Seek, CylinderHigh = (byte)((cylinder & 0xFF00) / 0x100), CylinderLow = (byte)((cylinder & 0xFF) / 0x1), DeviceHead = (byte)(head & 0x0F), Sector = sector }; 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", "SEEK took {0} ms.", duration); return(sense); }
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 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); }
public bool ReadDma(out byte[] buffer, out AtaErrorRegistersChs statusRegisters, bool retry, ushort cylinder, byte head, byte sector, byte count, uint timeout, out double duration) { buffer = count == 0 ? new byte[512 * 256] : new byte[512 * count]; AtaRegistersChs registers = new AtaRegistersChs { SectorCount = count, CylinderHigh = (byte)((cylinder & 0xFF00) / 0x100), CylinderLow = (byte)((cylinder & 0xFF) / 0x1), DeviceHead = (byte)(head & 0x0F), Sector = sector, Command = retry ? (byte)AtaCommands.ReadDmaRetry : (byte)AtaCommands.ReadDma }; LastError = SendAtaCommand(registers, out statusRegisters, AtaProtocol.Dma, AtaTransferRegister.SectorCount, ref buffer, timeout, true, out duration, out bool sense); Error = LastError != 0; DicConsole.DebugWriteLine("ATA Device", "READ DMA took {0} ms.", duration); return(sense); }
/// <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> /// 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 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 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 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); }