]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c
b52060d13d97024b4fa4cc19ca0997bb5161fef8
[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 IN UINT64 RingBaseShift
188 )
189 {
190 VIRTIO_PCI_DEVICE *Dev;
191
192 ASSERT (RingBaseShift == 0);
193
194 Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
195
196 return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_QUEUE_ADDRESS, sizeof (UINT32),
197 (UINT32)((UINTN)Ring->Base >> EFI_PAGE_SHIFT));
198 }
199
200 EFI_STATUS
201 EFIAPI
202 VirtioPciSetQueueSel (
203 IN VIRTIO_DEVICE_PROTOCOL *This,
204 IN UINT16 Sel
205 )
206 {
207 VIRTIO_PCI_DEVICE *Dev;
208
209 Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
210
211 return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_QUEUE_SELECT, sizeof (UINT16),
212 Sel);
213 }
214
215 EFI_STATUS
216 EFIAPI
217 VirtioPciSetQueueAlignment (
218 IN VIRTIO_DEVICE_PROTOCOL *This,
219 IN UINT32 Alignment
220 )
221 {
222 return EFI_SUCCESS;
223 }
224
225 EFI_STATUS
226 EFIAPI
227 VirtioPciSetPageSize (
228 IN VIRTIO_DEVICE_PROTOCOL *This,
229 IN UINT32 PageSize
230 )
231 {
232 return (PageSize == EFI_PAGE_SIZE) ? EFI_SUCCESS : EFI_UNSUPPORTED;
233 }
234
235 EFI_STATUS
236 EFIAPI
237 VirtioPciSetQueueNotify (
238 IN VIRTIO_DEVICE_PROTOCOL *This,
239 IN UINT16 Index
240 )
241 {
242 VIRTIO_PCI_DEVICE *Dev;
243
244 Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
245
246 return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_QUEUE_NOTIFY, sizeof (UINT16),
247 Index);
248 }
249
250 EFI_STATUS
251 EFIAPI
252 VirtioPciSetQueueSize (
253 IN VIRTIO_DEVICE_PROTOCOL *This,
254 IN UINT16 Size
255 )
256 {
257 //
258 // This function is only applicable in Virtio-MMIO.
259 // (The QueueSize field is read-only in Virtio proper (PCI))
260 //
261 return EFI_SUCCESS;
262 }
263
264 EFI_STATUS
265 EFIAPI
266 VirtioPciSetDeviceStatus (
267 IN VIRTIO_DEVICE_PROTOCOL *This,
268 IN UINT8 DeviceStatus
269 )
270 {
271 VIRTIO_PCI_DEVICE *Dev;
272
273 Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
274
275 return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_QUEUE_DEVICE_STATUS,
276 sizeof (UINT8), DeviceStatus);
277 }
278
279 EFI_STATUS
280 EFIAPI
281 VirtioPciAllocateSharedPages (
282 IN VIRTIO_DEVICE_PROTOCOL *This,
283 IN UINTN NumPages,
284 OUT VOID **HostAddress
285 )
286 {
287 VOID *Buffer;
288
289 Buffer = AllocatePages (NumPages);
290 if (Buffer == NULL) {
291 return EFI_OUT_OF_RESOURCES;
292 }
293
294 *HostAddress = Buffer;
295 return EFI_SUCCESS;
296 }
297
298 VOID
299 EFIAPI
300 VirtioPciFreeSharedPages (
301 IN VIRTIO_DEVICE_PROTOCOL *This,
302 IN UINTN NumPages,
303 IN VOID *HostAddress
304 )
305 {
306 FreePages (HostAddress, NumPages);
307 }
308
309 EFI_STATUS
310 EFIAPI
311 VirtioPciMapSharedBuffer (
312 IN VIRTIO_DEVICE_PROTOCOL *This,
313 IN VIRTIO_MAP_OPERATION Operation,
314 IN VOID *HostAddress,
315 IN OUT UINTN *NumberOfBytes,
316 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
317 OUT VOID **Mapping
318 )
319 {
320 *DeviceAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
321 *Mapping = NULL;
322
323 return EFI_SUCCESS;
324 }
325
326 EFI_STATUS
327 EFIAPI
328 VirtioPciUnmapSharedBuffer (
329 IN VIRTIO_DEVICE_PROTOCOL *This,
330 IN VOID *Mapping
331 )
332 {
333 return EFI_SUCCESS;
334 }