use heterob::{bit_numbering::Lsb, endianness::Le, Seq, P3, P4, P7};
use crate::capabilities::pci_express::{
ActiveStatePowerManagement, L0sExitLatency, L1ExitLatency, LinkSpeed, LinkWidth,
SupportedLinkSpeedsVector,
};
use super::ExtendedCapabilityDataError;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RootComplexInternalLinkControl {
pub root_complex_link_capabilities: RootComplexLinkCapabilities,
pub root_complex_link_control: RootComplexLinkControl,
pub root_complex_link_status: RootComplexLinkStatus,
}
impl RootComplexInternalLinkControl {
pub const SIZE: usize = 4 + 2 + 2;
}
impl From<[u8; Self::SIZE]> for RootComplexInternalLinkControl {
fn from(bytes: [u8; Self::SIZE]) -> Self {
let Le((
root_complex_link_capabilities,
root_complex_link_control,
root_complex_link_status,
)) = P3(bytes).into();
Self {
root_complex_link_capabilities: From::<u32>::from(root_complex_link_capabilities),
root_complex_link_control: From::<u16>::from(root_complex_link_control),
root_complex_link_status: From::<u16>::from(root_complex_link_status),
}
}
}
impl TryFrom<&[u8]> for RootComplexInternalLinkControl {
type Error = ExtendedCapabilityDataError;
fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
let Seq { head, .. } = slice.try_into().map_err(|_| ExtendedCapabilityDataError {
name: "Root Complex Internal Link Control",
size: Self::SIZE,
})?;
Ok(From::<[u8; Self::SIZE]>::from(head))
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RootComplexLinkCapabilities {
pub max_link_speed: LinkSpeed,
pub maximum_link_width: LinkWidth,
pub active_state_power_management_support: ActiveStatePowerManagement,
pub l0s_exit_latency: L0sExitLatency,
pub l1_exit_latency: L1ExitLatency,
pub supported_link_speeds_vector: SupportedLinkSpeedsVector,
}
impl From<u32> for RootComplexLinkCapabilities {
fn from(dword: u32) -> Self {
let Lsb((
max_link_speed,
maximum_link_width,
active_state_power_management_support,
l0s_exit_latency,
l1_exit_latency,
supported_link_speeds_vector,
(),
)) = P7::<_, 4, 6, 2, 3, 3, 7, 7>(dword).into();
Self {
max_link_speed: From::<u8>::from(max_link_speed),
maximum_link_width: From::<u8>::from(maximum_link_width),
active_state_power_management_support: From::<u8>::from(
active_state_power_management_support,
),
l0s_exit_latency: From::<u8>::from(l0s_exit_latency),
l1_exit_latency: From::<u8>::from(l1_exit_latency),
supported_link_speeds_vector: From::<u8>::from(supported_link_speeds_vector),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RootComplexLinkControl {
pub active_state_power_management_control: ActiveStatePowerManagement,
pub extended_synch: bool,
}
impl From<u16> for RootComplexLinkControl {
fn from(word: u16) -> Self {
let Lsb((active_state_power_management_control, (), extended_synch, ())) =
P4::<_, 2, 5, 1, 8>(word).into();
Self {
active_state_power_management_control: From::<u8>::from(
active_state_power_management_control,
),
extended_synch,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RootComplexLinkStatus {
pub current_link_speed: LinkSpeed,
pub negotiated_link_width: LinkWidth,
}
impl From<u16> for RootComplexLinkStatus {
fn from(word: u16) -> Self {
let Lsb((current_link_speed, negotiated_link_width, ())) = P3::<_, 4, 6, 6>(word).into();
Self {
current_link_speed: From::<u8>::from(current_link_speed),
negotiated_link_width: From::<u8>::from(negotiated_link_width),
}
}
}