virtio_driver/common/device_status.rs
1// Copyright 2026 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use bitfield::bitfield;
6
7bitfield! {
8 /// Modified by both the driver and the device during lifecycle transitions.
9 ///
10 /// The bits are intended to represent stages in the device + driver
11 /// lifecycle. After a device is reset, the value is guaranteed to be
12 /// [`DeviceStatus::RESET`].
13 ///
14 /// With the exception of resetting the device, the driver must not clear
15 /// (write 0 to) a bit that is set (to 1).
16 // @cite(virtio): sec="2.1" title="Device Status Field"
17 // @cite(virtio): sec="2.4" title="Device Reset"
18 // @cite(virtio): sec="3" title="General Initialization And Device Operation"
19 #[derive(Default, Copy, Clone, PartialEq, Eq)]
20 #[repr(transparent)]
21 pub struct DeviceStatus(u8);
22 impl Debug;
23
24 /// True iff the driver recognized the hardware as a virtio device.
25 ///
26 /// Set to true (1) by the driver in step 2 of device initialization.
27 ///
28 /// The specification recommends that the virtualized operating system sets
29 /// this bit. Fuchsia does not special-case virtio devices, so this bit is
30 /// set by Fuchsia drivers.
31 // @cite(virtio): sec="2.1" title="Device Status Field" bits=0
32 // @cite(virtio): sec="3.1.1" title="Driver Requirements: Device Initialization"
33 // @alias(virtio): theirs="ACKNOWLEDGE"
34 pub bool, virtio_device_detected, set_virtio_device_detected: 0;
35
36 /// True iff the guest OS has found a driver for the device.
37 ///
38 /// Set to true (1) by the driver in step 3 of device initialization. Fuchsia
39 /// does not special-case virtio devices, so the driver must perform this
40 /// step.
41 ///
42 /// The driver may only read the feature bits offered by the device after
43 /// setting this bit to true.
44 // @cite(virtio): sec="2.1" title="Device Status Field" bits=1
45 // @cite(virtio): sec="3.1.1" title="Driver Requirements: Device Initialization"
46 // @alias(virtio): theirs="DRIVER"
47 pub bool, driver_found, set_driver_found: 1;
48
49 /// True iff the driver is sufficiently initialized to drive the device.
50 ///
51 /// Set to true (1) by the driver in step 8 of device initialization.
52 ///
53 /// The driver must only set this bit to true after it has completed the
54 /// device-specific initialization process.
55 ///
56 /// The driver may only operate the device's virtqueues while this bit is
57 /// set to true (1).
58 // @cite(virtio): sec="2.1" title="Device Status Field" bits=2
59 // @cite(virtio): sec="3.1.1" title="Driver Requirements: Device Initialization"
60 // @alias(virtio): theirs="DRIVER_OK"
61 pub bool, driver_initialized, set_driver_initialized: 2;
62
63 /// True iff the feature negotiation is complete.
64 ///
65 /// Set to true (1) by the driver in step 5 of device initialization.
66 ///
67 /// The driver must only set this bit to true after it has acknowledged all
68 /// the features it understands.
69 // @cite(virtio): sec="2.1" title="Device Status Field" bits=3
70 // @cite(virtio): sec="3.1.1" title="Driver Requirements: Device Initialization"
71 // @alias(virtio): theirs="FEATURES_OK"
72 pub bool, feature_negotiation_complete, set_feature_negotiation_complete: 3;
73
74 /// True iff the device has been suspended by the driver.
75 ///
76 /// The driver triggers device suspension by setting this bit to true (1).
77 /// The device sets the [`driver_initialized`] bit to false (0) after the
78 /// device completes suspending.
79 ///
80 /// The driver triggers resuming a suspended device by setting the
81 /// [`driver_initialized`] bit to true (1). The device sets this bit to
82 /// false (0) after the device completes resuming.
83 ///
84 /// The driver is only allowed to set this bit if
85 /// [`VirtioFeatureBits::suspend_enabled`] is negotiated.
86 // @cite(virtio): sec="2.1" title="Device Status Field" bits=4
87 // @cite(virtio): sec="3.4" title="Device Suspend"
88 // @alias(virtio): theirs="SUSPEND"
89 pub bool, suspended, set_suspended: 4;
90
91 /// True iff the device has experienced an unrecoverable error.
92 ///
93 /// The device sends a configuration change notification when setting this
94 /// bit to true (1). The driver cannot assume that virtqueue operations will
95 /// complete (or, conversely, that the operations will be dropped) while
96 /// this bit is set.
97 // @cite(virtio): sec="2.1" title="Device Status Field" bits=6
98 // @alias(virtio): theirs="DEVICE_NEEDS_RESET"
99 pub bool, device_needs_reset, set_device_needs_reset: 6;
100
101 /// True iff the driver has experienced an unrecoverable error.
102 ///
103 /// The driver sets this bit when it gives up on driving the device.
104 // @cite(virtio): sec="2.1" title="Device Status Field" bits=7
105 // @alias(virtio): theirs="FAILED"
106 pub bool, driver_terminated, set_driver_terminated: 7;
107}
108
109impl DeviceStatus {
110 /// The status value that indicates the device has been reset.
111 // @cite(virtio): sec="2.4" title="Device Reset"
112 pub const RESET: DeviceStatus = DeviceStatus(0);
113}
114
115#[cfg(test)]
116mod tests {
117 use super::*;
118
119 #[fuchsia::test]
120 fn test_device_status() {
121 let mut status = DeviceStatus(0);
122 assert!(!status.virtio_device_detected());
123 status.set_virtio_device_detected(true);
124 assert!(status.virtio_device_detected());
125 assert_eq!(status.0, 1);
126 }
127
128 #[fuchsia::test]
129 fn test_device_status_debug() {
130 let mut status = DeviceStatus(0);
131 status.set_virtio_device_detected(true);
132 let debug_str = format!("{:?}", status);
133 assert_eq!(
134 debug_str,
135 "DeviceStatus { .0: 1, virtio_device_detected: true, driver_found: false, driver_initialized: false, feature_negotiation_complete: false, suspended: false, device_needs_reset: false, driver_terminated: false }"
136 );
137
138 let mut status3 = DeviceStatus(0);
139 status3.set_virtio_device_detected(true);
140 status3.set_driver_found(true);
141 status3.set_driver_initialized(true);
142 let debug_str3 = format!("{:?}", status3);
143 assert_eq!(
144 debug_str3,
145 "DeviceStatus { .0: 7, virtio_device_detected: true, driver_found: true, driver_initialized: true, feature_negotiation_complete: false, suspended: false, device_needs_reset: false, driver_terminated: false }"
146 );
147 }
148}