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