1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
use crate::{handler::PhysicalMapping, sdt::SdtHeader, Acpi, AcpiError};
use alloc::vec::Vec;
use core::{mem, slice};
#[derive(Clone, Debug)]
pub struct PciConfigRegions {
regions: Vec<McfgEntry>,
}
impl PciConfigRegions {
pub fn physical_address(&self, segment_group_no: u16, bus: u8, device: u8, function: u8) -> Option<u64> {
let region = self.regions.iter().find(|region| {
region.pci_segment_group == segment_group_no
&& (region.bus_number_start..=region.bus_number_end).contains(&bus)
})?;
Some(
region.base_address
+ ((u64::from(bus - region.bus_number_start) << 20)
| (u64::from(device) << 15)
| (u64::from(function) << 12)),
)
}
}
#[repr(C, packed)]
pub(crate) struct Mcfg {
header: SdtHeader,
_reserved: u64,
}
impl Mcfg {
fn entries(&self) -> &[McfgEntry] {
let length = self.header.length as usize - mem::size_of::<Mcfg>();
let num_entries = length / mem::size_of::<McfgEntry>();
unsafe {
let pointer =
(self as *const Mcfg as *const u8).offset(mem::size_of::<Mcfg>() as isize) as *const McfgEntry;
slice::from_raw_parts(pointer, num_entries)
}
}
}
#[derive(Clone, Copy, Debug)]
#[repr(C, packed)]
struct McfgEntry {
base_address: u64,
pci_segment_group: u16,
bus_number_start: u8,
bus_number_end: u8,
_reserved: u32,
}
pub(crate) fn parse_mcfg(acpi: &mut Acpi, mapping: &PhysicalMapping<Mcfg>) -> Result<(), AcpiError> {
(*mapping).header.validate(crate::sdt::Signature::MCFG)?;
acpi.pci_config_regions =
Some(PciConfigRegions { regions: mapping.entries().iter().map(|&entry| entry).collect() });
Ok(())
}