vmotherboard/chipset/
line_sets.rs1use chipset_device::ChipsetDevice;
5use chipset_device_resources::LineSetId;
6use closeable_mutex::CloseableMutex;
7use inspect::InspectMut;
8use state_unit::SpawnedUnit;
9use state_unit::StateUnit;
10use state_unit::StateUnits;
11use state_unit::UnitHandle;
12use std::collections::HashMap;
13use std::sync::Arc;
14use vmcore::line_interrupt::LineSet;
15use vmcore::line_interrupt::LineSetTarget;
16use vmcore::vm_task::VmTaskDriverSource;
17
18pub struct LineSets {
19 map: HashMap<LineSetId, (Arc<LineSet>, usize)>,
20 pub units: Vec<SpawnedUnit<()>>,
21}
22
23impl LineSets {
24 pub fn new() -> Self {
25 Self {
26 map: HashMap::new(),
27 units: Vec::new(),
28 }
29 }
30
31 pub fn line_set(
32 &mut self,
33 driver: &VmTaskDriverSource,
34 units: &StateUnits,
35 id: LineSetId,
36 ) -> (&LineSet, &UnitHandle) {
37 let (line_set, index) = self.map.entry(id.clone()).or_insert_with(|| {
38 let set = Arc::new(LineSet::new());
39 let unit = units
40 .add(format!("lines/{}", id.name()))
41 .spawn(driver.simple(), {
42 let set = set.clone();
43 async move |mut recv| {
44 while let Ok(req) = recv.recv().await {
45 req.apply(&mut LineSetUnit(&set)).await;
46 }
47 }
48 })
49 .unwrap();
50 let index = self.units.len();
51 self.units.push(unit);
52 (set, index)
53 });
54 (line_set, self.units[*index].handle())
55 }
56}
57
58#[derive(InspectMut)]
59#[inspect(transparent)]
60struct LineSetUnit<'a>(&'a LineSet);
61
62impl StateUnit for LineSetUnit<'_> {
63 async fn start(&mut self) {}
64
65 async fn stop(&mut self) {}
66
67 async fn reset(&mut self) -> anyhow::Result<()> {
68 Ok(())
69 }
70
71 async fn save(
72 &mut self,
73 ) -> Result<Option<vmcore::save_restore::SavedStateBlob>, vmcore::save_restore::SaveError> {
74 Ok(None)
75 }
76
77 async fn restore(
78 &mut self,
79 _: vmcore::save_restore::SavedStateBlob,
80 ) -> Result<(), vmcore::save_restore::RestoreError> {
81 Err(vmcore::save_restore::RestoreError::SavedStateNotSupported)
82 }
83}
84
85pub struct LineSetTargetDevice<T> {
86 device: Arc<CloseableMutex<T>>,
87}
88
89impl<T: ChipsetDevice> LineSetTargetDevice<T> {
90 pub fn new(device: Arc<CloseableMutex<T>>) -> Self {
91 Self { device }
92 }
93}
94
95impl<T: ChipsetDevice> LineSetTarget for LineSetTargetDevice<T> {
96 fn set_irq(&self, vector: u32, high: bool) {
97 self.device
98 .lock()
99 .supports_line_interrupt_target()
100 .unwrap()
101 .set_irq(vector, high);
102 }
103}