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
;
187 ASSERT (RingBaseShift
== 0);
189 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
191 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_QUEUE_PFN
,
192 (UINT32
)((UINTN
)Ring
->Base
>> EFI_PAGE_SHIFT
));
199 VirtioMmioSetGuestFeatures (
200 IN VIRTIO_DEVICE_PROTOCOL
*This
,
204 VIRTIO_MMIO_DEVICE
*Device
;
206 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
208 if (Features
> MAX_UINT32
) {
209 return EFI_UNSUPPORTED
;
211 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_GUEST_FEATURES
,
219 VirtioMmioDeviceWrite (
220 IN VIRTIO_DEVICE_PROTOCOL
*This
,
221 IN UINTN FieldOffset
,
226 UINTN DstBaseAddress
;
227 VIRTIO_MMIO_DEVICE
*Device
;
229 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
232 // Double-check fieldsize
234 if ((FieldSize
!= 1) && (FieldSize
!= 2) &&
235 (FieldSize
!= 4) && (FieldSize
!= 8)) {
236 return EFI_INVALID_PARAMETER
;
240 // Compute base address
242 DstBaseAddress
= Device
->BaseAddress
+
243 VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_MMIO
+ FieldOffset
;
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.
249 MmioWriteBuffer8 (DstBaseAddress
, FieldSize
, (UINT8
*)&Value
);
256 VirtioMmioDeviceRead (
257 IN VIRTIO_DEVICE_PROTOCOL
*This
,
258 IN UINTN FieldOffset
,
264 UINTN SrcBaseAddress
;
265 VIRTIO_MMIO_DEVICE
*Device
;
267 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
270 // Parameter validation
272 ASSERT (FieldSize
== BufferSize
);
275 // Double-check fieldsize
277 if ((FieldSize
!= 1) && (FieldSize
!= 2) &&
278 (FieldSize
!= 4) && (FieldSize
!= 8)) {
279 return EFI_INVALID_PARAMETER
;
283 // Compute base address
285 SrcBaseAddress
= Device
->BaseAddress
+
286 VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_MMIO
+ FieldOffset
;
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.
292 MmioReadBuffer8 (SrcBaseAddress
, BufferSize
, Buffer
);
299 VirtioMmioAllocateSharedPages (
300 IN VIRTIO_DEVICE_PROTOCOL
*This
,
302 OUT VOID
**HostAddress
307 Buffer
= AllocatePages (NumPages
);
308 if (Buffer
== NULL
) {
309 return EFI_OUT_OF_RESOURCES
;
312 *HostAddress
= Buffer
;
318 VirtioMmioFreeSharedPages (
319 IN VIRTIO_DEVICE_PROTOCOL
*This
,
324 FreePages (HostAddress
, NumPages
);
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
,
338 *DeviceAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) HostAddress
;
346 VirtioMmioUnmapSharedBuffer (
347 IN VIRTIO_DEVICE_PROTOCOL
*This
,