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}