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(())
}