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