virtio/devices/
mod.rs

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