nvme/admin/
identify.rs

1#![allow(dead_code)]
2use modular_bitfield::prelude::*;
3
4use crate::ds::{
5    cmd::admin::AdminCommand,
6    controller::ControllerId,
7    namespace::NamespaceId,
8    queue::{
9        subentry::{CommandDword0, CommonCommand, Dptr, FuseSpec},
10        CommandId,
11    },
12    uuid::UuidIndex,
13};
14#[bitfield(bits = 32)]
15#[repr(u32)]
16struct IdentifyDword10 {
17    cns: B8,
18    #[skip]
19    res: B8,
20    cntid: ControllerId,
21}
22
23#[bitfield(bits = 32)]
24#[repr(u32)]
25struct IdentifyDword11 {
26    cns_specific_id: u16,
27    #[skip]
28    res: B8,
29    csi: u8,
30}
31
32#[bitfield(bits = 32)]
33#[repr(u32)]
34struct IdentifyDword14 {
35    uuid_idx: UuidIndex,
36    #[skip]
37    res: B25,
38}
39
40pub struct Identify {
41    dw10: IdentifyDword10,
42    dw11: IdentifyDword11,
43    dw14: IdentifyDword14,
44    cdw0: CommandDword0,
45    dptr: Dptr,
46    nsid: NamespaceId,
47}
48
49impl From<Identify> for CommonCommand {
50    fn from(i: Identify) -> Self {
51        Self::new()
52            .with_cdw0(i.cdw0)
53            .with_cdw10(i.dw10.into())
54            .with_cdw11(i.dw11.into())
55            .with_cdw14(i.dw14.into())
56            .with_dptr(i.dptr)
57            .with_nsid(i.nsid)
58    }
59}
60
61impl Identify {
62    pub fn new(
63        cid: CommandId,
64        cns: IdentifyCNSValue,
65        dptr: Dptr,
66        uuid_index: Option<UuidIndex>,
67    ) -> Self {
68        Self {
69            dw10: IdentifyDword10::new()
70                .with_cns(cns.cns_value())
71                .with_cntid(cns.cntid_value().into()),
72            dw11: IdentifyDword11::new()
73                .with_csi(cns.csi_value())
74                .with_cns_specific_id(cns.specific_id_value()),
75            dw14: IdentifyDword14::new().with_uuid_idx(uuid_index.into()),
76            cdw0: CommandDword0::build(
77                AdminCommand::Identify.into(),
78                cid,
79                FuseSpec::Normal,
80                dptr.psdt(false),
81            ),
82            dptr,
83            nsid: cns.nsid().unwrap_or(NamespaceId::default()),
84        }
85    }
86}
87
88#[derive(BitfieldSpecifier, Clone, Copy)]
89#[bits = 8]
90pub enum CommandSetIdentifier {
91    NVM,
92    KeyValue,
93    Zoned,
94}
95
96pub enum IdentifyCNSValue {
97    IdentifyNamespace(NamespaceId),
98    IdentifyController,
99    ActiveNamespaceIdList(NamespaceId),
100    NamespaceIdentificationDescriptorList(NamespaceId),
101    IOCommandSetSpecificIdentifyNamespace(NamespaceId, CommandSetIdentifier),
102}
103
104impl IdentifyCNSValue {
105    pub fn nsid(&self) -> Option<NamespaceId> {
106        match self {
107            IdentifyCNSValue::IdentifyNamespace(n) => Some(*n),
108            IdentifyCNSValue::IdentifyController => None,
109            IdentifyCNSValue::ActiveNamespaceIdList(n) => Some(*n),
110            IdentifyCNSValue::NamespaceIdentificationDescriptorList(n) => Some(*n),
111            IdentifyCNSValue::IOCommandSetSpecificIdentifyNamespace(n, _) => Some(*n),
112        }
113    }
114
115    pub fn cns_value(&self) -> u8 {
116        match self {
117            IdentifyCNSValue::IdentifyNamespace(_) => 0,
118            IdentifyCNSValue::IdentifyController => 1,
119            IdentifyCNSValue::ActiveNamespaceIdList(_) => 2,
120            IdentifyCNSValue::NamespaceIdentificationDescriptorList(_) => 3,
121            IdentifyCNSValue::IOCommandSetSpecificIdentifyNamespace(_, _) => 5,
122        }
123    }
124
125    pub fn csi_value(&self) -> u8 {
126        match self {
127            IdentifyCNSValue::IdentifyNamespace(_) => 0,
128            IdentifyCNSValue::IdentifyController => 0,
129            IdentifyCNSValue::ActiveNamespaceIdList(_) => 0,
130            IdentifyCNSValue::NamespaceIdentificationDescriptorList(_) => 0,
131            IdentifyCNSValue::IOCommandSetSpecificIdentifyNamespace(_, c) => *c as u8,
132        }
133    }
134
135    pub fn cntid_value(&self) -> u16 {
136        match self {
137            IdentifyCNSValue::IdentifyNamespace(_) => 0,
138            IdentifyCNSValue::IdentifyController => 0,
139            IdentifyCNSValue::ActiveNamespaceIdList(_) => 0,
140            IdentifyCNSValue::NamespaceIdentificationDescriptorList(_) => 0,
141            IdentifyCNSValue::IOCommandSetSpecificIdentifyNamespace(_, _) => 0,
142        }
143    }
144
145    pub fn specific_id_value(&self) -> u16 {
146        match self {
147            IdentifyCNSValue::IdentifyNamespace(_) => 0,
148            IdentifyCNSValue::IdentifyController => 0,
149            IdentifyCNSValue::ActiveNamespaceIdList(_) => 0,
150            IdentifyCNSValue::NamespaceIdentificationDescriptorList(_) => 0,
151            IdentifyCNSValue::IOCommandSetSpecificIdentifyNamespace(_, _) => 0,
152        }
153    }
154}