Skip to main content

pcie/
test_helpers.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4use chipset_device::io::IoResult;
5use chipset_device::mmio::ControlMmioIntercept;
6use chipset_device::mmio::RegisterMmioIntercept;
7use pci_bus::GenericPciBusDevice;
8use std::fmt::Debug;
9
10pub struct TestPcieMmioRegistration {}
11
12impl RegisterMmioIntercept for TestPcieMmioRegistration {
13    fn new_io_region(&mut self, _debug_name: &str, len: u64) -> Box<dyn ControlMmioIntercept> {
14        Box::new(TestPcieControlMmioIntercept { mapping: None, len })
15    }
16}
17
18pub struct TestPcieControlMmioIntercept {
19    pub mapping: Option<u64>,
20    pub len: u64,
21}
22
23impl ControlMmioIntercept for TestPcieControlMmioIntercept {
24    /// Enables the IO region.
25    fn map(&mut self, addr: u64) {
26        match self.mapping {
27            Some(_) => panic!("already mapped"),
28            None => self.mapping = Some(addr),
29        }
30    }
31
32    /// Disables the IO region.
33    fn unmap(&mut self) {
34        match self.mapping {
35            Some(_) => self.mapping = None,
36            None => panic!("not mapped"),
37        }
38    }
39
40    /// Return the currently mapped address.
41    ///
42    /// Returns `None` if the region is currently unmapped.
43    fn addr(&self) -> Option<u64> {
44        self.mapping
45    }
46
47    fn len(&self) -> u64 {
48        self.len
49    }
50
51    /// Return the offset of `addr` from the region's base address.
52    ///
53    /// Returns `None` if the provided `addr` is outside of the memory
54    /// region, or the region is currently unmapped.
55    fn offset_of(&self, addr: u64) -> Option<u64> {
56        self.mapping.map(|base_addr| addr - base_addr)
57    }
58
59    fn region_name(&self) -> &str {
60        "???"
61    }
62}
63
64pub struct TestPcieEndpoint<R, W>
65where
66    R: Fn(u16, &mut u32) -> Option<IoResult> + 'static + Send,
67    W: FnMut(u16, u32) -> Option<IoResult> + 'static + Send,
68{
69    cfg_read_closure: R,
70    cfg_write_closure: W,
71}
72
73impl<R, W> TestPcieEndpoint<R, W>
74where
75    R: Fn(u16, &mut u32) -> Option<IoResult> + 'static + Send,
76    W: FnMut(u16, u32) -> Option<IoResult> + 'static + Send,
77{
78    pub fn new(cfg_read_closure: R, cfg_write_closure: W) -> Self {
79        Self {
80            cfg_read_closure,
81            cfg_write_closure,
82        }
83    }
84}
85
86impl<R, W> GenericPciBusDevice for TestPcieEndpoint<R, W>
87where
88    R: Fn(u16, &mut u32) -> Option<IoResult> + 'static + Send,
89    W: FnMut(u16, u32) -> Option<IoResult> + 'static + Send,
90{
91    fn pci_cfg_read(&mut self, offset: u16, value: &mut u32) -> Option<IoResult> {
92        (self.cfg_read_closure)(offset, value)
93    }
94
95    fn pci_cfg_write(&mut self, offset: u16, value: u32) -> Option<IoResult> {
96        (self.cfg_write_closure)(offset, value)
97    }
98}
99
100impl<R, W> Debug for TestPcieEndpoint<R, W>
101where
102    R: Fn(u16, &mut u32) -> Option<IoResult> + 'static + Send,
103    W: FnMut(u16, u32) -> Option<IoResult> + 'static + Send,
104{
105    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
106        writeln!(fmt, "TestPcieEndpoint")
107    }
108}