1use bitfield_struct::bitfield;
7use inspect::Inspect;
8use zerocopy::FromBytes;
9use zerocopy::Immutable;
10use zerocopy::IntoBytes;
11use zerocopy::KnownLayout;
12
13pub use packed_nums::*;
14
15#[expect(non_camel_case_types)]
16mod packed_nums {
17 pub type u16_le = zerocopy::U16<zerocopy::LittleEndian>;
18 pub type u32_le = zerocopy::U32<zerocopy::LittleEndian>;
19 pub type u64_le = zerocopy::U64<zerocopy::LittleEndian>;
20}
21
22#[bitfield(u32)]
23#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
24pub struct VirtioDeviceFeaturesBank0 {
25 #[bits(24)]
26 pub device_specific: u32,
27 #[bits(4)]
28 _reserved1: u8,
29 pub ring_indirect_desc: bool, pub ring_event_idx: bool, #[bits(2)]
32 _reserved2: u8,
33}
34
35#[bitfield(u32)]
36#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
37pub struct VirtioDeviceFeaturesBank1 {
38 pub version_1: bool, pub access_platform: bool, pub ring_packed: bool, pub in_order: bool, pub order_platform: bool, pub sriov: bool, pub notification_data: bool, pub notif_config_data: bool, pub ring_reset: bool, pub admin_vq: bool, pub device_specific_bit_42: bool,
49 pub suspend: bool, #[bits(7)]
51 _reserved: u8,
52 #[bits(13)]
53 pub device_specific: u16,
54}
55
56#[derive(Debug, Clone)]
57pub struct VirtioDeviceFeatures(Vec<u32>);
58impl VirtioDeviceFeatures {
59 pub fn new() -> Self {
60 Self(Vec::with_capacity(2))
61 }
62
63 pub fn len(&self) -> usize {
64 self.0.len()
65 }
66
67 pub fn set_bank(&mut self, index: usize, val: u32) {
68 if self.0.len() <= index {
69 self.0.resize(index + 1, 0);
70 }
71 self.0[index] = val;
72 }
73
74 pub fn with_bank(mut self, index: usize, val: u32) -> Self {
75 self.set_bank(index, val);
76 self
77 }
78
79 pub fn with_bank0(self, bank0: VirtioDeviceFeaturesBank0) -> Self {
80 self.with_bank(0, bank0.into_bits())
81 }
82
83 pub fn with_bank1(self, bank1: VirtioDeviceFeaturesBank1) -> Self {
84 self.with_bank(1, bank1.into_bits())
85 }
86
87 pub fn bank(&self, index: usize) -> u32 {
88 self.0.get(index).map_or(0, |x| *x)
89 }
90
91 pub fn bank0(&self) -> VirtioDeviceFeaturesBank0 {
92 VirtioDeviceFeaturesBank0::from_bits(self.bank(0))
93 }
94
95 pub fn bank1(&self) -> VirtioDeviceFeaturesBank1 {
96 VirtioDeviceFeaturesBank1::from_bits(self.bank(1))
97 }
98}
99
100impl Default for VirtioDeviceFeatures {
101 fn default() -> Self {
102 Self::new()
103 }
104}
105
106#[bitfield(u8)]
107#[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Inspect)]
108pub struct VirtioDeviceStatus {
109 pub acknowledge: bool,
110 pub driver: bool,
111 pub driver_ok: bool,
112 pub features_ok: bool,
113 pub suspend: bool,
114 _reserved1: bool,
115 pub device_needs_reset: bool,
116 pub failed: bool,
117}
118
119impl VirtioDeviceStatus {
120 pub fn as_u32(&self) -> u32 {
121 self.into_bits() as u32
122 }
123}
124
125pub const VIRTIO_MMIO_INTERRUPT_STATUS_USED_BUFFER: u32 = 1;
127pub const VIRTIO_MMIO_INTERRUPT_STATUS_CONFIG_CHANGE: u32 = 2;
128
129pub mod pci {
131 use open_enum::open_enum;
132
133 open_enum! {
134 pub enum VirtioPciCapType: u8 {
136 COMMON_CFG = 1,
137 NOTIFY_CFG = 2,
138 ISR_CFG = 3,
139 DEVICE_CFG = 4,
140 SHARED_MEMORY_CFG = 8,
142 }
143 }
144
145 pub const VIRTIO_VENDOR_ID: u16 = 0x1af4;
146 pub const VIRTIO_PCI_DEVICE_ID_BASE: u16 = 0x1040;
147
148 open_enum! {
149 pub enum VirtioPciCommonCfg: u16 {
152 DEVICE_FEATURE_SELECT = 0,
153 DEVICE_FEATURE = 4,
154 DRIVER_FEATURE_SELECT = 8,
155 DRIVER_FEATURE = 12,
156 MSIX_CONFIG = 16,
157 DEVICE_STATUS = 20,
158 QUEUE_SIZE = 24,
159 QUEUE_ENABLE = 28,
160 QUEUE_DESC_LO = 32,
161 QUEUE_DESC_HI = 36,
162 QUEUE_AVAIL_LO = 40,
163 QUEUE_AVAIL_HI = 44,
164 QUEUE_USED_LO = 48,
165 QUEUE_USED_HI = 52,
166 }
167 }
168
169 pub const VIRTIO_PCI_COMMON_CFG_SIZE: u16 = 56;
171}
172
173pub mod mmio {
175 use open_enum::open_enum;
176
177 open_enum! {
178 pub enum VirtioMmioRegister: u16 {
180 MAGIC_VALUE = 0x000,
181 VERSION = 0x004,
182 DEVICE_ID = 0x008,
183 VENDOR_ID = 0x00c,
184 DEVICE_FEATURES = 0x010,
185 DEVICE_FEATURES_SEL = 0x014,
186 DRIVER_FEATURES = 0x020,
187 DRIVER_FEATURES_SEL = 0x024,
188 QUEUE_SEL = 0x030,
189 QUEUE_NUM_MAX = 0x034,
190 QUEUE_NUM = 0x038,
191 QUEUE_READY = 0x044,
192 QUEUE_NOTIFY = 0x050,
193 INTERRUPT_STATUS = 0x060,
194 INTERRUPT_ACK = 0x064,
195 STATUS = 0x070,
196 QUEUE_DESC_LOW = 0x080,
197 QUEUE_DESC_HIGH = 0x084,
198 QUEUE_AVAIL_LOW = 0x090,
199 QUEUE_AVAIL_HIGH = 0x094,
200 QUEUE_USED_LOW = 0x0a0,
201 QUEUE_USED_HIGH = 0x0a4,
202 CONFIG_GENERATION = 0x0fc,
203 CONFIG = 0x100,
204 }
205 }
206}
207
208pub mod queue {
210 use super::u16_le;
211 use super::u32_le;
212 use super::u64_le;
213 use bitfield_struct::bitfield;
214
215 use zerocopy::FromBytes;
216 use zerocopy::Immutable;
217 use zerocopy::IntoBytes;
218 use zerocopy::KnownLayout;
219
220 #[repr(C)]
221 #[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
222 pub struct SplitDescriptor {
223 pub address: u64_le,
224 pub length: u32_le,
225 pub flags_raw: u16_le,
226 pub next: u16_le,
227 }
228
229 impl SplitDescriptor {
230 pub fn flags(&self) -> DescriptorFlags {
231 self.flags_raw.get().into()
232 }
233 }
234
235 #[bitfield(u16)]
236 #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
237 pub struct DescriptorFlags {
238 pub next: bool,
239 pub write: bool,
240 pub indirect: bool,
241 #[bits(13)]
242 _reserved: u16,
243 }
244
245 pub const AVAIL_OFFSET_FLAGS: u64 = 0;
254 pub const AVAIL_OFFSET_IDX: u64 = 2;
255 pub const AVAIL_OFFSET_RING: u64 = 4;
256 pub const AVAIL_ELEMENT_SIZE: u64 = size_of::<u16>() as u64;
257
258 #[bitfield(u16)]
259 pub struct AvailableFlags {
260 pub no_interrupt: bool,
261 #[bits(15)]
262 _reserved: u16,
263 }
264
265 pub const USED_OFFSET_FLAGS: u64 = 0;
274 pub const USED_OFFSET_IDX: u64 = 2;
275 pub const USED_OFFSET_RING: u64 = 4;
276 pub const USED_ELEMENT_SIZE: u64 = size_of::<UsedElement>() as u64;
277
278 #[repr(C)]
279 #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
280 pub struct UsedElement {
281 pub id: u32_le,
282 pub len: u32_le,
283 }
284
285 #[bitfield(u16)]
286 pub struct UsedFlags {
287 pub no_notify: bool,
288 #[bits(15)]
289 _reserved: u16,
290 }
291}