use crate::cell_collector::{BuildCellCollector, CellCollector, CollectCellsError};
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct PciAddress {
#[allow(missing_docs)]
pub hi: PciAddressHighBits,
#[allow(missing_docs)]
pub mid: u32,
#[allow(missing_docs)]
pub lo: u32,
}
impl CellCollector for PciAddress {
type Builder = PciAddressCollector;
type Output = Self;
fn map(builder_out: <Self::Builder as BuildCellCollector>::Output) -> Self::Output {
builder_out
}
}
impl PartialEq<&'_ PciAddress> for PciAddress {
fn eq(&self, other: &&'_ Self) -> bool {
self.eq(*other)
}
}
impl PartialEq<PciAddress> for &'_ PciAddress {
fn eq(&self, other: &PciAddress) -> bool {
(*self).eq(other)
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct PciAddressHighBits(u32);
#[allow(missing_docs)]
impl PciAddressHighBits {
#[inline(always)]
pub fn new(raw: u32) -> Self {
Self(raw)
}
#[inline(always)]
pub fn register(self) -> u8 {
self.0 as u8
}
#[inline(always)]
pub fn function(self) -> u8 {
((self.0 >> 8) & 0b111) as u8
}
#[inline(always)]
pub fn device(self) -> u8 {
((self.0 >> 12) & 0b11111) as u8
}
#[inline(always)]
pub fn bus(self) -> u8 {
(self.0 >> 16) as u8
}
#[inline(always)]
pub fn address_space(self) -> PciAddressSpace {
const CONFIGURATION: u8 = const { PciAddressSpace::Configuration as u8 };
const IO: u8 = const { PciAddressSpace::Io as u8 };
const MEMORY32: u8 = const { PciAddressSpace::Memory32 as u8 };
const MEMORY64: u8 = const { PciAddressSpace::Memory64 as u8 };
match ((self.0 >> 24) & 0b11) as u8 {
CONFIGURATION => PciAddressSpace::Configuration,
IO => PciAddressSpace::Io,
MEMORY32 => PciAddressSpace::Memory32,
MEMORY64 => PciAddressSpace::Memory64,
_ => unreachable!(),
}
}
#[inline(always)]
pub fn prefetchable(self) -> bool {
(self.0 >> 30) & 0b1 == 0b1
}
#[inline(always)]
pub fn relocatable(self) -> bool {
(self.0 >> 31) & 0b1 == 0b0
}
}
impl core::ops::BitAnd for PciAddress {
type Output = Self;
fn bitand(self, rhs: Self) -> Self::Output {
Self { hi: PciAddressHighBits(self.hi.0 & rhs.hi.0), mid: self.mid & rhs.mid, lo: self.lo & rhs.lo }
}
}
#[allow(missing_docs)]
#[repr(u8)]
pub enum PciAddressSpace {
Configuration = 0b00,
Io = 0b01,
Memory32 = 0b10,
Memory64 = 0b11,
}
#[allow(missing_docs)]
#[derive(Default)]
pub struct PciAddressCollector {
address: PciAddress,
num_pushes: u32,
}
impl BuildCellCollector for PciAddressCollector {
type Output = PciAddress;
fn push(&mut self, component: u32) -> Result<(), CollectCellsError> {
match self.num_pushes {
0 => self.address.hi = PciAddressHighBits(component),
1 => self.address.mid = component,
2 => self.address.lo = component,
_ => return Err(CollectCellsError),
}
self.num_pushes += 1;
Ok(())
}
fn finish(self) -> Self::Output {
self.address
}
}