1#![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 #[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, INVALID_PROTECTION_INFORMATION = 0x181, ATTEMPTED_WRITE_TO_READ_ONLY_RANGE = 0x182, COMMAND_SIZE_LIMIT_EXCEEDED = 0x183, 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#[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 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#[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#[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 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 pub lid: u8,
751 #[bits(7)]
752 pub lsp: u8,
753 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}