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}