use deku::ctx::{BitSize, Endian, Order};
use deku::{DekuError, DekuRead, DekuWrite};
use flagset::{FlagSet, flags};
use log::debug;
use crate::nvme::{
AdminFormatNvmConfiguration, AdminNamespaceAttachmentSelect, AdminNamespaceManagementSelect,
AdminSanitizeConfiguration, ControllerListRequest,
};
use crate::wire::{WireFlagSet, WireVec};
use crate::{CommandEffectError, Discriminant, Encode, MAX_CONTROLLERS};
use super::{AdminGetLogPageLidRequestType, AdminIdentifyCnsRequestType};
pub mod dev;
#[derive(Clone, Copy, Debug, DekuRead, DekuWrite, PartialEq, Eq)]
#[deku(
bits = "4",
bit_order = "order",
ctx = "endian: Endian, order: Order",
endian = "endian",
id_type = "u8"
)]
#[repr(u8)]
enum MessageType {
ControlPrimitive = 0x00,
NvmeMiCommand = 0x01,
NvmeAdminCommand = 0x02,
PcieCommand = 0x04,
AsynchronousEvent = 0x05,
}
#[derive(Debug, DekuRead, DekuWrite)]
#[deku(bit_order = "lsb", endian = "little")]
struct MessageHeader {
#[deku(bits = "1", pad_bits_after = "2")]
csi: u8,
nmimt: MessageType,
#[deku(bits = "1", pad_bytes_after = "2")]
ror: bool,
}
impl Encode<3> for MessageHeader {}
impl MessageHeader {
fn respond(nmimt: MessageType) -> Self {
Self {
csi: 0,
nmimt,
ror: true,
}
}
}
#[derive(Debug, DekuRead, DekuWrite, PartialEq)]
#[deku(endian = "endian", ctx = "endian: Endian", id_type = "u8")]
#[repr(u8)]
pub enum ResponseStatus {
Success = 0x00,
InternalError = 0x02,
InvalidCommandOpcode = 0x03,
InvalidParameter = 0x04,
InvalidCommandSize = 0x05,
InvalidCommandInputDataSize = 0x06,
AccessDenied = 0x07,
}
unsafe impl Discriminant<u8> for ResponseStatus {}
impl From<DekuError> for ResponseStatus {
fn from(err: DekuError) -> Self {
debug!("Codec operation failed: {err}");
Self::InternalError
}
}
impl From<()> for ResponseStatus {
fn from(_: ()) -> Self {
Self::InternalError
}
}
impl From<CommandEffectError> for ResponseStatus {
fn from(value: CommandEffectError) -> Self {
debug!("Failed to apply command effect: {value:?}");
Self::InternalError
}
}
#[derive(Debug, DekuRead, DekuWrite)]
#[deku(endian = "little")]
struct NvmeMiCommandRequestHeader {
#[deku(pad_bytes_after = "3")]
#[deku(update = "self.body.id()")]
opcode: u8,
#[deku(ctx = "*opcode")]
body: NvmeMiCommandRequestType,
}
impl Encode<4> for NvmeMiCommandRequestHeader {}
#[derive(Debug, DekuRead, DekuWrite, PartialEq, Eq)]
#[deku(ctx = "endian: Endian, opcode: u8", id = "opcode", endian = "endian")]
#[repr(u8)]
enum NvmeMiCommandRequestType {
#[deku(id = "0x00")]
ReadNvmeMiDataStructure(NvmeMiDataStructureRequest),
#[deku(id = "0x01")]
NvmSubsystemHealthStatusPoll(NvmSubsystemHealthStatusPollRequest),
#[deku(id = "0x02")]
ControllerHealthStatusPoll(ControllerHealthStatusPollRequest),
#[deku(id = "0x03")]
ConfigurationSet(NvmeMiConfigurationSetRequest),
#[deku(id = "0x04")]
ConfigurationGet(NvmeMiConfigurationGetRequest),
VpdRead = 0x05,
VpdWrite = 0x06,
Reset = 0x07,
SesReceive = 0x08,
SesSend = 0x09,
ManagementEndpointBufferRead = 0x0a,
ManagementEndpointBufferWrite = 0x0b,
Shutdown = 0x0c,
}
unsafe impl Discriminant<u8> for NvmeMiCommandRequestType {}
#[derive(Debug, DekuRead, DekuWrite)]
#[deku(endian = "little")]
struct NvmeManagementResponse {
#[deku(pad_bytes_after = "3")]
status: ResponseStatus,
}
impl Encode<4> for NvmeManagementResponse {}
#[derive(Debug, DekuRead, DekuWrite, Eq, PartialEq)]
#[deku(ctx = "endian: Endian", endian = "endian")]
struct NvmeMiConfigurationGetRequest {
body: NvmeMiConfigurationIdentifierRequestType,
}
#[derive(Debug, DekuRead, DekuWrite, Eq, PartialEq)]
#[deku(id_type = "u8", ctx = "endian: Endian", endian = "endian")]
#[repr(u8)]
enum NvmeMiConfigurationIdentifierRequestType {
Reserved = 0x00,
#[deku(id = "0x01")]
SmbusI2cFrequency(SmbusI2cFrequencyRequest),
#[deku(id = "0x02")]
HealthStatusChange(HealthStatusChangeRequest),
#[deku(id = "0x03")]
MctpTransmissionUnitSize(MctpTransmissionUnitSizeRequest),
AsynchronousEvent = 0x04,
}
#[derive(Debug, Clone, Copy, DekuRead, DekuWrite, Eq, PartialEq, PartialOrd)]
#[deku(
bits = "bits.0",
id_type = "u8",
ctx = "endian: Endian, bits: BitSize",
endian = "endian"
)]
#[repr(u8)]
enum SmbusFrequency {
Reserved = 0x00,
Freq100Khz = 0x01,
Freq400Khz = 0x02,
Freq1Mhz = 0x03,
}
impl From<SmbusFrequency> for crate::smbus::BusFrequency {
fn from(value: SmbusFrequency) -> Self {
match value {
SmbusFrequency::Reserved => Self::NotSupported,
SmbusFrequency::Freq100Khz => Self::Freq100Khz,
SmbusFrequency::Freq400Khz => Self::Freq400Khz,
SmbusFrequency::Freq1Mhz => Self::Freq1Mhz,
}
}
}
impl From<crate::smbus::BusFrequency> for SmbusFrequency {
fn from(value: crate::smbus::BusFrequency) -> Self {
match value {
crate::smbus::BusFrequency::NotSupported => Self::Reserved,
crate::smbus::BusFrequency::Freq100Khz => Self::Freq100Khz,
crate::smbus::BusFrequency::Freq400Khz => Self::Freq400Khz,
crate::smbus::BusFrequency::Freq1Mhz => Self::Freq1Mhz,
}
}
}
#[derive(Debug, DekuWrite, PartialEq)]
#[deku(endian = "little")]
struct GetSmbusI2cFrequencyResponse {
status: ResponseStatus,
#[deku(bits = "4", pad_bits_before = "4", pad_bytes_after = "2")]
sfreq: SmbusFrequency,
}
impl Encode<4> for GetSmbusI2cFrequencyResponse {}
#[derive(Debug, DekuWrite)]
#[deku(endian = "little")]
struct GetHealthStatusChangeResponse {
#[deku(pad_bytes_after = "3")]
status: ResponseStatus,
}
impl Encode<4> for GetHealthStatusChangeResponse {}
#[derive(Debug, DekuWrite)]
#[deku(endian = "little")]
struct GetMctpTransmissionUnitSizeResponse {
status: ResponseStatus,
#[deku(pad_bytes_after = "1")]
mr_mtus: u16,
}
impl Encode<4> for GetMctpTransmissionUnitSizeResponse {}
#[derive(Debug, DekuRead, DekuWrite, Eq, PartialEq)]
#[deku(ctx = "endian: Endian", endian = "endian")]
struct NvmeMiConfigurationSetRequest {
body: NvmeMiConfigurationIdentifierRequestType,
}
#[derive(Debug, DekuRead, DekuWrite, Eq, PartialEq)]
#[deku(ctx = "endian: Endian", endian = "endian")]
struct SmbusI2cFrequencyRequest {
#[deku(bits = "4", pad_bits_before = "4", pad_bytes_after = "1")]
sfreq: SmbusFrequency,
#[deku(pad_bytes_after = "4")]
portid: u8,
}
#[derive(Debug, DekuRead, DekuWrite, Eq, PartialEq)]
#[deku(ctx = "endian: Endian", endian = "endian")]
struct HealthStatusChangeRequest {
#[deku(seek_from_current = "3")]
dw1: u32,
}
flags! {
#[repr(u32)]
enum HealthStatusChangeFlags: u32 {
Rdy,
Cfs,
Shst,
Nssro,
Ceco,
Nac,
Fa,
Csts,
Ctemp,
Pldu,
Spare,
Cwarn,
Tcida,
}
}
#[derive(Debug, DekuRead, DekuWrite, Eq, PartialEq)]
#[deku(ctx = "endian: Endian", endian = "endian")]
struct MctpTransmissionUnitSizeRequest {
#[deku(seek_from_current = "2")]
dw0_portid: u8,
#[deku(pad_bytes_after = "2")]
dw1_mtus: u16,
}
flags! {
pub enum ControllerFunctionAndReportingFlags: u8 {
Incf = 1 << 0,
Incpf = 1 << 1,
Incvf = 1 << 2,
All = 1 << 7,
}
}
flags! {
pub enum ControllerPropertyFlags: u32 {
Csts = 1 << 0,
Ctemp = 1 << 1,
Pldu = 1 << 2,
Spare = 1 << 3,
Cwarn = 1 << 4,
Ccf = 1 << 31,
}
}
#[derive(Debug, DekuRead, DekuWrite, Eq, PartialEq)]
#[deku(ctx = "endian: Endian", endian = "endian")]
struct ControllerHealthStatusPollRequest {
sctlid: u16,
maxrent: u8,
functions: WireFlagSet<ControllerFunctionAndReportingFlags>,
properties: WireFlagSet<ControllerPropertyFlags>,
}
#[derive(Debug, DekuRead, DekuWrite)]
#[deku(endian = "little")]
struct ControllerHealthStatusPollResponse {
status: ResponseStatus,
#[deku(pad_bytes_before = "2", update = "self.body.len() as u8")]
rent: u8,
body: WireVec<ControllerHealthDataStructure, MAX_CONTROLLERS>,
}
impl Encode<{ 4 + 16 * MAX_CONTROLLERS }> for ControllerHealthStatusPollResponse {}
flags! {
pub enum ControllerStatusFlags: u16 {
Rdy = 1 << 0,
Cfs = 1 << 1,
ShstInProgress = 1 << 2,
ShstComplete = 1 << 3,
ShstReserved = (ControllerStatusFlags::ShstInProgress | ControllerStatusFlags::ShstComplete).bits(),
Nssro = 1 << 4,
Ceco = 1 << 5,
Nac = 1 << 6,
Fa = 1 << 7,
Tcida = 1 << 8,
}
}
impl From<FlagSet<super::ControllerStatusFlags>> for WireFlagSet<ControllerStatusFlags> {
fn from(value: FlagSet<super::ControllerStatusFlags>) -> Self {
use super::ControllerStatusFlags as F;
use ControllerStatusFlags as T;
let mut fs = FlagSet::empty();
for f in value {
fs |= match f {
F::Rdy => T::Rdy,
F::Cfs => T::Cfs,
F::ShstInProgress => T::ShstInProgress,
F::ShstComplete => T::ShstComplete,
F::ShstReserved => T::ShstReserved,
F::Nssro => T::Nssro,
F::Pp => todo!(),
F::St => todo!(),
};
}
Self(fs)
}
}
flags! {
pub enum CriticalWarningFlags: u8 {
St,
Taut,
Rd,
Ro,
Vmbf,
Pmre
}
}
#[derive(Debug, DekuRead, DekuWrite)]
#[deku(ctx = "endian: Endian", endian = "endian")]
struct ControllerHealthDataStructure {
ctlid: u16,
csts: WireFlagSet<ControllerStatusFlags>,
ctemp: u16,
pdlu: u8,
spare: u8,
cwarn: WireFlagSet<CriticalWarningFlags>,
#[deku(pad_bytes_after = "5")]
chsc: WireFlagSet<ControllerHealthStatusChangedFlags>,
}
flags! {
pub enum ControllerHealthStatusChangedFlags: u16 {
Rdy = 1 << 0,
Cfs = 1 << 1,
Shst = 1 << 2,
Nssro = 1 << 4,
Ceco = 1 << 5,
Nac = 1 << 6,
Fa = 1 << 7,
Csts = 1 << 8,
Ctemp = 1 << 9,
Pdlu = 1 << 10,
Spare = 1 << 11,
Cwarn = 1 << 12,
Tcida = 1 << 13,
}
}
#[derive(Debug, DekuRead, DekuWrite, Eq, PartialEq)]
#[deku(ctx = "endian: Endian", endian = "endian")]
struct NvmSubsystemHealthStatusPollRequest {
#[deku(bits = "1", pad_bits_after = "7", pad_bytes_before = "7")]
cs: bool,
}
flags! {
#[repr(u16)]
enum CompositeControllerStatusFlags: u16 {
Rdy = 1 << 0,
Cfs = 1 << 1,
Shst = 1 << 2,
Nssro = 1 << 4,
Ceco = 1 << 5,
Nac = 1 << 6,
Fa = 1 << 7,
Csts = 1 << 8,
Ctemp = 1 << 9,
Pdlu = 1 << 10,
Spare = 1 << 11,
Cwarn = 1 << 12,
Tcida = 1 << 13,
}
}
#[derive(Debug)]
pub struct CompositeControllerStatusFlagSet(FlagSet<CompositeControllerStatusFlags>);
impl CompositeControllerStatusFlagSet {
pub fn empty() -> Self {
Self(FlagSet::empty())
}
}
impl From<FlagSet<HealthStatusChangeFlags>> for CompositeControllerStatusFlagSet {
fn from(value: FlagSet<HealthStatusChangeFlags>) -> Self {
use CompositeControllerStatusFlags as T;
use HealthStatusChangeFlags as F;
let mut converted = FlagSet::empty();
for flag in value {
converted |= match flag {
F::Rdy => T::Rdy,
F::Cfs => T::Cfs,
F::Shst => T::Shst,
F::Nssro => T::Nssro,
F::Ceco => T::Ceco,
F::Nac => T::Nac,
F::Fa => T::Fa,
F::Csts => T::Csts,
F::Ctemp => T::Ctemp,
F::Pldu => T::Pdlu,
F::Spare => T::Spare,
F::Cwarn => T::Cwarn,
F::Tcida => T::Tcida,
}
}
Self(converted)
}
}
impl From<FlagSet<ControllerHealthStatusChangedFlags>> for CompositeControllerStatusFlagSet {
fn from(value: FlagSet<ControllerHealthStatusChangedFlags>) -> Self {
Self(FlagSet::new(value.bits()).expect("Divergent flag definitions"))
}
}
#[derive(Debug, DekuRead, DekuWrite)]
#[deku(endian = "little")]
struct CompositeControllerStatusDataStructureResponse {
#[deku(pad_bytes_after = "2")]
ccsf: u16,
}
impl Encode<4> for CompositeControllerStatusDataStructureResponse {}
flags! {
pub enum NvmSubsystemStatusFlags: u8 {
P1la = 1 << 2,
P0la = 1 << 3,
Rnr = 1 << 4,
Df = 1 << 5,
Sfm = 1 << 6,
Atf = 1 << 7,
}
}
flags! {
pub enum SmartWarningFlags: u8 {
Ascbt,
Ttc,
Ndr,
Amro,
Vmbf,
Pmrro,
}
}
impl From<FlagSet<super::CriticalWarningFlags>> for WireFlagSet<SmartWarningFlags> {
fn from(value: FlagSet<super::CriticalWarningFlags>) -> Self {
FlagSet::<SmartWarningFlags>::new((!value.bits()) & 0x3f)
.expect("Undefined bits set")
.into()
}
}
#[derive(Debug, DekuRead, DekuWrite)]
#[deku(endian = "little")]
struct NvmSubsystemHealthDataStructureResponse {
nss: WireFlagSet<NvmSubsystemStatusFlags>,
sw: WireFlagSet<SmartWarningFlags>,
ctemp: u8,
pldu: u8,
}
impl Encode<4> for NvmSubsystemHealthDataStructureResponse {}
#[derive(Debug, DekuRead, DekuWrite, PartialEq, Eq)]
#[deku(ctx = "endian: Endian, dtyp: u8", endian = "endian", id = "dtyp")]
#[repr(u8)]
enum NvmeMiDataStructureRequestType {
NvmSubsystemInformation = 0x00,
PortInformation = 0x01,
ControllerList = 0x02,
ControllerInformation = 0x03,
OptionallySupportedCommandList = 0x04,
ManagementEndpointBufferCommandSupportList = 0x05,
}
unsafe impl Discriminant<u8> for NvmeMiDataStructureRequestType {}
#[derive(Debug, DekuRead, DekuWrite, Eq, PartialEq)]
#[deku(ctx = "endian: Endian", endian = "endian")]
struct NvmeMiDataStructureRequest {
ctrlid: u16,
portid: u8,
#[deku(update = "self.body.id()")]
dtyp: u8,
#[deku(pad_bytes_after = "3")]
iocsi: u8,
#[deku(ctx = "*dtyp")]
body: NvmeMiDataStructureRequestType,
}
#[derive(Debug, DekuRead, DekuWrite)]
#[deku(endian = "little")]
struct NvmeMiDataStructureManagementResponse {
status: ResponseStatus,
rdl: u16,
}
impl Encode<4> for NvmeMiDataStructureManagementResponse {}
#[derive(Debug)]
pub struct SubsystemCapabilities {
sre: bool,
}
impl SubsystemCapabilities {
pub fn new() -> Self {
Self { sre: false }
}
}
impl Default for SubsystemCapabilities {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, DekuWrite)]
#[deku(endian = "little")]
struct NvmSubsystemInformationResponse {
nump: u8,
mjr: u8,
mnr: u8,
nnsc: u8,
}
impl Encode<32> for NvmSubsystemInformationResponse {}
#[derive(Clone, Copy, Debug, DekuRead, DekuWrite, PartialEq, Eq)]
#[deku(ctx = "endian: Endian", endian = "endian", id_type = "u8")]
#[repr(u8)]
pub enum PortType {
Inactive = 0x00,
Pcie = 0x01,
TwoWire = 0x02,
}
impl From<&crate::PortType> for PortType {
fn from(value: &crate::PortType) -> Self {
match value {
crate::PortType::Inactive => Self::Inactive,
crate::PortType::Pcie(_) => Self::Pcie,
crate::PortType::TwoWire(_) => Self::TwoWire,
}
}
}
flags! {
enum PortCapabilityFlags: u8 {
Ciaps,
Aems,
}
}
#[derive(Debug, DekuWrite)]
#[deku(endian = "little")]
struct PortInformationResponse {
prttyp: PortType,
prtcap: WireFlagSet<PortCapabilityFlags>,
mmtus: u16,
mebs: u32,
}
impl Encode<8> for PortInformationResponse {}
#[derive(Clone, Copy, DekuRead, DekuWrite, Debug, Eq, PartialEq)]
#[deku(ctx = "endian: Endian", endian = "endian", id_type = "u8")]
#[repr(u8)]
enum PciePayloadSize {
Payload128B = 0x00,
Payload256B = 0x01,
Payload512B = 0x02,
Payload1Kb = 0x03,
Payload2Kb = 0x04,
Payload4Kb = 0x05,
}
impl From<crate::pcie::PayloadSize> for PciePayloadSize {
fn from(value: crate::pcie::PayloadSize) -> Self {
match value {
crate::pcie::PayloadSize::Payload128B => Self::Payload128B,
crate::pcie::PayloadSize::Payload256B => Self::Payload256B,
crate::pcie::PayloadSize::Payload512B => Self::Payload512B,
crate::pcie::PayloadSize::Payload1Kb => Self::Payload1Kb,
crate::pcie::PayloadSize::Payload2Kb => Self::Payload2Kb,
crate::pcie::PayloadSize::Payload4Kb => Self::Payload4Kb,
}
}
}
impl From<PciePayloadSize> for crate::pcie::PayloadSize {
fn from(value: PciePayloadSize) -> Self {
match value {
PciePayloadSize::Payload128B => Self::Payload128B,
PciePayloadSize::Payload256B => Self::Payload256B,
PciePayloadSize::Payload512B => Self::Payload512B,
PciePayloadSize::Payload1Kb => Self::Payload1Kb,
PciePayloadSize::Payload2Kb => Self::Payload2Kb,
PciePayloadSize::Payload4Kb => Self::Payload4Kb,
}
}
}
flags! {
#[repr(u8)]
enum PcieSupportedLinkSpeeds: u8 {
Gts2p5,
Gts5,
Gts8,
Gts16,
Gts32,
Gts64,
}
}
#[derive(Clone, Copy, Debug, DekuRead, DekuWrite, Eq, PartialEq)]
#[deku(ctx = "endian: Endian", endian = "endian", id_type = "u8")]
#[repr(u8)]
enum PcieLinkSpeed {
Inactive = 0x00,
Gts2p5 = 0x01,
Gts5 = 0x02,
Gts8 = 0x03,
Gts16 = 0x04,
Gts32 = 0x05,
Gts64 = 0x06,
}
impl From<crate::pcie::LinkSpeed> for PcieLinkSpeed {
fn from(value: crate::pcie::LinkSpeed) -> Self {
match value {
crate::pcie::LinkSpeed::Inactive => Self::Inactive,
crate::pcie::LinkSpeed::Gts2p5 => Self::Gts2p5,
crate::pcie::LinkSpeed::Gts5 => Self::Gts5,
crate::pcie::LinkSpeed::Gts8 => Self::Gts8,
crate::pcie::LinkSpeed::Gts16 => Self::Gts16,
crate::pcie::LinkSpeed::Gts32 => Self::Gts32,
crate::pcie::LinkSpeed::Gts64 => Self::Gts64,
}
}
}
impl From<PcieLinkSpeed> for crate::pcie::LinkSpeed {
fn from(value: PcieLinkSpeed) -> Self {
match value {
PcieLinkSpeed::Inactive => Self::Inactive,
PcieLinkSpeed::Gts2p5 => Self::Gts2p5,
PcieLinkSpeed::Gts5 => Self::Gts5,
PcieLinkSpeed::Gts8 => Self::Gts8,
PcieLinkSpeed::Gts16 => Self::Gts16,
PcieLinkSpeed::Gts32 => Self::Gts32,
PcieLinkSpeed::Gts64 => Self::Gts64,
}
}
}
#[derive(Clone, Copy, Debug, DekuRead, DekuWrite, Eq, PartialEq)]
#[deku(ctx = "endian: Endian", endian = "endian", id_type = "u8")]
#[repr(u8)]
enum PcieLinkWidth {
X1 = 1,
X2 = 2,
X4 = 4,
X8 = 8,
X12 = 12,
X16 = 16,
X32 = 32,
}
impl From<crate::pcie::LinkWidth> for PcieLinkWidth {
fn from(value: crate::pcie::LinkWidth) -> Self {
match value {
crate::pcie::LinkWidth::X1 => Self::X1,
crate::pcie::LinkWidth::X2 => Self::X2,
crate::pcie::LinkWidth::X4 => Self::X4,
crate::pcie::LinkWidth::X8 => Self::X8,
crate::pcie::LinkWidth::X12 => Self::X12,
crate::pcie::LinkWidth::X16 => Self::X16,
crate::pcie::LinkWidth::X32 => Self::X32,
}
}
}
impl From<PcieLinkWidth> for crate::pcie::LinkWidth {
fn from(value: PcieLinkWidth) -> Self {
match value {
PcieLinkWidth::X1 => Self::X1,
PcieLinkWidth::X2 => Self::X2,
PcieLinkWidth::X4 => Self::X4,
PcieLinkWidth::X8 => Self::X8,
PcieLinkWidth::X12 => Self::X12,
PcieLinkWidth::X16 => Self::X16,
PcieLinkWidth::X32 => Self::X32,
}
}
}
#[derive(Debug, DekuRead, DekuWrite)]
#[deku(endian = "little")]
struct PciePortDataResponse {
pciemps: PciePayloadSize,
pcieslsv: WireFlagSet<PcieSupportedLinkSpeeds>,
pciecls: PcieLinkSpeed,
pciemlw: PcieLinkWidth,
pcienlw: PcieLinkWidth,
pciepn: u8,
}
impl Encode<24> for PciePortDataResponse {}
#[derive(Debug, DekuWrite)]
#[deku(endian = "little")]
struct TwoWirePortDataResponse {
cvpdaddr: u8,
#[deku(bits = "8")]
mvpdfreq: SmbusFrequency,
cmeaddr: u8,
#[deku(bits = "1", pad_bits_after = "5")]
twprt_i3csprt: bool,
#[deku(bits = "2")]
twprt_msmbfreq: SmbusFrequency,
nvmebm: u8,
}
impl Encode<24> for TwoWirePortDataResponse {}
#[derive(Debug, DekuRead, DekuWrite)]
#[deku(endian = "little")]
struct ControllerInformationResponse {
#[deku(pad_bytes_after = "4")]
portid: u8,
#[deku(bits = "1", pad_bits_before = "7")]
prii_pcieriv: bool,
#[deku(bits = "8")]
pri_pcibn: u16,
#[deku(bits = "5")]
pri_pcidn: u16,
#[deku(bits = "3")]
pri_pcifn: u16,
pcivid: u16,
pcidid: u16,
pcisvid: u16,
pcisdid: u16,
pciesn: u8,
}
impl Encode<32> for ControllerInformationResponse {}
#[expect(clippy::large_enum_variant)] #[derive(Debug, DekuRead, PartialEq, Eq)]
#[deku(ctx = "endian: Endian, opcode: u8", id = "opcode", endian = "endian")]
#[repr(u8)]
enum AdminCommandRequestType {
DeleteIoSubmissionQueue = 0x00, CreateIoSubmissionQueue = 0x01, #[deku(id = 0x02)]
GetLogPage(AdminGetLogPageRequest), DeleteIoCompletionQueue = 0x04, CreateIoCompletionQueue = 0x05, #[deku(id = 0x06)]
Identify(AdminIdentifyRequest), Abort = 0x08, GetFeatures = 0x0a, AsynchronousEventRequest = 0x0c, #[deku(id = 0x0d)]
NamespaceManagement(AdminNamespaceManagementRequest),
#[deku(id = 0x15)]
NamespaceAttachement(AdminNamespaceAttachmentRequest),
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)]
FormatNvm(AdminFormatNvmRequest),
#[deku(id = 0x84)]
Sanitize(AdminSanitizeRequest),
LoadProgram = 0x85, ProgramActivationManagement = 0x88, MemoryRangeSetManagement = 0x89, }
unsafe impl Discriminant<u8> for AdminCommandRequestType {}
#[derive(Debug, DekuRead)]
#[deku(endian = "little")]
struct AdminCommandRequestHeader {
_opcode: u8,
cflgs: u8,
ctlid: u16,
#[deku(ctx = "*_opcode")]
op: AdminCommandRequestType,
}
#[derive(Debug, DekuRead, DekuWrite, Eq, PartialEq)]
#[deku(ctx = "endian: Endian", endian = "endian")]
struct AdminFormatNvmRequest {
nsid: u32,
#[deku(seek_from_current = "16")]
dofst: u32,
dlen: u32,
#[deku(seek_from_current = "8")]
#[deku(pad_bytes_after = "20")]
config: AdminFormatNvmConfiguration,
}
#[derive(Debug, DekuRead, DekuWrite, Eq, PartialEq)]
#[deku(ctx = "endian: Endian", endian = "endian")]
struct AdminGetLogPageRequest {
nsid: u32,
#[deku(seek_from_current = "16")]
dofst: u32,
dlen: u32,
#[deku(seek_from_current = "8")]
#[deku(update = "self.req.id()")]
lid: u8,
lsp_rae: u8,
numdw: u32, lsi: u16,
lpo: u64, uidx: u8,
#[deku(seek_from_current = "1")]
ot: u8,
csi: u8,
#[deku(pad_bytes_after = "4")]
#[deku(ctx = "*lid")]
req: AdminGetLogPageLidRequestType,
}
#[derive(Debug, DekuRead, DekuWrite, Eq, PartialEq)]
#[deku(ctx = "endian: Endian", endian = "endian")]
struct AdminIdentifyRequest {
nsid: u32,
#[deku(seek_from_current = "16")]
dofst: u32,
dlen: u32,
#[deku(seek_from_current = "8")]
#[deku(update = "self.req.id()")]
cns: u8,
#[deku(seek_from_current = "1")]
cntid: u16,
cnssid: u16,
#[deku(seek_from_current = "1")]
csi: u8,
#[deku(seek_from_current = "8")]
uidx: u8,
#[deku(pad_bytes_after = "7")]
#[deku(ctx = "*cns")]
req: AdminIdentifyCnsRequestType,
}
#[derive(Debug, DekuRead, DekuWrite, Eq, PartialEq)]
#[deku(ctx = "endian: Endian", endian = "endian")]
struct AdminNamespaceManagementRequest {
nsid: u32,
#[deku(seek_from_current = "16")]
dofst: u32,
dlen: u32,
#[deku(seek_from_current = "8")]
sel: u8, #[deku(seek_from_current = "6")]
csi: u8,
#[deku(seek_from_current = "16")]
#[deku(ctx = "*sel")]
req: AdminNamespaceManagementSelect,
}
#[derive(Debug, DekuRead, Eq, PartialEq)]
#[deku(ctx = "endian: Endian", endian = "endian")]
struct AdminNamespaceAttachmentRequest {
nsid: u32,
#[deku(seek_from_current = "16")]
dofst: u32,
dlen: u32,
#[deku(seek_from_current = "8")]
sel: AdminNamespaceAttachmentSelect, #[deku(seek_from_current = "23")]
body: ControllerListRequest,
}
#[derive(Debug, DekuRead, Eq, PartialEq)]
#[deku(ctx = "endian: Endian", endian = "endian")]
struct AdminSanitizeRequest {
nsid: u32,
#[deku(seek_from_current = "16")]
dofst: u32,
dlen: u32,
#[deku(seek_from_current = "8")]
config: AdminSanitizeConfiguration,
#[deku(pad_bytes_after = "16")]
ovrpat: u32,
}
#[derive(Debug, DekuRead, DekuWrite)]
#[deku(endian = "little")]
struct AdminCommandResponseHeader {
status: ResponseStatus,
#[deku(seek_from_start = "4")]
cqedw0: u32,
cqedw1: u32,
cqedw3: super::AdminIoCqeStatus,
}
impl Encode<16> for AdminCommandResponseHeader {}
#[derive(Debug, DekuRead, DekuWrite)]
#[deku(endian = "little")]
struct PcieCommandRequestHeader {
_opcode: u8,
#[deku(seek_from_current = "1")]
ctlid: u16,
#[deku(ctx = "*_opcode")]
op: PcieCommandRequestType,
}
#[derive(Debug, DekuRead, DekuWrite, Eq, PartialEq)]
#[deku(ctx = "endian: Endian, opcode: u8", id = "opcode", endian = "endian")]
#[repr(u8)]
enum PcieCommandRequestType {
#[deku(id = 0x00)]
ConfigurationRead(PcieConfigurationAccessRequest),
#[deku(id = 0x01)]
ConfigurationWrite(PcieConfigurationAccessRequest),
MemoryRead = 0x02,
MemoryWrite = 0x03,
IoRead = 0x04,
IoWrite = 0x05,
}
#[derive(Debug, DekuRead, DekuWrite, Eq, PartialEq)]
#[deku(ctx = "endian: Endian", endian = "endian")]
struct PcieConfigurationAccessRequest {
length: u16,
#[deku(seek_from_current = "2")]
#[deku(pad_bytes_after = "6")]
offset: u16,
}