virtio/devices/mod.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
// Licensed under the Apache License, Version 2.0 or the MIT License.
// SPDX-License-Identifier: Apache-2.0 OR MIT
// Copyright Tock Contributors 2022.
use kernel::ErrorCode;
pub mod virtio_net;
pub mod virtio_rng;
/// VirtIO Device Types.
///
/// VirtIO is a flexible bus which can be used to expose various kinds of
/// virtual devices, such as network drivers, serial consoles, block devices or
/// random number generators. A VirtIO bus endpoint announces which type of
/// device it represents (and hence also which rules and semantics the VirtIO
/// driver should follow).
///
/// This enum maps the VirtIO device IDs to human-readable variants of an enum,
/// which can be used throughout the code base. Users should not rely on this
/// enum not being extended. Whenever an official device ID is missing, it can
/// be added to this enumeration.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[repr(u32)]
#[non_exhaustive]
pub enum VirtIODeviceType {
NetworkCard = 1,
BlockDevice = 2,
Console = 3,
EntropySource = 4,
TraditionalMemoryBallooning = 5,
IoMemory = 6,
RPMSG = 7,
SCSIHost = 8,
Transport9P = 9,
Mac80211Wlan = 10,
RPROCSerial = 11,
VirtIOCAIF = 12,
MemoryBalloon = 13,
GPUDevice = 14,
TimerClockDevice = 15,
InputDevice = 16,
SocketDevice = 17,
CryptoDevice = 18,
SignalDistributionModule = 19,
PstoreDevice = 20,
IOMMUDevice = 21,
MemoryDevice = 22,
}
impl VirtIODeviceType {
/// Try to create a [`VirtIODeviceType`] enum variant from a supplied
/// numeric device ID.
pub fn from_device_id(id: u32) -> Option<VirtIODeviceType> {
use VirtIODeviceType as DT;
match id {
1 => Some(DT::NetworkCard),
2 => Some(DT::BlockDevice),
3 => Some(DT::Console),
4 => Some(DT::EntropySource),
5 => Some(DT::TraditionalMemoryBallooning),
6 => Some(DT::IoMemory),
7 => Some(DT::RPMSG),
8 => Some(DT::SCSIHost),
9 => Some(DT::Transport9P),
10 => Some(DT::Mac80211Wlan),
11 => Some(DT::RPROCSerial),
12 => Some(DT::VirtIOCAIF),
13 => Some(DT::MemoryBalloon),
14 => Some(DT::GPUDevice),
15 => Some(DT::TimerClockDevice),
16 => Some(DT::InputDevice),
17 => Some(DT::SocketDevice),
18 => Some(DT::CryptoDevice),
19 => Some(DT::SignalDistributionModule),
20 => Some(DT::PstoreDevice),
21 => Some(DT::IOMMUDevice),
22 => Some(DT::MemoryDevice),
_ => None,
}
}
/// Convert a [`VirtIODeviceType`] variant to its corresponding device ID.
pub fn to_device_id(device_type: VirtIODeviceType) -> u32 {
device_type as u32
}
}
/// VirtIO Device Driver.
///
/// This trait is to be implemented by drivers for exposed VirtIO devices, using
/// the transports provided in [`crate::transports`] and queues in
/// [`crate::queues`] to communicate with VirtIO devices.
pub trait VirtIODeviceDriver {
/// VirtIO feature negotiation.
///
/// This function is passed all driver-specific feature bits which the
/// device exposes. Based on this function, the driver can select which
/// features to enable through the return value of this function. This
/// function is executed through the VirtIO transport, potentially before
/// the device is initialized. As such, implementations of this function
/// should be pure and only depend on the `offered_features` input
/// parameter.
fn negotiate_features(&self, offered_features: u64) -> Option<u64>;
/// VirtIO device type which the driver supports.
///
/// This function must return the VirtIO device type that the driver is able
/// to drive. Implementations of this function must be pure and return a
/// constant value.
fn device_type(&self) -> VirtIODeviceType;
/// Hook called before the transport indicates `DRIVER_OK` to the device.
///
/// Because this trait must be object safe, a device cannot convey arbitrary
/// errors through this interface. When this function returns an error, the
/// transport will indicate `FAILED` to the device and return the error to
/// the caller of
/// [`VirtIOTransport::initialize`](super::transports::VirtIOTransport::initialize).
/// The driver can store a more elaborate error internally and expose it
/// through a custom interface.
///
/// A default implementation of this function is provided which does nothing
/// and returns `Ok(())`.
fn pre_device_initialization(&self) -> Result<(), ErrorCode> {
Ok(())
}
/// Hook called after the transport indicated `DRIVER_OK` to the device.
///
/// Because this trait must be object safe, a device cannot convey arbitrary
/// errors through this interface. When this function returns an error, the
/// transport will **NOT** indicate `FAILED` to the device, but return the
/// error to the caller of
/// [`VirtIOTransport::initialize`](super::transports::VirtIOTransport::initialize).
/// The driver can store a more elaborate error internally and expose it
/// through a custom interface. The driver remains responsible for any
/// deinitialization of the device as a result of this error.
///
/// A default implementation of this function is provided which does nothing
/// and returns `Ok(())`.
fn device_initialized(&self) -> Result<(), ErrorCode> {
Ok(())
}
}