virtio_spec/
driver_notifications.rs

1use bitfield_struct::bitfield;
2
3use crate::le32;
4
5/// Notification Data.
6#[bitfield(u32, repr = le32, from = le32::from_ne, into = le32::to_ne)]
7pub struct NotificationData {
8    /// VQ number to be notified.
9    pub vqn: u16,
10
11    /// Offset
12    /// within the ring where the next available ring entry
13    /// will be written.
14    /// When [`VIRTIO_F_RING_PACKED`] has not been negotiated this refers to the
15    /// 15 least significant bits of the available index.
16    /// When `VIRTIO_F_RING_PACKED` has been negotiated this refers to the offset
17    /// (in units of descriptor entries)
18    /// within the descriptor ring where the next available
19    /// descriptor will be written.
20    ///
21    /// [`VIRTIO_F_RING_PACKED`]: F::RING_PACKED
22    #[bits(15)]
23    pub next_off: u16,
24
25    /// Wrap Counter.
26    /// With [`VIRTIO_F_RING_PACKED`] this is the wrap counter
27    /// referring to the next available descriptor.
28    /// Without `VIRTIO_F_RING_PACKED` this is the most significant bit
29    /// (bit 15) of the available index.
30    ///
31    /// [`VIRTIO_F_RING_PACKED`]: F::RING_PACKED
32    #[bits(1)]
33    pub next_wrap: u8,
34}
35
36impl NotificationData {
37    const NEXT_IDX_BITS: usize = 16;
38    const NEXT_IDX_OFFSET: usize = 16;
39
40    /// Available index
41    ///
42    /// <div class="warning">
43    ///
44    /// This collides with [`Self::next_off`] and [`Self::next_wrap`].
45    ///
46    /// </div>
47    ///
48    /// Bits: 16..32
49    pub const fn next_idx(&self) -> u16 {
50        let mask = u32::MAX >> (u32::BITS - Self::NEXT_IDX_BITS as u32);
51        let this = (le32::to_ne(self.0) >> Self::NEXT_IDX_OFFSET) & mask;
52        this as u16
53    }
54
55    /// Available index
56    ///
57    /// <div class="warning">
58    ///
59    /// This collides with [`Self::with_next_off`] and [`Self::with_next_wrap`].
60    ///
61    /// </div>
62    ///
63    /// Bits: 16..32
64    pub const fn with_next_idx(self, value: u16) -> Self {
65        let mask = u32::MAX >> (u32::BITS - Self::NEXT_IDX_BITS as u32);
66        let bits = le32::to_ne(self.0) & !(mask << Self::NEXT_IDX_OFFSET)
67            | (value as u32 & mask) << Self::NEXT_IDX_OFFSET;
68        Self(le32::from_ne(bits))
69    }
70
71    /// Available index
72    ///
73    /// <div class="warning">
74    ///
75    /// This collides with [`Self::set_next_off`] and [`Self::set_next_wrap`].
76    ///
77    /// </div>
78    ///
79    /// Bits: 16..32
80    pub fn set_next_idx(&mut self, value: u16) {
81        *self = self.with_next_idx(value);
82    }
83}