1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//! Write virtio devices in Rust.
//!
//! This crate provides utilities for virtio devices to manipulate descriptor rings. Only the device
//! side is targeted, and this crate is completely unsuitable, and not intended, for writing
//! drivers.
//!
//! The provided wrappers are built up in a series of layers, each providing a higher level and more
//! convenient interface, at the cost of injecting some policy opinions for managing the rings. The
//! layers/modules are:
//! - [`chain`] High level iteration and walking of descriptor chains as series of byte ranges
//!   including manipulation through [`std::io::read`] and [`std::io::write`] interfaces.
//! - [`queue`] Provides functional virt queue management allowing for descriptor chains to be
//!   retrieved, iterated and returned.
//! - [`ring`] Provides the barest minimum Rust type safety over accessing the rings.
//!   This is not expected to generally be needed, with [`queue`] completely hiding all [`ring`]
//!   details.
//! There are some additional modules providing:
//! - [`mem`] Definitions for memory translation between drivers and devices.
//! - [`util`] Small wrappers and trait implementations that are commonly useful, but very
//!   opinionated.
//! - [`fake_queue`] Helpers for writing unittests against virtio devices.
//!
//! What this crate does not provide is any transport or device type specific management. The user
//! then is responsible for performing all setup and feature negotiation prior to using this crate
//! to manage the negotiated queues. The user therefore needs to provide:
//! - Location of negotiated desc, used and avail rings as [`mem::DeviceRange`] definitions.
//! - Implementation of [`mem::DriverMem`] for driver to device memory address translation.
//! - Implementation of [`queue::DriverNotify`] for signaling the driver.
//! - A way to receive signals from the driver to know when to check for descriptors.
//!
//! With these pieces existing a typical usage of this crate is expected to be:
//! - Construct a [`queue::Queue`] by passing the ring definitions to [`queue::Queue::new`]
//! - Build a [`util::DescChainStream`] from the [`queue::Queue`] and connect the
//!   [`util::DescChainStream::waker`]
//! - Construct  [`chain::ReadableChain`] or [`chain::WritableChain`] from the [`queue::DescChain`]
//!   items generated by the [`util::DescChainStream`]
//! - Process the [`chain::ReadableChain`] or [`chain::WritableChain`] using their provided methods
//!   or the [`std::io::read`] and [`std::io::write`] trait implementations.
//! - Explicitly [return](chain::ReadableChain::return_complete) the chain or let it `drop` to have
//!   the [`queue::Queue`] return it to the driver.
//!
//! Commonly if expecting to process descriptors chains in batches you will also want to wrap your
//! [`queue::DriverNotify`] in a [`util::BufferedNotify`], but you must ensure to call
//! [`util::BufferedNotify::flush`].

pub mod chain;
pub mod fake_queue;
pub mod mem;
pub mod queue;
pub mod ring;
pub mod util;