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 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_GUEST_PAGE_SIZE
, PageSize
);
161 VirtioMmioSetQueueSel (
162 IN VIRTIO_DEVICE_PROTOCOL
*This
,
166 VIRTIO_MMIO_DEVICE
*Device
;
168 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
170 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_QUEUE_SEL
, Sel
);
176 VirtioMmioSetQueueAddress (
177 IN VIRTIO_DEVICE_PROTOCOL
*This
,
179 IN UINT64 RingBaseShift
182 VIRTIO_MMIO_DEVICE
*Device
;
184 ASSERT (RingBaseShift
== 0);
186 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
188 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_QUEUE_PFN
,
189 (UINT32
)((UINTN
)Ring
->Base
>> EFI_PAGE_SHIFT
));
196 VirtioMmioSetGuestFeatures (
197 IN VIRTIO_DEVICE_PROTOCOL
*This
,
201 VIRTIO_MMIO_DEVICE
*Device
;
203 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
205 if (Features
> MAX_UINT32
) {
206 return EFI_UNSUPPORTED
;
208 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_GUEST_FEATURES
,
216 VirtioMmioDeviceWrite (
217 IN VIRTIO_DEVICE_PROTOCOL
*This
,
218 IN UINTN FieldOffset
,
223 UINTN DstBaseAddress
;
224 VIRTIO_MMIO_DEVICE
*Device
;
226 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
229 // Double-check fieldsize
231 if ((FieldSize
!= 1) && (FieldSize
!= 2) &&
232 (FieldSize
!= 4) && (FieldSize
!= 8)) {
233 return EFI_INVALID_PARAMETER
;
237 // Compute base address
239 DstBaseAddress
= Device
->BaseAddress
+
240 VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_MMIO
+ FieldOffset
;
243 // The device-specific memory area of Virtio-MMIO can only be written in
244 // byte accesses. This is not currently in the Virtio spec.
246 MmioWriteBuffer8 (DstBaseAddress
, FieldSize
, (UINT8
*)&Value
);
253 VirtioMmioDeviceRead (
254 IN VIRTIO_DEVICE_PROTOCOL
*This
,
255 IN UINTN FieldOffset
,
261 UINTN SrcBaseAddress
;
262 VIRTIO_MMIO_DEVICE
*Device
;
264 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
267 // Parameter validation
269 ASSERT (FieldSize
== BufferSize
);
272 // Double-check fieldsize
274 if ((FieldSize
!= 1) && (FieldSize
!= 2) &&
275 (FieldSize
!= 4) && (FieldSize
!= 8)) {
276 return EFI_INVALID_PARAMETER
;
280 // Compute base address
282 SrcBaseAddress
= Device
->BaseAddress
+
283 VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_MMIO
+ FieldOffset
;
286 // The device-specific memory area of Virtio-MMIO can only be read in
287 // byte reads. This is not currently in the Virtio spec.
289 MmioReadBuffer8 (SrcBaseAddress
, BufferSize
, Buffer
);
296 VirtioMmioAllocateSharedPages (
297 IN VIRTIO_DEVICE_PROTOCOL
*This
,
299 OUT VOID
**HostAddress
304 Buffer
= AllocatePages (NumPages
);
305 if (Buffer
== NULL
) {
306 return EFI_OUT_OF_RESOURCES
;
309 *HostAddress
= Buffer
;
315 VirtioMmioFreeSharedPages (
316 IN VIRTIO_DEVICE_PROTOCOL
*This
,
321 FreePages (HostAddress
, NumPages
);
326 VirtioMmioMapSharedBuffer (
327 IN VIRTIO_DEVICE_PROTOCOL
*This
,
328 IN VIRTIO_MAP_OPERATION Operation
,
329 IN VOID
*HostAddress
,
330 IN OUT UINTN
*NumberOfBytes
,
331 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
335 *DeviceAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) HostAddress
;
343 VirtioMmioUnmapSharedBuffer (
344 IN VIRTIO_DEVICE_PROTOCOL
*This
,