Skip to main content

virtio_spec/
blk.rs

1//! Block Device
2
3use bitfield_struct::bitfield;
4use num_enum::{IntoPrimitive, TryFromPrimitive};
5use volatile::access::ReadOnly;
6use volatile_macro::VolatileFieldAccess;
7
8pub use super::features::blk::F;
9use crate::{le16, le32, le64};
10
11/// Block Device Configuration Layout
12///
13/// Use [`ConfigVolatileFieldAccess`] to work with this struct.
14#[doc(alias = "virtio_blk_config")]
15#[derive(VolatileFieldAccess)]
16#[repr(C)]
17pub struct Config {
18    #[access(ReadOnly)]
19    capacity: le64,
20
21    #[access(ReadOnly)]
22    size_max: le32,
23
24    #[access(ReadOnly)]
25    seg_max: le32,
26
27    #[access(ReadOnly)]
28    geometry: Geometry,
29
30    #[access(ReadOnly)]
31    blk_size: le32,
32
33    #[access(ReadOnly)]
34    topology: Topology,
35
36    #[access(ReadOnly)]
37    writeback: u8,
38
39    #[access(ReadOnly)]
40    unused0: u8,
41
42    #[access(ReadOnly)]
43    num_queues: u8,
44
45    #[access(ReadOnly)]
46    max_discard_sectors: le32,
47
48    #[access(ReadOnly)]
49    max_discard_seg: le32,
50
51    #[access(ReadOnly)]
52    discard_sector_alignment: le32,
53
54    #[access(ReadOnly)]
55    max_write_zeroes_sectors: le32,
56
57    #[access(ReadOnly)]
58    max_write_zeroes_seg: le32,
59
60    #[access(ReadOnly)]
61    write_zeroes_may_unmap: u8,
62
63    #[access(ReadOnly)]
64    unused1: [u8; 3],
65
66    #[access(ReadOnly)]
67    max_secure_erase_sectors: le32,
68
69    #[access(ReadOnly)]
70    max_secure_erase_seg: le32,
71
72    #[access(ReadOnly)]
73    secure_erase_sector_alignment: le32,
74
75    #[access(ReadOnly)]
76    zoned: ZonedCharacteristics,
77}
78
79/// Disk-style geometry.
80#[doc(alias = "virtio_blk_geometry")]
81#[derive(VolatileFieldAccess)]
82#[repr(C)]
83pub struct Geometry {
84    #[access(ReadOnly)]
85    cylinders: le16,
86
87    #[access(ReadOnly)]
88    heads: u8,
89
90    #[access(ReadOnly)]
91    sectors: u8,
92}
93
94/// Block device topology.
95#[doc(alias = "virtio_blk_topology")]
96#[derive(VolatileFieldAccess)]
97#[repr(C)]
98pub struct Topology {
99    /// # of logical blocks per physical block (log2)
100    #[access(ReadOnly)]
101    physical_block_exp: u8,
102
103    /// offset of first aligned logical block
104    #[access(ReadOnly)]
105    alignment_offset: u8,
106
107    /// suggested minimum I/O size in blocks
108    #[access(ReadOnly)]
109    min_io_size: le16,
110
111    /// optimal (suggested maximum) I/O size in blocks
112    #[access(ReadOnly)]
113    opt_io_size: le32,
114}
115
116#[doc(alias = "virtio_blk_zoned_characteristics")]
117#[derive(VolatileFieldAccess)]
118#[repr(C)]
119pub struct ZonedCharacteristics {
120    #[access(ReadOnly)]
121    zone_sectors: le32,
122
123    #[access(ReadOnly)]
124    max_open_zones: le32,
125
126    #[access(ReadOnly)]
127    max_active_zones: le32,
128
129    #[access(ReadOnly)]
130    max_append_sectors: le32,
131
132    #[access(ReadOnly)]
133    write_granularity: le32,
134
135    #[access(ReadOnly)]
136    model: u8,
137
138    #[access(ReadOnly)]
139    unused2: [u8; 3],
140}
141
142/// A zoning model.
143#[doc(alias = "VIRTIO_BLK_Z")]
144#[derive(IntoPrimitive, TryFromPrimitive, PartialEq, Eq, Clone, Copy, Debug)]
145#[non_exhaustive]
146#[repr(u8)]
147pub enum Z {
148    #[doc(alias = "VIRTIO_BLK_Z_NONE")]
149    None = 0,
150
151    #[doc(alias = "VIRTIO_BLK_Z_HM")]
152    Hm = 1,
153
154    #[doc(alias = "VIRTIO_BLK_Z_HA")]
155    Ha = 2,
156}
157
158/// The type of a request.
159#[doc(alias = "VIRTIO_BLK_T")]
160#[derive(IntoPrimitive, TryFromPrimitive, PartialEq, Eq, Clone, Copy, Debug)]
161#[non_exhaustive]
162#[repr(u32)]
163pub enum T {
164    #[doc(alias = "VIRTIO_BLK_T_IN")]
165    In = 0,
166
167    #[doc(alias = "VIRTIO_BLK_T_OUT")]
168    Out = 1,
169
170    #[doc(alias = "VIRTIO_BLK_T_FLUSH")]
171    Flush = 4,
172
173    #[doc(alias = "VIRTIO_BLK_T_GET_ID")]
174    GetId = 8,
175
176    #[doc(alias = "VIRTIO_BLK_T_GET_LIFETIME")]
177    GetLifetime = 10,
178
179    #[doc(alias = "VIRTIO_BLK_T_DISCARD")]
180    Discard = 11,
181
182    #[doc(alias = "VIRTIO_BLK_T_WRITE_ZEROES")]
183    WriteZeroes = 13,
184
185    #[doc(alias = "VIRTIO_BLK_T_SECURE_ERASE")]
186    SecureErase = 14,
187
188    #[doc(alias = "VIRTIO_BLK_T_ZONE_APPEND")]
189    ZoneAppend = 15,
190
191    #[doc(alias = "VIRTIO_BLK_T_ZONE_REPORT")]
192    ZoneReport = 16,
193
194    #[doc(alias = "VIRTIO_BLK_T_ZONE_OPEN")]
195    ZoneOpen = 18,
196
197    #[doc(alias = "VIRTIO_BLK_T_ZONE_CLOSE")]
198    ZoneClose = 20,
199
200    #[doc(alias = "VIRTIO_BLK_T_ZONE_FINISH")]
201    ZoneFinish = 22,
202
203    #[doc(alias = "VIRTIO_BLK_T_ZONE_RESET")]
204    ZoneReset = 24,
205
206    #[doc(alias = "VIRTIO_BLK_T_ZONE_RESET_ALL")]
207    ZoneResetAll = 26,
208}
209
210/// A segment for discard, secure erase or write zeroes.
211#[doc(alias = "virtio_blk_discard_write_zeroes")]
212#[cfg_attr(
213    feature = "zerocopy",
214    derive(
215        zerocopy_derive::KnownLayout,
216        zerocopy_derive::Immutable,
217        zerocopy_derive::FromBytes,
218        zerocopy_derive::IntoBytes,
219    )
220)]
221#[repr(C)]
222pub struct DiscardWriteZeroes {
223    pub sector: le64,
224    pub num_sectors: le32,
225    pub flags: le32,
226}
227
228/// The flags of a [`DiscardWriteZeroes`] segment.
229#[bitfield(u32, repr = le32, from = le32::from_ne, into = le32::to_ne)]
230pub struct DiscardWriteZeroesFlags {
231    #[bits(1)]
232    pub unmap: bool,
233
234    #[bits(31)]
235    pub reserved: u32,
236}
237
238/// Lifetime data populated by the device.
239#[doc(alias = "virtio_blk_lifetime")]
240#[cfg_attr(
241    feature = "zerocopy",
242    derive(
243        zerocopy_derive::KnownLayout,
244        zerocopy_derive::Immutable,
245        zerocopy_derive::FromBytes,
246        zerocopy_derive::IntoBytes,
247    )
248)]
249#[repr(C)]
250pub struct Lifetime {
251    pub pre_eol_info: le16,
252    pub device_lifetime_est_typ_a: le16,
253    pub device_lifetime_est_typ_b: le16,
254}
255
256/// End-of-life information.
257#[doc(alias = "VIRTIO_BLK_PRE_EOL_INFO")]
258#[derive(IntoPrimitive, TryFromPrimitive, PartialEq, Eq, Clone, Copy, Debug)]
259#[non_exhaustive]
260#[repr(u16)]
261pub enum PreEolInfo {
262    /// Value not available
263    #[doc(alias = "VIRTIO_BLK_PRE_EOL_INFO_UNDEFINED")]
264    Undefined = 0,
265
266    /// < 80% of reserved blocks are consumed
267    #[doc(alias = "VIRTIO_BLK_PRE_EOL_INFO_NORMAL")]
268    Normal = 1,
269
270    /// 80% of reserved blocks are consumed
271    #[doc(alias = "VIRTIO_BLK_PRE_EOL_INFO_WARNING")]
272    Warning = 2,
273
274    /// 90% of reserved blocks are consumed
275    #[doc(alias = "VIRTIO_BLK_PRE_EOL_INFO_URGENT")]
276    Urgent = 3,
277}
278
279/// A status byte.
280#[doc(alias = "VIRTIO_BLK_S")]
281#[derive(IntoPrimitive, TryFromPrimitive, PartialEq, Eq, Clone, Copy, Debug)]
282#[non_exhaustive]
283#[repr(u8)]
284pub enum S {
285    #[doc(alias = "VIRTIO_BLK_S_OK")]
286    Ok = 0,
287
288    #[doc(alias = "VIRTIO_BLK_S_IOERR")]
289    Ioerr = 1,
290
291    #[doc(alias = "VIRTIO_BLK_S_UNSUPP")]
292    Unsupp = 2,
293
294    #[doc(alias = "VIRTIO_BLK_S_ZONE_INVALID_CMD")]
295    ZoneInvalidCmd = 3,
296
297    #[doc(alias = "VIRTIO_BLK_S_ZONE_UNALIGNED_WP")]
298    ZoneUnalignedWp = 4,
299
300    #[doc(alias = "VIRTIO_BLK_S_ZONE_OPEN_RESOURCE")]
301    ZoneOpenResource = 5,
302
303    #[doc(alias = "VIRTIO_BLK_S_ZONE_ACTIVE_RESOURCE")]
304    ZoneActiveResource = 6,
305}
306
307/// A zone descriptor.
308#[doc(alias = "virtio_blk_zone_descriptor")]
309#[cfg_attr(
310    feature = "zerocopy",
311    derive(
312        zerocopy_derive::KnownLayout,
313        zerocopy_derive::Immutable,
314        zerocopy_derive::FromBytes,
315        zerocopy_derive::IntoBytes,
316    )
317)]
318#[repr(C)]
319pub struct ZoneDescriptor {
320    z_cap: le64,
321    z_start: le64,
322    z_wp: le64,
323    z_type: u8,
324    z_state: u8,
325    reserved: [u8; 38],
326}
327
328/// A zone type.
329#[doc(alias = "VIRTIO_BLK_ZT")]
330#[derive(IntoPrimitive, TryFromPrimitive, PartialEq, Eq, Clone, Copy, Debug)]
331#[non_exhaustive]
332#[repr(u8)]
333pub enum Zt {
334    #[doc(alias = "VIRTIO_BLK_ZT_CONV")]
335    Conv = 1,
336
337    #[doc(alias = "VIRTIO_BLK_ZT_SWR")]
338    Swr = 2,
339
340    #[doc(alias = "VIRTIO_BLK_ZT_SWP")]
341    Swp = 3,
342}
343
344/// A zone state.
345#[doc(alias = "VIRTIO_BLK_ZS")]
346#[derive(IntoPrimitive, TryFromPrimitive, PartialEq, Eq, Clone, Copy, Debug)]
347#[non_exhaustive]
348#[repr(u8)]
349pub enum Zs {
350    #[doc(alias = "VIRTIO_BLK_ZS_NOT_WP")]
351    NotWp = 0,
352
353    #[doc(alias = "VIRTIO_BLK_ZS_EMPTY")]
354    Empty = 1,
355
356    #[doc(alias = "VIRTIO_BLK_ZS_IOPEN")]
357    Iopen = 2,
358
359    #[doc(alias = "VIRTIO_BLK_ZS_EOPEN")]
360    Eopen = 3,
361
362    #[doc(alias = "VIRTIO_BLK_ZS_CLOSED")]
363    Closed = 4,
364
365    #[doc(alias = "VIRTIO_BLK_ZS_RDONLY")]
366    Rdonly = 13,
367
368    #[doc(alias = "VIRTIO_BLK_ZS_FULL")]
369    Full = 14,
370
371    #[doc(alias = "VIRTIO_BLK_ZS_OFFLINE")]
372    Offline = 15,
373}