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