nvme_spec/
lib.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Definitions from the NVMe specifications:
5//!
6//! Base 2.0c: <https://nvmexpress.org/wp-content/uploads/NVM-Express-Base-Specification-2.0c-2022.10.04-Ratified.pdf>
7//! PCIe transport 1.0c: <https://nvmexpress.org/wp-content/uploads/NVM-Express-PCIe-Transport-Specification-1.0c-2022.10.03-Ratified.pdf>
8
9#![expect(missing_docs)]
10#![forbid(unsafe_code)]
11#![no_std]
12
13pub mod nvm;
14
15use bitfield_struct::bitfield;
16use inspect::Inspect;
17use mesh::MeshPayload;
18use open_enum::open_enum;
19use storage_string::AsciiString;
20use zerocopy::FromBytes;
21use zerocopy::Immutable;
22use zerocopy::IntoBytes;
23use zerocopy::KnownLayout;
24
25type U128LE = zerocopy::U128<zerocopy::LE>;
26
27open_enum! {
28    pub enum Register: u16 {
29        CAP = 0x0,
30        VS = 0x8,
31        INTMS = 0xc,
32        INTMC = 0x10,
33        CC = 0x14,
34        RESERVED = 0x18,
35        CSTS = 0x1c,
36        NSSR = 0x20,
37        AQA = 0x24,
38        ASQ = 0x28,
39        ACQ = 0x30,
40        CMBLOC = 0x38,
41        CMBSZ = 0x3c,
42        BPINFO = 0x40,
43        BPRSEL = 0x44,
44        BPMBL = 0x48,
45    }
46}
47
48#[derive(Inspect)]
49#[bitfield(u64)]
50pub struct Cap {
51    pub mqes_z: u16,
52    pub cqr: bool,
53    pub ams_weighted_round_robin_with_urgent: bool,
54    pub ams_vendor_specific: bool,
55    #[bits(5)]
56    pub reserved: u8,
57    pub to: u8,
58    #[bits(4)]
59    pub dstrd: u8,
60    pub nssrs: bool,
61    pub css_nvm: bool,
62    #[bits(5)]
63    pub css_reserved: u8,
64    pub multiple_io: bool,
65    pub admin_only: bool,
66    pub bps: bool,
67    #[bits(2)]
68    pub cps: u8,
69    #[bits(4)]
70    pub mpsmin: u8,
71    #[bits(4)]
72    pub mpsmax: u8,
73    pub pmrs: bool,
74    pub cmbs: bool,
75    pub nsss: bool,
76    pub crwms: bool,
77    pub crims: bool,
78    #[bits(3)]
79    pub reserved2: u64,
80}
81
82#[derive(Inspect)]
83#[bitfield(u32)]
84pub struct Cc {
85    pub en: bool,
86    #[bits(3)]
87    pub reserved: u8,
88    #[bits(3)]
89    pub css: u8,
90    #[bits(4)]
91    pub mps: u8,
92    #[bits(3)]
93    pub ams: u8,
94    #[bits(2)]
95    pub shn: u8,
96    #[bits(4)]
97    pub iosqes: u8,
98    #[bits(4)]
99    pub iocqes: u8,
100    pub crime: bool,
101    #[bits(7)]
102    pub reserved2: u8,
103}
104
105#[derive(Inspect)]
106#[bitfield(u32)]
107pub struct Csts {
108    pub rdy: bool,
109    pub cfs: bool,
110    #[bits(2)]
111    pub shst: u8,
112    pub nssro: bool,
113    pub pp: bool,
114    pub st: bool,
115    #[bits(25)]
116    pub reserved: u32,
117}
118
119#[derive(Inspect)]
120#[bitfield(u32)]
121pub struct Aqa {
122    #[bits(12)]
123    pub asqs_z: u16,
124    #[bits(4)]
125    pub reserved: u8,
126    #[bits(12)]
127    pub acqs_z: u16,
128    #[bits(4)]
129    pub reserved2: u8,
130}
131
132#[repr(C)]
133#[derive(
134    Copy,
135    Clone,
136    Debug,
137    IntoBytes,
138    Immutable,
139    KnownLayout,
140    FromBytes,
141    Inspect,
142    MeshPayload,
143    PartialEq,
144)]
145pub struct Command {
146    pub cdw0: Cdw0,
147    pub nsid: u32,
148    pub cdw2: u32,
149    pub cdw3: u32,
150    pub mptr: u64,
151    #[inspect(iter_by_index)]
152    pub dptr: [u64; 2],
153    pub cdw10: u32,
154    pub cdw11: u32,
155    pub cdw12: u32,
156    pub cdw13: u32,
157    pub cdw14: u32,
158    pub cdw15: u32,
159}
160static_assertions::assert_eq_size!(Command, [u8; 64]);
161
162#[derive(Inspect)]
163#[bitfield(u32)]
164#[derive(PartialEq, IntoBytes, Immutable, KnownLayout, FromBytes, MeshPayload)]
165pub struct Cdw0 {
166    pub opcode: u8,
167    #[bits(2)]
168    pub fuse: u8,
169    #[bits(4)]
170    pub reserved: u8,
171    #[bits(2)]
172    pub psdt: u8,
173    pub cid: u16,
174}
175
176#[repr(C)]
177pub struct Opcode(pub u8);
178
179impl Opcode {
180    pub fn transfer_controller_to_host(&self) -> bool {
181        self.0 & 0b10 != 0
182    }
183
184    pub fn transfer_host_to_controller(&self) -> bool {
185        self.0 & 0b01 != 0
186    }
187}
188
189open_enum! {
190    pub enum AdminOpcode: u8 {
191        DELETE_IO_SUBMISSION_QUEUE = 0x00,
192        CREATE_IO_SUBMISSION_QUEUE = 0x01,
193        GET_LOG_PAGE = 0x02,
194        DELETE_IO_COMPLETION_QUEUE = 0x04,
195        CREATE_IO_COMPLETION_QUEUE = 0x05,
196        IDENTIFY = 0x06,
197        ABORT = 0x08,
198        SET_FEATURES = 0x09,
199        GET_FEATURES = 0x0a,
200        ASYNCHRONOUS_EVENT_REQUEST = 0x0c,
201        NAMESPACE_MANAGEMENT = 0x0d,
202        FIRMWARE_COMMIT = 0x10,
203        FIRMWARE_IMAGE_DOWNLOAD = 0x11,
204        DEVICE_SELF_TEST = 0x14,
205        NAMESPACE_ATTACHMENT = 0x15,
206        KEEP_ALIVE = 0x18,
207        DIRECTIVE_SEND = 0x19,
208        DIRECTIVE_RECEIVE = 0x1a,
209        VIRTUALIZATION_MANAGEMENT = 0x1c,
210        NV_ME_MI_SEND = 0x1d,
211        NV_ME_MI_RECEIVE = 0x1e,
212        CAPACITY_MANAGEMENT = 0x20,
213        LOCKDOWN = 0x24,
214        DOORBELL_BUFFER_CONFIG = 0x7c,
215        FABRICS_COMMANDS = 0x7f,
216        FORMAT_NVM = 0x80,
217        SECURITY_SEND = 0x81,
218        SECURITY_RECEIVE = 0x82,
219        SANITIZE = 0x84,
220        GET_LBA_STATUS = 0x86,
221    }
222}
223
224#[repr(C)]
225#[derive(Debug, Clone, IntoBytes, Immutable, KnownLayout, FromBytes, MeshPayload)]
226pub struct Completion {
227    pub dw0: u32,
228    pub dw1: u32,
229    pub sqhd: u16,
230    pub sqid: u16,
231    pub cid: u16,
232    pub status: CompletionStatus,
233}
234static_assertions::assert_eq_size!(Completion, [u8; 16]);
235
236#[bitfield(u16)]
237#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, MeshPayload)]
238pub struct CompletionStatus {
239    pub phase: bool,
240    /// 8 bits of status code followed by 3 bits of the status code type.
241    #[bits(11)]
242    pub status: u16,
243    #[bits(2)]
244    pub crd: u8,
245    pub more: bool,
246    pub dnr: bool,
247}
248
249open_enum! {
250    #[derive(Default)]
251    pub enum StatusCodeType: u8 {
252        GENERIC = 0,
253        COMMAND_SPECIFIC = 1,
254        MEDIA_ERROR = 2,
255        PATH_RELATED = 3,
256        VENDOR_SPECIFIC = 7,
257    }
258}
259
260open_enum! {
261    #[derive(Default)]
262    pub enum Status: u16 {
263        SUCCESS = 0x00,
264        INVALID_COMMAND_OPCODE = 0x01,
265        INVALID_FIELD_IN_COMMAND = 0x02,
266        COMMAND_ID_CONFLICT = 0x03,
267        DATA_TRANSFER_ERROR = 0x04,
268        COMMANDS_ABORTED_DUE_TO_POWER_LOSS_NOTIFICATION = 0x05,
269        INTERNAL_ERROR = 0x06,
270        COMMAND_ABORT_REQUESTED = 0x07,
271        COMMAND_ABORTED_DUE_TO_SQ_DELETION = 0x08,
272        COMMAND_ABORTED_DUE_TO_FAILED_FUSED_COMMAND = 0x09,
273        COMMAND_ABORTED_DUE_TO_MISSING_FUSED_COMMAND = 0x0a,
274        INVALID_NAMESPACE_OR_FORMAT = 0x0b,
275        COMMAND_SEQUENCE_ERROR = 0x0c,
276        INVALID_SGL_SEGMENT_DESCRIPTOR = 0x0d,
277        INVALID_NUMBER_OF_SGL_DESCRIPTORS = 0x0e,
278        DATA_SGL_LENGTH_INVALID = 0x0f,
279        METADATA_SGL_LENGTH_INVALID = 0x10,
280        SGL_DESCRIPTOR_TYPE_INVALID = 0x11,
281        INVALID_USE_OF_CONTROLLER_MEMORY_BUFFER = 0x12,
282        PRP_OFFSET_INVALID = 0x13,
283        ATOMIC_WRITE_UNIT_EXCEEDED = 0x14,
284        OPERATION_DENIED = 0x15,
285        SGL_OFFSET_INVALID = 0x16,
286        RESERVED = 0x17,
287        HOST_IDENTIFIER_INCONSISTENT_FORMAT = 0x18,
288        KEEP_ALIVE_TIMER_EXPIRED = 0x19,
289        KEEP_ALIVE_TIMEOUT_INVALID = 0x1a,
290        COMMAND_ABORTED_DUE_TO_PREEMPT_AND_ABORT = 0x1b,
291        SANITIZE_FAILED = 0x1c,
292        SANITIZE_IN_PROGRESS = 0x1d,
293        SGL_DATA_BLOCK_GRANULARITY_INVALID = 0x1e,
294        COMMAND_NOT_SUPPORTED_FOR_QUEUE_IN_CMB = 0x1f,
295        NAMESPACE_IS_WRITE_PROTECTED = 0x20,
296        COMMAND_INTERRUPTED = 0x21,
297        TRANSIENT_TRANSPORT_ERROR = 0x22,
298        COMMAND_PROHIBITED_BY_COMMAND_AND_FEATURE_LOCKDOWN = 0x23,
299        ADMIN_COMMAND_MEDIA_NOT_READY = 0x24,
300
301        LBA_OUT_OF_RANGE = 0x80,
302        CAPACITY_EXCEEDED = 0x81,
303        NAMESPACE_NOT_READY = 0x82,
304        RESERVATION_CONFLICT = 0x83,
305        FORMAT_IN_PROGRESS = 0x84,
306
307        COMPLETION_QUEUE_INVALID = 0x100,
308        INVALID_QUEUE_IDENTIFIER = 0x101,
309        INVALID_QUEUE_SIZE = 0x102,
310        ABORT_COMMAND_LIMIT_EXCEEDED = 0x103,
311        RESERVED2 = 0x104,
312        ASYNCHRONOUS_EVENT_REQUEST_LIMIT_EXCEEDED = 0x105,
313        INVALID_FIRMWARE_SLOT = 0x106,
314        INVALID_FIRMWARE_IMAGE = 0x107,
315        INVALID_INTERRUPT_VECTOR = 0x108,
316        INVALID_LOG_PAGE = 0x109,
317        INVALID_FORMAT = 0x10a,
318        FIRMWARE_ACTIVATION_REQUIRES_CONVENTIONAL_RESET = 0x10b,
319        INVALID_QUEUE_DELETION = 0x10c,
320        FEATURE_IDENTIFIER_NOT_SAVEABLE = 0x10d,
321        FEATURE_NOT_CHANGEABLE = 0x10e,
322        FEATURE_NOT_NAMESPACE_SPECIFIC = 0x10f,
323        FIRMWARE_ACTIVATION_REQUIRES_NVM_SUBSYSTEM_RESET = 0x110,
324        FIRMWARE_ACTIVATION_REQUIRES_CONTROLLER_LEVEL_RESET = 0x111,
325        FIRMWARE_ACTIVATION_REQUIRES_MAXIMUM_TIME_VIOLATION = 0x112,
326        FIRMWARE_ACTIVATION_PROHIBITED = 0x113,
327        OVERLAPPING_RANGE = 0x114,
328        NAMESPACE_INSUFFICIENT_CAPACITY = 0x115,
329        NAMESPACE_IDENTIFIER_UNAVAILABLE = 0x116,
330        RESERVED3 = 0x117,
331        NAMESPACE_ALREADY_ATTACHED = 0x118,
332        NAMESPACE_IS_PRIVATE = 0x119,
333        NAMESPACE_NOT_ATTACHED = 0x11a,
334        THIN_PROVISIONING_NOT_SUPPORTED = 0x11b,
335        CONTROLLER_LIST_INVALID = 0x11c,
336        DEVICE_SELF_TEST_IN_PROGRESS = 0x11d,
337        BOOT_PARTITION_WRITE_PROHIBITED = 0x11e,
338        INVALID_CONTROLLER_IDENTIFIER = 0x11f,
339        INVALID_SECONDARY_CONTROLLER_STATE = 0x120,
340        INVALID_NUMBER_OF_CONTROLLER_RESOURCES = 0x121,
341        INVALID_RESOURCE_IDENTIFIER = 0x122,
342        SANITIZE_PROHIBITED_WHILE_PERSISTENT_MEMORY_REGION_IS_ENABLED = 0x123,
343        ANA_GROUP_IDENTIFIER_INVALID = 0x124,
344        ANA_ATTACH_FAILED = 0x125,
345        INSUFFICIENT_CAPACITY = 0x126,
346        NAMESPACE_ATTACHMENT_LIMIT_EXCEEDED = 0x127,
347        PROHIBITION_OF_COMMAND_EXECUTION_NOT_SUPPORTED = 0x128,
348        IO_COMMAND_SET_NOT_SUPPORTED = 0x129,
349        IO_COMMAND_SET_NOT_ENABLED = 0x12a,
350        IO_COMMAND_SET_COMBINATION_REJECTED = 0x12b,
351        INVALID_IO_COMMAND_SET = 0x12c,
352        IDENTIFIER_UNAVAILABLE = 0x12d,
353
354        CONFLICTING_ATTRIBUTES = 0x180,         // Dataset Management, Read, Write
355        INVALID_PROTECTION_INFORMATION = 0x181,         // Compare, Read, Write, Write Zeroes
356        ATTEMPTED_WRITE_TO_READ_ONLY_RANGE = 0x182,         // Dataset Management, Write, Write Uncorrectable, Write Zeroes
357        COMMAND_SIZE_LIMIT_EXCEEDED = 0x183,         // Dataset Management
358
359        MEDIA_WRITE_FAULT                             = 0x280,
360        MEDIA_UNRECOVERED_READ_ERROR                  = 0x281,
361        MEDIA_END_TO_END_GUARD_CHECK_ERROR            = 0x282,
362        MEDIA_END_TO_END_APPLICATION_TAG_CHECK_ERROR  = 0x283,
363        MEDIA_END_TO_END_REFERENCE_TAG_CHECK_ERROR    = 0x284,
364        MEDIA_COMPARE_FAILURE                         = 0x285,
365        MEDIA_ACCESS_DENIED                           = 0x286,
366        MEDIA_DEALLOCATED_OR_UNWRITTEN_LOGICAL_BLOCK  = 0x287,
367    }
368}
369
370impl Status {
371    pub fn status_code(&self) -> u8 {
372        self.0 as u8
373    }
374
375    pub fn status_code_type(&self) -> StatusCodeType {
376        StatusCodeType((self.0 >> 8) as u8)
377    }
378}
379
380// Identify
381#[bitfield(u32)]
382pub struct Cdw10Identify {
383    pub cns: u8,
384    pub reserved: u8,
385    pub cntid: u16,
386}
387
388open_enum! {
389    pub enum Cns: u8 {
390        NAMESPACE = 0x0,
391        CONTROLLER = 0x1,
392        ACTIVE_NAMESPACES = 0x2,
393        DESCRIPTOR_NAMESPACE = 0x3,
394        NVM_SET = 0x4,
395        SPECIFIC_NAMESPACE_IO_COMMAND_SET = 0x5,
396        SPECIFIC_CONTROLLER_IO_COMMAND_SET = 0x6,
397        ACTIVE_NAMESPACE_LIST_IO_COMMAND_SET = 0x7,
398        ALLOCATED_NAMESPACE_LIST = 0x10,
399        ALLOCATED_NAMESPACE = 0x11,
400        CONTROLLER_LIST_OF_NSID = 0x12,
401        CONTROLLER_LIST_OF_NVM_SUBSYSTEM = 0x13,
402        PRIMARY_CONTROLLER_CAPABILITIES = 0x14,
403        SECONDARY_CONTROLLER_LIST = 0x15,
404        NAMESPACE_GRANULARITY_LIST = 0x16,
405        UUID_LIST = 0x17,
406        DOMAIN_LIST = 0x18,
407        ENDURANCE_GROUP_LIST = 0x19,
408        ALLOCATED_NAMESPACE_LIST_IO_COMMAND_SET = 0x1a,
409        ALLOCATED_NAMESPACE_IO_COMMAND_SET = 0x1b,
410        IO_COMMAND_SET = 0x1c,
411    }
412}
413
414#[derive(Inspect)]
415#[bitfield(u16)]
416#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
417pub struct OptionalAdminCommandSupport {
418    pub security_send_security_receive: bool,
419    pub format_nvm: bool,
420    pub firmware_activate_firmware_download: bool,
421    pub ns_management: bool,
422    pub self_test: bool,
423    pub directives: bool,
424    pub nvme_mi_send_nvme_mi_receive: bool,
425    pub virtualization_management: bool,
426    pub doorbell_buffer_config: bool,
427    pub get_lba_status: bool,
428    pub command_feature_lockdown: bool,
429    #[bits(5)]
430    pub rsvd: u16,
431}
432
433#[repr(C)]
434#[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes, Inspect, Clone)]
435pub struct IdentifyController {
436    pub vid: u16,
437    pub ssvid: u16,
438    pub sn: AsciiString<20>,
439    pub mn: AsciiString<40>,
440    pub fr: AsciiString<8>,
441    pub rab: u8,
442    pub ieee: [u8; 3],
443    pub cmic: u8,
444    /// Maximum data transfer size (in minimum page size units, as power of
445    /// two).
446    pub mdts: u8,
447    pub cntlid: u16,
448    pub ver: u32,
449    pub rtd3r: u32,
450    pub rtd3e: u32,
451    pub oaes: Oaes,
452    pub ctratt: u32,
453    pub rrls: u16,
454    #[inspect(skip)]
455    pub rsvd1: [u8; 9],
456    pub cntrltype: ControllerType,
457    pub fguid: [u8; 16],
458    pub crdt1: u16,
459    pub crdt2: u16,
460    pub crdt3: u16,
461    #[inspect(skip)]
462    pub rsvd2: [u8; 106],
463    #[inspect(skip)]
464    pub rsvd3: [u8; 13],
465    pub nvmsr: u8,
466    pub vwci: u8,
467    pub mec: u8,
468    pub oacs: OptionalAdminCommandSupport,
469    pub acl: u8,
470    pub aerl: u8,
471    pub frmw: FirmwareUpdates,
472    pub lpa: u8,
473    pub elpe: u8,
474    pub npss: u8,
475    pub avscc: u8,
476    pub apsta: u8,
477    pub wctemp: u16,
478    pub cctemp: u16,
479    pub mtfa: u16,
480    pub hmpre: u32,
481    pub hmmin: u32,
482    #[inspect(display)]
483    pub tnvmcap: U128LE,
484    #[inspect(display)]
485    pub unvmcap: U128LE,
486    pub rpmbs: u32,
487    pub edstt: u16,
488    pub dsto: u8,
489    pub fwug: u8,
490    pub kas: u16,
491    pub hctma: u16,
492    pub mntmt: u16,
493    pub mxtmt: u16,
494    pub sanicap: u32,
495    pub hmminds: u32,
496    pub hmmaxd: u16,
497    pub nsetidmax: u16,
498    pub endgidmax: u16,
499    pub anatt: u8,
500    pub anacap: u8,
501    pub anagrpmax: u32,
502    pub nanagrpid: u32,
503    pub pels: u32,
504    pub domain_id: u16,
505    #[inspect(skip)]
506    pub rsvd4: [u8; 10],
507    #[inspect(display)]
508    pub megcap: U128LE,
509    #[inspect(skip)]
510    pub rsvd5: [u8; 128],
511    pub sqes: QueueEntrySize,
512    pub cqes: QueueEntrySize,
513    pub maxcmd: u16,
514    pub nn: u32,
515    pub oncs: Oncs,
516    pub fuses: u16,
517    pub fna: u8,
518    pub vwc: VolatileWriteCache,
519    pub awun: u16,
520    pub awupf: u16,
521    pub icsvscc: u8,
522    pub nwpc: u8,
523    pub acwu: u16,
524    pub copy_descriptor_fmt: u16,
525    pub sgls: u32,
526    pub mnan: u32,
527    #[inspect(display)]
528    pub maxdna: U128LE,
529    pub maxcna: u32,
530    #[inspect(skip)]
531    pub rsvd6: [u8; 204],
532    #[inspect(with = "|x| core::str::from_utf8(x).map(|s| s.trim_end_matches('\0')).ok()")]
533    pub subnqn: [u8; 256],
534    #[inspect(skip)]
535    pub rsvd7: [u8; 768],
536    pub ioccsz: u32,
537    pub iorcsz: u32,
538    pub icdoff: u16,
539    pub fcatt: u8,
540    pub msdbd: u8,
541    pub ofcs: u16,
542    #[inspect(skip)]
543    pub rsvd8: [u8; 242],
544    #[inspect(skip)]
545    pub power: [u8; 1024],
546    #[inspect(skip)]
547    pub vendor: [u8; 1024],
548}
549
550const _: () = assert!(size_of::<IdentifyController>() == 4096);
551
552#[derive(Inspect)]
553#[bitfield(u8)]
554#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
555pub struct QueueEntrySize {
556    #[bits(4)]
557    pub min: u8,
558    #[bits(4)]
559    pub max: u8,
560}
561
562#[derive(Inspect)]
563#[bitfield(u8)]
564#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
565pub struct FirmwareUpdates {
566    pub ffsro: bool,
567    #[bits(3)]
568    pub nofs: u8,
569    pub fawr: bool,
570    pub smud: bool,
571    #[bits(2)]
572    pub rsvd: u8,
573}
574
575/// Optional asynchronous events supported
576#[derive(Inspect)]
577#[bitfield(u32)]
578#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
579pub struct Oaes {
580    _rsvd: u8,
581    pub namespace_attribute: bool,
582    pub firmware_activation: bool,
583    _rsvd2: bool,
584    pub asymmetric_namespace_access_change: bool,
585    pub predictable_latency_event_aggregate_log_change: bool,
586    pub lba_status_information: bool,
587    pub endurance_group_event_aggregate_log_page_change: bool,
588    pub normal_nvm_subsystem_shutdown: bool,
589    _rsvd3: u16,
590}
591
592/// Optional NVM command support
593#[derive(Inspect)]
594#[bitfield(u16)]
595#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
596pub struct Oncs {
597    pub compare: bool,
598    pub write_uncorrectable: bool,
599    pub dataset_management: bool,
600    pub write_zeroes: bool,
601    pub save: bool,
602    pub reservations: bool,
603    pub timestamp: bool,
604    pub verify: bool,
605    pub copy: bool,
606    #[bits(7)]
607    _rsvd: u16,
608}
609
610open_enum! {
611    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Inspect)]
612    #[inspect(debug)]
613    pub enum ControllerType: u8 {
614        RESERVED = 0,
615        IO_CONTROLLER = 1,
616        DISCOVERY_CONTROLLER = 2,
617        ADMINISTRATIVE_CONTROLLER = 3,
618    }
619}
620
621#[derive(Inspect)]
622#[bitfield(u8)]
623#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
624pub struct VolatileWriteCache {
625    pub present: bool,
626    #[bits(2)]
627    pub broadcast_flush_behavior: u8,
628    #[bits(5)]
629    _rsvd: u8,
630}
631
632open_enum! {
633    pub enum BroadcastFlushBehavior: u8 {
634        NOT_INDICATED = 0,
635        NOT_SUPPORTED = 2,
636        SUPPORTED = 3,
637    }
638}
639
640#[bitfield(u32)]
641pub struct Cdw10SetFeatures {
642    pub fid: u8,
643    #[bits(23)]
644    _rsvd: u32,
645    pub save: bool,
646}
647
648#[bitfield(u32)]
649pub struct Cdw10GetFeatures {
650    pub fid: u8,
651    #[bits(3)]
652    pub sel: u8,
653    #[bits(21)]
654    _rsvd: u32,
655}
656
657open_enum! {
658    pub enum Feature: u8 {
659        ARBITRATION = 0x01,
660        POWER_MANAGEMENT = 0x02,
661        LBA_RANGE_TYPE = 0x03,
662        TEMPERATURE_THRESHOLD = 0x04,
663        ERROR_RECOVERY = 0x05,
664        VOLATILE_WRITE_CACHE = 0x06,
665        NUMBER_OF_QUEUES = 0x07,
666        INTERRUPT_COALESCING = 0x08,
667        INTERRUPT_VECTOR_CONFIG = 0x09,
668        WRITE_ATOMICITY = 0x0a,
669        ASYNC_EVENT_CONFIG = 0x0b,
670        AUTONOMOUS_POWER_STATE_TRANSITION = 0x0c,
671        HOST_MEMORY_BUFFER = 0x0d,
672        TIMESTAMP = 0x0e,
673        KEEP_ALIVE = 0x0f,
674        HOST_CONTROLLED_THERMAL_MANAGEMENT = 0x10,
675        NONOPERATIONAL_POWER_STATE = 0x11,
676        READ_RECOVERY_LEVEL_CONFIG = 0x12,
677        PREDICTABLE_LATENCY_MODE_CONFIG = 0x13,
678        PREDICTABLE_LATENCY_MODE_WINDOW = 0x14,
679        LBA_STATUS_INFORMATION_REPORT_INTERVAL = 0x15,
680        HOST_BEHAVIOR_SUPPORT = 0x16,
681        SANITIZE_CONFIG = 0x17,
682        ENDURANCE_GROUP_EVENT_CONFIG = 0x18,
683        IO_COMMAND_SET_PROFILE = 0x19,
684        ENHANCED_CONTROLLER_METADATA = 0x7d,
685        CONTROLLER_METADATA = 0x7e,
686        NAMESPACE_METADATA = 0x7f,
687        NVM_SOFTWARE_PROGRESS_MARKER = 0x80,
688        NVM_HOST_IDENTIFIER = 0x81,
689        NVM_RESERVATION_NOTIFICATION_MASK = 0x82,
690        NVM_RESERVATION_PERSISTENCE = 0x83,
691        NVM_NAMESPACE_WRITE_PROTECTION_CONFIG = 0x84,
692    }
693}
694
695#[bitfield(u32)]
696pub struct Cdw11FeatureNumberOfQueues {
697    pub nsq_z: u16,
698    pub ncq_z: u16,
699}
700
701#[bitfield(u32)]
702pub struct Cdw11FeatureVolatileWriteCache {
703    pub wce: bool,
704    #[bits(31)]
705    _rsvd: u32,
706}
707
708#[bitfield(u32)]
709pub struct Cdw11FeatureReservationPersistence {
710    /// Persist through power loss
711    pub ptpl: bool,
712    #[bits(31)]
713    _rsvd: u32,
714}
715
716#[bitfield(u32)]
717pub struct Cdw10CreateIoQueue {
718    pub qid: u16,
719    pub qsize_z: u16,
720}
721
722#[bitfield(u32)]
723pub struct Cdw11CreateIoCompletionQueue {
724    pub pc: bool,
725    pub ien: bool,
726    #[bits(14)]
727    pub rsvd: u16,
728    pub iv: u16,
729}
730
731#[bitfield(u32)]
732pub struct Cdw11CreateIoSubmissionQueue {
733    pub pc: bool,
734    #[bits(2)]
735    pub qprio: u8,
736    #[bits(13)]
737    pub rsvd: u16,
738    pub cqid: u16,
739}
740
741#[bitfield(u32)]
742pub struct Cdw10DeleteIoQueue {
743    pub qid: u16,
744    pub rsvd: u16,
745}
746
747#[bitfield(u32)]
748pub struct Cdw10GetLogPage {
749    /// Log page identifier
750    pub lid: u8,
751    #[bits(7)]
752    pub lsp: u8,
753    /// Retain asynchronous event
754    pub rae: bool,
755    pub numdl_z: u16,
756}
757
758#[bitfield(u32)]
759pub struct Cdw11GetLogPage {
760    pub numdu: u16,
761    pub lsi: u16,
762}
763
764open_enum! {
765    pub enum LogPageIdentifier: u8 {
766        SUPPORTED_LOG_PAGES = 0,
767        ERROR_INFORMATION = 1,
768        HEALTH_INFORMATION = 2,
769        FIRMWARE_SLOT_INFORMATION = 3,
770        CHANGED_NAMESPACE_LIST = 4,
771    }
772}
773
774#[bitfield(u32)]
775pub struct AsynchronousEventRequestDw0 {
776    #[bits(3)]
777    pub event_type: u8,
778    #[bits(5)]
779    _rsvd: u8,
780    pub information: u8,
781    pub log_page_identifier: u8,
782    _rsvd2: u8,
783}
784
785open_enum! {
786    pub enum AsynchronousEventType: u8 {
787        ERROR_STATUS = 0b000,
788        HEALTH_STATUS = 0b001,
789        NOTICE = 0b010,
790        IMMEDIATE = 0b011,
791        IO_COMMAND_SPECIFIC = 0b110,
792        VENDOR_SPECIFIC = 0b111,
793    }
794}
795
796open_enum! {
797    pub enum AsynchronousEventInformationNotice: u8 {
798        NAMESPACE_ATTRIBUTE_CHANGED = 0,
799        FIRMWARE_ACTIVATION_STARTING = 1,
800        TELEMETRY_LOG_CHANGED = 2,
801        ASYMMETRIC_NAMESPACE_ACCESS_CHANGE = 3,
802        PREDICTABLE_LATENCY_EVENT_AGGREGATE_LOG_CHANGE = 4,
803        LBA_STATUS_INFORMATION_ALERT = 5,
804        ENDURANCE_GROUP_EVENT_AGGREGATE_LOG_PAGE_CHANGE = 6,
805    }
806}