3 This driver produces Virtio Device Protocol instances for Virtio MMIO devices.
5 Copyright (C) 2012, Red Hat, Inc.
6 Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>
7 Copyright (C) 2013, ARM Ltd.
9 SPDX-License-Identifier: BSD-2-Clause-Patent
13 #include "VirtioMmioDevice.h"
17 VirtioMmioGetDeviceFeatures (
18 IN VIRTIO_DEVICE_PROTOCOL
*This
,
19 OUT UINT64
*DeviceFeatures
22 VIRTIO_MMIO_DEVICE
*Device
;
23 UINT32 LowBits
, HighBits
;
25 if (DeviceFeatures
== NULL
) {
26 return EFI_INVALID_PARAMETER
;
29 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
31 if (Device
->Version
== VIRTIO_MMIO_DEVICE_VERSION_0_95
) {
32 *DeviceFeatures
= VIRTIO_CFG_READ (Device
, VIRTIO_MMIO_OFFSET_HOST_FEATURES
);
34 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_HOST_FEATURES_SEL
, 0);
35 LowBits
= VIRTIO_CFG_READ (Device
, VIRTIO_MMIO_OFFSET_HOST_FEATURES
);
36 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_HOST_FEATURES_SEL
, 1);
37 HighBits
= VIRTIO_CFG_READ (Device
, VIRTIO_MMIO_OFFSET_HOST_FEATURES
);
38 *DeviceFeatures
= LShiftU64 (HighBits
, 32) | LowBits
;
46 VirtioMmioGetQueueSize (
47 IN VIRTIO_DEVICE_PROTOCOL
*This
,
48 OUT UINT16
*QueueNumMax
51 VIRTIO_MMIO_DEVICE
*Device
;
53 if (QueueNumMax
== NULL
) {
54 return EFI_INVALID_PARAMETER
;
57 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
59 *QueueNumMax
= VIRTIO_CFG_READ (Device
, VIRTIO_MMIO_OFFSET_QUEUE_NUM_MAX
) & 0xFFFF;
66 VirtioMmioGetDeviceStatus (
67 IN VIRTIO_DEVICE_PROTOCOL
*This
,
68 OUT UINT8
*DeviceStatus
71 VIRTIO_MMIO_DEVICE
*Device
;
73 if (DeviceStatus
== NULL
) {
74 return EFI_INVALID_PARAMETER
;
77 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
79 *DeviceStatus
= VIRTIO_CFG_READ (Device
, VIRTIO_MMIO_OFFSET_STATUS
) & 0xFF;
86 VirtioMmioSetQueueSize (
87 IN VIRTIO_DEVICE_PROTOCOL
*This
,
91 VIRTIO_MMIO_DEVICE
*Device
;
93 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
95 if (Device
->Version
== VIRTIO_MMIO_DEVICE_VERSION_0_95
) {
96 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_QUEUE_NUM
, QueueSize
);
98 Device
->QueueNum
= QueueSize
;
106 VirtioMmioSetDeviceStatus (
107 IN VIRTIO_DEVICE_PROTOCOL
*This
,
108 IN UINT8 DeviceStatus
111 VIRTIO_MMIO_DEVICE
*Device
;
113 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
115 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_STATUS
, DeviceStatus
);
122 VirtioMmioSetQueueNotify (
123 IN VIRTIO_DEVICE_PROTOCOL
*This
,
124 IN UINT16 QueueNotify
127 VIRTIO_MMIO_DEVICE
*Device
;
129 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
131 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_QUEUE_NOTIFY
, QueueNotify
);
138 VirtioMmioSetQueueAlignment (
139 IN VIRTIO_DEVICE_PROTOCOL
*This
,
143 VIRTIO_MMIO_DEVICE
*Device
;
145 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
147 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_QUEUE_ALIGN
, Alignment
);
154 VirtioMmioSetPageSize (
155 IN VIRTIO_DEVICE_PROTOCOL
*This
,
159 VIRTIO_MMIO_DEVICE
*Device
;
161 if (PageSize
!= EFI_PAGE_SIZE
) {
162 return EFI_UNSUPPORTED
;
165 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
167 if (Device
->Version
== VIRTIO_MMIO_DEVICE_VERSION_0_95
) {
168 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_GUEST_PAGE_SIZE
, PageSize
);
176 VirtioMmioSetQueueSel (
177 IN VIRTIO_DEVICE_PROTOCOL
*This
,
181 VIRTIO_MMIO_DEVICE
*Device
;
183 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
185 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_QUEUE_SEL
, Sel
);
187 if (Device
->Version
== VIRTIO_MMIO_DEVICE_VERSION_0_95
) {
188 Device
->QueueNum
= VIRTIO_CFG_READ (Device
, VIRTIO_MMIO_OFFSET_QUEUE_NUM_MAX
) & 0xFFFF;
196 VirtioMmioSetQueueAddress (
197 IN VIRTIO_DEVICE_PROTOCOL
*This
,
199 IN UINT64 RingBaseShift
202 VIRTIO_MMIO_DEVICE
*Device
;
205 ASSERT (RingBaseShift
== 0);
207 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
209 if (Device
->Version
== VIRTIO_MMIO_DEVICE_VERSION_0_95
) {
212 VIRTIO_MMIO_OFFSET_QUEUE_PFN
,
213 (UINT32
)((UINTN
)Ring
->Base
>> EFI_PAGE_SHIFT
)
216 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_QUEUE_NUM
, Device
->QueueNum
);
218 Address
= (UINTN
)Ring
->Base
;
221 VIRTIO_MMIO_OFFSET_QUEUE_DESC_LO
,
226 VIRTIO_MMIO_OFFSET_QUEUE_DESC_HI
,
227 (UINT32
)RShiftU64 (Address
, 32)
230 Address
= (UINTN
)Ring
->Avail
.Flags
;
233 VIRTIO_MMIO_OFFSET_QUEUE_AVAIL_LO
,
238 VIRTIO_MMIO_OFFSET_QUEUE_AVAIL_HI
,
239 (UINT32
)RShiftU64 (Address
, 32)
242 Address
= (UINTN
)Ring
->Used
.Flags
;
245 VIRTIO_MMIO_OFFSET_QUEUE_USED_LO
,
250 VIRTIO_MMIO_OFFSET_QUEUE_USED_HI
,
251 (UINT32
)RShiftU64 (Address
, 32)
254 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_QUEUE_READY
, 1);
262 VirtioMmioSetGuestFeatures (
263 IN VIRTIO_DEVICE_PROTOCOL
*This
,
267 VIRTIO_MMIO_DEVICE
*Device
;
269 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
271 if (Device
->Version
== VIRTIO_MMIO_DEVICE_VERSION_0_95
) {
272 if (Features
> MAX_UINT32
) {
273 return EFI_UNSUPPORTED
;
278 VIRTIO_MMIO_OFFSET_GUEST_FEATURES
,
282 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_GUEST_FEATURES_SEL
, 0);
285 VIRTIO_MMIO_OFFSET_GUEST_FEATURES
,
288 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_GUEST_FEATURES_SEL
, 1);
291 VIRTIO_MMIO_OFFSET_GUEST_FEATURES
,
292 (UINT32
)RShiftU64 (Features
, 32)
301 VirtioMmioDeviceWrite (
302 IN VIRTIO_DEVICE_PROTOCOL
*This
,
303 IN UINTN FieldOffset
,
308 UINTN DstBaseAddress
;
309 VIRTIO_MMIO_DEVICE
*Device
;
311 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
314 // Double-check fieldsize
316 if ((FieldSize
!= 1) && (FieldSize
!= 2) &&
317 (FieldSize
!= 4) && (FieldSize
!= 8))
319 return EFI_INVALID_PARAMETER
;
323 // Compute base address
325 DstBaseAddress
= Device
->BaseAddress
+
326 VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_MMIO
+ FieldOffset
;
329 // The device-specific memory area of Virtio-MMIO can only be written in
330 // byte accesses. This is not currently in the Virtio spec.
332 MmioWriteBuffer8 (DstBaseAddress
, FieldSize
, (UINT8
*)&Value
);
339 VirtioMmioDeviceRead (
340 IN VIRTIO_DEVICE_PROTOCOL
*This
,
341 IN UINTN FieldOffset
,
347 UINTN SrcBaseAddress
;
348 VIRTIO_MMIO_DEVICE
*Device
;
350 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
353 // Parameter validation
355 ASSERT (FieldSize
== BufferSize
);
358 // Double-check fieldsize
360 if ((FieldSize
!= 1) && (FieldSize
!= 2) &&
361 (FieldSize
!= 4) && (FieldSize
!= 8))
363 return EFI_INVALID_PARAMETER
;
367 // Compute base address
369 SrcBaseAddress
= Device
->BaseAddress
+
370 VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_MMIO
+ FieldOffset
;
373 // The device-specific memory area of Virtio-MMIO can only be read in
374 // byte reads. This is not currently in the Virtio spec.
376 MmioReadBuffer8 (SrcBaseAddress
, BufferSize
, Buffer
);
383 VirtioMmioAllocateSharedPages (
384 IN VIRTIO_DEVICE_PROTOCOL
*This
,
386 OUT VOID
**HostAddress
391 Buffer
= AllocatePages (NumPages
);
392 if (Buffer
== NULL
) {
393 return EFI_OUT_OF_RESOURCES
;
396 *HostAddress
= Buffer
;
402 VirtioMmioFreeSharedPages (
403 IN VIRTIO_DEVICE_PROTOCOL
*This
,
408 FreePages (HostAddress
, NumPages
);
413 VirtioMmioMapSharedBuffer (
414 IN VIRTIO_DEVICE_PROTOCOL
*This
,
415 IN VIRTIO_MAP_OPERATION Operation
,
416 IN VOID
*HostAddress
,
417 IN OUT UINTN
*NumberOfBytes
,
418 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
422 *DeviceAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)HostAddress
;
430 VirtioMmioUnmapSharedBuffer (
431 IN VIRTIO_DEVICE_PROTOCOL
*This
,