]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c
OvmfPkg/VirtioMmioDeviceLib: Add virtio 1.0 detection.
[mirror_edk2.git] / OvmfPkg / Library / VirtioMmioDeviceLib / VirtioMmioDeviceFunctions.c
CommitLineData
6fb4e772
OM
1/** @file\r
2\r
3 This driver produces Virtio Device Protocol instances for Virtio MMIO devices.\r
4\r
5 Copyright (C) 2012, Red Hat, Inc.\r
6 Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>\r
7 Copyright (C) 2013, ARM Ltd.\r
8\r
b26f0cf9 9 SPDX-License-Identifier: BSD-2-Clause-Patent\r
6fb4e772
OM
10\r
11**/\r
12\r
13#include "VirtioMmioDevice.h"\r
14\r
15EFI_STATUS\r
16EFIAPI\r
17VirtioMmioGetDeviceFeatures (\r
18 IN VIRTIO_DEVICE_PROTOCOL *This,\r
bc8fde6f 19 OUT UINT64 *DeviceFeatures\r
6fb4e772
OM
20 )\r
21{\r
22 VIRTIO_MMIO_DEVICE *Device;\r
23\r
24 if (DeviceFeatures == NULL) {\r
25 return EFI_INVALID_PARAMETER;\r
26 }\r
27\r
28 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
29\r
30 *DeviceFeatures = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_HOST_FEATURES);\r
31\r
32 return EFI_SUCCESS;\r
33}\r
34\r
6fb4e772
OM
35EFI_STATUS\r
36EFIAPI\r
37VirtioMmioGetQueueSize (\r
38 IN VIRTIO_DEVICE_PROTOCOL *This,\r
39 OUT UINT16 *QueueNumMax\r
40 )\r
41{\r
42 VIRTIO_MMIO_DEVICE *Device;\r
43\r
44 if (QueueNumMax == NULL) {\r
45 return EFI_INVALID_PARAMETER;\r
46 }\r
47\r
48 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
49\r
50 *QueueNumMax = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_QUEUE_NUM_MAX) & 0xFFFF;\r
51\r
52 return EFI_SUCCESS;\r
53}\r
54\r
55EFI_STATUS\r
56EFIAPI\r
57VirtioMmioGetDeviceStatus (\r
58 IN VIRTIO_DEVICE_PROTOCOL *This,\r
59 OUT UINT8 *DeviceStatus\r
60 )\r
61{\r
62 VIRTIO_MMIO_DEVICE *Device;\r
63\r
64 if (DeviceStatus == NULL) {\r
65 return EFI_INVALID_PARAMETER;\r
66 }\r
67\r
68 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
69\r
70 *DeviceStatus = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_STATUS) & 0xFF;\r
71\r
72 return EFI_SUCCESS;\r
73}\r
74\r
75EFI_STATUS\r
76EFIAPI\r
77VirtioMmioSetQueueSize (\r
22701a3d
BS
78 IN VIRTIO_DEVICE_PROTOCOL *This,\r
79 IN UINT16 QueueSize\r
6fb4e772
OM
80 )\r
81{\r
82 VIRTIO_MMIO_DEVICE *Device;\r
83\r
84 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
85\r
86 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_NUM, QueueSize);\r
87\r
88 return EFI_SUCCESS;\r
89}\r
90\r
91EFI_STATUS\r
92EFIAPI\r
93VirtioMmioSetDeviceStatus (\r
22701a3d
BS
94 IN VIRTIO_DEVICE_PROTOCOL *This,\r
95 IN UINT8 DeviceStatus\r
6fb4e772
OM
96 )\r
97{\r
98 VIRTIO_MMIO_DEVICE *Device;\r
99\r
100 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
101\r
102 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_STATUS, DeviceStatus);\r
103\r
104 return EFI_SUCCESS;\r
105}\r
106\r
107EFI_STATUS\r
108EFIAPI\r
109VirtioMmioSetQueueNotify (\r
22701a3d
BS
110 IN VIRTIO_DEVICE_PROTOCOL *This,\r
111 IN UINT16 QueueNotify\r
6fb4e772
OM
112 )\r
113{\r
114 VIRTIO_MMIO_DEVICE *Device;\r
115\r
116 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
117\r
118 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_NOTIFY, QueueNotify);\r
119\r
120 return EFI_SUCCESS;\r
121}\r
122\r
123EFI_STATUS\r
124EFIAPI\r
125VirtioMmioSetQueueAlignment (\r
22701a3d
BS
126 IN VIRTIO_DEVICE_PROTOCOL *This,\r
127 IN UINT32 Alignment\r
6fb4e772
OM
128 )\r
129{\r
130 VIRTIO_MMIO_DEVICE *Device;\r
131\r
132 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
133\r
134 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_ALIGN, Alignment);\r
135\r
136 return EFI_SUCCESS;\r
137}\r
138\r
139EFI_STATUS\r
140EFIAPI\r
141VirtioMmioSetPageSize (\r
22701a3d
BS
142 IN VIRTIO_DEVICE_PROTOCOL *This,\r
143 IN UINT32 PageSize\r
6fb4e772
OM
144 )\r
145{\r
146 VIRTIO_MMIO_DEVICE *Device;\r
147\r
148 if (PageSize != EFI_PAGE_SIZE) {\r
149 return EFI_UNSUPPORTED;\r
150 }\r
151\r
152 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
153\r
154 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_GUEST_PAGE_SIZE, PageSize);\r
155\r
156 return EFI_SUCCESS;\r
157}\r
158\r
159EFI_STATUS\r
160EFIAPI\r
161VirtioMmioSetQueueSel (\r
22701a3d
BS
162 IN VIRTIO_DEVICE_PROTOCOL *This,\r
163 IN UINT16 Sel\r
6fb4e772
OM
164 )\r
165{\r
166 VIRTIO_MMIO_DEVICE *Device;\r
167\r
168 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
169\r
170 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_SEL, Sel);\r
171\r
172 return EFI_SUCCESS;\r
173}\r
174\r
175EFI_STATUS\r
75e9154f 176EFIAPI\r
6fb4e772 177VirtioMmioSetQueueAddress (\r
07af4eee 178 IN VIRTIO_DEVICE_PROTOCOL *This,\r
53a4c604
BS
179 IN VRING *Ring,\r
180 IN UINT64 RingBaseShift\r
6fb4e772
OM
181 )\r
182{\r
183 VIRTIO_MMIO_DEVICE *Device;\r
184\r
53a4c604
BS
185 ASSERT (RingBaseShift == 0);\r
186\r
6fb4e772
OM
187 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
188\r
07af4eee
LE
189 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_PFN,\r
190 (UINT32)((UINTN)Ring->Base >> EFI_PAGE_SHIFT));\r
6fb4e772
OM
191\r
192 return EFI_SUCCESS;\r
193}\r
194\r
195EFI_STATUS\r
196EFIAPI\r
197VirtioMmioSetGuestFeatures (\r
22701a3d
BS
198 IN VIRTIO_DEVICE_PROTOCOL *This,\r
199 IN UINT64 Features\r
6fb4e772
OM
200 )\r
201{\r
202 VIRTIO_MMIO_DEVICE *Device;\r
203\r
204 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
205\r
bc8fde6f
LE
206 if (Features > MAX_UINT32) {\r
207 return EFI_UNSUPPORTED;\r
208 }\r
209 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_GUEST_FEATURES,\r
210 (UINT32)Features);\r
6fb4e772
OM
211\r
212 return EFI_SUCCESS;\r
213}\r
214\r
215EFI_STATUS\r
216EFIAPI\r
217VirtioMmioDeviceWrite (\r
218 IN VIRTIO_DEVICE_PROTOCOL *This,\r
219 IN UINTN FieldOffset,\r
220 IN UINTN FieldSize,\r
221 IN UINT64 Value\r
222 )\r
223{\r
224 UINTN DstBaseAddress;\r
225 VIRTIO_MMIO_DEVICE *Device;\r
226\r
227 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
228\r
229 //\r
230 // Double-check fieldsize\r
231 //\r
232 if ((FieldSize != 1) && (FieldSize != 2) &&\r
233 (FieldSize != 4) && (FieldSize != 8)) {\r
234 return EFI_INVALID_PARAMETER;\r
235 }\r
236\r
237 //\r
238 // Compute base address\r
239 //\r
240 DstBaseAddress = Device->BaseAddress +\r
241 VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_MMIO + FieldOffset;\r
242\r
243 //\r
244 // The device-specific memory area of Virtio-MMIO can only be written in\r
245 // byte accesses. This is not currently in the Virtio spec.\r
246 //\r
247 MmioWriteBuffer8 (DstBaseAddress, FieldSize, (UINT8*)&Value);\r
248\r
249 return EFI_SUCCESS;\r
250}\r
251\r
252EFI_STATUS\r
253EFIAPI\r
254VirtioMmioDeviceRead (\r
255 IN VIRTIO_DEVICE_PROTOCOL *This,\r
256 IN UINTN FieldOffset,\r
257 IN UINTN FieldSize,\r
258 IN UINTN BufferSize,\r
259 OUT VOID *Buffer\r
260 )\r
261{\r
262 UINTN SrcBaseAddress;\r
263 VIRTIO_MMIO_DEVICE *Device;\r
264\r
265 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
266\r
267 //\r
268 // Parameter validation\r
269 //\r
270 ASSERT (FieldSize == BufferSize);\r
271\r
272 //\r
273 // Double-check fieldsize\r
274 //\r
275 if ((FieldSize != 1) && (FieldSize != 2) &&\r
276 (FieldSize != 4) && (FieldSize != 8)) {\r
277 return EFI_INVALID_PARAMETER;\r
278 }\r
279\r
280 //\r
281 // Compute base address\r
282 //\r
283 SrcBaseAddress = Device->BaseAddress +\r
284 VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_MMIO + FieldOffset;\r
285\r
286 //\r
287 // The device-specific memory area of Virtio-MMIO can only be read in\r
288 // byte reads. This is not currently in the Virtio spec.\r
289 //\r
290 MmioReadBuffer8 (SrcBaseAddress, BufferSize, Buffer);\r
291\r
292 return EFI_SUCCESS;\r
293}\r
084cfc1a
BS
294\r
295EFI_STATUS\r
296EFIAPI\r
297VirtioMmioAllocateSharedPages (\r
298 IN VIRTIO_DEVICE_PROTOCOL *This,\r
299 IN UINTN NumPages,\r
300 OUT VOID **HostAddress\r
301 )\r
302{\r
303 VOID *Buffer;\r
304\r
305 Buffer = AllocatePages (NumPages);\r
306 if (Buffer == NULL) {\r
307 return EFI_OUT_OF_RESOURCES;\r
308 }\r
309\r
310 *HostAddress = Buffer;\r
311 return EFI_SUCCESS;\r
312}\r
313\r
314VOID\r
315EFIAPI\r
316VirtioMmioFreeSharedPages (\r
317 IN VIRTIO_DEVICE_PROTOCOL *This,\r
318 IN UINTN NumPages,\r
319 IN VOID *HostAddress\r
320 )\r
321{\r
322 FreePages (HostAddress, NumPages);\r
323}\r
324\r
325EFI_STATUS\r
326EFIAPI\r
327VirtioMmioMapSharedBuffer (\r
328 IN VIRTIO_DEVICE_PROTOCOL *This,\r
329 IN VIRTIO_MAP_OPERATION Operation,\r
330 IN VOID *HostAddress,\r
331 IN OUT UINTN *NumberOfBytes,\r
332 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,\r
333 OUT VOID **Mapping\r
334 )\r
335{\r
336 *DeviceAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;\r
337 *Mapping = NULL;\r
338\r
339 return EFI_SUCCESS;\r
340}\r
341\r
342EFI_STATUS\r
343EFIAPI\r
344VirtioMmioUnmapSharedBuffer (\r
345 IN VIRTIO_DEVICE_PROTOCOL *This,\r
346 IN VOID *Mapping\r
347 )\r
348{\r
349 return EFI_SUCCESS;\r
350}\r