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