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