Files
yggdrasil/kernel/driver/block/scsi/src/command.rs
T

103 lines
2.7 KiB
Rust

use libk::error::Error;
use crate::device::ScsiDeviceType;
pub trait ScsiCommand {
type Response;
const REQUEST_LEN: usize;
const RESPONSE_LEN: usize;
fn into_bytes(self) -> [u8; Self::REQUEST_LEN];
fn parse_response(bytes: &[u8]) -> Result<Self::Response, Error>;
}
// Add more info when needed
pub struct ScsiInquiry;
#[derive(Debug)]
pub struct ScsiInquiryResponse {
pub device_type: ScsiDeviceType,
}
impl ScsiCommand for ScsiInquiry {
type Response = ScsiInquiryResponse;
const REQUEST_LEN: usize = 6;
const RESPONSE_LEN: usize = 36;
fn into_bytes(self) -> [u8; Self::REQUEST_LEN] {
[0x12, 0x00, 0x00, 0x00, 0x00, 0x00]
}
fn parse_response(bytes: &[u8]) -> Result<Self::Response, Error> {
if bytes.len() != 36 {
return Err(Error::InvalidArgument);
}
let device_type = ScsiDeviceType::try_from(bytes[0] & 0x1F).unwrap_or_default();
Ok(ScsiInquiryResponse { device_type })
}
}
pub struct ScsiTestUnitReady;
#[derive(Debug)]
pub struct ScsiTestUnitReadyResponse;
impl ScsiCommand for ScsiTestUnitReady {
type Response = ScsiTestUnitReadyResponse;
const RESPONSE_LEN: usize = 0;
const REQUEST_LEN: usize = 6;
fn into_bytes(self) -> [u8; Self::REQUEST_LEN] {
[0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
}
fn parse_response(_bytes: &[u8]) -> Result<Self::Response, Error> {
Ok(ScsiTestUnitReadyResponse)
}
}
pub struct ScsiRequestSense;
#[derive(Debug)]
pub struct ScsiRequestSenseResponse;
impl ScsiCommand for ScsiRequestSense {
type Response = ScsiRequestSenseResponse;
const RESPONSE_LEN: usize = 0;
const REQUEST_LEN: usize = 6;
fn into_bytes(self) -> [u8; Self::REQUEST_LEN] {
[0x03, 0x00, 0x00, 0x00, 0x00, 0x00]
}
fn parse_response(_bytes: &[u8]) -> Result<Self::Response, Error> {
Ok(ScsiRequestSenseResponse)
}
}
pub struct ScsiReadCapacity;
#[derive(Debug)]
pub struct ScsiReadCapacityResponse {
pub block_size: u32,
pub block_count: u32,
}
impl ScsiCommand for ScsiReadCapacity {
type Response = ScsiReadCapacityResponse;
const REQUEST_LEN: usize = 10;
const RESPONSE_LEN: usize = 8;
fn into_bytes(self) -> [u8; Self::REQUEST_LEN] {
[0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
}
fn parse_response(bytes: &[u8]) -> Result<Self::Response, Error> {
if bytes.len() != 8 {
return Err(Error::InvalidArgument);
}
let block_count = u32::from_be_bytes(bytes[0..4].try_into().unwrap());
let block_size = u32::from_be_bytes(bytes[4..8].try_into().unwrap());
Ok(ScsiReadCapacityResponse {
block_size,
block_count,
})
}
}