1use deku::ctx::{BitSize, Endian, Order};
7use deku::{DekuError, DekuRead, DekuWrite};
8use flagset::{FlagSet, flags};
9use log::debug;
10
11use crate::nvme::{
12 AdminFormatNvmConfiguration, AdminNamespaceAttachmentSelect, AdminNamespaceManagementSelect,
13 AdminSanitizeConfiguration, ControllerListRequest,
14};
15use crate::wire::{WireFlagSet, WireVec};
16use crate::{CommandEffectError, Discriminant, Encode, MAX_CONTROLLERS};
17
18use super::{AdminGetLogPageLidRequestType, AdminIdentifyCnsRequestType};
19
20pub mod dev;
21
22#[derive(Clone, Copy, Debug, DekuRead, DekuWrite, PartialEq, Eq)]
24#[deku(
25 bits = "4",
26 bit_order = "order",
27 ctx = "endian: Endian, order: Order",
28 endian = "endian",
29 id_type = "u8"
30)]
31#[repr(u8)]
32enum MessageType {
33 ControlPrimitive = 0x00,
34 NvmeMiCommand = 0x01,
35 NvmeAdminCommand = 0x02,
36 PcieCommand = 0x04,
37 AsynchronousEvent = 0x05,
38}
39
40#[derive(Debug, DekuRead, DekuWrite)]
42#[deku(bit_order = "lsb", endian = "little")]
43struct MessageHeader {
44 #[deku(bits = "1", pad_bits_after = "2")]
45 csi: u8,
46 nmimt: MessageType,
47 #[deku(bits = "1", pad_bytes_after = "2")]
48 ror: bool,
49}
50impl Encode<3> for MessageHeader {}
51
52impl MessageHeader {
53 fn respond(nmimt: MessageType) -> Self {
54 Self {
55 csi: 0,
56 nmimt,
57 ror: true,
58 }
59 }
60}
61#[derive(Debug, DekuRead, DekuWrite, PartialEq)]
63#[deku(endian = "endian", ctx = "endian: Endian", id_type = "u8")]
64#[repr(u8)]
65pub enum ResponseStatus {
66 Success = 0x00,
67 InternalError = 0x02,
68 InvalidCommandOpcode = 0x03,
69 InvalidParameter = 0x04,
70 InvalidCommandSize = 0x05,
71 InvalidCommandInputDataSize = 0x06,
72 AccessDenied = 0x07,
73}
74unsafe impl Discriminant<u8> for ResponseStatus {}
75
76impl From<DekuError> for ResponseStatus {
77 fn from(err: DekuError) -> Self {
78 debug!("Codec operation failed: {err}");
79 Self::InternalError
80 }
81}
82
83impl From<()> for ResponseStatus {
84 fn from(_: ()) -> Self {
85 Self::InternalError
86 }
87}
88
89impl From<CommandEffectError> for ResponseStatus {
90 fn from(value: CommandEffectError) -> Self {
91 debug!("Failed to apply command effect: {value:?}");
92 Self::InternalError
93 }
94}
95
96#[derive(Debug, DekuRead, DekuWrite)]
98#[deku(endian = "little")]
99struct NvmeMiCommandRequestHeader {
100 #[deku(pad_bytes_after = "3")]
101 #[deku(update = "self.body.id()")]
102 opcode: u8,
103 #[deku(ctx = "*opcode")]
104 body: NvmeMiCommandRequestType,
105}
106impl Encode<4> for NvmeMiCommandRequestHeader {}
107
108#[derive(Debug, DekuRead, DekuWrite, PartialEq, Eq)]
110#[deku(ctx = "endian: Endian, opcode: u8", id = "opcode", endian = "endian")]
111#[repr(u8)]
112enum NvmeMiCommandRequestType {
113 #[deku(id = "0x00")]
114 ReadNvmeMiDataStructure(NvmeMiDataStructureRequest),
115 #[deku(id = "0x01")]
116 NvmSubsystemHealthStatusPoll(NvmSubsystemHealthStatusPollRequest),
117 #[deku(id = "0x02")]
118 ControllerHealthStatusPoll(ControllerHealthStatusPollRequest),
119 #[deku(id = "0x03")]
120 ConfigurationSet(NvmeMiConfigurationSetRequest),
121 #[deku(id = "0x04")]
122 ConfigurationGet(NvmeMiConfigurationGetRequest),
123 VpdRead = 0x05,
124 VpdWrite = 0x06,
125 Reset = 0x07,
126 SesReceive = 0x08,
127 SesSend = 0x09,
128 ManagementEndpointBufferRead = 0x0a,
129 ManagementEndpointBufferWrite = 0x0b,
130 Shutdown = 0x0c,
131}
132unsafe impl Discriminant<u8> for NvmeMiCommandRequestType {}
133
134#[derive(Debug, DekuRead, DekuWrite)]
136#[deku(endian = "little")]
137struct NvmeManagementResponse {
138 #[deku(pad_bytes_after = "3")]
139 status: ResponseStatus,
140}
141impl Encode<4> for NvmeManagementResponse {}
142
143#[derive(Debug, DekuRead, DekuWrite, Eq, PartialEq)]
145#[deku(ctx = "endian: Endian", endian = "endian")]
146struct NvmeMiConfigurationGetRequest {
147 body: NvmeMiConfigurationIdentifierRequestType,
148}
149
150#[derive(Debug, DekuRead, DekuWrite, Eq, PartialEq)]
152#[deku(id_type = "u8", ctx = "endian: Endian", endian = "endian")]
153#[repr(u8)]
154enum NvmeMiConfigurationIdentifierRequestType {
155 Reserved = 0x00,
156 #[deku(id = "0x01")]
157 SmbusI2cFrequency(SmbusI2cFrequencyRequest),
158 #[deku(id = "0x02")]
159 HealthStatusChange(HealthStatusChangeRequest),
160 #[deku(id = "0x03")]
161 MctpTransmissionUnitSize(MctpTransmissionUnitSizeRequest),
162 AsynchronousEvent = 0x04,
163}
164
165#[derive(Debug, Clone, Copy, DekuRead, DekuWrite, Eq, PartialEq, PartialOrd)]
167#[deku(
168 bits = "bits.0",
169 id_type = "u8",
170 ctx = "endian: Endian, bits: BitSize",
171 endian = "endian"
172)]
173#[repr(u8)]
174enum SmbusFrequency {
175 Reserved = 0x00,
176 Freq100Khz = 0x01,
177 Freq400Khz = 0x02,
178 Freq1Mhz = 0x03,
179}
180
181impl From<SmbusFrequency> for crate::smbus::BusFrequency {
182 fn from(value: SmbusFrequency) -> Self {
183 match value {
184 SmbusFrequency::Reserved => Self::NotSupported,
185 SmbusFrequency::Freq100Khz => Self::Freq100Khz,
186 SmbusFrequency::Freq400Khz => Self::Freq400Khz,
187 SmbusFrequency::Freq1Mhz => Self::Freq1Mhz,
188 }
189 }
190}
191
192impl From<crate::smbus::BusFrequency> for SmbusFrequency {
193 fn from(value: crate::smbus::BusFrequency) -> Self {
194 match value {
195 crate::smbus::BusFrequency::NotSupported => Self::Reserved,
196 crate::smbus::BusFrequency::Freq100Khz => Self::Freq100Khz,
197 crate::smbus::BusFrequency::Freq400Khz => Self::Freq400Khz,
198 crate::smbus::BusFrequency::Freq1Mhz => Self::Freq1Mhz,
199 }
200 }
201}
202
203#[derive(Debug, DekuWrite, PartialEq)]
205#[deku(endian = "little")]
206struct GetSmbusI2cFrequencyResponse {
207 status: ResponseStatus,
208 #[deku(bits = "4", pad_bits_before = "4", pad_bytes_after = "2")]
209 sfreq: SmbusFrequency,
210}
211impl Encode<4> for GetSmbusI2cFrequencyResponse {}
212
213#[derive(Debug, DekuWrite)]
215#[deku(endian = "little")]
216struct GetHealthStatusChangeResponse {
217 #[deku(pad_bytes_after = "3")]
218 status: ResponseStatus,
219}
220impl Encode<4> for GetHealthStatusChangeResponse {}
221
222#[derive(Debug, DekuWrite)]
224#[deku(endian = "little")]
225struct GetMctpTransmissionUnitSizeResponse {
226 status: ResponseStatus,
227 #[deku(pad_bytes_after = "1")]
228 mr_mtus: u16,
229}
230impl Encode<4> for GetMctpTransmissionUnitSizeResponse {}
231
232#[derive(Debug, DekuRead, DekuWrite, Eq, PartialEq)]
234#[deku(ctx = "endian: Endian", endian = "endian")]
235struct NvmeMiConfigurationSetRequest {
236 body: NvmeMiConfigurationIdentifierRequestType,
237}
238
239#[derive(Debug, DekuRead, DekuWrite, Eq, PartialEq)]
241#[deku(ctx = "endian: Endian", endian = "endian")]
242struct SmbusI2cFrequencyRequest {
243 #[deku(bits = "4", pad_bits_before = "4", pad_bytes_after = "1")]
244 sfreq: SmbusFrequency,
245 #[deku(pad_bytes_after = "4")]
246 portid: u8,
247}
248
249#[derive(Debug, DekuRead, DekuWrite, Eq, PartialEq)]
251#[deku(ctx = "endian: Endian", endian = "endian")]
252struct HealthStatusChangeRequest {
253 #[deku(seek_from_current = "3")]
255 dw1: u32,
256}
257
258flags! {
260 #[repr(u32)]
261 enum HealthStatusChangeFlags: u32 {
262 Rdy,
263 Cfs,
264 Shst,
265 Nssro,
266 Ceco,
267 Nac,
268 Fa,
269 Csts,
270 Ctemp,
271 Pldu,
272 Spare,
273 Cwarn,
274 Tcida,
275 }
276}
277
278#[derive(Debug, DekuRead, DekuWrite, Eq, PartialEq)]
280#[deku(ctx = "endian: Endian", endian = "endian")]
281struct MctpTransmissionUnitSizeRequest {
282 #[deku(seek_from_current = "2")]
283 dw0_portid: u8,
284 #[deku(pad_bytes_after = "2")]
285 dw1_mtus: u16,
286}
287
288flags! {
290 pub enum ControllerFunctionAndReportingFlags: u8 {
291 Incf = 1 << 0,
292 Incpf = 1 << 1,
293 Incvf = 1 << 2,
294 All = 1 << 7,
295 }
296}
297
298flags! {
300 pub enum ControllerPropertyFlags: u32 {
301 Csts = 1 << 0,
302 Ctemp = 1 << 1,
303 Pldu = 1 << 2,
304 Spare = 1 << 3,
305 Cwarn = 1 << 4,
306 Ccf = 1 << 31,
307 }
308}
309
310#[derive(Debug, DekuRead, DekuWrite, Eq, PartialEq)]
312#[deku(ctx = "endian: Endian", endian = "endian")]
313struct ControllerHealthStatusPollRequest {
314 sctlid: u16,
315 maxrent: u8,
316 functions: WireFlagSet<ControllerFunctionAndReportingFlags>,
317 properties: WireFlagSet<ControllerPropertyFlags>,
318}
319
320#[derive(Debug, DekuRead, DekuWrite)]
322#[deku(endian = "little")]
323struct ControllerHealthStatusPollResponse {
324 status: ResponseStatus,
325 #[deku(pad_bytes_before = "2", update = "self.body.len() as u8")]
326 rent: u8,
327 body: WireVec<ControllerHealthDataStructure, MAX_CONTROLLERS>,
328}
329impl Encode<{ 4 + 16 * MAX_CONTROLLERS }> for ControllerHealthStatusPollResponse {}
330
331flags! {
333 pub enum ControllerStatusFlags: u16 {
334 Rdy = 1 << 0,
335 Cfs = 1 << 1,
336 ShstInProgress = 1 << 2,
337 ShstComplete = 1 << 3,
338 ShstReserved = (ControllerStatusFlags::ShstInProgress | ControllerStatusFlags::ShstComplete).bits(),
339 Nssro = 1 << 4,
340 Ceco = 1 << 5,
341 Nac = 1 << 6,
342 Fa = 1 << 7,
343 Tcida = 1 << 8,
344 }
345}
346
347impl From<FlagSet<super::ControllerStatusFlags>> for WireFlagSet<ControllerStatusFlags> {
350 fn from(value: FlagSet<super::ControllerStatusFlags>) -> Self {
351 use super::ControllerStatusFlags as F;
352 use ControllerStatusFlags as T;
353
354 let mut fs = FlagSet::empty();
355
356 for f in value {
357 fs |= match f {
358 F::Rdy => T::Rdy,
359 F::Cfs => T::Cfs,
360 F::ShstInProgress => T::ShstInProgress,
361 F::ShstComplete => T::ShstComplete,
362 F::ShstReserved => T::ShstReserved,
363 F::Nssro => T::Nssro,
364 F::Pp => todo!(),
365 F::St => todo!(),
366 };
367 }
368
369 Self(fs)
370 }
371}
372
373flags! {
375 pub enum CriticalWarningFlags: u8 {
376 St,
377 Taut,
378 Rd,
379 Ro,
380 Vmbf,
381 Pmre
382 }
383}
384
385#[derive(Debug, DekuRead, DekuWrite)]
387#[deku(ctx = "endian: Endian", endian = "endian")]
388struct ControllerHealthDataStructure {
389 ctlid: u16,
390 csts: WireFlagSet<ControllerStatusFlags>,
391 ctemp: u16,
392 pdlu: u8,
393 spare: u8,
394 cwarn: WireFlagSet<CriticalWarningFlags>,
395 #[deku(pad_bytes_after = "5")]
396 chsc: WireFlagSet<ControllerHealthStatusChangedFlags>,
397}
398
399flags! {
401 pub enum ControllerHealthStatusChangedFlags: u16 {
403 Rdy = 1 << 0,
404 Cfs = 1 << 1,
405 Shst = 1 << 2,
406 Nssro = 1 << 4,
407 Ceco = 1 << 5,
408 Nac = 1 << 6,
409 Fa = 1 << 7,
410 Csts = 1 << 8,
411 Ctemp = 1 << 9,
412 Pdlu = 1 << 10,
413 Spare = 1 << 11,
414 Cwarn = 1 << 12,
415 Tcida = 1 << 13,
416 }
417}
418
419#[derive(Debug, DekuRead, DekuWrite, Eq, PartialEq)]
421#[deku(ctx = "endian: Endian", endian = "endian")]
422struct NvmSubsystemHealthStatusPollRequest {
423 #[deku(bits = "1", pad_bits_after = "7", pad_bytes_before = "7")]
424 cs: bool,
425}
426
427flags! {
429 #[repr(u16)]
430 enum CompositeControllerStatusFlags: u16 {
431 Rdy = 1 << 0,
432 Cfs = 1 << 1,
433 Shst = 1 << 2,
434 Nssro = 1 << 4,
435 Ceco = 1 << 5,
436 Nac = 1 << 6,
437 Fa = 1 << 7,
438 Csts = 1 << 8,
439 Ctemp = 1 << 9,
440 Pdlu = 1 << 10,
441 Spare = 1 << 11,
442 Cwarn = 1 << 12,
443 Tcida = 1 << 13,
444 }
445}
446
447#[derive(Debug)]
448pub struct CompositeControllerStatusFlagSet(FlagSet<CompositeControllerStatusFlags>);
449
450impl CompositeControllerStatusFlagSet {
451 pub fn empty() -> Self {
452 Self(FlagSet::empty())
453 }
454}
455
456impl From<FlagSet<HealthStatusChangeFlags>> for CompositeControllerStatusFlagSet {
457 fn from(value: FlagSet<HealthStatusChangeFlags>) -> Self {
458 use CompositeControllerStatusFlags as T;
459 use HealthStatusChangeFlags as F;
460
461 let mut converted = FlagSet::empty();
462 for flag in value {
463 converted |= match flag {
464 F::Rdy => T::Rdy,
465 F::Cfs => T::Cfs,
466 F::Shst => T::Shst,
467 F::Nssro => T::Nssro,
468 F::Ceco => T::Ceco,
469 F::Nac => T::Nac,
470 F::Fa => T::Fa,
471 F::Csts => T::Csts,
472 F::Ctemp => T::Ctemp,
473 F::Pldu => T::Pdlu,
474 F::Spare => T::Spare,
475 F::Cwarn => T::Cwarn,
476 F::Tcida => T::Tcida,
477 }
478 }
479 Self(converted)
480 }
481}
482
483impl From<FlagSet<ControllerHealthStatusChangedFlags>> for CompositeControllerStatusFlagSet {
484 fn from(value: FlagSet<ControllerHealthStatusChangedFlags>) -> Self {
485 Self(FlagSet::new(value.bits()).expect("Divergent flag definitions"))
487 }
488}
489
490#[derive(Debug, DekuRead, DekuWrite)]
492#[deku(endian = "little")]
493struct CompositeControllerStatusDataStructureResponse {
494 #[deku(pad_bytes_after = "2")]
495 ccsf: u16,
496}
497impl Encode<4> for CompositeControllerStatusDataStructureResponse {}
498
499flags! {
501 pub enum NvmSubsystemStatusFlags: u8 {
502 P1la = 1 << 2,
503 P0la = 1 << 3,
504 Rnr = 1 << 4,
505 Df = 1 << 5,
506 Sfm = 1 << 6,
507 Atf = 1 << 7,
508 }
509}
510
511flags! {
513 pub enum SmartWarningFlags: u8 {
514 Ascbt,
515 Ttc,
516 Ndr,
517 Amro,
518 Vmbf,
519 Pmrro,
520 }
521}
522
523impl From<FlagSet<super::CriticalWarningFlags>> for WireFlagSet<SmartWarningFlags> {
524 fn from(value: FlagSet<super::CriticalWarningFlags>) -> Self {
525 FlagSet::<SmartWarningFlags>::new((!value.bits()) & 0x3f)
526 .expect("Undefined bits set")
527 .into()
528 }
529}
530
531#[derive(Debug, DekuRead, DekuWrite)]
533#[deku(endian = "little")]
534struct NvmSubsystemHealthDataStructureResponse {
535 nss: WireFlagSet<NvmSubsystemStatusFlags>,
536 sw: WireFlagSet<SmartWarningFlags>,
537 ctemp: u8,
538 pldu: u8,
539}
540impl Encode<4> for NvmSubsystemHealthDataStructureResponse {}
541
542#[derive(Debug, DekuRead, DekuWrite, PartialEq, Eq)]
544#[deku(ctx = "endian: Endian, dtyp: u8", endian = "endian", id = "dtyp")]
545#[repr(u8)]
546enum NvmeMiDataStructureRequestType {
547 NvmSubsystemInformation = 0x00,
548 PortInformation = 0x01,
549 ControllerList = 0x02,
550 ControllerInformation = 0x03,
551 OptionallySupportedCommandList = 0x04,
552 ManagementEndpointBufferCommandSupportList = 0x05,
553}
554unsafe impl Discriminant<u8> for NvmeMiDataStructureRequestType {}
555
556#[derive(Debug, DekuRead, DekuWrite, Eq, PartialEq)]
558#[deku(ctx = "endian: Endian", endian = "endian")]
559struct NvmeMiDataStructureRequest {
560 ctrlid: u16,
561 portid: u8,
562 #[deku(update = "self.body.id()")]
563 dtyp: u8,
564 #[deku(pad_bytes_after = "3")]
565 iocsi: u8,
566 #[deku(ctx = "*dtyp")]
567 body: NvmeMiDataStructureRequestType,
568}
569
570#[derive(Debug, DekuRead, DekuWrite)]
572#[deku(endian = "little")]
573struct NvmeMiDataStructureManagementResponse {
574 status: ResponseStatus,
575 rdl: u16,
576}
577impl Encode<4> for NvmeMiDataStructureManagementResponse {}
578
579#[derive(Debug)]
582pub struct SubsystemCapabilities {
583 sre: bool,
584}
585
586impl SubsystemCapabilities {
587 pub fn new() -> Self {
588 Self { sre: false }
589 }
590}
591
592impl Default for SubsystemCapabilities {
593 fn default() -> Self {
594 Self::new()
595 }
596}
597
598#[derive(Debug, DekuWrite)]
600#[deku(endian = "little")]
601struct NvmSubsystemInformationResponse {
602 nump: u8,
603 mjr: u8,
604 mnr: u8,
605 nnsc: u8,
606}
607impl Encode<32> for NvmSubsystemInformationResponse {}
608
609#[derive(Clone, Copy, Debug, DekuRead, DekuWrite, PartialEq, Eq)]
611#[deku(ctx = "endian: Endian", endian = "endian", id_type = "u8")]
612#[repr(u8)]
613pub enum PortType {
614 Inactive = 0x00,
615 Pcie = 0x01,
616 TwoWire = 0x02,
617}
618
619impl From<&crate::PortType> for PortType {
620 fn from(value: &crate::PortType) -> Self {
621 match value {
622 crate::PortType::Inactive => Self::Inactive,
623 crate::PortType::Pcie(_) => Self::Pcie,
624 crate::PortType::TwoWire(_) => Self::TwoWire,
625 }
626 }
627}
628
629flags! {
631 enum PortCapabilityFlags: u8 {
632 Ciaps,
633 Aems,
634 }
635}
636
637#[derive(Debug, DekuWrite)]
639#[deku(endian = "little")]
640struct PortInformationResponse {
641 prttyp: PortType,
642 prtcap: WireFlagSet<PortCapabilityFlags>,
643 mmtus: u16,
644 mebs: u32,
645}
646impl Encode<8> for PortInformationResponse {}
647
648#[derive(Clone, Copy, DekuRead, DekuWrite, Debug, Eq, PartialEq)]
650#[deku(ctx = "endian: Endian", endian = "endian", id_type = "u8")]
651#[repr(u8)]
652enum PciePayloadSize {
653 Payload128B = 0x00,
654 Payload256B = 0x01,
655 Payload512B = 0x02,
656 Payload1Kb = 0x03,
657 Payload2Kb = 0x04,
658 Payload4Kb = 0x05,
659}
660
661impl From<crate::pcie::PayloadSize> for PciePayloadSize {
662 fn from(value: crate::pcie::PayloadSize) -> Self {
663 match value {
664 crate::pcie::PayloadSize::Payload128B => Self::Payload128B,
665 crate::pcie::PayloadSize::Payload256B => Self::Payload256B,
666 crate::pcie::PayloadSize::Payload512B => Self::Payload512B,
667 crate::pcie::PayloadSize::Payload1Kb => Self::Payload1Kb,
668 crate::pcie::PayloadSize::Payload2Kb => Self::Payload2Kb,
669 crate::pcie::PayloadSize::Payload4Kb => Self::Payload4Kb,
670 }
671 }
672}
673
674impl From<PciePayloadSize> for crate::pcie::PayloadSize {
675 fn from(value: PciePayloadSize) -> Self {
676 match value {
677 PciePayloadSize::Payload128B => Self::Payload128B,
678 PciePayloadSize::Payload256B => Self::Payload256B,
679 PciePayloadSize::Payload512B => Self::Payload512B,
680 PciePayloadSize::Payload1Kb => Self::Payload1Kb,
681 PciePayloadSize::Payload2Kb => Self::Payload2Kb,
682 PciePayloadSize::Payload4Kb => Self::Payload4Kb,
683 }
684 }
685}
686
687flags! {
689 #[repr(u8)]
690 enum PcieSupportedLinkSpeeds: u8 {
691 Gts2p5,
692 Gts5,
693 Gts8,
694 Gts16,
695 Gts32,
696 Gts64,
697 }
698}
699
700#[derive(Clone, Copy, Debug, DekuRead, DekuWrite, Eq, PartialEq)]
702#[deku(ctx = "endian: Endian", endian = "endian", id_type = "u8")]
703#[repr(u8)]
704enum PcieLinkSpeed {
705 Inactive = 0x00,
706 Gts2p5 = 0x01,
707 Gts5 = 0x02,
708 Gts8 = 0x03,
709 Gts16 = 0x04,
710 Gts32 = 0x05,
711 Gts64 = 0x06,
712}
713
714impl From<crate::pcie::LinkSpeed> for PcieLinkSpeed {
715 fn from(value: crate::pcie::LinkSpeed) -> Self {
716 match value {
717 crate::pcie::LinkSpeed::Inactive => Self::Inactive,
718 crate::pcie::LinkSpeed::Gts2p5 => Self::Gts2p5,
719 crate::pcie::LinkSpeed::Gts5 => Self::Gts5,
720 crate::pcie::LinkSpeed::Gts8 => Self::Gts8,
721 crate::pcie::LinkSpeed::Gts16 => Self::Gts16,
722 crate::pcie::LinkSpeed::Gts32 => Self::Gts32,
723 crate::pcie::LinkSpeed::Gts64 => Self::Gts64,
724 }
725 }
726}
727
728impl From<PcieLinkSpeed> for crate::pcie::LinkSpeed {
729 fn from(value: PcieLinkSpeed) -> Self {
730 match value {
731 PcieLinkSpeed::Inactive => Self::Inactive,
732 PcieLinkSpeed::Gts2p5 => Self::Gts2p5,
733 PcieLinkSpeed::Gts5 => Self::Gts5,
734 PcieLinkSpeed::Gts8 => Self::Gts8,
735 PcieLinkSpeed::Gts16 => Self::Gts16,
736 PcieLinkSpeed::Gts32 => Self::Gts32,
737 PcieLinkSpeed::Gts64 => Self::Gts64,
738 }
739 }
740}
741
742#[derive(Clone, Copy, Debug, DekuRead, DekuWrite, Eq, PartialEq)]
744#[deku(ctx = "endian: Endian", endian = "endian", id_type = "u8")]
745#[repr(u8)]
746enum PcieLinkWidth {
747 X1 = 1,
748 X2 = 2,
749 X4 = 4,
750 X8 = 8,
751 X12 = 12,
752 X16 = 16,
753 X32 = 32,
754}
755
756impl From<crate::pcie::LinkWidth> for PcieLinkWidth {
757 fn from(value: crate::pcie::LinkWidth) -> Self {
758 match value {
759 crate::pcie::LinkWidth::X1 => Self::X1,
760 crate::pcie::LinkWidth::X2 => Self::X2,
761 crate::pcie::LinkWidth::X4 => Self::X4,
762 crate::pcie::LinkWidth::X8 => Self::X8,
763 crate::pcie::LinkWidth::X12 => Self::X12,
764 crate::pcie::LinkWidth::X16 => Self::X16,
765 crate::pcie::LinkWidth::X32 => Self::X32,
766 }
767 }
768}
769
770impl From<PcieLinkWidth> for crate::pcie::LinkWidth {
771 fn from(value: PcieLinkWidth) -> Self {
772 match value {
773 PcieLinkWidth::X1 => Self::X1,
774 PcieLinkWidth::X2 => Self::X2,
775 PcieLinkWidth::X4 => Self::X4,
776 PcieLinkWidth::X8 => Self::X8,
777 PcieLinkWidth::X12 => Self::X12,
778 PcieLinkWidth::X16 => Self::X16,
779 PcieLinkWidth::X32 => Self::X32,
780 }
781 }
782}
783
784#[derive(Debug, DekuRead, DekuWrite)]
786#[deku(endian = "little")]
787struct PciePortDataResponse {
788 pciemps: PciePayloadSize,
789 pcieslsv: WireFlagSet<PcieSupportedLinkSpeeds>,
790 pciecls: PcieLinkSpeed,
791 pciemlw: PcieLinkWidth,
792 pcienlw: PcieLinkWidth,
793 pciepn: u8,
794}
795impl Encode<24> for PciePortDataResponse {}
796
797#[derive(Debug, DekuWrite)]
799#[deku(endian = "little")]
800struct TwoWirePortDataResponse {
801 cvpdaddr: u8,
802 #[deku(bits = "8")]
803 mvpdfreq: SmbusFrequency,
804 cmeaddr: u8,
805 #[deku(bits = "1", pad_bits_after = "5")]
806 twprt_i3csprt: bool,
807 #[deku(bits = "2")]
808 twprt_msmbfreq: SmbusFrequency,
809 nvmebm: u8,
810}
811impl Encode<24> for TwoWirePortDataResponse {}
812
813#[derive(Debug, DekuRead, DekuWrite)]
815#[deku(endian = "little")]
816struct ControllerInformationResponse {
817 #[deku(pad_bytes_after = "4")]
818 portid: u8,
819 #[deku(bits = "1", pad_bits_before = "7")]
820 prii_pcieriv: bool,
821 #[deku(bits = "8")]
822 pri_pcibn: u16,
823 #[deku(bits = "5")]
824 pri_pcidn: u16,
825 #[deku(bits = "3")]
826 pri_pcifn: u16,
827 pcivid: u16,
828 pcidid: u16,
829 pcisvid: u16,
830 pcisdid: u16,
831 pciesn: u8,
832}
833impl Encode<32> for ControllerInformationResponse {}
834
835#[expect(clippy::large_enum_variant)] #[derive(Debug, DekuRead, PartialEq, Eq)]
838#[deku(ctx = "endian: Endian, opcode: u8", id = "opcode", endian = "endian")]
839#[repr(u8)]
840enum AdminCommandRequestType {
841 DeleteIoSubmissionQueue = 0x00, CreateIoSubmissionQueue = 0x01, #[deku(id = 0x02)]
844 GetLogPage(AdminGetLogPageRequest), DeleteIoCompletionQueue = 0x04, CreateIoCompletionQueue = 0x05, #[deku(id = 0x06)]
848 Identify(AdminIdentifyRequest), Abort = 0x08, GetFeatures = 0x0a, AsynchronousEventRequest = 0x0c, #[deku(id = 0x0d)]
853 NamespaceManagement(AdminNamespaceManagementRequest),
854 #[deku(id = 0x15)]
855 NamespaceAttachement(AdminNamespaceAttachmentRequest),
856 KeepAlive = 0x18, DirectiveSend = 0x19, DirectiveReceive = 0x1a, NvmeMiSend = 0x1d, NvmeMiReceive = 0x1e, DiscoveryInformationManagement = 0x21, FabricZoningReceive = 0x22, FabricZoningLookup = 0x25, FabricZoningSend = 0x29, SendDiscoveryLogPage = 0x39, TrackSend = 0x3d, TrackReceive = 0x3e, MigrationSend = 0x41, MigrationReceive = 0x42, ControllerDataQueue = 0x45, DoorbellBufferConfig = 0x7c, FabricsCommands = 0x7f, #[deku(id = 0x80)]
874 FormatNvm(AdminFormatNvmRequest),
875 #[deku(id = 0x84)]
876 Sanitize(AdminSanitizeRequest),
877 LoadProgram = 0x85, ProgramActivationManagement = 0x88, MemoryRangeSetManagement = 0x89, }
881unsafe impl Discriminant<u8> for AdminCommandRequestType {}
882
883#[derive(Debug, DekuRead)]
885#[deku(endian = "little")]
886struct AdminCommandRequestHeader {
887 _opcode: u8,
888 cflgs: u8,
889 ctlid: u16,
890 #[deku(ctx = "*_opcode")]
891 op: AdminCommandRequestType,
892}
893
894#[derive(Debug, DekuRead, DekuWrite, Eq, PartialEq)]
897#[deku(ctx = "endian: Endian", endian = "endian")]
898struct AdminFormatNvmRequest {
899 nsid: u32,
900 #[deku(seek_from_current = "16")]
901 dofst: u32,
902 dlen: u32,
903 #[deku(seek_from_current = "8")]
904 #[deku(pad_bytes_after = "20")]
905 config: AdminFormatNvmConfiguration,
906}
907
908#[derive(Debug, DekuRead, DekuWrite, Eq, PartialEq)]
911#[deku(ctx = "endian: Endian", endian = "endian")]
912struct AdminGetLogPageRequest {
913 nsid: u32,
914 #[deku(seek_from_current = "16")]
915 dofst: u32,
916 dlen: u32,
917 #[deku(seek_from_current = "8")]
918 #[deku(update = "self.req.id()")]
919 lid: u8,
920 lsp_rae: u8,
921 numdw: u32, lsi: u16,
923 lpo: u64, uidx: u8,
925 #[deku(seek_from_current = "1")]
926 ot: u8,
927 csi: u8,
928 #[deku(pad_bytes_after = "4")]
929 #[deku(ctx = "*lid")]
930 req: AdminGetLogPageLidRequestType,
931}
932
933#[derive(Debug, DekuRead, DekuWrite, Eq, PartialEq)]
936#[deku(ctx = "endian: Endian", endian = "endian")]
937struct AdminIdentifyRequest {
938 nsid: u32,
939 #[deku(seek_from_current = "16")]
940 dofst: u32,
941 dlen: u32,
942 #[deku(seek_from_current = "8")]
943 #[deku(update = "self.req.id()")]
944 cns: u8,
945 #[deku(seek_from_current = "1")]
946 cntid: u16,
947 cnssid: u16,
948 #[deku(seek_from_current = "1")]
949 csi: u8,
950 #[deku(seek_from_current = "8")]
951 uidx: u8,
952 #[deku(pad_bytes_after = "7")]
953 #[deku(ctx = "*cns")]
954 req: AdminIdentifyCnsRequestType,
955}
956
957#[derive(Debug, DekuRead, DekuWrite, Eq, PartialEq)]
960#[deku(ctx = "endian: Endian", endian = "endian")]
961struct AdminNamespaceManagementRequest {
962 nsid: u32,
963 #[deku(seek_from_current = "16")]
964 dofst: u32,
965 dlen: u32,
966 #[deku(seek_from_current = "8")]
967 sel: u8, #[deku(seek_from_current = "6")]
969 csi: u8,
970 #[deku(seek_from_current = "16")]
971 #[deku(ctx = "*sel")]
972 req: AdminNamespaceManagementSelect,
973}
974
975#[derive(Debug, DekuRead, Eq, PartialEq)]
978#[deku(ctx = "endian: Endian", endian = "endian")]
979struct AdminNamespaceAttachmentRequest {
980 nsid: u32,
981 #[deku(seek_from_current = "16")]
982 dofst: u32,
983 dlen: u32,
984 #[deku(seek_from_current = "8")]
985 sel: AdminNamespaceAttachmentSelect, #[deku(seek_from_current = "23")]
987 body: ControllerListRequest,
988}
989
990#[derive(Debug, DekuRead, Eq, PartialEq)]
993#[deku(ctx = "endian: Endian", endian = "endian")]
994struct AdminSanitizeRequest {
995 nsid: u32,
996 #[deku(seek_from_current = "16")]
997 dofst: u32,
998 dlen: u32,
999 #[deku(seek_from_current = "8")]
1000 config: AdminSanitizeConfiguration,
1001 #[deku(pad_bytes_after = "16")]
1002 ovrpat: u32,
1003}
1004
1005#[derive(Debug, DekuRead, DekuWrite)]
1007#[deku(endian = "little")]
1008struct AdminCommandResponseHeader {
1009 status: ResponseStatus,
1010 #[deku(seek_from_start = "4")]
1011 cqedw0: u32,
1012 cqedw1: u32,
1013 cqedw3: super::AdminIoCqeStatus,
1014}
1015impl Encode<16> for AdminCommandResponseHeader {}
1016
1017#[derive(Debug, DekuRead, DekuWrite)]
1019#[deku(endian = "little")]
1020struct PcieCommandRequestHeader {
1021 _opcode: u8,
1022 #[deku(seek_from_current = "1")]
1023 ctlid: u16,
1024 #[deku(ctx = "*_opcode")]
1025 op: PcieCommandRequestType,
1026}
1027
1028#[derive(Debug, DekuRead, DekuWrite, Eq, PartialEq)]
1030#[deku(ctx = "endian: Endian, opcode: u8", id = "opcode", endian = "endian")]
1031#[repr(u8)]
1032enum PcieCommandRequestType {
1033 #[deku(id = 0x00)]
1034 ConfigurationRead(PcieConfigurationAccessRequest),
1035 #[deku(id = 0x01)]
1036 ConfigurationWrite(PcieConfigurationAccessRequest),
1037 MemoryRead = 0x02,
1038 MemoryWrite = 0x03,
1039 IoRead = 0x04,
1040 IoWrite = 0x05,
1041}
1042
1043#[derive(Debug, DekuRead, DekuWrite, Eq, PartialEq)]
1045#[deku(ctx = "endian: Endian", endian = "endian")]
1046struct PcieConfigurationAccessRequest {
1047 length: u16,
1048 #[deku(seek_from_current = "2")]
1049 #[deku(pad_bytes_after = "6")]
1050 offset: u16,
1051}