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}