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