diff --git a/uefi-raw/CHANGELOG.md b/uefi-raw/CHANGELOG.md
index 15a8d793f..7dd2014d3 100644
--- a/uefi-raw/CHANGELOG.md
+++ b/uefi-raw/CHANGELOG.md
@@ -1,5 +1,9 @@
 # uefi-raw - [Unreleased]
 
+## Added
+
+- Added `ScsiIoProtocol`.
+
 ## Changed
 - `maximum_capsule_size` of `query_capsule_capabilities` now takes a *mut u64 instead of a *mut usize.
 
diff --git a/uefi-raw/src/protocol/mod.rs b/uefi-raw/src/protocol/mod.rs
index 16616ca0a..d62300ed1 100644
--- a/uefi-raw/src/protocol/mod.rs
+++ b/uefi-raw/src/protocol/mod.rs
@@ -16,4 +16,5 @@ pub mod memory_protection;
 pub mod misc;
 pub mod network;
 pub mod rng;
+pub mod scsi;
 pub mod shell_params;
diff --git a/uefi-raw/src/protocol/scsi.rs b/uefi-raw/src/protocol/scsi.rs
new file mode 100644
index 000000000..c90ba6b3c
--- /dev/null
+++ b/uefi-raw/src/protocol/scsi.rs
@@ -0,0 +1,160 @@
+use core::ffi::c_void;
+
+use crate::{guid, Event, Guid, Status};
+
+/// TODO: use #define TARGET_MAX_BYTES 0x10, the limit of target.
+#[allow(unused)]
+const TARGET_MAX_BYTES: u32 = 0x10;
+
+newtype_enum! {
+    /// DataDirection
+    #[derive(Default)]
+    pub enum DataDirection: u8 => {
+        READ            = 0,
+        WRITE           = 1,
+        BIDIRECTIONAL   = 2,
+    }
+}
+
+newtype_enum! {
+    /// HostAdapterStatus
+    #[derive(Default)]
+    pub enum HostAdapterStatus: u8 => {
+
+        /// EFI_SCSI_IO_STATUS_HOST_ADAPTER_OK
+       OK                    = 0x00,
+       TIMEOUT_COMMAND       = 0x09,
+       TIMEOUT               = 0x0b,
+       MESSAGE_REJECT        = 0x0d,
+       BUS_RESET             = 0x0e,
+       PARITY_ERROR          = 0x0f,
+       REQUEST_SENSE_FAILED  = 0x10,
+       SELECTION_TIMEOUT     = 0x11,
+       DATA_OVERRUN_UNDERRUN = 0x12,
+       BUS_FREE              = 0x13,
+       PHASE_ERROR           = 0x14,
+       OTHER                 = 0x7f,
+    }
+}
+
+newtype_enum! {
+    /// TargetStatus
+    #[derive(Default)]
+    pub enum TargetStatus: u8 => {
+        /// EFI_SCSI_IO_STATUS_TARGET_GOOD
+        GOOD                         = 0x00,
+        CHECK_CONDITION              = 0x02,
+        CONDITION_MET                = 0x04,
+        BUSY                         = 0x08,
+        INTERMEDIATE                 = 0x10,
+        INTERMEDIATE_CONDITION_MET   = 0x14,
+        RESERVATION_CONFLICT         = 0x18,
+        COMMAND_TERMINATED           = 0x22,
+        QUEUE_FULL                   = 0x28,
+    }
+}
+
+/// EFI_SCSI_IO_SCSI_REQUEST_PACKET
+#[derive(Debug, Copy, Clone)]
+#[repr(C)]
+pub struct ScsiIoScsiRequestPacket {
+    /// Timeout: The timeout, in 100 ns units, to use for the execution of this SCSI Request Packet.
+    /// A Timeout value of 0 means that this function will wait indefinitely for the SCSI Request Packet to execute.
+    /// If Timeout is greater than zero, then this function will return EFI_TIMEOUT if the time required to execute the SCSI Request Packet is greater than Timeout .
+    pub timeout: u64,
+
+    /// []DataBuffer: A pointer to the data buffer to transfer from or to the SCSI device.
+    /// InDataBuffer: A pointer to the data buffer to transfer between the SCSI controller and the SCSI device for SCSI READ command.
+    /// For all SCSI WRITE Commands this must point to NULL .
+    pub in_data_buffer: *mut c_void,
+    /// OutDataBuffer: A pointer to the data buffer to transfer between the SCSI controller and the SCSI device for SCSI WRITE command.
+    /// For all SCSI READ commands this field must point to NULL .
+    pub out_data_buffer: *mut c_void,
+    /// SenseData: A pointer to the sense data that was generated by the execution of the SCSI Request Packet.
+    pub sense_data: *mut c_void,
+    /// Cdb: A pointer to buffer that contains the Command Data Block to send to the SCSI device.
+    pub cdb: *mut c_void,
+
+    /// InTransferLength: On Input, the size, in bytes, of InDataBuffer .
+    /// On output, the number of bytes transferred between the SCSI controller and the SCSI device.
+    /// If InTransferLength is larger than the SCSI controller can handle, no data will be transferred,
+    /// InTransferLength will be updated to contain the number of bytes that the SCSI controller is able to transfer, and EFI_BAD_BUFFER_SIZE will be returned.
+    pub in_transfer_length: u32,
+    /// OutTransferLength: On Input, the size, in bytes of OutDataBuffer .
+    /// On Output, the Number of bytes transferred between SCSI Controller and the SCSI device.
+    /// If OutTransferLength is larger than the SCSI controller can handle, no data will be transferred,
+    /// OutTransferLength will be updated to contain the number of bytes that the SCSI controller is able to transfer, and EFI_BAD_BUFFER_SIZE will be returned.
+    pub out_transfer_length: u32,
+
+    /// CdbLength: The length, in bytes, of the buffer Cdb .
+    /// The standard values are 6, 10, 12, and 16, but other values are possible if a variable length CDB is used.
+    pub cdb_length: u8,
+    /// DataDirection: The direction of the data transfer. 0 for reads, 1 for writes.
+    /// A value of 2 is Reserved for Bi-Directional SCSI commands. For example XDREADWRITE.
+    /// All other values are reserved, and must not be used.
+    pub data_direction: DataDirection,
+    /// HostAdapterStatus: The status of the SCSI Host Controller that produces the SCSI bus
+    /// where the SCSI device attached when the SCSI Request Packet was executed on the SCSI Controller.
+    pub host_adapter_status: HostAdapterStatus,
+    /// TargetStatus: The status returned by the SCSI device when the SCSI Request Packet was executed.
+    pub target_status: TargetStatus,
+    /// SenseDataLength: On input, the length in bytes of the SenseData buffer.
+    /// On output, the number of bytes written to the SenseData buffer.
+    pub sense_data_length: u8,
+}
+
+newtype_enum! {
+    /// DeviceType
+    /// Defined in the SCSI Primary Commands standard (e.g., SPC-4)
+    #[derive(Default)]
+    pub enum DeviceType: u8  => {
+        DISK              = 0x00, // Disk device
+        TAPE              = 0x01, // Tape device
+        PRINTER           = 0x02,// Printer
+        PROCESSOR         = 0x03,// Processor
+        WORM              = 0x04,// Write-once read-multiple
+        CDROM             = 0x05,// CD or DVD device
+        SCANNER           = 0x06,// Scanner device
+        OPTICAL           = 0x07,// Optical memory device
+        MEDIUMCHANGER     = 0x08,// Medium Changer device
+        COMMUNICATION     = 0x09,// Communications device
+
+
+        MFI_A               =   0x0A, // Obsolete
+        MFI_B               =   0x0B, // Obsolete
+        MFI_RAID            =   0x0C, // Storage array controller
+        MFI_SES             =   0x0D, // Enclosure services device
+        MFI_RBC             =   0x0E, // Simplified direct-access
+        MFI_OCRW            =   0x0F, // Optical card reader/
+        MFI_BRIDGE          =   0x10, // Bridge Controller
+        MFI_OSD             =   0x11, // Object-based Storage
+
+        RESERVED_LOW    =   0x12, // Reserved (low)
+        RESERVED_HIGH   =   0x1E, // Reserved (high)
+        UNKNOWN         =   0x1F, // Unknown no device type
+    }
+}
+
+#[derive(Debug)]
+#[repr(C)]
+pub struct ScsiIoProtocol {
+    //TODO: return deviceType
+    pub get_device_type:
+        unsafe extern "efiapi" fn(this: *const Self, device_type: *mut DeviceType) -> Status,
+    //TODO: raw pointer need to fixed, see uefi-rs service code like pointer *u8
+    pub get_device_location:
+        unsafe extern "efiapi" fn(this: *const Self, target: *mut *mut u8, lun: *mut u64) -> Status,
+    pub reset_bus: unsafe extern "efiapi" fn(this: *mut Self) -> Status,
+    pub reset_device: unsafe extern "efiapi" fn(this: *mut Self) -> Status,
+    pub execute_scsi_command: unsafe extern "efiapi" fn(
+        this: *const Self,
+        packet: *mut ScsiIoScsiRequestPacket,
+        event: Event,
+    ) -> Status,
+    pub io_align: u32,
+}
+
+/// 15.4. EFI SCSI I/O Protocol
+impl ScsiIoProtocol {
+    pub const GUID: Guid = guid!("932f47e6-2362-4002-803e-3cd54b138f85");
+}
diff --git a/uefi-test-runner/examples/scsi.rs b/uefi-test-runner/examples/scsi.rs
new file mode 100644
index 000000000..2840bd8f5
--- /dev/null
+++ b/uefi-test-runner/examples/scsi.rs
@@ -0,0 +1,132 @@
+// ANCHOR: all
+// ANCHOR: features
+#![no_main]
+#![no_std]
+// ANCHOR_END: features
+
+extern crate alloc;
+
+use alloc::vec;
+use core::mem;
+
+use log::info;
+
+// ANCHOR: use
+use uefi::prelude::*;
+use uefi::proto::scsi::{ScsiIo, ScsiRequestPacket};
+
+// ANCHOR_END: use
+
+// ANCHOR: entry
+#[entry]
+fn main(image_handle: Handle, mut system_table: SystemTable<Boot>) -> Status {
+    // ANCHOR_END: entry
+    // ANCHOR: services
+    uefi::helpers::init(&mut system_table).unwrap();
+    let boot_services = system_table.boot_services();
+    // ANCHOR_END: services
+
+    // ANCHOR: params, all api OK, but memory panic when return, maybe the vec.
+    test_scsi_io(boot_services);
+    // ANCHOR_END: params, panic at uefi/src/allocator.rs#L130  (*boot_services()).free_pool(ptr).unwrap();
+
+
+    // ANCHOR: stall
+    boot_services.stall(10_000_000);
+    // ANCHOR_END: stall
+
+    // ANCHOR: return
+    Status::SUCCESS
+}
+// ANCHOR_END: return
+
+pub fn test_scsi_io(bt: &BootServices) {
+    info!("Running loaded Scsi protocol test");
+
+    let handle = bt
+        .get_handle_for_protocol::<ScsiIo>()
+        .expect("Failed to get handles for `ScsiIo` protocol");
+
+    let mut scsi_protocol = bt
+        .open_protocol_exclusive::<ScsiIo>(handle)
+        .expect("Founded ScsiIo Protocol but open failed");
+
+    // value efi_reset_fn is the type of ResetSystemFn, a function pointer
+
+    let result = scsi_protocol.get_device_type();
+    info!("SCSI_IO Protocol get device_type: {:?}", result);
+
+    let result = scsi_protocol.io_align();
+    info!("SCSI_IO Protocol's io_align: {:?}", result);
+
+    let result = scsi_protocol.get_device_location();
+    info!("SCSI_IO Protocol get dev location: {:?}", result);
+
+    let result = scsi_protocol.reset_bus();
+    info!("SCSI_IO Protocol reset bus test: {:?}", result);
+
+    let result = scsi_protocol.reset_device();
+    info!("SCSI_IO Protocol reset dev test: {:?}", result);
+
+    bt.stall(10_000);
+
+    let mut packet_tur: ScsiRequestPacket = ScsiRequestPacket::default();
+    packet_tur.is_a_write_packet = false;
+    packet_tur.cdb = vec![0x00, 0, 0, 0, 0, 0x00];
+    packet_tur.timeout = 0;
+    info!("packet_tur: {:?}", packet_tur);
+    let result = scsi_protocol.execute_scsi_command(&mut packet_tur, None);
+    info!("=================SCSI_IO Protocol exec scsi command [TestUnitReady] test: {:?}", result);
+
+    let mut packet_icmd: ScsiRequestPacket = ScsiRequestPacket::default();
+    packet_icmd.is_a_write_packet = false;
+    packet_icmd.cdb = vec![0x12, 0x01, 0x00, 0, 0, 0x00];
+    packet_icmd.data_buffer = vec![0; 96];
+    packet_icmd.sense_data = vec![0; 18];
+    packet_icmd.timeout = 0;
+    let result = scsi_protocol.execute_scsi_command(&mut packet_icmd, None);
+    info!("=================SCSI_IO Protocol exec scsi command [InquiryCommand] test: {:?}", result);
+
+    // drop(packet)
+    // now send Req is ok. but it seems couldn't receive Resp.
+}
+
+/*
+// The InquiryCommand
+
+
+// sense_data with UINT8*18
+///
+/// Error codes 70h and 71h sense data format
+///
+typedef struct {
+UINT8    Error_Code  : 7;
+UINT8    Valid       : 1;
+UINT8    Segment_Number;
+UINT8    Sense_Key   : 4;
+UINT8    Reserved_21 : 1;
+UINT8    Ili         : 1;
+UINT8    Reserved_22 : 2;
+UINT8    Information_3_6[4];
+UINT8    Addnl_Sense_Length;        ///< Additional sense length (n-7)
+UINT8    Vendor_Specific_8_11[4];
+UINT8    Addnl_Sense_Code;            ///< Additional sense code
+UINT8    Addnl_Sense_Code_Qualifier;  ///< Additional sense code qualifier
+UINT8    Field_Replaceable_Unit_Code; ///< Field replaceable unit code
+UINT8    Reserved_15_17[3];
+} EFI_SCSI_SENSE_DATA;
+
+
+
+// in_data_buf with UINT8 * 96
+typedef struct {
+  UINT8    Peripheral_Type      : 5;
+  UINT8    Peripheral_Qualifier : 3;
+  UINT8    DeviceType_Modifier  : 7;
+  UINT8    Rmb                  : 1;
+  UINT8    Version;
+  UINT8    Response_Data_Format;
+  UINT8    Addnl_Length;
+  UINT8    Reserved_5_95[95 - 5 + 1];
+} EFI_SCSI_INQUIRY_DATA;
+*/
diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md
index 8e7e3930e..4298bedf1 100644
--- a/uefi/CHANGELOG.md
+++ b/uefi/CHANGELOG.md
@@ -1,5 +1,9 @@
 # uefi - [Unreleased]
 
+## Added
+
+- Added `ScsiIo` Protocol.
+
 ## Added
 - Added `RuntimeServices::update_capsule`.
 
diff --git a/uefi/src/proto/mod.rs b/uefi/src/proto/mod.rs
index 5919b7afc..dbb750c9f 100644
--- a/uefi/src/proto/mod.rs
+++ b/uefi/src/proto/mod.rs
@@ -9,9 +9,12 @@
 //!
 //! [`BootServices`]: crate::table::boot::BootServices#accessing-protocols
 
-use crate::Identify;
 use core::ffi::c_void;
 
+pub use uefi_macros::unsafe_protocol;
+
+use crate::Identify;
+
 /// Common trait implemented by all standard UEFI protocols.
 ///
 /// You can derive the `Protocol` trait and specify the protocol's GUID using
@@ -64,8 +67,6 @@ where
     }
 }
 
-pub use uefi_macros::unsafe_protocol;
-
 pub mod console;
 pub mod debug;
 pub mod device_path;
@@ -76,6 +77,7 @@ pub mod misc;
 pub mod network;
 pub mod pi;
 pub mod rng;
+pub mod scsi;
 pub mod security;
 pub mod shell_params;
 pub mod shim;
diff --git a/uefi/src/proto/scsi.rs b/uefi/src/proto/scsi.rs
new file mode 100644
index 000000000..c53d3f440
--- /dev/null
+++ b/uefi/src/proto/scsi.rs
@@ -0,0 +1,281 @@
+//! EFI SCSI I/O protocols.
+
+use alloc::vec::Vec;
+use core::ffi::c_void;
+use core::ptr;
+use core::ptr::null_mut;
+
+use log::info;
+
+use uefi_raw::protocol::scsi;
+use uefi_raw::protocol::scsi::{
+    DataDirection, HostAdapterStatus, ScsiIoProtocol, ScsiIoScsiRequestPacket, TargetStatus,
+};
+
+use crate::{Event, Result, StatusExt};
+use crate::proto::unsafe_protocol;
+
+/// Protocol for who running in the EFI boot services environment such as code, typically drivers, able to access SCSI devices.
+/// see example at `uefi-test-runner/examples/scsi.rs`
+#[derive(Debug)]
+#[repr(transparent)]
+#[unsafe_protocol(ScsiIoProtocol::GUID)]
+pub struct ScsiIo(ScsiIoProtocol);
+
+/// Represents a scsi device location which {target, lun}.
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub struct ScsiDeviceLocation {
+    /// Target ID
+    pub target: *mut u8,
+    /// Logical Unit Number
+    pub lun: u64,
+}
+
+impl ScsiDeviceLocation {
+    /// constructor for ScsiDeviceLocation {target, lun}
+    pub fn new(target: *mut u8, lun: u64) -> Self {
+        ScsiDeviceLocation { target, lun }
+    }
+}
+
+impl Default for ScsiDeviceLocation {
+    fn default() -> Self {
+        ScsiDeviceLocation {
+            target: null_mut(),
+            lun: 0,
+        }
+    }
+}
+impl ScsiIo {
+    /// Retrieves the device type information of the SCSI Device.
+    pub fn get_device_type(&self) -> Result<scsi::DeviceType> {
+        let mut device_type = scsi::DeviceType::default();
+        unsafe { (self.0.get_device_type)(&self.0, &mut device_type) }
+            .to_result_with_val(|| device_type)
+    }
+
+    /// Retrieves the SCSI device location in the SCSI channel.
+    pub fn get_device_location(&self) -> Result<ScsiDeviceLocation> {
+        let mut location = ScsiDeviceLocation::default();
+        unsafe { (self.0.get_device_location)(&self.0, &mut location.target, &mut location.lun) }
+            .to_result_with_val(|| location)
+    }
+    /// Resets the SCSI Bus that the SCSI Device is attached to.
+    pub fn reset_bus(&mut self) -> Result {
+        unsafe { (self.0.reset_bus)(&mut self.0) }.to_result()
+    }
+    /// Resets the SCSI Device that is specified by the device handle that the SCSI I/O Protocol is attached.
+    pub fn reset_device(&mut self) -> Result {
+        unsafe { (self.0.reset_device)(&mut self.0) }.to_result()
+    }
+
+    /// Sends a SCSI Request Packet to the SCSI Device for execution.
+    ///TODO:  ScsiIoScsiRequestPacket must to refactor
+    pub fn execute_scsi_command(
+        &self,
+        packet: &mut ScsiRequestPacket,
+        event: Option<Event>,
+    ) -> Result<ScsiRequestPacket> {
+        info!("before: ffi_packet = {:?}", packet);
+        let in_packet = &mut (packet.convert_auto_request_packet());
+        info!("before: raw_packet = {:?}", in_packet);
+
+        let event_arg = match event {
+            Some(event) => event.as_ptr(),
+            None => ptr::null_mut(),
+        };
+
+        let status = unsafe { (self.0.execute_scsi_command)(&self.0, in_packet, event_arg) };
+        info!("after: raw_packet = {:?}", in_packet);
+        // TODO: print log with raw dat/len about `ScsiIoScsiRequestPacket`
+
+        status.to_result_with_val(|| packet.sync_from_request_packet(in_packet))
+    }
+
+    /// the value of ioAlign
+    pub fn io_align(&self) -> Result<u32> {
+        Ok(self.0.io_align)
+    }
+}
+
+/// the rust FFI for `EFI_SCSI_IO_SCSI_REQUEST_PACKET`
+#[derive(Debug, Default, Clone)]
+pub struct ScsiRequestPacket {
+    /// whether the request is written scsi
+    pub is_a_write_packet: bool,
+    /// timeout
+    pub timeout: u64,
+    /// data_buffer is `in_data_buffer` or `out_data_buffer`
+    pub data_buffer: Vec<u8>,
+    /// SCSI's cdb, refer to T10 SPC
+    pub cdb: Vec<u8>,
+    /// SCSI's sense data, refer to T10 SPC, scsi resp return it
+    pub sense_data: Vec<u8>,
+    /// uefi_raw::protocol::scsi::DataDirection
+    pub data_direction: DataDirection,
+    /// uefi_raw::protocol::scsi::HostAdapterStatus, scsi resp status
+    pub host_adapter_status: HostAdapterStatus,
+    /// uefi_raw::protocol::scsi::TargetStatus, scsi resp status
+    pub target_status: TargetStatus,
+}
+
+impl ScsiRequestPacket {
+    /// convert FFI `ScsiRequestPacket` to raw UEFI SCSI request packet `EFI_SCSI_IO_SCSI_REQUEST_PACKET`
+    pub fn convert_zero_request_packet(&mut self) -> ScsiIoScsiRequestPacket {
+        let packet: ScsiIoScsiRequestPacket = ScsiIoScsiRequestPacket {
+            timeout: self.timeout,
+
+            in_data_buffer: null_mut(),
+            out_data_buffer: null_mut(),
+            sense_data: null_mut(),
+            cdb: self.cdb.as_mut_ptr() as *mut c_void,
+
+            in_transfer_length: 0,
+            out_transfer_length: 0,
+            sense_data_length: 0,
+            cdb_length: self.cdb.len() as u8,
+
+            data_direction: self.data_direction,
+            host_adapter_status: self.host_adapter_status,
+            target_status: self.target_status,
+        };
+        packet
+    }
+    // auto convert
+    /// convert auto
+    pub fn convert_auto_request_packet(&mut self) -> ScsiIoScsiRequestPacket {
+        ScsiIoScsiRequestPacket {
+            timeout: 0,
+
+            in_data_buffer: if (self.data_buffer.len() != 0) && !self.is_a_write_packet {
+                self.data_buffer.as_mut_ptr().cast::<c_void>()
+            } else {
+                null_mut()
+            },
+            out_data_buffer: if self.data_buffer.len() != 0 && self.is_a_write_packet {
+                self.data_buffer.as_mut_ptr().cast::<c_void>()
+            } else {
+                null_mut()
+            },
+
+            sense_data: if self.sense_data.len() != 0 {
+                self.sense_data.as_mut_ptr().cast::<c_void>()
+            } else {
+                null_mut()
+            },
+            cdb: if self.cdb.len() != 0 {
+                self.cdb.as_mut_ptr().cast::<c_void>()
+            } else {
+                null_mut()
+            },
+
+            in_transfer_length: if !self.is_a_write_packet {
+                self.data_buffer.len() as u32
+            } else {
+                0
+            },
+            out_transfer_length: if self.is_a_write_packet {
+                self.data_buffer.len() as u32
+            } else {
+                0
+            },
+            cdb_length: self.cdb.len() as u8,
+            sense_data_length: self.sense_data.len() as u8,
+
+            data_direction: Default::default(),
+            host_adapter_status: Default::default(),
+            target_status: Default::default(),
+        }
+    }
+
+    /// convert FFI `ScsiRequestPacket` to raw UEFI SCSI request packet `EFI_SCSI_IO_SCSI_REQUEST_PACKET`
+    pub fn convert_to_request_packet(&mut self) -> ScsiIoScsiRequestPacket {
+        if self.is_a_write_packet {
+            self._convert_to_write_request_packet()
+        } else {
+            self._convert_to_read_request_packet()
+        }
+    }
+
+    /// `ScsiRequestPacket` FFI sync from raw_packet `ScsiIoScsiRequestPacket` by ptr.
+    pub fn sync_from_request_packet(
+        &mut self,
+        raw_packet: &mut ScsiIoScsiRequestPacket,
+    ) -> ScsiRequestPacket {
+        unsafe {
+            self.timeout = raw_packet.timeout;
+            // c (void* data, int len) => rust Vec<u8>
+
+            self.cdb = Vec::from_raw_parts(
+                raw_packet.cdb as *mut u8,
+                raw_packet.cdb_length as usize,
+                isize::MAX as usize,
+            );
+            self.sense_data = Vec::from_raw_parts(
+                raw_packet.sense_data as *mut u8,
+                raw_packet.sense_data_length as usize,
+                isize::MAX as usize,
+            );
+            self.data_buffer = if self.is_a_write_packet {
+                Vec::from_raw_parts(
+                    raw_packet.in_data_buffer as *mut u8,
+                    raw_packet.in_transfer_length as usize,
+                    isize::MAX as usize,
+                )
+            } else {
+                Vec::from_raw_parts(
+                    raw_packet.out_data_buffer as *mut u8,
+                    raw_packet.out_transfer_length as usize,
+                    isize::MAX as usize,
+                )
+            };
+
+            self.data_direction = raw_packet.data_direction;
+            self.host_adapter_status = raw_packet.host_adapter_status;
+            self.target_status = raw_packet.target_status;
+        }
+        self.clone()
+    }
+
+    fn _convert_to_read_request_packet(&mut self) -> ScsiIoScsiRequestPacket {
+        let packet: ScsiIoScsiRequestPacket = ScsiIoScsiRequestPacket {
+            timeout: self.timeout,
+
+            in_data_buffer: self.data_buffer.as_mut_ptr() as *mut c_void,
+            out_data_buffer: null_mut(),
+            sense_data: self.sense_data.as_mut_ptr() as *mut c_void,
+            cdb: self.cdb.as_mut_ptr() as *mut c_void,
+
+            in_transfer_length: self.data_buffer.len() as u32,
+            out_transfer_length: 0,
+            sense_data_length: self.sense_data.len() as u8,
+            cdb_length: self.cdb.len() as u8,
+
+            data_direction: self.data_direction,
+            host_adapter_status: self.host_adapter_status,
+            target_status: self.target_status,
+        };
+        packet
+    }
+
+    fn _convert_to_write_request_packet(&mut self) -> ScsiIoScsiRequestPacket {
+        let packet: ScsiIoScsiRequestPacket = ScsiIoScsiRequestPacket {
+            timeout: self.timeout,
+
+            in_data_buffer: null_mut(),
+            out_data_buffer: self.data_buffer.as_mut_ptr() as *mut c_void,
+            sense_data: self.sense_data.as_mut_ptr() as *mut c_void,
+            cdb: self.cdb.as_mut_ptr() as *mut c_void,
+
+            in_transfer_length: 0,
+            out_transfer_length: self.data_buffer.len() as u32,
+            sense_data_length: self.sense_data.len() as u8,
+            cdb_length: self.cdb.len() as u8,
+
+            data_direction: self.data_direction,
+            host_adapter_status: self.host_adapter_status,
+            target_status: self.target_status,
+        };
+        packet
+    }
+}