virtio_drivers/transport/
some.rs

1use zerocopy::{FromBytes, Immutable, IntoBytes};
2
3use super::{mmio::MmioTransport, pci::PciTransport, DeviceStatus, DeviceType, Transport};
4use crate::{transport::InterruptStatus, PhysAddr, Result};
5
6/// A wrapper for an arbitrary VirtIO transport, either MMIO or PCI.
7#[derive(Debug)]
8pub enum SomeTransport<'a> {
9    /// An MMIO transport.
10    Mmio(MmioTransport<'a>),
11    /// A PCI transport.
12    Pci(PciTransport),
13    /// An x86-64 pKVM PCI transport.
14    #[cfg(target_arch = "x86_64")]
15    HypPci(super::x86_64::HypPciTransport),
16}
17
18impl<'a> From<MmioTransport<'a>> for SomeTransport<'a> {
19    fn from(mmio: MmioTransport<'a>) -> Self {
20        Self::Mmio(mmio)
21    }
22}
23
24impl From<PciTransport> for SomeTransport<'_> {
25    fn from(pci: PciTransport) -> Self {
26        Self::Pci(pci)
27    }
28}
29
30impl Transport for SomeTransport<'_> {
31    fn device_type(&self) -> DeviceType {
32        match self {
33            Self::Mmio(mmio) => mmio.device_type(),
34            Self::Pci(pci) => pci.device_type(),
35            #[cfg(target_arch = "x86_64")]
36            Self::HypPci(pci) => pci.device_type(),
37        }
38    }
39
40    fn read_device_features(&mut self) -> u64 {
41        match self {
42            Self::Mmio(mmio) => mmio.read_device_features(),
43            Self::Pci(pci) => pci.read_device_features(),
44            #[cfg(target_arch = "x86_64")]
45            Self::HypPci(pci) => pci.read_device_features(),
46        }
47    }
48
49    fn write_driver_features(&mut self, driver_features: u64) {
50        match self {
51            Self::Mmio(mmio) => mmio.write_driver_features(driver_features),
52            Self::Pci(pci) => pci.write_driver_features(driver_features),
53            #[cfg(target_arch = "x86_64")]
54            Self::HypPci(pci) => pci.write_driver_features(driver_features),
55        }
56    }
57
58    fn max_queue_size(&mut self, queue: u16) -> u32 {
59        match self {
60            Self::Mmio(mmio) => mmio.max_queue_size(queue),
61            Self::Pci(pci) => pci.max_queue_size(queue),
62            #[cfg(target_arch = "x86_64")]
63            Self::HypPci(pci) => pci.max_queue_size(queue),
64        }
65    }
66
67    fn notify(&mut self, queue: u16) {
68        match self {
69            Self::Mmio(mmio) => mmio.notify(queue),
70            Self::Pci(pci) => pci.notify(queue),
71            #[cfg(target_arch = "x86_64")]
72            Self::HypPci(pci) => pci.notify(queue),
73        }
74    }
75
76    fn get_status(&self) -> DeviceStatus {
77        match self {
78            Self::Mmio(mmio) => mmio.get_status(),
79            Self::Pci(pci) => pci.get_status(),
80            #[cfg(target_arch = "x86_64")]
81            Self::HypPci(pci) => pci.get_status(),
82        }
83    }
84
85    fn set_status(&mut self, status: DeviceStatus) {
86        match self {
87            Self::Mmio(mmio) => mmio.set_status(status),
88            Self::Pci(pci) => pci.set_status(status),
89            #[cfg(target_arch = "x86_64")]
90            Self::HypPci(pci) => pci.set_status(status),
91        }
92    }
93
94    fn set_guest_page_size(&mut self, guest_page_size: u32) {
95        match self {
96            Self::Mmio(mmio) => mmio.set_guest_page_size(guest_page_size),
97            Self::Pci(pci) => pci.set_guest_page_size(guest_page_size),
98            #[cfg(target_arch = "x86_64")]
99            Self::HypPci(pci) => pci.set_guest_page_size(guest_page_size),
100        }
101    }
102
103    fn requires_legacy_layout(&self) -> bool {
104        match self {
105            Self::Mmio(mmio) => mmio.requires_legacy_layout(),
106            Self::Pci(pci) => pci.requires_legacy_layout(),
107            #[cfg(target_arch = "x86_64")]
108            Self::HypPci(pci) => pci.requires_legacy_layout(),
109        }
110    }
111
112    fn queue_set(
113        &mut self,
114        queue: u16,
115        size: u32,
116        descriptors: PhysAddr,
117        driver_area: PhysAddr,
118        device_area: PhysAddr,
119    ) {
120        match self {
121            Self::Mmio(mmio) => mmio.queue_set(queue, size, descriptors, driver_area, device_area),
122            Self::Pci(pci) => pci.queue_set(queue, size, descriptors, driver_area, device_area),
123            #[cfg(target_arch = "x86_64")]
124            Self::HypPci(pci) => pci.queue_set(queue, size, descriptors, driver_area, device_area),
125        }
126    }
127
128    fn queue_unset(&mut self, queue: u16) {
129        match self {
130            Self::Mmio(mmio) => mmio.queue_unset(queue),
131            Self::Pci(pci) => pci.queue_unset(queue),
132            #[cfg(target_arch = "x86_64")]
133            Self::HypPci(pci) => pci.queue_unset(queue),
134        }
135    }
136
137    fn queue_used(&mut self, queue: u16) -> bool {
138        match self {
139            Self::Mmio(mmio) => mmio.queue_used(queue),
140            Self::Pci(pci) => pci.queue_used(queue),
141            #[cfg(target_arch = "x86_64")]
142            Self::HypPci(pci) => pci.queue_used(queue),
143        }
144    }
145
146    fn ack_interrupt(&mut self) -> InterruptStatus {
147        match self {
148            Self::Mmio(mmio) => mmio.ack_interrupt(),
149            Self::Pci(pci) => pci.ack_interrupt(),
150            #[cfg(target_arch = "x86_64")]
151            Self::HypPci(pci) => pci.ack_interrupt(),
152        }
153    }
154
155    fn read_config_generation(&self) -> u32 {
156        match self {
157            Self::Mmio(mmio) => mmio.read_config_generation(),
158            Self::Pci(pci) => pci.read_config_generation(),
159            #[cfg(target_arch = "x86_64")]
160            Self::HypPci(pci) => pci.read_config_generation(),
161        }
162    }
163
164    fn read_config_space<T: FromBytes + IntoBytes>(&self, offset: usize) -> Result<T> {
165        match self {
166            Self::Mmio(mmio) => mmio.read_config_space(offset),
167            Self::Pci(pci) => pci.read_config_space(offset),
168            #[cfg(target_arch = "x86_64")]
169            Self::HypPci(pci) => pci.read_config_space(offset),
170        }
171    }
172
173    fn write_config_space<T: IntoBytes + Immutable>(
174        &mut self,
175        offset: usize,
176        value: T,
177    ) -> Result<()> {
178        match self {
179            Self::Mmio(mmio) => mmio.write_config_space(offset, value),
180            Self::Pci(pci) => pci.write_config_space(offset, value),
181            #[cfg(target_arch = "x86_64")]
182            Self::HypPci(pci) => pci.write_config_space(offset, value),
183        }
184    }
185}