use core::fmt;
use pcics::{
capabilities::PciExpress,
extended_capabilities::{
multifunction_virtual_channel::MultifunctionVirtualChannelError, tph_requester::StTable,
AccessControlServices, AddressTranslationServices, AlternativeRoutingIdInterpretation,
ConfigurationAccessCorrelation, DataLinkFeature, DeviceSerialNumber,
DownstreamPortContainment, DynamicPowerAllocation, ExtendedCapability,
ExtendedCapabilityError, ExtendedCapabilityKind, FrsQueuing, HierarchyId, L1PmSubstates,
LaneMarginingAtTheReceiver, LatencyToleranceReporting, LnRequester,
MultiRootIoVirtualization, MultifunctionVirtualChannel, NativePcieEnclosureManagement,
PageRequestInterface, PciExpressOverMphy, PhysicalLayer16GTps, PowerBudgeting,
PrecisionTimeMeasurement, ProcessAddressSpaceId, ProtocolMultiplexing,
ReadinessTimeReporting, RootComplexEventCollectorEndpointAssociation,
RootComplexInternalLinkControl, RootComplexRegisterBlockHeader, SecondaryPciExpress,
TphRequester, VendorSpecificExtendedCapability,
},
};
use crate::{
device::Device,
view::{DisplayMultiView, MultiView},
};
use self::vc::VcView;
use super::{Flag, Simple, Verbose, View};
pub(super) struct ViewArgs<'a> {
pub verbose: usize,
pub device: &'a Device,
pub maybe_pci_express: Option<&'a PciExpress>,
}
impl<'a> fmt::Display for View<ExtendedCapability<'a>, &'a ViewArgs<'a>> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let &ViewArgs {
verbose,
device,
maybe_pci_express,
} = self.args;
let ExtendedCapability {
ref kind,
version,
offset,
} = self.data;
write!(f, "\tCapabilities: [{:03x}", offset)?;
if verbose > 1 {
write!(f, " v{}", version)?;
}
write!(f, "] ")?;
match kind {
ExtendedCapabilityKind::Null => writeln!(f, "Null"),
ExtendedCapabilityKind::AdvancedErrorReporting(data) => {
let is_type_root = maybe_pci_express
.filter(|pcie| pcie.device_type.is_root())
.is_some();
let args = &aer::ViewArgs {
verbose,
is_type_root,
};
write!(f, "{}", View { data, args })
}
ExtendedCapabilityKind::VirtualChannel(c) => {
write!(f, "{}", c.display(VcView { verbose, offset }))
}
ExtendedCapabilityKind::DeviceSerialNumber(c) => write!(f, "{}", c.display(())),
ExtendedCapabilityKind::PowerBudgeting(c) => write!(f, "{}", c.display(())),
ExtendedCapabilityKind::RootComplexLinkDeclaration(c) => {
write!(f, "{}", Verbose { data: c, verbose })
}
ExtendedCapabilityKind::RootComplexInternalLinkControl(c) => {
write!(f, "{}", Simple(c))
}
ExtendedCapabilityKind::RootComplexEventCollectorEndpointAssociation(c) => {
write!(f, "{}", Simple(c))
}
ExtendedCapabilityKind::MultifunctionVirtualChannel(c) => {
write!(f, "{}", Simple(c))
}
ExtendedCapabilityKind::VirtualChannelMfvcPresent(c) => {
write!(f, "{}", c.display(VcView { verbose, offset }))
}
ExtendedCapabilityKind::RootComplexRegisterBlockHeader(c) => {
write!(f, "{}", Simple(c))
}
ExtendedCapabilityKind::VendorSpecificExtendedCapability(c) => {
write!(f, "{}", c.display(()))
}
ExtendedCapabilityKind::AccessControlServices(c) => {
write!(f, "{}", Verbose { data: c, verbose })
}
ExtendedCapabilityKind::AlternativeRoutingIdInterpretation(c) => {
write!(f, "{}", Verbose { data: c, verbose })
}
ExtendedCapabilityKind::AddressTranslationServices(c) => {
write!(f, "{}", Verbose { data: c, verbose })
}
ExtendedCapabilityKind::SingleRootIoVirtualization(c) => {
write!(f, "{}", Verbose { data: c, verbose })
}
ExtendedCapabilityKind::MultiRootIoVirtualization(c) => {
write!(f, "{}", Simple(c))
}
ExtendedCapabilityKind::Multicast(c) => {
write!(
f,
"{}",
MulticastView {
data: c,
verbose,
maybe_device_type: maybe_pci_express.map(|pcie| &pcie.device_type)
}
)
}
ExtendedCapabilityKind::PageRequestInterface(c) => {
write!(f, "{}", Verbose { data: c, verbose })
}
ExtendedCapabilityKind::ResizableBar(data) => {
write!(
f,
"{}",
rebar::View {
result: Ok(data),
verbose,
is_virtual: false,
}
)
}
ExtendedCapabilityKind::DynamicPowerAllocation(c) => {
write!(f, "{}", Simple(c))
}
ExtendedCapabilityKind::TphRequester(c) => {
write!(f, "{}", Verbose { data: c, verbose })
}
ExtendedCapabilityKind::LatencyToleranceReporting(c) => {
write!(f, "{}", Verbose { data: c, verbose })
}
ExtendedCapabilityKind::SecondaryPciExpress(c) => {
write!(f, "{}", Verbose { data: c, verbose })
}
ExtendedCapabilityKind::ProtocolMultiplexing(c) => {
write!(f, "{}", Simple(c))
}
ExtendedCapabilityKind::ProcessAddressSpaceId(c) => {
write!(f, "{}", Verbose { data: c, verbose })
}
ExtendedCapabilityKind::LnRequester(c) => {
write!(f, "{}", Simple(c))
}
ExtendedCapabilityKind::DownstreamPortContainment(c) => {
let offset = offset as usize + 0x08 - 0x100;
let maybe_raw_dpc_trigger_reason_extension = device
.extended_configuration_space
.as_ref()
.and_then(|ecs| ecs.0.get(offset).map(|byte| *byte >> 5 & 0b11));
let view = DpcView {
verbose,
maybe_raw_dpc_trigger_reason_extension,
};
write!(f, "{}", c.display(view))
}
ExtendedCapabilityKind::L1PmSubstates(c) => {
write!(f, "{}", Verbose { data: c, verbose })
}
ExtendedCapabilityKind::PrecisionTimeMeasurement(c) => {
write!(f, "{}", Verbose { data: c, verbose })
}
ExtendedCapabilityKind::PciExpressOverMphy(c) => {
write!(f, "{}", Simple(c))
}
ExtendedCapabilityKind::FrsQueuing(c) => {
write!(f, "{}", Simple(c))
}
ExtendedCapabilityKind::ReadinessTimeReporting(c) => {
write!(f, "{}", Simple(c))
}
ExtendedCapabilityKind::DesignatedVendorSpecificExtendedCapability(data) => {
write!(f, "{}", Verbose { data, verbose })
}
ExtendedCapabilityKind::VfResizableBar(data) => {
write!(
f,
"{}",
rebar::View {
result: Ok(data),
verbose,
is_virtual: true,
}
)
}
ExtendedCapabilityKind::DataLinkFeature(c) => write!(f, "{}", Simple(c)),
ExtendedCapabilityKind::PhysicalLayer16GTps(c) => write!(f, "{}", Simple(c)),
ExtendedCapabilityKind::LaneMarginingAtTheReceiver(c) => {
write!(f, "{}", Simple(c))
}
ExtendedCapabilityKind::HierarchyId(c) => write!(f, "{}", Simple(c)),
ExtendedCapabilityKind::NativePcieEnclosureManagement(c) => {
write!(f, "{}", Simple(c))
}
_ => writeln!(f, "Extended Capability ID {:#x}", &self.data.id()),
}
}
}
impl fmt::Display for Verbose<ExtendedCapabilityError> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let verbose = self.verbose;
let (offset, msg) = match &self.data {
offset @ ExtendedCapabilityError::Offset => (&0, format!("{}", offset)),
header @ ExtendedCapabilityError::Header { offset } => (offset, format!("{}", header)),
header @ ExtendedCapabilityError::EmptyHeader { offset } => {
(offset, format!("{}", header))
}
ExtendedCapabilityError::Data { offset, source } => (offset, format!("{}", source)),
ExtendedCapabilityError::AdvancedErrorReporting { offset, source } => {
(offset, format!("{}", source))
}
ExtendedCapabilityError::RootComplexLinkDeclaration {
offset,
source: ref data,
} => (offset, format!("{}", Verbose { data, verbose })),
ExtendedCapabilityError::SingleRootIoVirtualization { offset, source } => {
(offset, format!("{}", source))
}
ExtendedCapabilityError::DownstreamPortContainment { offset, source } => {
(offset, format!("{}", source))
}
ExtendedCapabilityError::MultifunctionVirtualChannel { offset, source } => {
(offset, format!("{}", Simple(source)))
}
ExtendedCapabilityError::ResizableBar { offset, source } => (
offset,
format!(
"{}",
rebar::View {
result: Err(source),
verbose,
is_virtual: false,
}
),
),
ExtendedCapabilityError::DynamicPowerAllocation { offset, source } => {
(offset, format!("{}", source))
}
ExtendedCapabilityError::ProtocolMultiplexing { offset, source } => {
(offset, format!("{}", source))
}
ExtendedCapabilityError::DesignatedVendorSpecificExtendedCapability {
offset,
source: data,
} => (offset, format!("{}", Simple(data))),
ExtendedCapabilityError::VfResizableBar { offset, source } => (
offset,
format!(
"{}",
rebar::View {
result: Err(source),
verbose,
is_virtual: true,
}
),
),
};
let ver = if verbose > 1 { " v0" } else { "" };
write!(f, "\tCapabilities: [{:03x}{}] {}", offset, ver, msg)
}
}
mod aer;
mod vc;
impl DisplayMultiView<()> for DeviceSerialNumber {}
impl<'a> fmt::Display for MultiView<&'a DeviceSerialNumber, ()> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let DeviceSerialNumber {
lower_dword,
upper_dword,
} = self.data;
let [b0, b1, b2, b3] = lower_dword.to_le_bytes();
let [b4, b5, b6, b7] = upper_dword.to_le_bytes();
writeln!(
f,
"Device Serial Number {:02x}-{:02x}-{:02x}-{:02x}-{:02x}-{:02x}-{:02x}-{:02x}",
b7, b6, b5, b4, b3, b2, b1, b0
)
}
}
impl DisplayMultiView<()> for PowerBudgeting {}
impl<'a> fmt::Display for MultiView<&'a PowerBudgeting, ()> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "Power Budgeting <?>")
}
}
mod rclink;
impl<'a> fmt::Display for Simple<&'a RootComplexInternalLinkControl> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "Root Complex Internal Link <?>")
}
}
impl<'a> fmt::Display for Simple<&'a RootComplexEventCollectorEndpointAssociation> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "Root Complex Event Collector <?>")
}
}
impl<'a> fmt::Display for Simple<&'a MultifunctionVirtualChannel<'a>> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "Multi-Function Virtual Channel <?>")
}
}
impl<'a> fmt::Display for Simple<&'a MultifunctionVirtualChannelError> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "Multi-Function Virtual Channel <?>")
}
}
impl<'a> fmt::Display for Simple<&'a RootComplexRegisterBlockHeader> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "Root Complex Register Block <?>")
}
}
impl<'a> DisplayMultiView<()> for VendorSpecificExtendedCapability<'a> {}
impl<'a> fmt::Display for MultiView<&'a VendorSpecificExtendedCapability<'a>, ()> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let h = &self.data.header;
writeln!(
f,
"Vendor Specific Information: ID={:04x} Rev={} Len={:03x} <?>",
h.vsec_id, h.vsec_rev, h.vsec_length
)
}
}
impl<'a> fmt::Display for Simple<&'a ConfigurationAccessCorrelation> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, " <?>")
}
}
impl<'a> fmt::Display for Verbose<&'a AccessControlServices<'a>> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let AccessControlServices {
acs_capability,
acs_control,
..
} = self.data;
let verbose = self.verbose;
writeln!(f, "Access Control Services")?;
if verbose < 2 {
return Ok(());
}
writeln!(f,
"\t\tACSCap:\tSrcValid{} TransBlk{} ReqRedir{} CmpltRedir{} UpstreamFwd{} EgressCtrl{} DirectTrans{}",
Flag(acs_capability.acs_source_validation),
Flag(acs_capability.acs_translation_blocking),
Flag(acs_capability.acs_p2p_request_redirect),
Flag(acs_capability.acs_p2p_completion_redirect),
Flag(acs_capability.acs_upstream_forwarding),
Flag(acs_capability.acs_p2p_egress_control),
Flag(acs_capability.acs_direct_translated_p2p),
)?;
writeln!(f,
"\t\tACSCtl:\tSrcValid{} TransBlk{} ReqRedir{} CmpltRedir{} UpstreamFwd{} EgressCtrl{} DirectTrans{}",
Flag(acs_control.acs_source_validation_enable),
Flag(acs_control.acs_translation_blocking_enable),
Flag(acs_control.acs_p2p_request_redirect_enable),
Flag(acs_control.acs_p2p_completion_redirect_enable),
Flag(acs_control.acs_upstream_forwarding_enable),
Flag(acs_control.acs_p2p_egress_control_enable),
Flag(acs_control.acs_direct_translated_p2p_enable),
)
}
}
impl<'a> fmt::Display for Verbose<&'a AlternativeRoutingIdInterpretation> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let AlternativeRoutingIdInterpretation {
ari_capability: caps,
ari_control: ctrl,
} = self.data;
let verbose = self.verbose;
writeln!(f, "Alternative Routing-ID Interpretation (ARI)")?;
if verbose < 2 {
return Ok(());
}
writeln!(
f,
"\t\tARICap:\tMFVC{} ACS{}, Next Function: {}",
Flag(caps.mfvc_function_groups_capability),
Flag(caps.acs_function_groups_capability),
caps.next_function_number,
)?;
writeln!(
f,
"\t\tARICtl:\tMFVC{} ACS{}, Function Group: {}",
Flag(ctrl.mfvc_function_groups_enable),
Flag(ctrl.acs_function_groups_enable),
ctrl.function_group,
)
}
}
impl<'a> fmt::Display for Verbose<&'a AddressTranslationServices> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let AddressTranslationServices {
ats_capability: caps,
ats_control: ctrl,
} = self.data;
let verbose = self.verbose;
writeln!(f, "Address Translation Service (ATS)")?;
if verbose < 2 {
return Ok(());
}
writeln!(
f,
"\t\tATSCap:\tInvalidate Queue Depth: {:02x}",
caps.invalidate_queue_depth,
)?;
writeln!(
f,
"\t\tATSCtl:\tEnable{}, Smallest Translation Unit: {:02x}",
Flag(ctrl.enable),
ctrl.smallest_translation_unit,
)
}
}
mod sr_iov;
impl<'a> fmt::Display for Simple<&'a MultiRootIoVirtualization> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "Multi-Root I/O Virtualization <?>")
}
}
mod multicast;
use multicast::MulticastView;
impl<'a> fmt::Display for Verbose<&'a PageRequestInterface> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let PageRequestInterface {
page_request_control: ctrl,
page_request_status: sta,
outstanding_page_request_capacity,
outstanding_page_request_allocation,
} = self.data;
let verbose = self.verbose;
writeln!(f, "Page Request Interface (PRI)")?;
if verbose < 2 {
return Ok(());
}
writeln!(
f,
"\t\tPRICtl: Enable{} Reset{}",
Flag(ctrl.enable),
Flag(ctrl.reset),
)?;
writeln!(
f,
"\t\tPRISta: RF{} UPRGI{} Stopped{}",
Flag(sta.response_failure),
Flag(sta.unexpected_page_request_group_index),
Flag(sta.stopped),
)?;
writeln!(
f,
"\t\tPage Request Capacity: {:08x}, Page Request Allocation: {:08x}",
outstanding_page_request_capacity, outstanding_page_request_allocation,
)
}
}
mod rebar;
impl<'a> fmt::Display for Simple<&'a DynamicPowerAllocation<'a>> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "Dynamic Power Allocation <?>")
}
}
impl<'a> fmt::Display for Verbose<&'a TphRequester<'a>> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let verbose = self.verbose;
let TphRequester {
tph_requester_capability: caps,
..
} = self.data;
writeln!(f, "Transaction Processing Hints")?;
if verbose < 2 {
return Ok(());
}
if caps.interrupt_vector_mode_supported {
writeln!(f, "\t\tInterrupt vector mode supported")?;
}
if caps.device_specific_mode_supported {
writeln!(f, "\t\tDevice specific mode supported")?;
}
if caps.extended_tph_requester_supported {
writeln!(f, "\t\tExtended requester support")?;
}
match caps.st_table {
StTable::NotPresent => writeln!(f, "\t\tNo steering table available"),
StTable::Valid { .. } => writeln!(f, "\t\tSteering table in TPH capability structure"),
StTable::Invalid { .. } => {
writeln!(f, "\t\tSteering table in TPH capability structure")
}
StTable::MsiXTable { .. } => writeln!(f, "\t\tSteering table in MSI-X table"),
StTable::Reserved => writeln!(f, "\t\tReserved steering table location"),
}
}
}
impl<'a> fmt::Display for Verbose<&'a LatencyToleranceReporting> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let verbose = self.verbose;
writeln!(f, "Latency Tolerance Reporting")?;
if verbose < 2 {
return Ok(());
}
let LatencyToleranceReporting {
max_snoop_latency: snoop,
max_no_snoop_latency: nosnoop,
} = self.data;
fn calc(value: u16, scale: u8) -> u64 {
let value = (value as u64) & 0x3ff;
let scale = 1u32.wrapping_shl(5 * (scale as u32));
value * (scale as u64)
}
writeln!(
f,
"\t\tMax snoop latency: {}ns",
calc(snoop.value, snoop.scale)
)?;
writeln!(
f,
"\t\tMax no snoop latency: {}ns",
calc(nosnoop.value, nosnoop.scale)
)
}
}
impl<'a> fmt::Display for Verbose<&'a SecondaryPciExpress<'a>> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let SecondaryPciExpress {
link_control_3: ctrl,
lane_error_status,
..
} = self.data;
let verbose = self.verbose;
writeln!(f, "Secondary PCI Express")?;
if verbose < 2 {
return Ok(());
}
writeln!(
f,
"\t\tLnkCtl3: LnkEquIntrruptEn{} PerformEqu{}",
Flag(ctrl.link_equalization_request_interrupt_enable),
Flag(ctrl.perform_equalization),
)?;
let mut lane_err_sta = lane_error_status.0 as u16;
write!(f, "\t\tLaneErrStat: ")?;
if lane_err_sta > 0 {
write!(f, "LaneErr at lane:")?;
for n in 0.. {
if lane_err_sta == 0 {
break;
}
if lane_err_sta & 1 != 0 {
write!(f, " {}", n)?;
}
lane_err_sta >>= 1;
}
} else {
write!(f, "0")?;
}
writeln!(f)
}
}
impl<'a> fmt::Display for Simple<&'a ProtocolMultiplexing<'a>> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "Protocol Multiplexing <?>")
}
}
impl<'a> fmt::Display for Verbose<&'a ProcessAddressSpaceId> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let verbose = self.verbose;
writeln!(f, "Process Address Space ID (PASID)")?;
if verbose < 2 {
return Ok(());
}
let ProcessAddressSpaceId {
pacid_capability: caps,
pacid_control: ctrl,
} = self.data;
writeln!(
f,
"\t\tPASIDCap: Exec{} Priv{}, Max PASID Width: {:02x}",
Flag(caps.execute_permission_supported),
Flag(caps.privileged_mode_supported),
caps.max_pasid_width,
)?;
writeln!(
f,
"\t\tPASIDCtl: Enable{} Exec{} Priv{}",
Flag(ctrl.pasid_enable),
Flag(ctrl.execute_permission_enable),
Flag(ctrl.privileged_mode_enable),
)?;
Ok(())
}
}
impl<'a> fmt::Display for Simple<&'a LnRequester> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "LN Requester <?>")
}
}
struct DpcView {
verbose: usize,
maybe_raw_dpc_trigger_reason_extension: Option<u8>,
}
impl DisplayMultiView<DpcView> for DownstreamPortContainment {}
impl<'a> fmt::Display for MultiView<&'a DownstreamPortContainment, DpcView> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let DpcView {
verbose,
maybe_raw_dpc_trigger_reason_extension,
} = self.view;
writeln!(f, "Downstream Port Containment")?;
if verbose < 2 {
return Ok(());
}
let DownstreamPortContainment {
dpc_capability,
dpc_control,
dpc_status,
dpc_error_source_id,
..
} = self.data;
writeln!(f,
"\t\tDpcCap:\tINT Msg #{}, RPExt{} PoisonedTLP{} SwTrigger{} RP PIO Log {}, DL_ActiveErr{}",
dpc_capability.dpc_interrupt_message_number,
Flag(dpc_capability.rp_extensions_for_dpc),
Flag(dpc_capability.poisoned_tlp_egress_blocking_supported),
Flag(dpc_capability.dpc_software_triggering_supported),
dpc_capability.rp_pio_log_size,
Flag(dpc_capability.dl_active_err_cor_signaling_supported),
)?;
writeln!(f,
"\t\tDpcCtl:\tTrigger:{:x} Cmpl{} INT{} ErrCor{} PoisonedTLP{} SwTrigger{} DL_ActiveErr{}",
dpc_control.dpc_trigger_enable as usize,
Flag(dpc_control.dpc_completion_control),
Flag(dpc_control.dpc_interrupt_enable),
Flag(dpc_control.dpc_err_cor_enable),
Flag(dpc_control.poisoned_tlp_egress_blocking_enable),
Flag(dpc_control.dpc_software_trigger),
Flag(dpc_control.dl_active_err_cor_enable),
)?;
writeln!(f,
"\t\tDpcSta:\tTrigger{} Reason:{:02x} INT{} RPBusy{} TriggerExt:{:02x} RP PIO ErrPtr:{:02x}",
Flag(dpc_status.dpc_trigger_status),
dpc_status.dpc_trigger_reason.value(),
Flag(dpc_status.dpc_interrupt_status),
Flag(dpc_status.dpc_rp_busy),
maybe_raw_dpc_trigger_reason_extension.unwrap_or(0),
dpc_status.rp_pio_first_error_pointer,
)?;
writeln!(f, "\t\tSource:\t{:04x}", dpc_error_source_id)
}
}
impl<'a> fmt::Display for Verbose<&'a L1PmSubstates> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let verbose = self.verbose;
writeln!(f, "L1 PM Substates")?;
if verbose < 2 {
return Ok(());
}
let L1PmSubstates {
l1_pm_substates_capabilities: caps,
l1_pm_substates_control_1: ctl1,
l1_pm_substates_control_2: ctl2,
} = self.data;
writeln!(
f,
"\t\tL1SubCap: PCI-PM_L1.2{} PCI-PM_L1.1{} ASPM_L1.2{} ASPM_L1.1{} L1_PM_Substates{}",
Flag(caps.pci_pm_l1_2_supported),
Flag(caps.pci_pm_l1_1_supported),
Flag(caps.aspm_l1_2_supported),
Flag(caps.aspm_l1_1_supported),
Flag(
caps.pci_pm_l1_1_supported
|| caps.aspm_l1_2_supported
|| caps.l1_pm_substates_supported
),
)?;
let is_l1_2_supported = caps.pci_pm_l1_2_supported || caps.aspm_l1_2_supported;
if is_l1_2_supported {
write!(
f,
"\t\t\t PortCommonModeRestoreTime={}us ",
caps.port_common_mode_restore_time
)?;
if let Some(time) = caps.port_t_power_on.value() {
writeln!(f, "PortTPowerOnTime={}us", time)?;
} else {
writeln!(f, "PortTPowerOnTime=<error>")?;
};
}
writeln!(
f,
"\t\tL1SubCtl1: PCI-PM_L1.2{} PCI-PM_L1.1{} ASPM_L1.2{} ASPM_L1.1{}",
Flag(ctl1.pci_pm_l1_2_enable),
Flag(ctl1.pci_pm_l1_1_enable),
Flag(ctl1.aspm_l1_2_enable),
Flag(ctl1.aspm_l1_1_enable),
)?;
if is_l1_2_supported {
write!(
f,
"\t\t\t T_CommonMode={}us",
ctl1.common_mode_restore_time
)?;
if caps.aspm_l1_2_supported {
if ctl1.ltr_l1_2_threshold.scale > 5 {
write!(f, " LTR1.2_Threshold=<error>")?;
} else {
write!(f, " LTR1.2_Threshold={}ns", ctl1.ltr_l1_2_threshold.value())?;
}
}
writeln!(f)?;
}
write!(f, "\t\tL1SubCtl2:")?;
if is_l1_2_supported {
if let Some(time) = ctl2.t_power_on.value() {
write!(f, " T_PwrOn={}us", time)?;
} else {
write!(f, " T_PwrOn=<error>")?;
};
}
writeln!(f)
}
}
impl<'a> fmt::Display for Verbose<&'a PrecisionTimeMeasurement> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let verbose = self.verbose;
writeln!(f, "Precision Time Measurement")?;
if verbose < 2 {
return Ok(());
}
let PrecisionTimeMeasurement {
ptm_capability: caps,
ptm_control: ctrl,
} = self.data;
writeln!(
f,
"\t\tPTMCap: Requester:{} Responder:{} Root:{}",
Flag(caps.ptm_requester_capable),
Flag(caps.ptm_responder_capable),
Flag(caps.ptm_root_capable),
)?;
write!(f, "\t\tPTMClockGranularity: ",)?;
match caps.local_clock_granularity {
0x00 => writeln!(f, "Unimplemented"),
0xff => writeln!(f, "Greater than 254ns"),
v => writeln!(f, "{}ns", v),
}?;
writeln!(
f,
"\t\tPTMControl: Enabled:{} RootSelected:{}",
Flag(ctrl.ptm_enable),
Flag(ctrl.root_select),
)?;
write!(f, "\t\tPTMEffectiveGranularity: ",)?;
match ctrl.effective_granularity {
0x00 => writeln!(f, "Unknown"),
0xff => writeln!(f, "Greater than 254ns"),
v => writeln!(f, "{}ns", v),
}
}
}
impl<'a> fmt::Display for Simple<&'a PciExpressOverMphy> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "PCI Express over M_PHY <?>")
}
}
impl<'a> fmt::Display for Simple<&'a FrsQueuing> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "FRS Queueing <?>")
}
}
impl<'a> fmt::Display for Simple<&'a ReadinessTimeReporting> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "Readiness Time Reporting <?>")
}
}
mod dvsec;
impl<'a> fmt::Display for Simple<&'a DataLinkFeature> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "Data Link Feature <?>")
}
}
impl<'a> fmt::Display for Simple<&'a PhysicalLayer16GTps> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "Physical Layer 16.0 GT/s <?>")
}
}
impl<'a> fmt::Display for Simple<&'a LaneMarginingAtTheReceiver> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "Lane Margining at the Receiver <?>")
}
}
impl<'a> fmt::Display for Simple<&'a HierarchyId> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "Hierarchy ID <?>")
}
}
impl<'a> fmt::Display for Simple<&'a NativePcieEnclosureManagement> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "Native PCIe Enclosure Management <?>")
}
}