virtio/
spec.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Constants defined by the virtio spec
5
6pub use packed_nums::*;
7
8#[allow(non_camel_case_types)]
9mod packed_nums {
10    pub type u16_le = zerocopy::U16<zerocopy::LittleEndian>;
11    pub type u32_le = zerocopy::U32<zerocopy::LittleEndian>;
12    pub type u64_le = zerocopy::U64<zerocopy::LittleEndian>;
13}
14
15// Device features - first bank
16pub const VIRTIO_F_RING_INDIRECT_DESC: u32 = 0x10000000;
17pub const VIRTIO_F_RING_EVENT_IDX: u32 = 0x20000000;
18// Device features - second bank
19pub const VIRTIO_F_VERSION_1: u32 = 1;
20
21// Device status
22pub const VIRTIO_ACKNOWLEDGE: u32 = 1;
23pub const VIRTIO_DRIVER: u32 = 2;
24pub const VIRTIO_DRIVER_OK: u32 = 4;
25pub const VIRTIO_FEATURES_OK: u32 = 8;
26// const VIRTIO_DEVICE_NEEDS_RESET: u32 = 0x40;
27pub const VIRTIO_FAILED: u32 = 0x80;
28
29// ACPI interrupt status flags
30pub const VIRTIO_MMIO_INTERRUPT_STATUS_USED_BUFFER: u32 = 1;
31pub const VIRTIO_MMIO_INTERRUPT_STATUS_CONFIG_CHANGE: u32 = 2;
32
33/// Virtio over PCI specific constants
34pub mod pci {
35    pub const VIRTIO_PCI_CAP_COMMON_CFG: u8 = 1;
36    pub const VIRTIO_PCI_CAP_NOTIFY_CFG: u8 = 2;
37    pub const VIRTIO_PCI_CAP_ISR_CFG: u8 = 3;
38    pub const VIRTIO_PCI_CAP_DEVICE_CFG: u8 = 4;
39    // pub const VIRTIO_PCI_CAP_PCI_CFG: u8 = 5;
40    pub const VIRTIO_PCI_CAP_SHARED_MEMORY_CFG: u8 = 8;
41
42    pub const VIRTIO_VENDOR_ID: u16 = 0x1af4;
43    pub const VIRTIO_PCI_DEVICE_ID_BASE: u16 = 0x1040;
44}
45
46/// Virtio queue definitions.
47pub mod queue {
48    use super::u16_le;
49    use super::u32_le;
50    use super::u64_le;
51    use bitfield_struct::bitfield;
52
53    use zerocopy::FromBytes;
54    use zerocopy::Immutable;
55    use zerocopy::IntoBytes;
56    use zerocopy::KnownLayout;
57
58    #[repr(C)]
59    #[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
60    pub struct Descriptor {
61        pub address: u64_le,
62        pub length: u32_le,
63        pub flags_raw: u16_le,
64        pub next: u16_le,
65    }
66
67    impl Descriptor {
68        pub fn flags(&self) -> DescriptorFlags {
69            self.flags_raw.get().into()
70        }
71    }
72
73    #[bitfield(u16)]
74    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
75    pub struct DescriptorFlags {
76        pub next: bool,
77        pub write: bool,
78        pub indirect: bool,
79        #[bits(13)]
80        _reserved: u16,
81    }
82
83    /*
84    struct virtq_avail {
85        le16 flags;
86        le16 idx;
87        le16 ring[ /* Queue Size */ ];
88        le16 used_event;
89    }
90    */
91    pub const AVAIL_OFFSET_FLAGS: u64 = 0;
92    pub const AVAIL_OFFSET_IDX: u64 = 2;
93    pub const AVAIL_OFFSET_RING: u64 = 4;
94    pub const AVAIL_ELEMENT_SIZE: u64 = size_of::<u16>() as u64;
95
96    #[bitfield(u16)]
97    pub struct AvailableFlags {
98        pub no_interrupt: bool,
99        #[bits(15)]
100        _reserved: u16,
101    }
102
103    /*
104    struct virtq_used {
105        le16 flags;
106        le16 idx;
107        struct virtq_used_elem ring[ /* Queue Size */];
108        le16 avail_event;
109    };
110    */
111    pub const USED_OFFSET_FLAGS: u64 = 0;
112    pub const USED_OFFSET_IDX: u64 = 2;
113    pub const USED_OFFSET_RING: u64 = 4;
114    pub const USED_ELEMENT_SIZE: u64 = size_of::<UsedElement>() as u64;
115
116    #[repr(C)]
117    #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
118    pub struct UsedElement {
119        pub id: u32_le,
120        pub len: u32_le,
121    }
122
123    #[bitfield(u16)]
124    pub struct UsedFlags {
125        pub no_notify: bool,
126        #[bits(15)]
127        _reserved: u16,
128    }
129}