nvme/ds/queue/
subentry.rs

1#![allow(dead_code)]
2
3use modular_bitfield::prelude::*;
4
5use super::CommandId;
6use crate::ds::{namespace::NamespaceId, sgl::SglDescriptor, Address};
7// 2b::3.3.3.1
8
9#[bitfield(bits = 32)]
10#[derive(Default, Clone, Copy, Debug)]
11pub struct CommandDword0 {
12    op: B8,
13    fuse: FuseSpec,
14    #[skip]
15    res0: B4,
16    psdt: Psdt,
17    cid: CommandId,
18}
19
20impl CommandDword0 {
21    pub fn build(op: u8, cid: CommandId, fuse: FuseSpec, psdt: Psdt) -> Self {
22        Self::new()
23            .with_op(op)
24            .with_cid(cid)
25            .with_fuse(fuse)
26            .with_psdt(psdt)
27    }
28}
29
30#[derive(BitfieldSpecifier, Clone, Copy, Debug)]
31#[bits = 2]
32pub enum Psdt {
33    Prp,
34    Sgl,
35    SglAndMeta,
36}
37
38#[derive(BitfieldSpecifier, Clone, Copy, Debug)]
39#[bits = 2]
40pub enum FuseSpec {
41    Normal,
42    FuseFirst,
43    FuseSecond,
44}
45
46#[derive(Clone, Copy)]
47#[repr(C)]
48union DptrData {
49    prp: [Address; 2],
50    sgl: SglDescriptor,
51}
52
53impl Default for DptrData {
54    fn default() -> Self {
55        Self { prp: [0; 2] }
56    }
57}
58
59#[derive(Default, Clone, Copy)]
60#[repr(C)]
61pub struct CommonCommand {
62    cdw0: CommandDword0,
63    nsid: NamespaceId,
64    cdw2: u32,
65    cdw3: u32,
66    mptr: Address,
67    dptr: DptrData,
68    cdw10: u32,
69    cdw11: u32,
70    cdw12: u32,
71    cdw13: u32,
72    cdw14: u32,
73    cdw15: u32,
74}
75
76impl CommonCommand {
77    pub fn new() -> Self {
78        Self::default()
79    }
80
81    pub fn with_cdw0(self, cdw0: CommandDword0) -> Self {
82        Self { cdw0, ..self }
83    }
84
85    pub fn with_nsid(self, nsid: NamespaceId) -> Self {
86        Self { nsid, ..self }
87    }
88
89    pub fn with_cdw2(self, cdw2: u32) -> Self {
90        Self { cdw2, ..self }
91    }
92
93    pub fn with_cdw3(self, cdw3: u32) -> Self {
94        Self { cdw3, ..self }
95    }
96
97    pub fn with_cdw10(self, cdw10: u32) -> Self {
98        Self { cdw10, ..self }
99    }
100
101    pub fn with_cdw11(self, cdw11: u32) -> Self {
102        Self { cdw11, ..self }
103    }
104
105    pub fn with_cdw12(self, cdw12: u32) -> Self {
106        Self { cdw12, ..self }
107    }
108
109    pub fn with_cdw13(self, cdw13: u32) -> Self {
110        Self { cdw13, ..self }
111    }
112
113    pub fn with_cdw14(self, cdw14: u32) -> Self {
114        Self { cdw14, ..self }
115    }
116
117    pub fn with_cdw15(self, cdw15: u32) -> Self {
118        Self { cdw15, ..self }
119    }
120
121    pub fn with_mptr(self, mptr: Address) -> Self {
122        Self { mptr, ..self }
123    }
124
125    pub fn with_dptr(self, dptr: Dptr) -> Self {
126        match dptr {
127            Dptr::Prp(a1, a2) => Self {
128                dptr: DptrData { prp: [a1, a2] },
129                ..self
130            },
131            Dptr::Sgl(s) => Self {
132                dptr: DptrData { sgl: s },
133                ..self
134            },
135        }
136    }
137
138    pub fn with_cid(self, cid: CommandId) -> Self {
139        let n = self.cdw0.with_cid(cid);
140        self.with_cdw0(n)
141    }
142
143    pub fn set_cid(&mut self, cid: CommandId) {
144        self.cdw0.set_cid(cid);
145    }
146}
147
148pub enum Dptr {
149    Prp(Address, Address),
150    Sgl(SglDescriptor),
151}
152
153impl Dptr {
154    pub fn psdt(&self, meta_is_sgl: bool) -> Psdt {
155        match self {
156            Dptr::Prp(_, _) => Psdt::Prp,
157            Dptr::Sgl(_) => {
158                if meta_is_sgl {
159                    Psdt::SglAndMeta
160                } else {
161                    Psdt::Sgl
162                }
163            }
164        }
165    }
166}