1pub mod mi;
6
7use deku::ctx::{BitSize, Endian, Order};
8use deku::{DekuError, DekuRead, DekuWrite, deku_derive};
9use flagset::flags;
10use log::debug;
11
12use crate::wire::WireFlagSet;
13use crate::wire::WireString;
14use crate::wire::WireUuid;
15use crate::wire::WireVec;
16use crate::{Discriminant, Encode};
17
18#[repr(usize)]
20pub enum ControllerProperties {
21 Cc(ControllerConfiguration) = 0x14,
22}
23
24#[derive(Clone, Copy, Debug, Default)]
26pub struct ControllerConfiguration {
27 pub en: bool,
28}
29
30flags! {
32 #[repr(u32)]
33 pub enum ControllerStatusFlags: u32 {
34 Rdy = 1 << 0,
35 Cfs = 1 << 1,
36 ShstInProgress = 1 << 2,
37 ShstComplete = 1 << 3,
38 ShstReserved = (ControllerStatusFlags::ShstInProgress | ControllerStatusFlags::ShstComplete).bits(),
39 Nssro = 1 << 4,
40 Pp = 1 << 5,
41 St = 1 << 6,
42 }
43}
44
45#[derive(Debug, DekuRead, DekuWrite)]
51#[deku(bit_order = "lsb", ctx = "endian: Endian", endian = "endian")]
52struct AdminIoCqeStatus {
53 cid: u16,
54 #[deku(bits = 1)]
55 p: bool,
56 #[deku(bits = 8)]
57 sc: u8,
58 #[deku(bits = 3)]
59 sct: u8,
60 #[deku(bits = 2)]
61 crd: CommandRetryDelay,
62 #[deku(bits = 1)]
63 m: bool,
64 #[deku(bits = 1)]
65 dnr: bool,
66}
67
68impl From<AdminIoCqeStatusType> for AdminIoCqeStatus {
69 fn from(value: AdminIoCqeStatusType) -> Self {
70 match value {
71 AdminIoCqeStatusType::GenericCommandStatus(sts) => AdminIoCqeStatus {
72 cid: 0,
73 sc: sts as u8,
74 p: true,
75 dnr: sts != AdminIoCqeGenericCommandStatus::SuccessfulCompletion,
76 m: false,
77 crd: CommandRetryDelay::None,
78 sct: value.id(),
79 },
80 AdminIoCqeStatusType::CommandSpecificStatus(sts) => AdminIoCqeStatus {
81 cid: 0,
82 sc: sts,
83 p: true,
84 dnr: true,
85 m: false,
86 crd: CommandRetryDelay::None,
87 sct: value.id(),
88 },
89 AdminIoCqeStatusType::MediaAndDataIntegrityErrors => todo!(),
90 AdminIoCqeStatusType::PathRelatedStatus => todo!(),
91 AdminIoCqeStatusType::VendorSpecific => todo!(),
92 }
93 }
94}
95
96#[derive(Debug, DekuRead, DekuWrite)]
98#[deku(
99 bits = "bits.0",
100 bit_order = "order",
101 ctx = "endian: Endian, bits: BitSize, order: Order",
102 endian = "endian",
103 id_type = "u8"
104)]
105#[repr(u8)]
106enum CommandRetryDelay {
107 None = 0x00,
108 Time1 = 0x01,
109 Time2 = 0x02,
110 Time3 = 0x03,
111}
112
113#[derive(Clone, Copy, Debug, Eq, PartialEq)]
115#[repr(u8)]
116enum AdminIoCqeStatusType {
117 GenericCommandStatus(AdminIoCqeGenericCommandStatus) = 0x00,
118 CommandSpecificStatus(u8) = 0x01,
119 #[expect(dead_code)]
120 MediaAndDataIntegrityErrors = 0x02,
121 #[expect(dead_code)]
122 PathRelatedStatus = 0x03,
123 #[expect(dead_code)]
124 VendorSpecific = 0x07,
125}
126unsafe impl Discriminant<u8> for AdminIoCqeStatusType {}
127
128#[derive(Clone, Copy, Debug, Eq, PartialEq)]
130#[repr(u8)]
131enum AdminIoCqeGenericCommandStatus {
132 SuccessfulCompletion = 0x00,
133 InvalidFieldInCommand = 0x02,
134 InternalError = 0x06,
135 InvalidNamespaceOrFormat = 0x0b,
136}
137
138impl From<DekuError> for AdminIoCqeGenericCommandStatus {
139 fn from(err: DekuError) -> Self {
140 debug!("Codec operation failed: {err}");
141 Self::InternalError
142 }
143}
144
145#[derive(Debug, DekuRead, Eq, PartialEq)]
148#[deku(ctx = "endian: Endian", endian = "little")]
149struct ControllerListRequest {
150 numids: u16,
151 #[deku(count = "*numids")]
152 ids: WireVec<u16, 2047>,
153}
154
155#[derive(Debug, DekuRead, DekuWrite, Eq, PartialEq)]
157#[deku(
158 bits = "bits.0",
159 ctx = "endian: Endian, bits: BitSize",
160 endian = "endian",
161 id_type = "u8"
162)]
163#[repr(u8)]
164enum SecureEraseSettings {
165 NoOperation = 0b000,
166 UserDataErase = 0b001,
167 CryptographicErase = 0b010,
168}
169
170#[derive(Debug, DekuRead, DekuWrite, Eq, PartialEq)]
172#[deku(ctx = "endian: Endian", endian = "endian")]
173struct AdminFormatNvmConfiguration {
174 #[deku(bits = "3")]
175 pi: u8,
176 #[deku(bits = "1")]
177 mset: bool,
178 #[deku(bits = "4")]
179 lbafl: u8,
180 #[deku(bits = "2", pad_bits_before = "2")]
181 lbafu: u8,
182 #[deku(bits = "3")]
183 ses: SecureEraseSettings,
184 #[deku(bits = "1", pad_bytes_after = "2")]
185 pil: bool,
186}
187
188impl AdminFormatNvmConfiguration {
189 fn lbafi(&self) -> u8 {
190 self.lbafu << 4 | self.lbafl
191 }
192}
193
194#[derive(Debug, DekuRead, DekuWrite, Eq, PartialEq)]
197#[deku(ctx = "endian: Endian, lid: u8", id = "lid", endian = "endian")]
198#[repr(u8)]
199pub enum AdminGetLogPageLidRequestType {
200 SupportedLogPages = 0x00,
201 ErrorInformation = 0x01,
202 SmartHealthInformation = 0x02,
203 FeatureIdentifiersSupportedAndEffects = 0x12,
204 SanitizeStatus = 0x81,
205}
206unsafe impl crate::Discriminant<u8> for AdminGetLogPageLidRequestType {}
207
208#[derive(Debug, DekuRead, DekuWrite)]
210#[deku(endian = "little")]
211pub struct AdminGetLogPageSupportedLogPagesResponse {
212 lsids: WireVec<LidSupportedAndEffectsDataStructure, 256>,
213}
214impl Encode<1024> for AdminGetLogPageSupportedLogPagesResponse {}
215
216flags! {
218 pub enum LidSupportedAndEffectsFlags: u8 {
219 Lsupp,
220 Ios,
221 }
222}
223
224#[derive(Clone, Copy, Debug, DekuRead, DekuWrite)]
226#[deku(ctx = "endian: Endian", endian = "endian")]
227pub struct LidSupportedAndEffectsDataStructure {
228 flags: WireFlagSet<LidSupportedAndEffectsFlags>,
229 #[deku(seek_from_current = "1")]
230 lidsp: u16,
231}
232
233flags! {
235 pub enum CriticalWarningFlags: u8 {
236 Ascbt,
237 Ttc,
238 Ndr,
239 Amro,
240 Vmbf,
241 Pmrro,
242 }
243}
244
245flags! {
247 pub enum EnduranceGroupCriticalWarningSummaryFlags: u8 {
248 Egascbt = 1 << 0,
249 Egdr = 1 << 2,
250 Egro = 1 << 3,
251 }
252}
253
254#[derive(Debug, Default, DekuRead, DekuWrite)]
256#[deku(endian = "little")]
257pub struct SmartHealthInformationLogPageResponse {
258 cw: WireFlagSet<CriticalWarningFlags>,
259 ctemp: u16,
260 avsp: u8,
261 avspt: u8,
262 pused: u8,
263 egcws: WireFlagSet<EnduranceGroupCriticalWarningSummaryFlags>,
264 #[deku(seek_from_current = "25")]
265 dur: u128,
266 duw: u128,
267 hrc: u128,
268 hwc: u128,
269 cbt: u128,
270 pwrc: u128,
271 poh: u128,
272 upl: u128,
273 mdie: u128,
274 neile: u128,
275 wctt: u32,
276 cctt: u32,
277 tsen: [u16; 8],
278 tmttc: [u32; 2],
279 #[deku(pad_bytes_after = "280")]
280 tttmt: [u32; 2],
281}
282impl Encode<512> for SmartHealthInformationLogPageResponse {}
283
284flags! {
286 pub enum FidSupportedAndEffectsFlags: u32 {
287 Fsupp = 1 << 0,
288 Udcc = 1 << 1,
289 Ncc = 1 << 2,
290 Nic = 1 << 3,
291 Ccc = 1 << 4,
292 Uss = 1 << 19,
293 FspNscpe = 1 << 20,
294 FspCscpe = 1 << 21,
295 FspNsetscpe = 1 << 22,
296 FspEgscpe = 1 << 23,
297 FspDscpe = 1 << 24,
298 FspNsubscpe = 1 << 25,
299 FspCdqscp = 1 << 26,
300 FspMask = (
301 FidSupportedAndEffectsFlags::FspNscpe
302 | FidSupportedAndEffectsFlags::FspNsetscpe
303 | FidSupportedAndEffectsFlags::FspEgscpe
304 | FidSupportedAndEffectsFlags::FspNsubscpe
305 | FidSupportedAndEffectsFlags::FspCdqscp
306 ).bits()
307 }
308}
309
310#[derive(Clone, Copy, Debug, Default, DekuRead, DekuWrite, Eq, PartialEq)]
312#[deku(
313 bits = "bits.0",
314 ctx = "endian: Endian, bits: BitSize",
315 endian = "endian",
316 id_type = "u8"
317)]
318#[repr(u8)]
319pub enum SanitizeOperationStatus {
320 #[default]
321 SanitizeNeverStarted = 0b000,
322 Sanitized = 0b001,
323 Sanitizing = 0b010,
324 SanitizeFailed = 0b011,
325 SanitizedUnexpectedDeallocate = 0b100,
326}
327unsafe impl crate::Discriminant<u8> for SanitizeOperationStatus {}
328
329#[derive(Clone, Copy, Debug, Default, DekuRead, DekuWrite)]
331#[deku(ctx = "endian: Endian", endian = "endian")]
332pub struct SanitizeStatus {
333 #[deku(bits = "5")]
334 opc: u8,
335 #[deku(bits = "3")]
336 sos: SanitizeOperationStatus,
337 #[deku(bits = "1", pad_bits_before = "6")]
338 mvcncled: bool,
339 #[deku(bits = "1")]
340 gde: bool,
341}
342
343#[derive(Clone, Copy, Debug, Default, DekuRead, DekuWrite, Eq, PartialEq)]
345#[deku(
346 bits = "bits.0",
347 ctx = "endian: Endian, bits: BitSize",
348 endian = "endian",
349 id_type = "u8"
350)]
351#[repr(u8)]
352enum SanitizeState {
353 #[default]
354 Idle = 0x00,
355 RestrictedProcessing = 0x01,
356 RestrictedFailure = 0x02,
357 UnrestrictedProcessing = 0x03,
358 UnrestrictedFailure = 0x04,
359 MediaVerification = 0x05,
360 PostVerificationDeallocation = 0x06,
361}
362unsafe impl crate::Discriminant<u8> for SanitizeState {}
363
364#[derive(Clone, Copy, Debug, Default, DekuRead, DekuWrite)]
366#[deku(ctx = "endian: Endian", endian = "endian")]
367pub struct SanitizeStateInformation {
368 #[deku(bits = "4")]
369 fails: u8,
370 #[deku(bits = "4")]
371 sans: SanitizeState,
372}
373
374#[derive(Debug, DekuRead, DekuWrite)]
376#[deku(endian = "little")]
377struct SanitizeStatusLogPageResponse {
378 sprog: u16,
379 sstat: SanitizeStatus,
380 scdw10: AdminSanitizeConfiguration,
381 eto: u32,
382 etbe: u32,
383 etce: u32,
384 etodmm: u32,
385 etbenmm: u32,
386 etcenmm: u32,
387 etpvds: u32,
388 ssi: SanitizeStateInformation,
389}
390impl Encode<512> for SanitizeStatusLogPageResponse {}
391
392#[derive(Clone, Copy, Debug, DekuRead, DekuWrite, Eq, PartialEq)]
394#[deku(ctx = "endian: Endian, cns: u8", id = "cns", endian = "endian")]
395#[repr(u8)]
396enum AdminIdentifyCnsRequestType {
397 NvmIdentifyNamespace = 0x00,
398 IdentifyController = 0x01,
399 ActiveNamespaceIDList = 0x02,
400 NamespaceIdentificationDescriptorList = 0x03,
401 IoIdentifyNamespace = 0x05,
402 IoIdentifyController = 0x06,
403 IoActiveNamespaceIdList = 0x07,
404 IdentifyNamespace = 0x08,
405 AllocatedNamespaceIdList = 0x10,
406 IdentifyNamespaceForAllocatedNamespaceId = 0x11,
407 NamespaceAttachedControllerList = 0x12,
408 NvmSubsystemControllerList = 0x13,
409 SecondaryControllerList = 0x15,
410}
411unsafe impl Discriminant<u8> for AdminIdentifyCnsRequestType {}
412
413#[derive(Debug, Default, DekuRead, DekuWrite)]
416#[deku(endian = "little")]
417pub struct AdminIdentifyNvmIdentifyNamespaceResponse {
418 nsze: u64,
419 ncap: u64,
420 nuse: u64,
421 nsfeat: u8,
422 nlbaf: u8,
423 flbas: u8,
424 mc: u8,
425 dpc: u8,
426 dps: u8,
427 #[deku(seek_from_current = "18")]
428 nvmcap: u128,
429 #[deku(seek_from_current = "64")]
430 lbaf0: u16,
432 lbaf0_lbads: u8,
433 lbaf0_rp: u8,
434}
435impl Encode<4096> for AdminIdentifyNvmIdentifyNamespaceResponse {}
436
437impl From<&crate::Namespace> for AdminIdentifyNvmIdentifyNamespaceResponse {
438 fn from(value: &crate::Namespace) -> Self {
439 Self {
440 nsze: value.size,
441 ncap: value.capacity,
442 nuse: value.used,
443 nsfeat: ((value.size == value.capacity) as u8),
444 nlbaf: 0,
445 flbas: 0,
446 mc: 0,
447 dpc: 0,
448 dps: 0,
449 nvmcap: 2_u128.pow(value.block_order as u32) * value.size as u128,
450 lbaf0: 0,
451 lbaf0_lbads: value.block_order,
452 lbaf0_rp: 0,
453 }
454 }
455}
456
457#[derive(Clone, Copy, Debug, DekuRead, DekuWrite)]
459#[deku(id_type = "u8", endian = "endian", ctx = "endian: Endian")]
460#[repr(u8)]
461pub enum CommandSetIdentifier {
462 Nvm = 0x00,
463 KeyValue = 0x01,
464 ZonedNamespace = 0x02,
465 SubsystemLocalMemory = 0x03,
466 ComputationalPrograms = 0x04,
467}
468
469flags! {
471 enum ControllerMultipathIoNamespaceSharingCapabilityFlags: u8 {
472 Mports,
473 Mctrs,
474 Ft,
475 Anars,
476 }
477}
478
479flags! {
481 enum ControllerAttributeFlags: u32 {
482 Hids,
483 Nopspm,
484 Nsets,
485 Rrlvls,
486 Egs,
487 Plm,
488 Tbkas,
489 Ng,
490 Sqa,
491 Ulist,
492 Mds,
493 Fcm,
494 Vcm,
495 Deg,
496 Dnvms,
497 Elbas,
498 Mem,
499 Hmbr,
500 Rhii,
501 Fdps,
502 }
503}
504
505#[derive(Clone, Copy, Debug, DekuRead, DekuWrite, PartialEq)]
507#[deku(id_type = "u8", endian = "endian", ctx = "endian: Endian")]
508#[repr(u8)]
509enum ControllerType {
510 Reserved = 0x00,
511 IoController = 0x01,
512 DiscoveryController = 0x02,
513 AdministrativeController = 0x03,
514}
515
516impl From<crate::ControllerType> for ControllerType {
517 fn from(value: crate::ControllerType) -> Self {
518 match value {
519 crate::ControllerType::Io => Self::IoController,
520 crate::ControllerType::Discovery => Self::DiscoveryController,
521 crate::ControllerType::Administrative => Self::AdministrativeController,
522 }
523 }
524}
525
526flags! {
528 enum NvmSubsystemReportFlags: u8 {
529 Nvmesd,
530 Nvmee,
531 }
532}
533
534flags! {
536 enum ManagementEndpointCapabilityFlags: u8 {
537 Twpme,
538 Pcieme,
539 }
540}
541
542flags! {
544 #[repr(u8)]
545 pub enum LogPageAttributes: u8 {
546 Smarts,
547 Cses,
548 Lpeds,
549 Ts,
550 Pes,
551 Mlps,
552 Da4s,
553 }
554}
555
556#[derive(Clone, Copy, Debug, Default, DekuRead, DekuWrite)]
558#[deku(
559 bits = "bits.0",
560 bit_order = "order",
561 ctx = "endian: Endian, bits: BitSize, order: Order",
562 endian = "endian",
563 id_type = "u8"
564)]
565#[repr(u8)]
566pub enum NoDeallocateModifiesMediaAfterSanitize {
567 Undefined = 0b00,
568 #[default]
569 Unmodified = 0b01,
570 Modified = 0b10,
571 Reserved = 0b11,
572}
573
574flags! {
576 pub enum SanitizeCapabilityFlags: u32 {
577 Ces = 1 << 0,
578 Bes = 1 << 1,
579 Ows = 1 << 2,
580 Vers = 1 << 3,
581 Ndi = 1 << 29,
582 }
583}
584
585#[derive(Clone, Copy, Debug, DekuRead, DekuWrite)]
587#[deku(bit_order = "lsb", ctx = "endian: Endian", endian = "endian")]
588pub struct SanitizeCapabilities {
589 #[deku(bits = 30)]
590 caps: WireFlagSet<SanitizeCapabilityFlags>,
591 #[deku(bits = 2)]
592 nodmmas: NoDeallocateModifiesMediaAfterSanitize,
593}
594
595flags! {
597 pub enum FormatNvmAttributes: u8 {
598 Fns,
599 Sens,
600 Cryes,
601 Fnvmbs,
602 }
603}
604
605#[derive(Debug, DekuRead, DekuWrite)]
607#[deku(endian = "little")]
608struct AdminIdentifyControllerResponse {
609 vid: u16,
610 ssvid: u16,
611 sn: WireString<20>,
612 mn: WireString<40>,
613 fr: WireString<8>,
614 rab: u8,
615 ieee: [u8; 3],
616 cmic: WireFlagSet<ControllerMultipathIoNamespaceSharingCapabilityFlags>,
617 mdts: u8,
618 cntlid: u16,
619 ver: u32,
620 rtd3r: u32,
621 rtd3e: u32,
622 oaes: u32,
623 ctratt: WireFlagSet<ControllerAttributeFlags>,
624 #[deku(seek_from_current = "11")]
625 cntrltype: crate::nvme::ControllerType,
626 #[deku(seek_from_current = "141")]
627 nvmsr: WireFlagSet<NvmSubsystemReportFlags>,
628 vwci: u8,
629 mec: WireFlagSet<ManagementEndpointCapabilityFlags>,
630 ocas: u16,
631 acl: u8,
632 aerl: u8,
633 frmw: u8,
634 lpa: WireFlagSet<LogPageAttributes>,
635 elpe: u8,
636 npss: u8,
637 avscc: u8,
638 apsta: u8,
639 wctemp: u16,
640 cctemp: u16,
641 #[deku(seek_from_current = "49")]
642 fwug: u8,
643 kas: u16,
644 #[deku(seek_from_current = "6")]
645 sanicap: SanitizeCapabilities,
646 #[deku(seek_from_current = "54")]
647 cqt: u16,
648 #[deku(seek_from_current = "124")]
649 sqes: u8,
650 cqes: u8,
651 maxcmd: u16,
652 nn: u32,
653 oncs: u16,
654 fuses: u16,
655 fna: WireFlagSet<FormatNvmAttributes>,
656 vwc: u8,
657 awun: u16,
658 awupf: u16,
659 icsvscc: u8,
660 nwpc: u8,
661 #[deku(seek_from_current = "8")]
662 mnan: u32,
663 #[deku(seek_from_current = "224")]
664 subnqn: WireString<256>,
665 #[deku(seek_from_current = "778")]
666 fcatt: u8,
667 msdbd: u8,
668 ofcs: u16,
669}
670impl Encode<4096> for AdminIdentifyControllerResponse {}
671
672#[derive(Debug, DekuRead, DekuWrite)]
674#[deku(endian = "little")]
675struct AdminIdentifyActiveNamespaceIdListResponse {
676 nsid: WireVec<u32, 1024>,
677}
678impl Encode<4096> for AdminIdentifyActiveNamespaceIdListResponse {}
679
680impl AdminIdentifyActiveNamespaceIdListResponse {
681 fn new() -> Self {
682 Self {
683 nsid: WireVec::new(),
684 }
685 }
686}
687
688#[derive(Clone, Copy, Debug, DekuRead, DekuWrite)]
690#[deku(id_type = "u8", endian = "endian", ctx = "endian: Endian")]
691#[repr(u8)]
692enum NamespaceIdentifierType {
693 Reserved = 0,
694 #[deku(id = 1)]
695 Ieuid(u8, u16, [u8; 8]),
696 #[deku(id = 2)]
697 Nguid(u8, u16, [u8; 16]),
698 #[deku(id = 3)]
699 Nuuid(u8, u16, WireUuid),
700 #[deku(id = 4)]
701 Csi(u8, u16, crate::nvme::CommandSetIdentifier),
702}
703
704impl From<crate::NamespaceIdentifierType> for NamespaceIdentifierType {
705 fn from(value: crate::NamespaceIdentifierType) -> Self {
706 match value {
707 crate::NamespaceIdentifierType::Ieuid(v) => Self::Ieuid(v.len() as u8, 0, v),
708 crate::NamespaceIdentifierType::Nguid(v) => Self::Nguid(v.len() as u8, 0, v),
709 crate::NamespaceIdentifierType::Nuuid(uuid) => Self::Nuuid(16, 0, WireUuid::new(uuid)),
710 crate::NamespaceIdentifierType::Csi(v) => Self::Csi(1, 0, v),
711 }
712 }
713}
714
715#[derive(Debug)]
717#[deku_derive(DekuRead, DekuWrite)]
718#[deku(endian = "little")]
719struct AdminIdentifyNamespaceIdentificationDescriptorListResponse {
720 nids: WireVec<NamespaceIdentifierType, { crate::MAX_NIDTS }>,
721}
722impl Encode<4096> for AdminIdentifyNamespaceIdentificationDescriptorListResponse {}
723
724#[derive(Debug, DekuRead, DekuWrite)]
726#[deku(endian = "little")]
727struct AdminIdentifyAllocatedNamespaceIdListResponse {
728 nsid: WireVec<u32, 1024>,
729}
730impl Encode<4096> for AdminIdentifyAllocatedNamespaceIdListResponse {}
731
732#[derive(Debug, DekuWrite)]
734#[deku(endian = "little")]
735struct ControllerListResponse {
736 #[deku(update = "self.ids.len()")]
737 numids: u16,
738 #[deku(count = "numids")]
739 ids: WireVec<u16, 2047>,
740}
741impl Encode<4096> for ControllerListResponse {}
742
743impl ControllerListResponse {
744 fn new() -> Self {
745 Self {
746 numids: 0,
747 ids: WireVec::new(),
748 }
749 }
750}
751
752#[derive(Debug, DekuRead, Eq, PartialEq)]
754#[deku(ctx = "endian: Endian", endian = "endian", id_type = "u8")]
755#[repr(u8)]
756enum AdminNamespaceAttachmentSelect {
757 ControllerAttach = 0x00,
758 ControllerDetach = 0x01,
759}
760
761#[derive(Debug, DekuRead, DekuWrite, Eq, PartialEq)]
763#[deku(ctx = "endian: Endian, sel: u8", endian = "endian", id = "sel")]
764#[repr(u8)]
765enum AdminNamespaceManagementSelect {
766 #[deku(id = 0x00)]
767 Create(NvmNamespaceManagementCreate),
768 Delete = 0x01,
769}
770
771#[derive(Debug, DekuRead, DekuWrite, Eq, PartialEq)]
774#[deku(ctx = "endian: Endian", endian = "endian")]
775struct NvmNamespaceManagementCreate {
776 nsze: u64,
777 ncap: u64,
778 #[deku(seek_from_current = "10")]
779 flbas: u8,
780 #[deku(seek_from_current = "2")]
781 dps: u8,
782 nmic: u8,
783 #[deku(seek_from_current = "61")]
784 anagrpid: u32,
785 #[deku(seek_from_current = "4")]
786 nvmsetid: u16,
787 endgid: u16,
788 #[deku(seek_from_current = "280")]
789 #[deku(pad_bytes_after = "3704")]
790 lbstm: u64,
791}
792
793#[derive(Clone, Copy, Debug, Default, DekuRead, DekuWrite, Eq, PartialEq)]
795#[deku(
796 bits = "bits.0",
797 ctx = "endian: Endian, bits: BitSize",
798 endian = "endian",
799 id_type = "u8"
800)]
801#[repr(u8)]
802enum SanitizeAction {
803 #[default]
804 Reserved = 0x00,
805 ExitFailureMode = 0x01,
806 StartBlockErase = 0x02,
807 StartOverwrite = 0x03,
808 StartCryptoErase = 0x04,
809 ExitMediaVerificationState = 0x05,
810}
811
812impl TryFrom<u32> for SanitizeAction {
813 type Error = ();
814
815 fn try_from(value: u32) -> Result<Self, Self::Error> {
816 match value {
817 0x00 => Ok(Self::Reserved),
818 0x01 => Ok(Self::ExitFailureMode),
819 0x02 => Ok(Self::StartBlockErase),
820 0x03 => Ok(Self::StartOverwrite),
821 0x04 => Ok(Self::StartCryptoErase),
822 0x05 => Ok(Self::ExitMediaVerificationState),
823 _ => Err(()),
824 }
825 }
826}
827
828#[derive(Clone, Copy, Debug, Default, DekuRead, DekuWrite, Eq, PartialEq)]
830#[deku(ctx = "endian: Endian", endian = "endian")]
831pub struct AdminSanitizeConfiguration {
832 #[deku(bits = "4")]
833 owpass: u8,
834 #[deku(bits = "1")]
835 ause: bool,
836 #[deku(bits = "3")]
837 sanact: SanitizeAction,
838 #[deku(bits = "1", pad_bits_before = "5")]
839 emvs: bool,
840 #[deku(bits = "1")]
841 ndas: bool,
842 #[deku(bits = "1", pad_bytes_after = "2")]
843 oipbp: bool,
844}
845
846#[derive(Debug, DekuRead, DekuWrite)]
849#[deku(ctx = "endian: Endian", endian = "endian", id_type = "u8")]
850#[repr(u8)]
851pub enum FeatureIdentifiers {
852 KeepAliveTimer = 0x0f,
853}