virtio/transports/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
5//! VirtIO transports.
6//!
7//! This module and its submodules provide abstractions for and implementations
8//! of VirtIO transports. For more information, see the documentation of the
9//! [`VirtIOTransport`] trait.
10
11use kernel::ErrorCode;
12
13use super::devices::{VirtIODeviceDriver, VirtIODeviceType};
14use super::queues::Virtqueue;
15
16pub mod mmio;
17
18#[derive(Debug, Copy, Clone)]
19pub enum VirtIOInitializationError {
20 /// Device does not identify itself or can be recognized as a VirtIO device.
21 NotAVirtIODevice,
22 /// An unknown or incompatible VirtIO standard version.
23 InvalidVirtIOVersion,
24 /// An unknown or incompatible VirtIO transport device version.
25 InvalidTransportVersion,
26 /// Unknown VirtIO device type (as defined by the [`VirtIODeviceType`] enum).
27 UnknownDeviceType(u32),
28 /// Driver does not support driving the recognized device type.
29 IncompatibleDriverDeviceType(VirtIODeviceType),
30 /// Feature negotiation between the device and transport + device driver has
31 /// failed.
32 ///
33 /// The device offered the `offered` features, the driver has either not
34 /// accepted this feature set `accepted == None` or has responded with the
35 /// `accepted` feature bitset, which the device has subsequently not
36 /// acknowledged.
37 FeatureNegotiationFailed { offered: u64, accepted: Option<u64> },
38 /// The requested [`Virtqueue`] with respective index is not available with
39 /// this VirtIO device.
40 VirtqueueNotAvailable(usize),
41 /// An error was reported by the
42 /// [`VirtIODeviceDriver::pre_device_initialization`] function. The device
43 /// has been put into the `FAILED` state.
44 DriverPreInitializationError(ErrorCode),
45 /// An error was reported by the [`VirtIODeviceDriver::device_initialized`]
46 /// function. The device status has been previously indicated as `DRIVER_OK`
47 /// and the transport has **NOT** put it into the `FAILED` state, although
48 /// the driver might have. The initialization has continued as usual,
49 /// despite reporting this error, hence it also carries the device type.
50 DriverInitializationError(VirtIODeviceType, ErrorCode),
51 /// An invariant was violated by the device. This error should not occur
52 /// assuming a compliant device, transport and driver implementation.
53 DeviceError,
54}
55
56/// VirtIO transports.
57///
58/// VirtIO can be used over multiple different transports, such as over a PCI
59/// bus, an MMIO device or channel IO. This trait provides a basic abstraction
60/// over such transports.
61pub trait VirtIOTransport {
62 /// Initialize the VirtIO transport using a device driver instance.
63 ///
64 /// This function is expected to run the basic initialization routine as
65 /// defined for the various VirtIO transports. As part of this routine, it
66 /// shall
67 ///
68 /// - negotiate device features,
69 /// - invoke the driver `pre_device_initialization` hook before and
70 /// `device_initialized` hook after announcing the `DRIVER_OK` device
71 /// status flag to the device,
72 /// - register the passed [`Virtqueue`]s with the device, calling the
73 /// [`Virtqueue::initialize`] function with the registered queue ID
74 /// _before_ registration,
75 /// - as well as perform any other required initialization of the VirtIO
76 /// transport.
77 ///
78 /// The passed [`Virtqueue`]s are registered with a queue ID matching their
79 /// offset in the supplied slice.
80 ///
81 /// If the initialization fails, it shall report this condition to the
82 /// device _(setting `FAILED`) if_ it has started initializing the device
83 /// (setting the `ACKNOWLEDGE` device status flag), and return an
84 /// appropriate [`VirtIOInitializationError`]. Otherwise, it shall return
85 /// the type of device connected to this VirtIO transport.
86 fn initialize(
87 &self,
88 driver: &dyn VirtIODeviceDriver,
89 queues: &'static [&'static dyn Virtqueue],
90 ) -> Result<VirtIODeviceType, VirtIOInitializationError>;
91
92 /// Notify the device of a changed [`Virtqueue`].
93 ///
94 /// Whenever a queue has been updated (e.g. move descriptors from the used
95 /// to available ring) and these updates shall be made visible to the
96 /// driver, the queue can invoke this function, passing its own respective
97 /// queue ID.
98 fn queue_notify(&self, queue_id: u32);
99}