示例#1
0
        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);
        }
示例#2
0
 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));
 }
示例#3
0
        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);
        }
示例#4
0
        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);
        }
示例#5
0
 /// <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);
示例#6
0
文件: Command.cs 项目: paulyc/Aaru
        /// <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));
        }
示例#7
0
        /// <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());
        }
示例#9
0
        /// <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.");
            }
        }
示例#10
0
        /// <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);
        }
示例#11
0
        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);
        }
示例#12
0
        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);
        }
示例#13
0
        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);
        }
示例#14
0
 /// <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);
示例#15
0
 /// <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));
 }
示例#16
0
 /// <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 _);
示例#17
0
 /// <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);
示例#18
0
        /// <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);
        }
示例#19
0
 /// <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 _));
 }
示例#20
0
        /// <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);
        }
示例#21
0
 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);
示例#22
0
        /// <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();
            }
        }
示例#23
0
 public bool DisableMediaCardPassThrough(out AtaErrorRegistersChs statusRegisters, uint timeout,
                                         out double duration)
 {
     return(CheckMediaCardType(0, out statusRegisters, timeout, out duration));
 }
示例#24
0
 public bool EnableMediaCardPassThrough(out AtaErrorRegistersChs statusRegisters, uint timeout,
                                        out double duration) =>
 CheckMediaCardType(1, out statusRegisters, timeout, out duration);
示例#25
0
        /// <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);
        }
示例#26
0
 public bool SetFeatures(out AtaErrorRegistersChs statusRegisters, AtaFeatures feature, uint timeout,
                         out double duration) =>
 SetFeatures(out statusRegisters, feature, 0, 0, 0, 0, timeout, out duration);
示例#27
0
 /// <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));
 }
示例#28
0
        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);
        }
示例#29
0
        /// <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);
        }
示例#30
0
        /// <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();
            }
        }