Esempio n. 1
0
            private static void SendSCSIRequest <TCommand, TData>(UnixFileDescriptor fd, ref TCommand cmd, out TData data) where TCommand : struct where TData : struct
            {
                var cmdlen = Util.SizeOfStructure <TCommand>();

                if (cmdlen > 16)
                {
                    throw new InvalidOperationException("A SCSI command must not exceed 16 bytes in size.");
                }
                var req = new SCSIRequest {
                    interface_id    = 'S',
                    dxfer_direction = SCSITransferDirection.FROM_DEV,
                    timeout         = NativeApi.DefaultSCSIRequestTimeOut,
                    cmd_len         = (byte)cmdlen,
                    mx_sb_len       = (byte)64,
                    dxfer_len       = (uint)Util.SizeOfStructure <TData>(),
                };
                var memlen = (uint)(req.cmd_len + req.mx_sb_len + req.dxfer_len);
                var bytes  = NativeApi.AllocZero(new UIntPtr(1), new UIntPtr(memlen));

                try {
                    req.cmdp   = bytes;
                    req.sbp    = req.cmdp + req.cmd_len;
                    req.dxferp = req.sbp + req.mx_sb_len;
                    Marshal.StructureToPtr(cmd, req.cmdp, false);
                    try {
                        if (NativeApi.SendSCSIRequest(fd.Value, IOCTL.SG_IO, ref req) != 0)
                        {
                            throw new UnixException();
                        }
                        if (req.status == SAM.StatusCode.CHECK_CONDITION || req.driver_status == SCSIDriverStatus.DRIVER_SENSE)
                        {
                            var response = Marshal.ReadByte(req.sbp) & 0x7f;
                            switch (response)
                            {
                            case 0x70:
                            case 0x71: // Fixed Format (Current or Deferred)
                                throw new ScsiException(Util.MarshalPointerToStructure <SPC.FixedSenseData>(req.sbp));

                            case 0x72:
                            case 0x73: // Descriptor Format (Current or Deferred)
                                throw new ScsiException(Util.MarshalPointerToStructure <SPC.DescriptorSenseData>(req.sbp));

                            default:
                                throw new IOException($"SCSI CHECK CONDITION: BAD RESPONSE CODE ({response:X2})");
                            }
                        }
                        data = Util.MarshalPointerToStructure <TData>(req.dxferp);
                    }
                    finally {
                        Util.DestroyStructure <TCommand>(req.cmdp);
                    }
                }
                finally {
                    NativeApi.Free(bytes);
                }
            }
Esempio n. 2
0
 private static extern int SendSCSIRequest(int fd, IOCTL command, ref SCSIRequest request);