// // BwgBurn - CD-R/CD-RW/DVD-R/DVD-RW burning program for DotNet // // Copyright (C) 2006 by Jack W. Griffin (butchg@comcast.net) // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License // for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the // // Free Software Foundation, Inc., // 59 Temple Place, Suite 330, // Boston, MA 02111-1307 USA // using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; using System.Diagnostics; namespace Bwg.Scsi { class Command : IDisposable { [DllImport("ntdll.dll")] internal static extern void RtlZeroMemory(IntPtr dest, int size); public enum CmdDirection { In, Out, None } ; /// /// The data buffer for the SCSI command /// private int m_buffer_size; private IntPtr m_buffer; private bool m_delete_buffer; /// /// The CDB buffer for the command. This gets copied into the SCSI_PASS_THROUGH_DIRECT /// structure when this command is sent to the SCSI target. /// private byte[] m_cdb; /// /// The direction of data transfer via the m_buffer field above /// private CmdDirection m_dir; /// /// The amount of time to pass in seconds before a timeout /// private int m_timeout; public Command(ScsiCommandCode code, byte cdbsize, int bufsize, CmdDirection dir, int timeout) { Debug.Assert(bufsize < UInt16.MaxValue); m_cdb = new byte[cdbsize]; m_cdb[0] = (byte)code; m_buffer_size = bufsize; if (bufsize == 0) m_buffer = IntPtr.Zero; else { m_delete_buffer = true; m_buffer = Marshal.AllocHGlobal(bufsize); RtlZeroMemory(m_buffer, bufsize); } m_dir = dir; m_timeout = timeout; } public Command(ScsiCommandCode code, byte cdbsize, IntPtr buffer, int bufsize, CmdDirection dir, int timeout) { m_cdb = new byte[cdbsize]; m_cdb[0] = (byte)code; m_buffer_size = bufsize; if (bufsize == 0) m_buffer = IntPtr.Zero; else { m_delete_buffer = false; m_buffer = buffer; } m_dir = dir; m_timeout = timeout; } public int TimeOut { get { return m_timeout; } } public ushort GetCDBLength() { return (ushort)m_cdb.GetLength(0); } public CmdDirection Direction { get { return m_dir; } } public int BufferSize { get { return m_buffer_size; } } public IntPtr GetBuffer() { return m_buffer ; } public byte GetCDB(byte addr) { return m_cdb[addr] ; } public void SetCDB8(byte addr, byte value) { m_cdb[addr] = value; } public void SetCDB16(byte addr, ushort value) { m_cdb[addr] = (byte)((value >> 8) & 0xff); m_cdb[addr + 1] = (byte)(value & 0xff); } public void SetCDB24(byte addr, uint value) { m_cdb[addr] = (byte)((value >> 16) & 0xff); m_cdb[addr + 1] = (byte)((value >> 8) & 0xff); m_cdb[addr + 2] = (byte)(value & 0xff); } public void SetCDB24(byte addr, int value) { m_cdb[addr] = (byte)((value >> 16) & 0xff); m_cdb[addr + 1] = (byte)((value >> 8) & 0xff); m_cdb[addr + 2] = (byte)(value & 0xff); } public void SetCDB32(byte addr, uint value) { m_cdb[addr] = (byte)((value >> 24) & 0xff); m_cdb[addr + 1] = (byte)((value >> 16) & 0xff); m_cdb[addr + 2] = (byte)((value >> 8) & 0xff); m_cdb[addr + 3] = (byte)(value & 0xff); } public void SetCDB32(byte addr, int value) { m_cdb[addr] = (byte)((value >> 24) & 0xff); m_cdb[addr + 1] = (byte)((value >> 16) & 0xff); m_cdb[addr + 2] = (byte)((value >> 8) & 0xff); m_cdb[addr + 3] = (byte)(value & 0xff); } public void SetBuffer8(ushort addr, byte value) { Marshal.WriteByte(m_buffer, addr, value); } public void SetBuffer16(ushort addr, ushort value) { Marshal.WriteByte(m_buffer, addr + 0, (byte)((value >> 8) & 0xff)); Marshal.WriteByte(m_buffer, addr + 1, (byte)((value >> 0) & 0xff)); } public void SetBuffer24(ushort addr, uint value) { Marshal.WriteByte(m_buffer, addr + 0, (byte)((value >> 16) & 0xff)); Marshal.WriteByte(m_buffer, addr + 1, (byte)((value >> 8) & 0xff)); Marshal.WriteByte(m_buffer, addr + 2, (byte)((value >> 0) & 0xff)); } public void SetBuffer32(ushort addr, uint value) { Marshal.WriteByte(m_buffer, addr + 0, (byte)((value >> 24) & 0xff)); Marshal.WriteByte(m_buffer, addr + 1, (byte)((value >> 16) & 0xff)); Marshal.WriteByte(m_buffer, addr + 2, (byte)((value >> 8) & 0xff)); Marshal.WriteByte(m_buffer, addr + 3, (byte)((value >> 0) & 0xff)); } public byte GetBuffer8(ushort addr) { return Marshal.ReadByte(m_buffer, addr); } public ushort GetBuffer16(ushort addr) { ushort v = 0; v |= (ushort)(Marshal.ReadByte(m_buffer, addr) << 8); v |= (ushort)(Marshal.ReadByte(m_buffer, addr + 1) << 0); return v; } public uint GetBuffer24(ushort addr) { uint v = 0; v |= (uint)(Marshal.ReadByte(m_buffer, addr) << 16); v |= (uint)(Marshal.ReadByte(m_buffer, addr + 1) << 8); v |= (uint)(Marshal.ReadByte(m_buffer, addr + 2) << 0); return v; } public uint GetBuffer32(ushort addr) { uint v = 0; v |= (uint)(Marshal.ReadByte(m_buffer, addr + 0) << 24); v |= (uint)(Marshal.ReadByte(m_buffer, addr + 1) << 16); v |= (uint)(Marshal.ReadByte(m_buffer, addr + 2) << 8); v |= (uint)(Marshal.ReadByte(m_buffer, addr + 3) << 0); return v; } public void Dispose() { if (m_buffer_size > 0 && m_delete_buffer) Marshal.FreeHGlobal(m_buffer); m_cdb = null; } } }