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}