nvme_spec/
nvm.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! NVM command set definitions
5//!
6//! NVM Command Set 1.0c: <https://nvmexpress.org/wp-content/uploads/NVM-Express-NVM-Command-Set-Specification-1.0c-2022.10.03-Ratified.pdf>
7
8use crate::U128LE;
9use bitfield_struct::bitfield;
10use inspect::Inspect;
11use open_enum::open_enum;
12use zerocopy::FromBytes;
13use zerocopy::Immutable;
14use zerocopy::IntoBytes;
15use zerocopy::KnownLayout;
16use zerocopy::LE;
17use zerocopy::U16;
18
19#[repr(C)]
20#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes, Inspect, Clone)]
21pub struct IdentifyNamespace {
22    pub nsze: u64,
23    pub ncap: u64,
24    pub nuse: u64,
25    pub nsfeat: Nsfeat,
26    /// Number of LBA formats. Zero based.
27    pub nlbaf: u8,
28    pub flbas: Flbas,
29    pub mc: u8,
30    pub dpc: u8,
31    pub dps: u8,
32    pub nmic: u8,
33    pub rescap: ReservationCapabilities,
34    pub fpi: u8,
35    pub dlfeat: u8,
36    pub nawun: u16,
37    pub nawupf: u16,
38    pub nacwu: u16,
39    pub nabsn: u16,
40    pub nabo: u16,
41    pub nabspf: u16,
42    pub noiob: u16,
43    #[inspect(display)]
44    pub nvmcap: U128LE,
45    pub npwg: u16,
46    pub npwa: u16,
47    pub npdg: u16,
48    pub npda: u16,
49    pub nows: u16,
50    pub mssrl: u16,
51    pub mcl: u32,
52    pub msrc: u8,
53    #[inspect(skip)]
54    pub rsvd1: [u8; 11],
55    pub anagrpid: u32,
56    #[inspect(skip)]
57    pub rsvd2: [u8; 3],
58    pub nsattr: u8,
59    pub nvmsetid: u16,
60    pub endgid: u16,
61    pub nguid: [u8; 16],
62    pub eui64: [u8; 8],
63    #[inspect(iter_by_index)]
64    pub lbaf: [Lbaf; 16],
65    #[inspect(skip)]
66    pub rsvd3: [u8; 192],
67    #[inspect(skip)]
68    pub vs: [u8; 3712],
69}
70
71open_enum! {
72    pub enum NamespaceIdentifierType: u8 {
73        RESERVED = 0x00,
74        IEEE = 0x01,
75        NSGUID = 0x02,
76        NSUUID = 0x03,
77        CSI = 0x04,
78    }
79}
80
81#[repr(C)]
82#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes, Inspect)]
83pub struct NamespaceIdentificationDescriptor {
84    pub nidt: u8, // NamespaceIdentifierType
85    pub nidl: u8,
86    pub rsvd: [u8; 2],
87    pub nid: [u8; 16],
88}
89
90#[derive(Inspect)]
91#[bitfield(u8)]
92#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
93pub struct Nsfeat {
94    /// Thin provisioning
95    pub thinp: bool,
96    /// NAWUN, NAWUPF, NACWU are defined.
97    pub nsabp: bool,
98    /// Namespace supports deallocated or unwritten logical block error.
99    pub dae: bool,
100    pub uidreuse: bool,
101    /// NPWG, NPWA, NPDG, NPDA, and NOWS are defined for this namespace.
102    pub optperf: bool,
103    #[bits(3)]
104    _rsvd: u8,
105}
106
107/// LBA format
108#[derive(Inspect)]
109#[bitfield(u32)]
110#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
111pub struct Lbaf {
112    /// Metadata size
113    pub ms: u16,
114    /// LBA data size (as power of two)
115    pub lbads: u8,
116    /// Relative performance
117    #[bits(2)]
118    pub rp: u8,
119    #[bits(6)]
120    _rsvd: u8,
121}
122
123/// Formatted LBA size
124#[derive(Inspect)]
125#[bitfield(u8)]
126#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
127pub struct Flbas {
128    #[bits(4)]
129    pub low_index: u8,
130    pub inband_metadata: bool,
131    /// High bits of the index. Only valid if NLBAF > 16.
132    #[bits(2)]
133    pub high_index: u8,
134    #[bits(1)]
135    _rsvd: u8,
136}
137
138#[derive(Inspect)]
139#[bitfield(u8)]
140#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
141pub struct ReservationCapabilities {
142    pub persist_through_power_loss: bool,
143    pub write_exclusive: bool,
144    pub exclusive_access: bool,
145    pub write_exclusive_registrants_only: bool,
146    pub exclusive_access_registrants_only: bool,
147    pub write_exclusive_all_registrants: bool,
148    pub exclusive_access_all_registrants: bool,
149    _rsvd: bool,
150}
151
152open_enum! {
153    pub enum NvmOpcode: u8 {
154        FLUSH = 0x00,
155        WRITE = 0x01,
156        READ = 0x02,
157        /// Dataset management.
158        DSM = 0x09,
159
160        RESERVATION_REGISTER = 0xd,
161        RESERVATION_REPORT = 0xe,
162        RESERVATION_ACQUIRE = 0x11,
163        RESERVATION_RELEASE = 0x15,
164    }
165}
166
167#[bitfield(u32)]
168pub struct Cdw10ReadWrite {
169    /// Starting LBA, low 32 bits.
170    pub sbla_low: u32,
171}
172
173#[bitfield(u32)]
174pub struct Cdw11ReadWrite {
175    /// Starting LBA, high 32 bits.
176    pub sbla_high: u32,
177}
178
179#[bitfield(u32)]
180pub struct Cdw12ReadWrite {
181    /// Number of logical blocks. Zero-based.
182    pub nlb_z: u16,
183    #[bits(4)]
184    _rsvd: u8,
185    /// Directive type (write only).
186    #[bits(4)]
187    pub dtype: u8,
188    /// Storage tag check.
189    pub stc: bool,
190    _rsvd2: bool,
191    /// Protection information
192    #[bits(4)]
193    pub prinfo: u8,
194    /// Force unit access
195    pub fua: bool,
196    /// Limited retry
197    pub lr: bool,
198}
199
200#[bitfield(u32)]
201pub struct Cdw10Dsm {
202    /// Number of ranges. Zero-based.
203    pub nr_z: u8,
204    #[bits(24)]
205    _rsvd: u32,
206}
207
208#[bitfield(u32)]
209pub struct Cdw11Dsm {
210    /// Integral dataset for read.
211    pub idr: bool,
212    /// Integral dataset for write.
213    pub idw: bool,
214    /// Deallocate.
215    pub ad: bool,
216    #[bits(29)]
217    _rsvd: u32,
218}
219
220#[repr(C)]
221#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
222pub struct DsmRange {
223    pub context_attributes: u32,
224    pub lba_count: u32,
225    pub starting_lba: u64,
226}
227
228#[bitfield(u32)]
229pub struct Cdw10ReservationRegister {
230    /// Reservation register action
231    #[bits(3)]
232    pub rrega: u8,
233    /// Ignore existing key
234    pub iekey: bool,
235    #[bits(26)]
236    _rsvd: u32,
237    /// Change "persist through power loss" state
238    #[bits(2)]
239    pub cptpl: u8,
240}
241
242open_enum! {
243    pub enum ReservationRegisterAction: u8 {
244        REGISTER = 0,
245        UNREGISTER = 1,
246        REPLACE = 2,
247    }
248}
249
250open_enum! {
251    pub enum ChangePersistThroughPowerLoss: u8 {
252        NO_CHANGE = 0,
253        CLEAR = 2,
254        SET = 3,
255    }
256}
257
258#[repr(C)]
259#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
260pub struct ReservationRegister {
261    /// Current reservation key
262    pub crkey: u64,
263    /// New reservation key
264    pub nrkey: u64,
265}
266
267#[bitfield(u32)]
268pub struct Cdw10ReservationAcquire {
269    /// Reservation acquire action
270    #[bits(3)]
271    pub racqa: u8,
272    /// Ignore existing key (obsolete)
273    pub iekey: bool,
274    #[bits(4)]
275    _rsvd: u32,
276    pub rtype: u8,
277    _rsvd2: u16,
278}
279
280open_enum! {
281    pub enum ReservationAcquireAction: u8 {
282        ACQUIRE = 0,
283        PREEMPT = 1,
284        PREEMPT_AND_ABORT = 2,
285    }
286}
287
288open_enum! {
289    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
290    pub enum ReservationType: u8 {
291        WRITE_EXCLUSIVE = 1,
292        EXCLUSIVE_ACCESS = 2,
293        WRITE_EXCLUSIVE_REGISTRANTS_ONLY = 3,
294        EXCLUSIVE_ACCESS_REGISTRANTS_ONLY = 4,
295        WRITE_EXCLUSIVE_ALL_REGISTRANTS = 5,
296        EXCLUSIVE_ACCESS_ALL_REGISTRANTS = 6,
297    }
298}
299
300#[repr(C)]
301#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
302pub struct ReservationAcquire {
303    /// Current reservation key
304    pub crkey: u64,
305    /// Preempt reservation key
306    pub prkey: u64,
307}
308
309#[bitfield(u32)]
310pub struct Cdw10ReservationRelease {
311    /// Reservation release action
312    #[bits(3)]
313    pub rrela: u8,
314    /// Ignore existing key (obsolete)
315    pub iekey: bool,
316    #[bits(4)]
317    _rsvd: u32,
318    pub rtype: u8,
319    _rsvd2: u16,
320}
321
322open_enum! {
323    pub enum ReservationReleaseAction: u8 {
324        RELEASE = 0,
325        CLEAR = 1,
326    }
327}
328
329#[repr(C)]
330#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
331pub struct ReservationRelease {
332    /// Current reservation key
333    pub crkey: u64,
334}
335
336#[bitfield(u32)]
337pub struct Cdw10ReservationReport {
338    pub numd_z: u32,
339}
340
341#[bitfield(u32)]
342pub struct Cdw11ReservationReport {
343    /// Extended data structure
344    pub eds: bool,
345    #[bits(31)]
346    _rsvd: u32,
347}
348
349#[repr(C)]
350#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
351pub struct ReservationReport {
352    /// Generation
353    pub generation: u32,
354    /// Reservation type
355    pub rtype: ReservationType,
356    /// Number of registered controllers
357    pub regctl: U16<LE>,
358    pub reserved: [u8; 2],
359    /// Persist through power loss state
360    pub ptpls: u8,
361    pub reserved2: [u8; 14],
362    // Followed by `[RegisteredController; _]`.
363}
364
365#[repr(C)]
366#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
367pub struct ReservationReportExtended {
368    pub report: ReservationReport,
369    pub reserved: [u8; 40],
370    // Followed by `[RegisteredControllerExtended; _]`.
371}
372
373#[repr(C)]
374#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
375pub struct RegisteredController {
376    /// Controller ID
377    pub cntlid: u16,
378    /// Reservation status
379    pub rcsts: ReservationStatus,
380    pub reserved: [u8; 5],
381    /// Host ID
382    pub hostid: [u8; 8],
383    /// Reservation key
384    pub rkey: u64,
385}
386
387#[repr(C)]
388#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
389pub struct RegisteredControllerExtended {
390    /// Controller ID
391    pub cntlid: u16,
392    /// Reservation status
393    pub rcsts: ReservationStatus,
394    pub reserved: [u8; 5],
395    /// Reservation key
396    pub rkey: u64,
397    /// Host ID
398    pub hostid: [u8; 16],
399    pub reserved2: [u8; 32],
400}
401
402#[bitfield(u8)]
403#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
404pub struct ReservationStatus {
405    pub holds_reservation: bool,
406    #[bits(7)]
407    _rsvd: u8,
408}