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}