pci_core/test_helpers/
mod.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Mock types for unit-testing various PCI behaviors.
5
6use crate::msi::MsiControl;
7use crate::msi::MsiInterruptTarget;
8use parking_lot::Mutex;
9use std::collections::VecDeque;
10use std::sync::Arc;
11
12/// A test-only interrupt controller that simply stashes incoming interrupt
13/// requests in a FIFO queue. Implements [`MsiInterruptTarget`].
14#[derive(Debug, Clone)]
15pub struct TestPciInterruptController {
16    inner: Arc<TestPciInterruptControllerInner>,
17}
18
19#[derive(Debug)]
20struct TestPciInterruptControllerInner {
21    // TODO: also support INTx interrupts
22    msi_requests: Mutex<VecDeque<(u64, u32)>>, // (addr, data)
23}
24
25impl TestPciInterruptController {
26    /// Return a new test PCI interrupt controller
27    pub fn new() -> Self {
28        Self {
29            inner: Arc::new(TestPciInterruptControllerInner {
30                msi_requests: Mutex::new(VecDeque::new()),
31            }),
32        }
33    }
34
35    /// Fetch the first (addr, data) MSI-X interrupt in the FIFO interrupt queue
36    pub fn get_next_interrupt(&self) -> Option<(u64, u32)> {
37        self.inner.msi_requests.lock().pop_front()
38    }
39}
40
41impl MsiInterruptTarget for TestPciInterruptController {
42    fn new_interrupt(&self) -> Box<dyn MsiControl> {
43        let controller = self.inner.clone();
44        Box::new(move |address, data| controller.msi_requests.lock().push_back((address, data)))
45    }
46}