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 (Dev
,
57 Dev
->DeviceSpecificConfigurationOffset
+ FieldOffset
,
58 FieldSize
, BufferSize
, Buffer
);
63 Write a word into Region 0 of the device specified by VirtIo Device protocol.
65 @param[in] This VirtIo Device protocol.
67 @param[in] FieldOffset Destination offset.
69 @param[in] FieldSize Destination field size, must be in { 1, 2, 4, 8 }.
71 @param[in] Value Little endian value to write, converted to UINT64.
72 The least significant FieldSize bytes will be used.
75 @return Status code returned by PciIo->Io.Write().
80 VirtioPciDeviceWrite (
81 IN VIRTIO_DEVICE_PROTOCOL
*This
,
87 VIRTIO_PCI_DEVICE
*Dev
;
89 Dev
= VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This
);
91 return VirtioPciIoWrite (Dev
,
92 Dev
->DeviceSpecificConfigurationOffset
+ FieldOffset
, FieldSize
, Value
);
97 VirtioPciGetDeviceFeatures (
98 IN VIRTIO_DEVICE_PROTOCOL
*This
,
99 OUT UINT64
*DeviceFeatures
102 VIRTIO_PCI_DEVICE
*Dev
;
106 if (DeviceFeatures
== NULL
) {
107 return EFI_INVALID_PARAMETER
;
110 Dev
= VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This
);
112 Status
= VirtioPciIoRead (Dev
, VIRTIO_PCI_OFFSET_DEVICE_FEATURES
,
113 sizeof (UINT32
), sizeof (UINT32
), &Features32
);
114 if (!EFI_ERROR (Status
)) {
115 *DeviceFeatures
= Features32
;
122 VirtioPciGetQueueSize (
123 IN VIRTIO_DEVICE_PROTOCOL
*This
,
124 OUT UINT16
*QueueNumMax
127 VIRTIO_PCI_DEVICE
*Dev
;
129 if (QueueNumMax
== NULL
) {
130 return EFI_INVALID_PARAMETER
;
133 Dev
= VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This
);
135 return VirtioPciIoRead (Dev
, VIRTIO_PCI_OFFSET_QUEUE_SIZE
, sizeof (UINT16
),
136 sizeof (UINT16
), QueueNumMax
);
141 VirtioPciGetDeviceStatus (
142 IN VIRTIO_DEVICE_PROTOCOL
*This
,
143 OUT UINT8
*DeviceStatus
146 VIRTIO_PCI_DEVICE
*Dev
;
148 if (DeviceStatus
== NULL
) {
149 return EFI_INVALID_PARAMETER
;
152 Dev
= VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This
);
154 return VirtioPciIoRead (Dev
, VIRTIO_PCI_OFFSET_QUEUE_DEVICE_STATUS
,
155 sizeof (UINT8
), sizeof (UINT8
), DeviceStatus
);
160 VirtioPciSetGuestFeatures (
161 IN VIRTIO_DEVICE_PROTOCOL
*This
,
165 VIRTIO_PCI_DEVICE
*Dev
;
167 Dev
= VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This
);
169 if (Features
> MAX_UINT32
) {
170 return EFI_UNSUPPORTED
;
172 return VirtioPciIoWrite (Dev
, VIRTIO_PCI_OFFSET_GUEST_FEATURES
,
173 sizeof (UINT32
), Features
);
178 VirtioPciSetQueueAddress (
179 IN VIRTIO_DEVICE_PROTOCOL
*This
,
181 IN UINT64 RingBaseShift
184 VIRTIO_PCI_DEVICE
*Dev
;
186 ASSERT (RingBaseShift
== 0);
188 Dev
= VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This
);
190 return VirtioPciIoWrite (Dev
, VIRTIO_PCI_OFFSET_QUEUE_ADDRESS
, sizeof (UINT32
),
191 (UINT32
)((UINTN
)Ring
->Base
>> EFI_PAGE_SHIFT
));
196 VirtioPciSetQueueSel (
197 IN VIRTIO_DEVICE_PROTOCOL
*This
,
201 VIRTIO_PCI_DEVICE
*Dev
;
203 Dev
= VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This
);
205 return VirtioPciIoWrite (Dev
, VIRTIO_PCI_OFFSET_QUEUE_SELECT
, sizeof (UINT16
),
211 VirtioPciSetQueueAlignment (
212 IN VIRTIO_DEVICE_PROTOCOL
*This
,
221 VirtioPciSetPageSize (
222 IN VIRTIO_DEVICE_PROTOCOL
*This
,
226 return (PageSize
== EFI_PAGE_SIZE
) ? EFI_SUCCESS
: EFI_UNSUPPORTED
;
231 VirtioPciSetQueueNotify (
232 IN VIRTIO_DEVICE_PROTOCOL
*This
,
236 VIRTIO_PCI_DEVICE
*Dev
;
238 Dev
= VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This
);
240 return VirtioPciIoWrite (Dev
, VIRTIO_PCI_OFFSET_QUEUE_NOTIFY
, sizeof (UINT16
),
246 VirtioPciSetQueueSize (
247 IN VIRTIO_DEVICE_PROTOCOL
*This
,
252 // This function is only applicable in Virtio-MMIO.
253 // (The QueueSize field is read-only in Virtio proper (PCI))
260 VirtioPciSetDeviceStatus (
261 IN VIRTIO_DEVICE_PROTOCOL
*This
,
262 IN UINT8 DeviceStatus
265 VIRTIO_PCI_DEVICE
*Dev
;
267 Dev
= VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This
);
269 return VirtioPciIoWrite (Dev
, VIRTIO_PCI_OFFSET_QUEUE_DEVICE_STATUS
,
270 sizeof (UINT8
), DeviceStatus
);
275 VirtioPciAllocateSharedPages (
276 IN VIRTIO_DEVICE_PROTOCOL
*This
,
278 OUT VOID
**HostAddress
283 Buffer
= AllocatePages (NumPages
);
284 if (Buffer
== NULL
) {
285 return EFI_OUT_OF_RESOURCES
;
288 *HostAddress
= Buffer
;
294 VirtioPciFreeSharedPages (
295 IN VIRTIO_DEVICE_PROTOCOL
*This
,
300 FreePages (HostAddress
, NumPages
);
305 VirtioPciMapSharedBuffer (
306 IN VIRTIO_DEVICE_PROTOCOL
*This
,
307 IN VIRTIO_MAP_OPERATION Operation
,
308 IN VOID
*HostAddress
,
309 IN OUT UINTN
*NumberOfBytes
,
310 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
314 *DeviceAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) HostAddress
;
322 VirtioPciUnmapSharedBuffer (
323 IN VIRTIO_DEVICE_PROTOCOL
*This
,