Skip to main content

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