pcitool 0.1.0

Tool and library for portable access to PCI bus configuration registres.
Documentation
use core::fmt;

use pcics::capabilities::enhanced_allocation::{
    BarEquivalentIndicator, EnhancedAllocation, EnhancedAllocationEntry, ResourceDefinition,
    ResourceRangeAddress, Type1SecondDw,
};

use super::{Flag, Verbose};

impl<'a> fmt::Display for Verbose<&'a EnhancedAllocation<'a>> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let EnhancedAllocation {
            num_entries,
            type_1_second_dw,
            entries,
        } = self.data;
        let verbose = self.verbose;
        write!(f, "Enhanced Allocation (EA): NumEntries={}", num_entries)?;
        if let Some(Type1SecondDw {
            fixed_secondary_bus_number,
            fixed_subordinate_bus_number,
        }) = type_1_second_dw
        {
            write!(
                f,
                ", secondary={}, subordinate={}",
                fixed_secondary_bus_number, fixed_subordinate_bus_number
            )?;
        }
        writeln!(f)?;
        if verbose < 2 {
            return Ok(());
        }
        for (n, entry) in entries.clone().enumerate() {
            let EnhancedAllocationEntry {
                entry_size,
                bar_equivalent_indicator,
                primary_properties,
                secondary_properties,
                writable,
                enable,
                base,
                max_offset,
            } = entry;
            writeln!(
                f,
                "\t\tEntry {}: Enable{} Writable{} EntrySize={}",
                n,
                Flag(enable),
                Flag(writable),
                entry_size
            )?;
            let bei = match bar_equivalent_indicator {
                BarEquivalentIndicator::Location10h => "BAR 0",
                BarEquivalentIndicator::Location14h => "BAR 1",
                BarEquivalentIndicator::Location18h => "BAR 2",
                BarEquivalentIndicator::Location1Ch => "BAR 3",
                BarEquivalentIndicator::Location20h => "BAR 4",
                BarEquivalentIndicator::Location24h => "BAR 5",
                BarEquivalentIndicator::BehindType1Function => "resource behind function",
                BarEquivalentIndicator::EquivalentNotIndicated => "not indicated",
                BarEquivalentIndicator::ExpansionRomBaseAddress => "expansion ROM",
                BarEquivalentIndicator::VfBar0 => "VF-BAR 0",
                BarEquivalentIndicator::VfBar1 => "VF-BAR 1",
                BarEquivalentIndicator::VfBar2 => "VF-BAR 2",
                BarEquivalentIndicator::VfBar3 => "VF-BAR 3",
                BarEquivalentIndicator::VfBar4 => "VF-BAR 4",
                BarEquivalentIndicator::VfBar5 => "VF-BAR 5",
                BarEquivalentIndicator::Reserved => "reserved",
            };
            writeln!(f, "\t\t\t BAR Equivalent Indicator: {}", bei)?;
            writeln!(
                f,
                "\t\t\t PrimaryProperties: {}",
                ResourceDefinitionView {
                    rd: &primary_properties,
                    is_secondary: false
                },
            )?;
            writeln!(
                f,
                "\t\t\t SecondaryProperties: {}",
                ResourceDefinitionView {
                    rd: &secondary_properties,
                    is_secondary: true
                },
            )?;
            writeln!(f, "\t\t\t Base: {}", ResourceRangeAddressView(base))?;
            writeln!(
                f,
                "\t\t\t MaxOffset: {}",
                ResourceRangeAddressView(max_offset)
            )?;
        }

        Ok(())
    }
}

struct ResourceDefinitionView<'a> {
    rd: &'a ResourceDefinition,
    is_secondary: bool,
}

impl<'a> fmt::Display for ResourceDefinitionView<'a> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let &ResourceDefinitionView { rd, is_secondary } = self;
        match rd {
            ResourceDefinition::MemorySpaceNonPrefetchable => {
                write!(f, "memory space, non-prefetchable")
            }
            ResourceDefinition::MemorySpacePrefetchable => write!(f, "memory space, prefetchable"),
            ResourceDefinition::IoSpace => write!(f, "I/O space"),
            ResourceDefinition::PfForVfMemorySpacePrefetchable => {
                write!(f, "VF memory space, prefetchable")
            }
            ResourceDefinition::PfForVfMemorySpaceNonPrefetchable => {
                write!(f, "VF memory space, non-prefetchable")
            }
            ResourceDefinition::Type1ForAbbMemoryNonPrefetchable => {
                write!(f, "allocation behind bridge, non-prefetchable memory")
            }
            ResourceDefinition::Type1ForAbbMemoryPrefetchable => {
                write!(f, "allocation behind bridge, prefetchable memory")
            }
            ResourceDefinition::Type1ForAbbIoSpace => {
                write!(f, "allocation behind bridge, I/O space")
            }
            ResourceDefinition::Reserved(v) => write!(f, "[{:02x}]", v),
            ResourceDefinition::UnavailableMemorySpace => {
                write!(f, "memory space resource unavailable for use")
            }
            ResourceDefinition::UnavailableIoSpace => {
                write!(f, "I/O space resource unavailable for use")
            }
            ResourceDefinition::Unavailable => {
                if is_secondary {
                    write!(
                        f,
                        "entry unavailable for use, PrimaryProperties should be used"
                    )
                } else {
                    write!(f, "entry unavailable for use")
                }
            }
        }
    }
}

struct ResourceRangeAddressView(ResourceRangeAddress);

impl fmt::Display for ResourceRangeAddressView {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self.0 {
            ResourceRangeAddress::U32(v) => write!(f, "{:08x}", v),
            ResourceRangeAddress::U64(v) => write!(f, "{:08x}", v),
        }
    }
}