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