]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c
OvmfPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / OvmfPkg / VirtioPciDeviceDxe / VirtioPciFunctions.c
1 /** @file
2
3 This driver produces Virtio Device Protocol instances for Virtio PCI devices.
4
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>
9
10 SPDX-License-Identifier: BSD-2-Clause-Patent
11
12 **/
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"
19
20 /**
21
22 Read a word from Region 0 of the device specified by VirtIo Device protocol.
23
24 The function implements the ReadDevice protocol member of
25 VIRTIO_DEVICE_PROTOCOL.
26
27 @param[in] This VirtIo Device protocol.
28
29 @param[in] FieldOffset Source offset.
30
31 @param[in] FieldSize Source field size, must be in { 1, 2, 4, 8 }.
32
33 @param[in] BufferSize Number of bytes available in the target buffer. Must
34 equal FieldSize.
35
36 @param[out] Buffer Target buffer.
37
38
39 @return Status code returned by PciIo->Io.Read().
40
41 **/
42 EFI_STATUS
43 EFIAPI
44 VirtioPciDeviceRead (
45 IN VIRTIO_DEVICE_PROTOCOL *This,
46 IN UINTN FieldOffset,
47 IN UINTN FieldSize,
48 IN UINTN BufferSize,
49 OUT VOID *Buffer
50 )
51 {
52 VIRTIO_PCI_DEVICE *Dev;
53
54 Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
55
56 return VirtioPciIoRead (Dev,
57 Dev->DeviceSpecificConfigurationOffset + FieldOffset,
58 FieldSize, BufferSize, Buffer);
59 }
60
61 /**
62
63 Write a word into Region 0 of the device specified by VirtIo Device protocol.
64
65 @param[in] This VirtIo Device protocol.
66
67 @param[in] FieldOffset Destination offset.
68
69 @param[in] FieldSize Destination field size, must be in { 1, 2, 4, 8 }.
70
71 @param[in] Value Little endian value to write, converted to UINT64.
72 The least significant FieldSize bytes will be used.
73
74
75 @return Status code returned by PciIo->Io.Write().
76
77 **/
78 EFI_STATUS
79 EFIAPI
80 VirtioPciDeviceWrite (
81 IN VIRTIO_DEVICE_PROTOCOL *This,
82 IN UINTN FieldOffset,
83 IN UINTN FieldSize,
84 IN UINT64 Value
85 )
86 {
87 VIRTIO_PCI_DEVICE *Dev;
88
89 Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
90
91 return VirtioPciIoWrite (Dev,
92 Dev->DeviceSpecificConfigurationOffset + FieldOffset, FieldSize, Value);
93 }
94
95 EFI_STATUS
96 EFIAPI
97 VirtioPciGetDeviceFeatures (
98 IN VIRTIO_DEVICE_PROTOCOL *This,
99 OUT UINT64 *DeviceFeatures
100 )
101 {
102 VIRTIO_PCI_DEVICE *Dev;
103 EFI_STATUS Status;
104 UINT32 Features32;
105
106 if (DeviceFeatures == NULL) {
107 return EFI_INVALID_PARAMETER;
108 }
109
110 Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
111
112 Status = VirtioPciIoRead (Dev, VIRTIO_PCI_OFFSET_DEVICE_FEATURES,
113 sizeof (UINT32), sizeof (UINT32), &Features32);
114 if (!EFI_ERROR (Status)) {
115 *DeviceFeatures = Features32;
116 }
117 return Status;
118 }
119
120 EFI_STATUS
121 EFIAPI
122 VirtioPciGetQueueSize (
123 IN VIRTIO_DEVICE_PROTOCOL *This,
124 OUT UINT16 *QueueNumMax
125 )
126 {
127 VIRTIO_PCI_DEVICE *Dev;
128
129 if (QueueNumMax == NULL) {
130 return EFI_INVALID_PARAMETER;
131 }
132
133 Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
134
135 return VirtioPciIoRead (Dev, VIRTIO_PCI_OFFSET_QUEUE_SIZE, sizeof (UINT16),
136 sizeof (UINT16), QueueNumMax);
137 }
138
139 EFI_STATUS
140 EFIAPI
141 VirtioPciGetDeviceStatus (
142 IN VIRTIO_DEVICE_PROTOCOL *This,
143 OUT UINT8 *DeviceStatus
144 )
145 {
146 VIRTIO_PCI_DEVICE *Dev;
147
148 if (DeviceStatus == NULL) {
149 return EFI_INVALID_PARAMETER;
150 }
151
152 Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
153
154 return VirtioPciIoRead (Dev, VIRTIO_PCI_OFFSET_QUEUE_DEVICE_STATUS,
155 sizeof (UINT8), sizeof (UINT8), DeviceStatus);
156 }
157
158 EFI_STATUS
159 EFIAPI
160 VirtioPciSetGuestFeatures (
161 IN VIRTIO_DEVICE_PROTOCOL *This,
162 IN UINT64 Features
163 )
164 {
165 VIRTIO_PCI_DEVICE *Dev;
166
167 Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
168
169 if (Features > MAX_UINT32) {
170 return EFI_UNSUPPORTED;
171 }
172 return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_GUEST_FEATURES,
173 sizeof (UINT32), Features);
174 }
175
176 EFI_STATUS
177 EFIAPI
178 VirtioPciSetQueueAddress (
179 IN VIRTIO_DEVICE_PROTOCOL *This,
180 IN VRING *Ring,
181 IN UINT64 RingBaseShift
182 )
183 {
184 VIRTIO_PCI_DEVICE *Dev;
185
186 ASSERT (RingBaseShift == 0);
187
188 Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
189
190 return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_QUEUE_ADDRESS, sizeof (UINT32),
191 (UINT32)((UINTN)Ring->Base >> EFI_PAGE_SHIFT));
192 }
193
194 EFI_STATUS
195 EFIAPI
196 VirtioPciSetQueueSel (
197 IN VIRTIO_DEVICE_PROTOCOL *This,
198 IN UINT16 Sel
199 )
200 {
201 VIRTIO_PCI_DEVICE *Dev;
202
203 Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
204
205 return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_QUEUE_SELECT, sizeof (UINT16),
206 Sel);
207 }
208
209 EFI_STATUS
210 EFIAPI
211 VirtioPciSetQueueAlignment (
212 IN VIRTIO_DEVICE_PROTOCOL *This,
213 IN UINT32 Alignment
214 )
215 {
216 return EFI_SUCCESS;
217 }
218
219 EFI_STATUS
220 EFIAPI
221 VirtioPciSetPageSize (
222 IN VIRTIO_DEVICE_PROTOCOL *This,
223 IN UINT32 PageSize
224 )
225 {
226 return (PageSize == EFI_PAGE_SIZE) ? EFI_SUCCESS : EFI_UNSUPPORTED;
227 }
228
229 EFI_STATUS
230 EFIAPI
231 VirtioPciSetQueueNotify (
232 IN VIRTIO_DEVICE_PROTOCOL *This,
233 IN UINT16 Index
234 )
235 {
236 VIRTIO_PCI_DEVICE *Dev;
237
238 Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
239
240 return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_QUEUE_NOTIFY, sizeof (UINT16),
241 Index);
242 }
243
244 EFI_STATUS
245 EFIAPI
246 VirtioPciSetQueueSize (
247 IN VIRTIO_DEVICE_PROTOCOL *This,
248 IN UINT16 Size
249 )
250 {
251 //
252 // This function is only applicable in Virtio-MMIO.
253 // (The QueueSize field is read-only in Virtio proper (PCI))
254 //
255 return EFI_SUCCESS;
256 }
257
258 EFI_STATUS
259 EFIAPI
260 VirtioPciSetDeviceStatus (
261 IN VIRTIO_DEVICE_PROTOCOL *This,
262 IN UINT8 DeviceStatus
263 )
264 {
265 VIRTIO_PCI_DEVICE *Dev;
266
267 Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
268
269 return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_QUEUE_DEVICE_STATUS,
270 sizeof (UINT8), DeviceStatus);
271 }
272
273 EFI_STATUS
274 EFIAPI
275 VirtioPciAllocateSharedPages (
276 IN VIRTIO_DEVICE_PROTOCOL *This,
277 IN UINTN NumPages,
278 OUT VOID **HostAddress
279 )
280 {
281 VOID *Buffer;
282
283 Buffer = AllocatePages (NumPages);
284 if (Buffer == NULL) {
285 return EFI_OUT_OF_RESOURCES;
286 }
287
288 *HostAddress = Buffer;
289 return EFI_SUCCESS;
290 }
291
292 VOID
293 EFIAPI
294 VirtioPciFreeSharedPages (
295 IN VIRTIO_DEVICE_PROTOCOL *This,
296 IN UINTN NumPages,
297 IN VOID *HostAddress
298 )
299 {
300 FreePages (HostAddress, NumPages);
301 }
302
303 EFI_STATUS
304 EFIAPI
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,
311 OUT VOID **Mapping
312 )
313 {
314 *DeviceAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
315 *Mapping = NULL;
316
317 return EFI_SUCCESS;
318 }
319
320 EFI_STATUS
321 EFIAPI
322 VirtioPciUnmapSharedBuffer (
323 IN VIRTIO_DEVICE_PROTOCOL *This,
324 IN VOID *Mapping
325 )
326 {
327 return EFI_SUCCESS;
328 }