Skip to content

Commit a72a0a7

Browse files
Gaelanvireshk
authored andcommitted
scsi: Add high-level scsi abstraction
This defines the basic interface that any scsi device will have to implement (along with some sensing constants that may be useful to share). The vast majority of this work was done by Gaelan Steele as part of a GSoC project [1][2]. [1] #4 [2] https://gist.github.com/Gaelan/febec4e4606e1320026a0924c3bf74d0 Co-developed-by: Erik Schilling <[email protected]> Signed-off-by: Erik Schilling <[email protected]> Signed-off-by: Gaelan Steele <[email protected]>
1 parent 98c99b6 commit a72a0a7

File tree

3 files changed

+109
-0
lines changed

3 files changed

+109
-0
lines changed

crates/scsi/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub mod scsi;

crates/scsi/src/scsi/mod.rs

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
pub mod sense;
2+
3+
use std::io::{self, Read, Write};
4+
5+
use self::sense::SenseTriple;
6+
7+
#[derive(PartialEq, Eq, Debug, Clone, Copy)]
8+
pub enum TaskAttr {
9+
Simple,
10+
Ordered,
11+
HeadOfQueue,
12+
Aca,
13+
}
14+
15+
#[derive(Debug, PartialEq, Eq)]
16+
pub struct CmdOutput {
17+
pub status: u8,
18+
pub status_qualifier: u16,
19+
pub sense: Vec<u8>,
20+
}
21+
22+
impl CmdOutput {
23+
pub const fn ok() -> Self {
24+
Self {
25+
status: 0,
26+
status_qualifier: 0,
27+
sense: Vec::new(),
28+
}
29+
}
30+
31+
pub fn check_condition(sense: SenseTriple) -> Self {
32+
Self {
33+
status: 2,
34+
status_qualifier: 0,
35+
sense: sense.to_fixed_sense(),
36+
}
37+
}
38+
}
39+
40+
pub struct Request<'a> {
41+
pub id: u64,
42+
pub cdb: &'a [u8],
43+
pub task_attr: TaskAttr,
44+
pub crn: u8,
45+
pub prio: u8,
46+
}
47+
48+
/// An transport-level error encountered while processing a SCSI command.
49+
///
50+
/// This is only for transport-level errors; anything else should be handled by
51+
/// returning a CHECK CONDITION status at the SCSI level.
52+
#[derive(Debug)]
53+
pub enum CmdError {
54+
/// The provided CDB is too short for its operation code.
55+
CdbTooShort,
56+
/// An error occurred while writing to the provided data in writer.
57+
DataIn(io::Error),
58+
}
59+
60+
/// A transport-independent implementation of a SCSI target.
61+
///
62+
/// Currently, we only support emulated targets (see the `emulation` module),
63+
/// but other implementations of this trait could implement pass-through to
64+
/// iSCSI targets or SCSI devices on the host.
65+
pub trait Target: Send + Sync {
66+
fn execute_command(
67+
&mut self,
68+
lun: u16,
69+
data_out: &mut dyn Read,
70+
data_in: &mut dyn Write,
71+
req: Request,
72+
) -> Result<CmdOutput, CmdError>;
73+
}

crates/scsi/src/scsi/sense.rs

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// SPDX-License-Identifier: Apache-2.0 or BSD-3-Clause
2+
3+
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
4+
pub struct SenseTriple(u8, u8, u8);
5+
6+
impl SenseTriple {
7+
pub fn to_fixed_sense(self) -> Vec<u8> {
8+
vec![
9+
0x70, // response code (fixed, current); valid bit (0)
10+
0x0, // reserved
11+
self.0, // sk; various upper bits 0
12+
0x0, 0x0, 0x0, 0x0, // information
13+
0xa, // add'l sense length
14+
0x0, 0x0, 0x0, 0x0, // cmd-specific information
15+
self.1, // asc
16+
self.2, // ascq
17+
0x0, // field-replacable unit code
18+
0x0, 0x0, 0x0, // sense-key-sepcific information
19+
]
20+
}
21+
}
22+
23+
const NO_SENSE: u8 = 0;
24+
const MEDIUM_ERROR: u8 = 0x3;
25+
const ILLEGAL_REQUEST: u8 = 0x5;
26+
27+
pub const NO_ADDITIONAL_SENSE_INFORMATION: SenseTriple = SenseTriple(NO_SENSE, 0, 0);
28+
29+
pub const INVALID_COMMAND_OPERATION_CODE: SenseTriple = SenseTriple(ILLEGAL_REQUEST, 0x20, 0x0);
30+
pub const LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE: SenseTriple = SenseTriple(ILLEGAL_REQUEST, 0x21, 0x0);
31+
pub const INVALID_FIELD_IN_CDB: SenseTriple = SenseTriple(ILLEGAL_REQUEST, 0x24, 0x0);
32+
pub const LOGICAL_UNIT_NOT_SUPPORTED: SenseTriple = SenseTriple(ILLEGAL_REQUEST, 0x21, 0x0);
33+
pub const SAVING_PARAMETERS_NOT_SUPPORTED: SenseTriple = SenseTriple(ILLEGAL_REQUEST, 0x39, 0x0);
34+
35+
pub const UNRECOVERED_READ_ERROR: SenseTriple = SenseTriple(MEDIUM_ERROR, 0x11, 0x0);

0 commit comments

Comments
 (0)