1 /** @file
2 
3   Generic type and macro definitions corresponding to the virtio-0.9.5
4   specification.
5 
6   Copyright (C) 2012-2016, Red Hat, Inc.
7   Portion of Copyright (C) 2013, ARM Ltd.
8 
9   SPDX-License-Identifier: BSD-2-Clause-Patent
10 
11 **/
12 
13 #ifndef _VIRTIO_0_9_5_H_
14 #define _VIRTIO_0_9_5_H_
15 
16 #include <Base.h>
17 
18 //
19 // VirtIo Subsystem Device IDs
20 //
21 #define VIRTIO_SUBSYSTEM_NETWORK_CARD       1
22 #define VIRTIO_SUBSYSTEM_BLOCK_DEVICE       2
23 #define VIRTIO_SUBSYSTEM_CONSOLE            3
24 #define VIRTIO_SUBSYSTEM_ENTROPY_SOURCE     4
25 #define VIRTIO_SUBSYSTEM_MEMORY_BALLOONING  5
26 #define VIRTIO_SUBSYSTEM_IO_MEMORY          6
27 #define VIRTIO_SUBSYSTEM_RPMSG              7
28 #define VIRTIO_SUBSYSTEM_SCSI_HOST          8
29 #define VIRTIO_SUBSYSTEM_9P_TRANSPORT       9
30 #define VIRTIO_SUBSYSTEM_MAC80211_WLAN      10
31 
32 //
33 // Virtio IDs
34 //
35 #define VIRTIO_VENDOR_ID                    0x1AF4
36 #define VIRTIO_MMIO_MAGIC                   0x74726976 // "virt"
37 
38 
39 //
40 // VirtIo Device Specific Configuration Offsets
41 //
42 #define VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_PCI             20
43 #define VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_PCI_WITH_MSI_X  24
44 #define VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_MMIO            0x100
45 
46 //
47 // PCI VirtIo Header Offsets
48 //
49 #define VIRTIO_PCI_OFFSET_DEVICE_FEATURES           0x00
50 #define VIRTIO_PCI_OFFSET_GUEST_FEATURES            0x04
51 #define VIRTIO_PCI_OFFSET_QUEUE_ADDRESS             0x08
52 #define VIRTIO_PCI_OFFSET_QUEUE_SIZE                0x0C
53 #define VIRTIO_PCI_OFFSET_QUEUE_SELECT              0x0E
54 #define VIRTIO_PCI_OFFSET_QUEUE_NOTIFY              0x10
55 #define VIRTIO_PCI_OFFSET_QUEUE_DEVICE_STATUS       0x12
56 #define VIRTIO_PCI_OFFSET_QUEUE_DEVICE_ISR          0x13
57 
58 //
59 // MMIO VirtIo Header Offsets
60 //
61 #define VIRTIO_MMIO_OFFSET_MAGIC                    0x00
62 #define VIRTIO_MMIO_OFFSET_VERSION                  0x04
63 #define VIRTIO_MMIO_OFFSET_DEVICE_ID                0x08
64 #define VIRTIO_MMIO_OFFSET_VENDOR_ID                0x0C
65 #define VIRTIO_MMIO_OFFSET_HOST_FEATURES            0x10
66 #define VIRTIO_MMIO_OFFSET_HOST_FEATURES_SEL        0x14
67 #define VIRTIO_MMIO_OFFSET_GUEST_FEATURES           0x20
68 #define VIRTIO_MMIO_OFFSET_GUEST_FEATURES_SEL       0x24
69 #define VIRTIO_MMIO_OFFSET_GUEST_PAGE_SIZE          0x28
70 #define VIRTIO_MMIO_OFFSET_QUEUE_SEL                0x30
71 #define VIRTIO_MMIO_OFFSET_QUEUE_NUM_MAX            0x34
72 #define VIRTIO_MMIO_OFFSET_QUEUE_NUM                0x38
73 #define VIRTIO_MMIO_OFFSET_QUEUE_ALIGN              0x3C
74 #define VIRTIO_MMIO_OFFSET_QUEUE_PFN                0x40
75 #define VIRTIO_MMIO_OFFSET_QUEUE_NOTIFY             0x50
76 #define VIRTIO_MMIO_OFFSET_INTERRUPT_STATUS         0x60
77 #define VIRTIO_MMIO_OFFSET_INTERRUPT_ACK            0x64
78 #define VIRTIO_MMIO_OFFSET_STATUS                   0x70
79 
80 //
81 // Data in the communication area is defined as packed and accessed as
82 // volatile.
83 //
84 // Some structures contain arrays with dynamically determined size. In such
85 // cases the array and its sibling fields are replaced with pointers.
86 //
87 // All indices (variables and fields named *Idx) are free-running and wrap
88 // around after 0xFFFF. The queue size reported by the host is always an
89 // integral power of 2, not greater than 32768. Actual array indices are
90 // consistently calculated by taking the remainder of a given Idx object modulo
91 // QueueSize. Since 0x10000 is an integral multiple of the QueueSize, UINT16
92 // wraparound is a correct wraparound modulo QueueSize too (it doesn't offset
93 // the remainder class).
94 //
95 // virtio-0.9.5, 2.3.4 Available Ring
96 //
97 #define VRING_AVAIL_F_NO_INTERRUPT BIT0
98 
99 typedef struct {
100   volatile UINT16 *Flags;
101   volatile UINT16 *Idx;
102 
103   volatile UINT16 *Ring;      // QueueSize elements
104   volatile UINT16 *UsedEvent; // unused as per negotiation
105 } VRING_AVAIL;
106 
107 
108 //
109 // virtio-0.9.5, 2.3.5 Used Ring
110 //
111 #define VRING_USED_F_NO_NOTIFY BIT0
112 
113 #pragma pack(1)
114 typedef struct {
115   UINT32 Id;
116   UINT32 Len;
117 } VRING_USED_ELEM;
118 #pragma pack()
119 
120 typedef struct {
121   volatile UINT16          *Flags;
122   volatile UINT16          *Idx;
123   volatile VRING_USED_ELEM *UsedElem;   // QueueSize elements
124   volatile UINT16          *AvailEvent; // unused as per negotiation
125 } VRING_USED;
126 
127 
128 //
129 // virtio-0.9.5, 2.3.2 Descriptor Table
130 //
131 #define VRING_DESC_F_NEXT     BIT0 // more descriptors in this request
132 #define VRING_DESC_F_WRITE    BIT1 // buffer to be written *by the host*
133 #define VRING_DESC_F_INDIRECT BIT2 // unused
134 
135 #pragma pack(1)
136 typedef struct {
137   UINT64 Addr;
138   UINT32 Len;
139   UINT16 Flags;
140   UINT16 Next;
141 } VRING_DESC;
142 #pragma pack()
143 
144 typedef struct {
145   UINTN               NumPages;
146   VOID                *Base;     // deallocate only this field
147   volatile VRING_DESC *Desc;     // QueueSize elements
148   VRING_AVAIL         Avail;
149   VRING_USED          Used;
150   UINT16              QueueSize;
151 } VRING;
152 
153 //
154 // virtio-0.9.5, 2.2.2.1 Device Status
155 //
156 #define VSTAT_ACK       BIT0
157 #define VSTAT_DRIVER    BIT1
158 #define VSTAT_DRIVER_OK BIT2
159 #define VSTAT_FAILED    BIT7
160 
161 //
162 // virtio-0.9.5, Appendix B: Reserved (Device-Independent) Feature Bits
163 //
164 #define VIRTIO_F_NOTIFY_ON_EMPTY    BIT24
165 #define VIRTIO_F_RING_INDIRECT_DESC BIT28
166 #define VIRTIO_F_RING_EVENT_IDX     BIT29
167 
168 
169 #endif // _VIRTIO_0_9_5_H_
170