3 This driver produces Virtio Device Protocol instances for Virtio PCI devices.
5 Copyright (C) 2012, Red Hat, Inc.
6 Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>
7 Copyright (C) 2013, ARM Ltd.
8 Copyright (C) 2017, AMD Inc, All rights reserved.<BR>
10 SPDX-License-Identifier: BSD-2-Clause-Patent
13 #include <Library/BaseMemoryLib.h>
14 #include <Library/DebugLib.h>
15 #include <Library/MemoryAllocationLib.h>
16 #include <Library/UefiBootServicesTableLib.h>
17 #include <Library/UefiLib.h>
18 #include "VirtioPciDevice.h"
22 Read a word from Region 0 of the device specified by VirtIo Device protocol.
24 The function implements the ReadDevice protocol member of
25 VIRTIO_DEVICE_PROTOCOL.
27 @param[in] This VirtIo Device protocol.
29 @param[in] FieldOffset Source offset.
31 @param[in] FieldSize Source field size, must be in { 1, 2, 4, 8 }.
33 @param[in] BufferSize Number of bytes available in the target buffer. Must
36 @param[out] Buffer Target buffer.
39 @return Status code returned by PciIo->Io.Read().
45 IN VIRTIO_DEVICE_PROTOCOL
*This
,
52 VIRTIO_PCI_DEVICE
*Dev
;
54 Dev
= VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This
);
56 return VirtioPciIoRead (
58 Dev
->DeviceSpecificConfigurationOffset
+ FieldOffset
,
67 Write a word into Region 0 of the device specified by VirtIo Device protocol.
69 @param[in] This VirtIo Device protocol.
71 @param[in] FieldOffset Destination offset.
73 @param[in] FieldSize Destination field size, must be in { 1, 2, 4, 8 }.
75 @param[in] Value Little endian value to write, converted to UINT64.
76 The least significant FieldSize bytes will be used.
79 @return Status code returned by PciIo->Io.Write().
84 VirtioPciDeviceWrite (
85 IN VIRTIO_DEVICE_PROTOCOL
*This
,
91 VIRTIO_PCI_DEVICE
*Dev
;
93 Dev
= VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This
);
95 return VirtioPciIoWrite (
97 Dev
->DeviceSpecificConfigurationOffset
+ FieldOffset
,
105 VirtioPciGetDeviceFeatures (
106 IN VIRTIO_DEVICE_PROTOCOL
*This
,
107 OUT UINT64
*DeviceFeatures
110 VIRTIO_PCI_DEVICE
*Dev
;
114 if (DeviceFeatures
== NULL
) {
115 return EFI_INVALID_PARAMETER
;
118 Dev
= VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This
);
120 Status
= VirtioPciIoRead (
122 VIRTIO_PCI_OFFSET_DEVICE_FEATURES
,
127 if (!EFI_ERROR (Status
)) {
128 *DeviceFeatures
= Features32
;
136 VirtioPciGetQueueSize (
137 IN VIRTIO_DEVICE_PROTOCOL
*This
,
138 OUT UINT16
*QueueNumMax
141 VIRTIO_PCI_DEVICE
*Dev
;
143 if (QueueNumMax
== NULL
) {
144 return EFI_INVALID_PARAMETER
;
147 Dev
= VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This
);
149 return VirtioPciIoRead (
151 VIRTIO_PCI_OFFSET_QUEUE_SIZE
,
160 VirtioPciGetDeviceStatus (
161 IN VIRTIO_DEVICE_PROTOCOL
*This
,
162 OUT UINT8
*DeviceStatus
165 VIRTIO_PCI_DEVICE
*Dev
;
167 if (DeviceStatus
== NULL
) {
168 return EFI_INVALID_PARAMETER
;
171 Dev
= VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This
);
173 return VirtioPciIoRead (
175 VIRTIO_PCI_OFFSET_QUEUE_DEVICE_STATUS
,
184 VirtioPciSetGuestFeatures (
185 IN VIRTIO_DEVICE_PROTOCOL
*This
,
189 VIRTIO_PCI_DEVICE
*Dev
;
191 Dev
= VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This
);
193 if (Features
> MAX_UINT32
) {
194 return EFI_UNSUPPORTED
;
197 return VirtioPciIoWrite (
199 VIRTIO_PCI_OFFSET_GUEST_FEATURES
,
207 VirtioPciSetQueueAddress (
208 IN VIRTIO_DEVICE_PROTOCOL
*This
,
210 IN UINT64 RingBaseShift
213 VIRTIO_PCI_DEVICE
*Dev
;
215 ASSERT (RingBaseShift
== 0);
217 Dev
= VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This
);
219 return VirtioPciIoWrite (
221 VIRTIO_PCI_OFFSET_QUEUE_ADDRESS
,
223 (UINT32
)((UINTN
)Ring
->Base
>> EFI_PAGE_SHIFT
)
229 VirtioPciSetQueueSel (
230 IN VIRTIO_DEVICE_PROTOCOL
*This
,
234 VIRTIO_PCI_DEVICE
*Dev
;
236 Dev
= VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This
);
238 return VirtioPciIoWrite (
240 VIRTIO_PCI_OFFSET_QUEUE_SELECT
,
248 VirtioPciSetQueueAlignment (
249 IN VIRTIO_DEVICE_PROTOCOL
*This
,
258 VirtioPciSetPageSize (
259 IN VIRTIO_DEVICE_PROTOCOL
*This
,
263 return (PageSize
== EFI_PAGE_SIZE
) ? EFI_SUCCESS
: EFI_UNSUPPORTED
;
268 VirtioPciSetQueueNotify (
269 IN VIRTIO_DEVICE_PROTOCOL
*This
,
273 VIRTIO_PCI_DEVICE
*Dev
;
275 Dev
= VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This
);
277 return VirtioPciIoWrite (
279 VIRTIO_PCI_OFFSET_QUEUE_NOTIFY
,
287 VirtioPciSetQueueSize (
288 IN VIRTIO_DEVICE_PROTOCOL
*This
,
293 // This function is only applicable in Virtio-MMIO.
294 // (The QueueSize field is read-only in Virtio proper (PCI))
301 VirtioPciSetDeviceStatus (
302 IN VIRTIO_DEVICE_PROTOCOL
*This
,
303 IN UINT8 DeviceStatus
306 VIRTIO_PCI_DEVICE
*Dev
;
308 Dev
= VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This
);
310 return VirtioPciIoWrite (
312 VIRTIO_PCI_OFFSET_QUEUE_DEVICE_STATUS
,
320 VirtioPciAllocateSharedPages (
321 IN VIRTIO_DEVICE_PROTOCOL
*This
,
323 OUT VOID
**HostAddress
328 Buffer
= AllocatePages (NumPages
);
329 if (Buffer
== NULL
) {
330 return EFI_OUT_OF_RESOURCES
;
333 *HostAddress
= Buffer
;
339 VirtioPciFreeSharedPages (
340 IN VIRTIO_DEVICE_PROTOCOL
*This
,
345 FreePages (HostAddress
, NumPages
);
350 VirtioPciMapSharedBuffer (
351 IN VIRTIO_DEVICE_PROTOCOL
*This
,
352 IN VIRTIO_MAP_OPERATION Operation
,
353 IN VOID
*HostAddress
,
354 IN OUT UINTN
*NumberOfBytes
,
355 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
359 *DeviceAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)HostAddress
;
367 VirtioPciUnmapSharedBuffer (
368 IN VIRTIO_DEVICE_PROTOCOL
*This
,