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