mycelium_pci/device/
bar.rs1use crate::error::{self, UnexpectedValue};
3use mycelium_bitfield::{pack::Pack32, FromBits};
4#[derive(Copy, Clone, Debug, Eq, PartialEq)]
11pub enum BaseAddress {
12 Memory32 { prefetchable: bool, addr: u32 },
13 Memory64 { prefetchable: bool, addr: u64 },
14 Io(u32),
15}
16
17impl BaseAddress {
18 const BAR_KIND: Pack32 = Pack32::least_significant(1);
19 const MEM_TYPE: Pack32<MemoryBarType> = Self::BAR_KIND.then();
20 const MEM_PREFETCHABLE: Pack32<bool> = Self::MEM_TYPE.then();
21 const MEM_ADDR: Pack32 = Self::MEM_PREFETCHABLE.remaining();
22 const MEM_MASK: u32 = Self::MEM_ADDR.raw_mask();
23
24 const IO_MASK: u32 = !0b11;
26
27 pub(crate) fn decode_bars<const BARS: usize>(
28 bars: &[u32; BARS],
29 ) -> Result<[Option<Self>; BARS], UnexpectedValue<u32>> {
30 let mut decoded = [None; BARS];
31 let mut curr_64_bit = None;
32 for (i, &bits) in bars.iter().enumerate() {
33 if let Some((prefetchable, low_bits)) = curr_64_bit.take() {
36 let addr = ((bits as u64) << 32) | (low_bits as u64);
37 decoded[i - 1] = Some(Self::Memory64 { prefetchable, addr });
39 decoded[i] = None;
42 continue;
43 }
44
45 if Self::BAR_KIND.unpack(bits) == 1 {
47 decoded[i] = Some(Self::Io(bits & Self::IO_MASK));
48 continue;
49 }
50
51 let prefetchable = Self::MEM_PREFETCHABLE.unpack(bits);
53 match Self::MEM_TYPE.try_unpack(bits)? {
54 MemoryBarType::Base32 => {
56 decoded[i] = Some(Self::Memory32 {
57 prefetchable,
58 addr: bits & Self::MEM_MASK,
59 });
60 }
61 MemoryBarType::Base64 => curr_64_bit = Some((prefetchable, bits & Self::MEM_MASK)),
64
65 MemoryBarType::Legacy16 => {
67 return Err(
68 error::unexpected(bits).named("unsupported legacy 16-bit memory BAR")
69 );
70 }
71 }
72 }
73
74 Ok(decoded)
75 }
76}
77
78#[derive(Copy, Clone, Debug, PartialEq, Eq)]
79#[repr(u8)]
80enum MemoryBarType {
81 Base32 = 0x0,
83 Legacy16 = 0x1,
85 Base64 = 0x2,
87}
88
89impl FromBits<u32> for MemoryBarType {
92 type Error = UnexpectedValue<u32>;
93 const BITS: u32 = 2;
94 fn try_from_bits(bits: u32) -> Result<Self, Self::Error> {
95 match bits as u8 {
96 bits if bits == Self::Base32 as u8 => Ok(Self::Base32),
97 bits if bits == Self::Base64 as u8 => Ok(Self::Base64),
98 bits if bits == Self::Legacy16 as u8 => Ok(Self::Legacy16),
99 _ => Err(crate::error::unexpected(bits).named("MemoryBarType")),
100 }
101 }
102
103 fn into_bits(self) -> u32 {
104 self as u8 as u32
105 }
106}