pci_core/
bar_mapping.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! BAR Management.
5
6use crate::spec::cfg_space;
7use inspect::Inspect;
8
9/// A parsed BAR mapping.
10#[derive(Debug, Inspect)]
11pub struct BarMapping {
12    /// Associated BAR register index
13    pub index: u8,
14    /// Base address of the mapping
15    pub base_address: u64,
16    /// Length of the mapping
17    pub len: u64,
18}
19
20/// A set of parsed BAR mappings.
21#[derive(Debug, Default)]
22pub struct BarMappings(Vec<BarMapping>);
23
24impl Inspect for BarMappings {
25    fn inspect(&self, req: inspect::Request<'_>) {
26        let mut res = req.respond();
27        for bar in self.0.iter() {
28            res.field(
29                &format!("bar{}", bar.index),
30                format!("{:#010x?}:{:#x?}", bar.base_address, bar.len),
31            );
32        }
33    }
34}
35
36impl BarMappings {
37    /// Parses a set of BARs into mappings.
38    pub fn parse(base_addresses: &[u32; 6], bar_masks: &[u32; 6]) -> Self {
39        let mut mappings = Vec::new();
40        let mut i = 0;
41        while i < base_addresses.len() {
42            let bar_address;
43            let mut bar_mask;
44            let len;
45            if cfg_space::BarEncodingBits::from_bits(bar_masks[i]).type_64_bit() {
46                bar_mask = (bar_masks[i + 1] as u64) << 32 | bar_masks[i] as u64;
47                bar_address = (base_addresses[i + 1] as u64) << 32 | base_addresses[i] as u64;
48                len = 2;
49            } else {
50                bar_mask = bar_masks[i] as i32 as i64 as u64; // sign extend
51                bar_address = base_addresses[i] as u64;
52                len = 1;
53            };
54            bar_mask &= !0xf;
55            if bar_mask != 0 {
56                mappings.push(BarMapping {
57                    index: i as u8,
58                    base_address: bar_address & bar_mask,
59                    len: !bar_mask + 1,
60                });
61            }
62            i += len;
63        }
64        Self(mappings)
65    }
66
67    /// Finds a BAR + offset by address.
68    pub fn find(&self, address: u64) -> Option<(u8, u16)> {
69        for bar_mapping in self.0.iter() {
70            if address >= bar_mapping.base_address
71                && address - bar_mapping.base_address < bar_mapping.len
72            {
73                return Some((
74                    bar_mapping.index,
75                    (address - bar_mapping.base_address).try_into().unwrap(),
76                ));
77            }
78        }
79        None
80    }
81
82    /// Gets the base address configured for `bar`.
83    pub fn get(&self, bar: u8) -> Option<u64> {
84        for bar_mapping in self.0.iter() {
85            if bar_mapping.index == bar {
86                return Some(bar_mapping.base_address);
87            }
88        }
89        None
90    }
91
92    /// Returns an iterator through the mappings.
93    pub fn iter(&self) -> impl Iterator<Item = &BarMapping> {
94        self.0.iter()
95    }
96}