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
;
24 if (DeviceFeatures
== NULL
) {
25 return EFI_INVALID_PARAMETER
;
28 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
30 *DeviceFeatures
= VIRTIO_CFG_READ (Device
, VIRTIO_MMIO_OFFSET_HOST_FEATURES
);
37 VirtioMmioGetQueueSize (
38 IN VIRTIO_DEVICE_PROTOCOL
*This
,
39 OUT UINT16
*QueueNumMax
42 VIRTIO_MMIO_DEVICE
*Device
;
44 if (QueueNumMax
== NULL
) {
45 return EFI_INVALID_PARAMETER
;
48 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
50 *QueueNumMax
= VIRTIO_CFG_READ (Device
, VIRTIO_MMIO_OFFSET_QUEUE_NUM_MAX
) & 0xFFFF;
57 VirtioMmioGetDeviceStatus (
58 IN VIRTIO_DEVICE_PROTOCOL
*This
,
59 OUT UINT8
*DeviceStatus
62 VIRTIO_MMIO_DEVICE
*Device
;
64 if (DeviceStatus
== NULL
) {
65 return EFI_INVALID_PARAMETER
;
68 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
70 *DeviceStatus
= VIRTIO_CFG_READ (Device
, VIRTIO_MMIO_OFFSET_STATUS
) & 0xFF;
77 VirtioMmioSetQueueSize (
78 IN VIRTIO_DEVICE_PROTOCOL
*This
,
82 VIRTIO_MMIO_DEVICE
*Device
;
84 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
86 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_QUEUE_NUM
, QueueSize
);
93 VirtioMmioSetDeviceStatus (
94 IN VIRTIO_DEVICE_PROTOCOL
*This
,
98 VIRTIO_MMIO_DEVICE
*Device
;
100 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
102 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_STATUS
, DeviceStatus
);
109 VirtioMmioSetQueueNotify (
110 IN VIRTIO_DEVICE_PROTOCOL
*This
,
111 IN UINT16 QueueNotify
114 VIRTIO_MMIO_DEVICE
*Device
;
116 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
118 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_QUEUE_NOTIFY
, QueueNotify
);
125 VirtioMmioSetQueueAlignment (
126 IN VIRTIO_DEVICE_PROTOCOL
*This
,
130 VIRTIO_MMIO_DEVICE
*Device
;
132 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
134 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_QUEUE_ALIGN
, Alignment
);
141 VirtioMmioSetPageSize (
142 IN VIRTIO_DEVICE_PROTOCOL
*This
,
146 VIRTIO_MMIO_DEVICE
*Device
;
148 if (PageSize
!= EFI_PAGE_SIZE
) {
149 return EFI_UNSUPPORTED
;
152 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
154 if (Device
->Version
== VIRTIO_MMIO_DEVICE_VERSION_0_95
) {
155 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_GUEST_PAGE_SIZE
, PageSize
);
163 VirtioMmioSetQueueSel (
164 IN VIRTIO_DEVICE_PROTOCOL
*This
,
168 VIRTIO_MMIO_DEVICE
*Device
;
170 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
172 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_QUEUE_SEL
, Sel
);
179 VirtioMmioSetQueueAddress (
180 IN VIRTIO_DEVICE_PROTOCOL
*This
,
182 IN UINT64 RingBaseShift
185 VIRTIO_MMIO_DEVICE
*Device
;
188 ASSERT (RingBaseShift
== 0);
190 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
192 if (Device
->Version
== VIRTIO_MMIO_DEVICE_VERSION_0_95
) {
193 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_QUEUE_PFN
,
194 (UINT32
)((UINTN
)Ring
->Base
>> EFI_PAGE_SHIFT
));
196 Address
= (UINTN
)Ring
->Base
;
197 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_QUEUE_DESC_LO
,
199 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_QUEUE_DESC_HI
,
200 (UINT32
)RShiftU64(Address
, 32));
202 Address
= (UINTN
)Ring
->Avail
.Flags
;
203 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_QUEUE_AVAIL_LO
,
205 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_QUEUE_AVAIL_HI
,
206 (UINT32
)RShiftU64(Address
, 32));
208 Address
= (UINTN
)Ring
->Used
.Flags
;
209 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_QUEUE_USED_LO
,
211 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_QUEUE_USED_HI
,
212 (UINT32
)RShiftU64(Address
, 32));
214 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_QUEUE_READY
, 1);
222 VirtioMmioSetGuestFeatures (
223 IN VIRTIO_DEVICE_PROTOCOL
*This
,
227 VIRTIO_MMIO_DEVICE
*Device
;
229 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
231 if (Features
> MAX_UINT32
) {
232 return EFI_UNSUPPORTED
;
234 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_GUEST_FEATURES
,
242 VirtioMmioDeviceWrite (
243 IN VIRTIO_DEVICE_PROTOCOL
*This
,
244 IN UINTN FieldOffset
,
249 UINTN DstBaseAddress
;
250 VIRTIO_MMIO_DEVICE
*Device
;
252 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
255 // Double-check fieldsize
257 if ((FieldSize
!= 1) && (FieldSize
!= 2) &&
258 (FieldSize
!= 4) && (FieldSize
!= 8)) {
259 return EFI_INVALID_PARAMETER
;
263 // Compute base address
265 DstBaseAddress
= Device
->BaseAddress
+
266 VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_MMIO
+ FieldOffset
;
269 // The device-specific memory area of Virtio-MMIO can only be written in
270 // byte accesses. This is not currently in the Virtio spec.
272 MmioWriteBuffer8 (DstBaseAddress
, FieldSize
, (UINT8
*)&Value
);
279 VirtioMmioDeviceRead (
280 IN VIRTIO_DEVICE_PROTOCOL
*This
,
281 IN UINTN FieldOffset
,
287 UINTN SrcBaseAddress
;
288 VIRTIO_MMIO_DEVICE
*Device
;
290 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
293 // Parameter validation
295 ASSERT (FieldSize
== BufferSize
);
298 // Double-check fieldsize
300 if ((FieldSize
!= 1) && (FieldSize
!= 2) &&
301 (FieldSize
!= 4) && (FieldSize
!= 8)) {
302 return EFI_INVALID_PARAMETER
;
306 // Compute base address
308 SrcBaseAddress
= Device
->BaseAddress
+
309 VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_MMIO
+ FieldOffset
;
312 // The device-specific memory area of Virtio-MMIO can only be read in
313 // byte reads. This is not currently in the Virtio spec.
315 MmioReadBuffer8 (SrcBaseAddress
, BufferSize
, Buffer
);
322 VirtioMmioAllocateSharedPages (
323 IN VIRTIO_DEVICE_PROTOCOL
*This
,
325 OUT VOID
**HostAddress
330 Buffer
= AllocatePages (NumPages
);
331 if (Buffer
== NULL
) {
332 return EFI_OUT_OF_RESOURCES
;
335 *HostAddress
= Buffer
;
341 VirtioMmioFreeSharedPages (
342 IN VIRTIO_DEVICE_PROTOCOL
*This
,
347 FreePages (HostAddress
, NumPages
);
352 VirtioMmioMapSharedBuffer (
353 IN VIRTIO_DEVICE_PROTOCOL
*This
,
354 IN VIRTIO_MAP_OPERATION Operation
,
355 IN VOID
*HostAddress
,
356 IN OUT UINTN
*NumberOfBytes
,
357 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
361 *DeviceAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) HostAddress
;
369 VirtioMmioUnmapSharedBuffer (
370 IN VIRTIO_DEVICE_PROTOCOL
*This
,