]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c
OvmfPkg/VirtioLib: take VirtIo instance in VirtioRingInit/VirtioRingUninit
[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 )
186 {
187 VIRTIO_MMIO_DEVICE *Device;
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 }