chipset_arc_mutex_device/services.rs
1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Chipset-facing traits required to wire-up a Arc + Mutex backed
5//! [`ChipsetDevice`](chipset_device::ChipsetDevice).
6
7use chipset_device::mmio::RegisterMmioIntercept;
8use chipset_device::pio::RegisterPortIoIntercept;
9
10/// Compile-time type metadata bundle specified by concrete [`ChipsetServices`]
11/// implementations.
12///
13/// If an implementation doesn't support a particular service, the service's
14/// corresponding type should be set to [`Unimplemented`].
15///
16/// Rather than having `ChipsetServices` directly encode all these type (and
17/// make the type signatures for the `supports_XXX` methods absolutely
18/// _nightmarish_), we split them all out into their own trait, which can be
19/// references via a single type parameter.
20pub trait ChipsetServicesMeta {
21 // DEVNOTE: ideally, these would all have a default `= Unimplemented`, but
22 // associated type defaults are still unstable...
23 //
24 /// Concrete type that impls `RegisterMmioIntercept`
25 type RegisterMmioIntercept: RegisterMmioIntercept;
26 /// Concrete type that impls `RegisterPortIoIntercept`
27 type RegisterPortIoIntercept: RegisterPortIoIntercept;
28}
29
30/// The intermediary that allows a device to wire itself up to various VM
31/// chipset services.
32pub trait ChipsetServices {
33 /// A bundle of associated types used by the concrete implementation.
34 type M: ChipsetServicesMeta;
35
36 /// Support for MMIO intercepts.
37 #[inline(always)]
38 fn supports_mmio(&mut self) -> Option<&mut dyn MmioInterceptServices<M = Self::M>> {
39 None
40 }
41
42 /// Support for Port IO intercepts.
43 #[inline(always)]
44 fn supports_pio(&mut self) -> Option<&mut dyn PortIoInterceptServices<M = Self::M>> {
45 None
46 }
47
48 /// Support for PCI configuration space.
49 #[inline(always)]
50 fn supports_pci(&mut self) -> Option<&mut dyn PciConfigSpaceServices<M = Self::M>> {
51 None
52 }
53
54 /// Support for poll.
55 #[inline(always)]
56 fn supports_poll_device(&mut self) -> Option<&mut dyn PollDeviceServices<M = Self::M>> {
57 None
58 }
59}
60
61/// Implemented by chipsets that can support [`MmioIntercept`] devices.
62///
63/// [`MmioIntercept`]: chipset_device::mmio::MmioIntercept
64pub trait MmioInterceptServices: ChipsetServices {
65 /// Obtain an instance of [`RegisterMmioIntercept`]
66 fn register_mmio(&self) -> <Self::M as ChipsetServicesMeta>::RegisterMmioIntercept;
67
68 /// Return `true` if any [`MmioInterceptServices`] method has been invoked.
69 fn is_being_used(&self) -> bool;
70}
71
72/// Implemented by chipsets that can support [`PciConfigSpace`] devices.
73///
74/// [`PciConfigSpace`]: chipset_device::pci::PciConfigSpace
75pub trait PciConfigSpaceServices: ChipsetServices {
76 /// Register the device at the specified (bus, device, function)
77 fn register_static_pci(&mut self, bus: u8, device: u8, function: u8);
78
79 /// Return `true` if any [`PciConfigSpaceServices`] method has been invoked.
80 fn is_being_used(&self) -> bool;
81}
82
83/// Implemented by chipsets that can support [`PortIoIntercept`] devices.
84///
85/// [`PortIoIntercept`]: chipset_device::pio::PortIoIntercept
86pub trait PortIoInterceptServices: ChipsetServices {
87 /// Obtain an instance of [`RegisterPortIoIntercept`]
88 fn register_pio(&self) -> <Self::M as ChipsetServicesMeta>::RegisterPortIoIntercept;
89
90 /// Return `true` if any [`PortIoInterceptServices`] method has been invoked.
91 fn is_being_used(&self) -> bool;
92}
93
94/// Implemented by chipsets that can support [`PollDevice`] devices.
95///
96/// [`PollDevice`]: chipset_device::poll_device::PollDevice
97pub trait PollDeviceServices: ChipsetServices {
98 /// Register for asynchronous polling.
99 fn register_poll(&mut self);
100
101 /// Return `true` if [`Self::register_poll`] has been invoked.
102 fn is_being_used(&self) -> bool;
103}
104
105/// A placeholder type to represent a bit of unimplemented functionality.
106pub enum Unimplemented {}
107
108impl RegisterMmioIntercept for Unimplemented {
109 fn new_io_region(
110 &mut self,
111 _: &str,
112 _: u64,
113 ) -> Box<dyn chipset_device::mmio::ControlMmioIntercept> {
114 unreachable!()
115 }
116}
117
118impl RegisterPortIoIntercept for Unimplemented {
119 fn new_io_region(
120 &mut self,
121 _: &str,
122 _: u16,
123 ) -> Box<dyn chipset_device::pio::ControlPortIoIntercept> {
124 unreachable!()
125 }
126}