virtio_drivers/transport/
mod.rs#[cfg(test)]
pub mod fake;
pub mod mmio;
pub mod pci;
mod some;
use crate::{PhysAddr, Result, PAGE_SIZE};
use bitflags::{bitflags, Flags};
use core::{fmt::Debug, ops::BitAnd};
use log::debug;
pub use some::SomeTransport;
use zerocopy::{FromBytes, IntoBytes};
pub trait Transport {
fn device_type(&self) -> DeviceType;
fn read_device_features(&mut self) -> u64;
fn write_driver_features(&mut self, driver_features: u64);
fn max_queue_size(&mut self, queue: u16) -> u32;
fn notify(&mut self, queue: u16);
fn get_status(&self) -> DeviceStatus;
fn set_status(&mut self, status: DeviceStatus);
fn set_guest_page_size(&mut self, guest_page_size: u32);
fn requires_legacy_layout(&self) -> bool;
fn queue_set(
&mut self,
queue: u16,
size: u32,
descriptors: PhysAddr,
driver_area: PhysAddr,
device_area: PhysAddr,
);
fn queue_unset(&mut self, queue: u16);
fn queue_used(&mut self, queue: u16) -> bool;
fn ack_interrupt(&mut self) -> bool;
fn begin_init<F: Flags<Bits = u64> + BitAnd<Output = F> + Debug>(
&mut self,
supported_features: F,
) -> F {
self.set_status(DeviceStatus::empty());
self.set_status(DeviceStatus::ACKNOWLEDGE | DeviceStatus::DRIVER);
let device_features = F::from_bits_truncate(self.read_device_features());
debug!("Device features: {:?}", device_features);
let negotiated_features = device_features & supported_features;
self.write_driver_features(negotiated_features.bits());
self.set_status(
DeviceStatus::ACKNOWLEDGE | DeviceStatus::DRIVER | DeviceStatus::FEATURES_OK,
);
self.set_guest_page_size(PAGE_SIZE as u32);
negotiated_features
}
fn finish_init(&mut self) {
self.set_status(
DeviceStatus::ACKNOWLEDGE
| DeviceStatus::DRIVER
| DeviceStatus::FEATURES_OK
| DeviceStatus::DRIVER_OK,
);
}
fn read_config_space<T: FromBytes>(&self, offset: usize) -> Result<T>;
fn write_config_space<T: IntoBytes>(&mut self, offset: usize, value: T) -> Result<()>;
}
bitflags! {
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
pub struct DeviceStatus: u32 {
const ACKNOWLEDGE = 1;
const DRIVER = 2;
const FAILED = 128;
const FEATURES_OK = 8;
const DRIVER_OK = 4;
const DEVICE_NEEDS_RESET = 64;
}
}
#[repr(u8)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[allow(missing_docs)]
pub enum DeviceType {
Invalid = 0,
Network = 1,
Block = 2,
Console = 3,
EntropySource = 4,
MemoryBallooning = 5,
IoMemory = 6,
Rpmsg = 7,
ScsiHost = 8,
_9P = 9,
Mac80211 = 10,
RprocSerial = 11,
VirtioCAIF = 12,
MemoryBalloon = 13,
GPU = 16,
Timer = 17,
Input = 18,
Socket = 19,
Crypto = 20,
SignalDistributionModule = 21,
Pstore = 22,
IOMMU = 23,
Memory = 24,
Sound = 25,
}
impl From<u32> for DeviceType {
fn from(virtio_device_id: u32) -> Self {
match virtio_device_id {
1 => DeviceType::Network,
2 => DeviceType::Block,
3 => DeviceType::Console,
4 => DeviceType::EntropySource,
5 => DeviceType::MemoryBalloon,
6 => DeviceType::IoMemory,
7 => DeviceType::Rpmsg,
8 => DeviceType::ScsiHost,
9 => DeviceType::_9P,
10 => DeviceType::Mac80211,
11 => DeviceType::RprocSerial,
12 => DeviceType::VirtioCAIF,
13 => DeviceType::MemoryBalloon,
16 => DeviceType::GPU,
17 => DeviceType::Timer,
18 => DeviceType::Input,
19 => DeviceType::Socket,
20 => DeviceType::Crypto,
21 => DeviceType::SignalDistributionModule,
22 => DeviceType::Pstore,
23 => DeviceType::IOMMU,
24 => DeviceType::Memory,
25 => DeviceType::Sound,
_ => DeviceType::Invalid,
}
}
}
impl From<u16> for DeviceType {
fn from(virtio_device_id: u16) -> Self {
u32::from(virtio_device_id).into()
}
}
impl From<u8> for DeviceType {
fn from(virtio_device_id: u8) -> Self {
u32::from(virtio_device_id).into()
}
}