]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c
MdeModulePkg/Bds: Fix a boot hang due to Ram Disk boot support
[mirror_edk2.git] / OvmfPkg / Library / VirtioMmioDeviceLib / VirtioMmioDeviceFunctions.c
... / ...
CommitLineData
1/** @file\r
2\r
3 This driver produces Virtio Device Protocol instances for Virtio MMIO 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
8\r
9 This program and the accompanying materials are licensed and made available\r
10 under the terms and conditions of the BSD License which accompanies this\r
11 distribution. The full text of the license may be found at\r
12 http://opensource.org/licenses/bsd-license.php\r
13\r
14 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
15 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
16\r
17**/\r
18\r
19#include "VirtioMmioDevice.h"\r
20\r
21EFI_STATUS\r
22EFIAPI\r
23VirtioMmioGetDeviceFeatures (\r
24 IN VIRTIO_DEVICE_PROTOCOL *This,\r
25 OUT UINT32 *DeviceFeatures\r
26 )\r
27{\r
28 VIRTIO_MMIO_DEVICE *Device;\r
29\r
30 if (DeviceFeatures == NULL) {\r
31 return EFI_INVALID_PARAMETER;\r
32 }\r
33\r
34 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
35\r
36 *DeviceFeatures = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_HOST_FEATURES);\r
37\r
38 return EFI_SUCCESS;\r
39}\r
40\r
41EFI_STATUS\r
42EFIAPI\r
43VirtioMmioGetQueueAddress (\r
44 IN VIRTIO_DEVICE_PROTOCOL *This,\r
45 OUT UINT32 *QueueAddress\r
46 )\r
47{\r
48 VIRTIO_MMIO_DEVICE *Device;\r
49\r
50 if (QueueAddress == NULL) {\r
51 return EFI_INVALID_PARAMETER;\r
52 }\r
53\r
54 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
55\r
56 *QueueAddress = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_QUEUE_PFN);\r
57\r
58 return EFI_SUCCESS;\r
59}\r
60\r
61EFI_STATUS\r
62EFIAPI\r
63VirtioMmioGetQueueSize (\r
64 IN VIRTIO_DEVICE_PROTOCOL *This,\r
65 OUT UINT16 *QueueNumMax\r
66 )\r
67{\r
68 VIRTIO_MMIO_DEVICE *Device;\r
69\r
70 if (QueueNumMax == NULL) {\r
71 return EFI_INVALID_PARAMETER;\r
72 }\r
73\r
74 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
75\r
76 *QueueNumMax = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_QUEUE_NUM_MAX) & 0xFFFF;\r
77\r
78 return EFI_SUCCESS;\r
79}\r
80\r
81EFI_STATUS\r
82EFIAPI\r
83VirtioMmioGetDeviceStatus (\r
84 IN VIRTIO_DEVICE_PROTOCOL *This,\r
85 OUT UINT8 *DeviceStatus\r
86 )\r
87{\r
88 VIRTIO_MMIO_DEVICE *Device;\r
89\r
90 if (DeviceStatus == NULL) {\r
91 return EFI_INVALID_PARAMETER;\r
92 }\r
93\r
94 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
95\r
96 *DeviceStatus = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_STATUS) & 0xFF;\r
97\r
98 return EFI_SUCCESS;\r
99}\r
100\r
101EFI_STATUS\r
102EFIAPI\r
103VirtioMmioSetQueueSize (\r
104 VIRTIO_DEVICE_PROTOCOL *This,\r
105 UINT16 QueueSize\r
106 )\r
107{\r
108 VIRTIO_MMIO_DEVICE *Device;\r
109\r
110 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
111\r
112 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_NUM, QueueSize);\r
113\r
114 return EFI_SUCCESS;\r
115}\r
116\r
117EFI_STATUS\r
118EFIAPI\r
119VirtioMmioSetDeviceStatus (\r
120 VIRTIO_DEVICE_PROTOCOL *This,\r
121 UINT8 DeviceStatus\r
122 )\r
123{\r
124 VIRTIO_MMIO_DEVICE *Device;\r
125\r
126 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
127\r
128 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_STATUS, DeviceStatus);\r
129\r
130 return EFI_SUCCESS;\r
131}\r
132\r
133EFI_STATUS\r
134EFIAPI\r
135VirtioMmioSetQueueNotify (\r
136 VIRTIO_DEVICE_PROTOCOL *This,\r
137 UINT16 QueueNotify\r
138 )\r
139{\r
140 VIRTIO_MMIO_DEVICE *Device;\r
141\r
142 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
143\r
144 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_NOTIFY, QueueNotify);\r
145\r
146 return EFI_SUCCESS;\r
147}\r
148\r
149EFI_STATUS\r
150EFIAPI\r
151VirtioMmioSetQueueAlignment (\r
152 VIRTIO_DEVICE_PROTOCOL *This,\r
153 UINT32 Alignment\r
154 )\r
155{\r
156 VIRTIO_MMIO_DEVICE *Device;\r
157\r
158 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
159\r
160 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_ALIGN, Alignment);\r
161\r
162 return EFI_SUCCESS;\r
163}\r
164\r
165EFI_STATUS\r
166EFIAPI\r
167VirtioMmioSetPageSize (\r
168 VIRTIO_DEVICE_PROTOCOL *This,\r
169 UINT32 PageSize\r
170 )\r
171{\r
172 VIRTIO_MMIO_DEVICE *Device;\r
173\r
174 if (PageSize != EFI_PAGE_SIZE) {\r
175 return EFI_UNSUPPORTED;\r
176 }\r
177\r
178 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
179\r
180 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_GUEST_PAGE_SIZE, PageSize);\r
181\r
182 return EFI_SUCCESS;\r
183}\r
184\r
185EFI_STATUS\r
186EFIAPI\r
187VirtioMmioSetQueueSel (\r
188 VIRTIO_DEVICE_PROTOCOL *This,\r
189 UINT16 Sel\r
190 )\r
191{\r
192 VIRTIO_MMIO_DEVICE *Device;\r
193\r
194 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
195\r
196 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_SEL, Sel);\r
197\r
198 return EFI_SUCCESS;\r
199}\r
200\r
201EFI_STATUS\r
202VirtioMmioSetQueueAddress (\r
203 VIRTIO_DEVICE_PROTOCOL *This,\r
204 UINT32 Address\r
205 )\r
206{\r
207 VIRTIO_MMIO_DEVICE *Device;\r
208\r
209 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
210\r
211 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_PFN, Address);\r
212\r
213 return EFI_SUCCESS;\r
214}\r
215\r
216EFI_STATUS\r
217EFIAPI\r
218VirtioMmioSetGuestFeatures (\r
219 VIRTIO_DEVICE_PROTOCOL *This,\r
220 UINT32 Features\r
221 )\r
222{\r
223 VIRTIO_MMIO_DEVICE *Device;\r
224\r
225 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
226\r
227 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_GUEST_FEATURES, Features);\r
228\r
229 return EFI_SUCCESS;\r
230}\r
231\r
232EFI_STATUS\r
233EFIAPI\r
234VirtioMmioDeviceWrite (\r
235 IN VIRTIO_DEVICE_PROTOCOL *This,\r
236 IN UINTN FieldOffset,\r
237 IN UINTN FieldSize,\r
238 IN UINT64 Value\r
239 )\r
240{\r
241 UINTN DstBaseAddress;\r
242 VIRTIO_MMIO_DEVICE *Device;\r
243\r
244 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
245\r
246 //\r
247 // Double-check fieldsize\r
248 //\r
249 if ((FieldSize != 1) && (FieldSize != 2) &&\r
250 (FieldSize != 4) && (FieldSize != 8)) {\r
251 return EFI_INVALID_PARAMETER;\r
252 }\r
253\r
254 //\r
255 // Compute base address\r
256 //\r
257 DstBaseAddress = Device->BaseAddress +\r
258 VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_MMIO + FieldOffset;\r
259\r
260 //\r
261 // The device-specific memory area of Virtio-MMIO can only be written in\r
262 // byte accesses. This is not currently in the Virtio spec.\r
263 //\r
264 MmioWriteBuffer8 (DstBaseAddress, FieldSize, (UINT8*)&Value);\r
265\r
266 return EFI_SUCCESS;\r
267}\r
268\r
269EFI_STATUS\r
270EFIAPI\r
271VirtioMmioDeviceRead (\r
272 IN VIRTIO_DEVICE_PROTOCOL *This,\r
273 IN UINTN FieldOffset,\r
274 IN UINTN FieldSize,\r
275 IN UINTN BufferSize,\r
276 OUT VOID *Buffer\r
277 )\r
278{\r
279 UINTN SrcBaseAddress;\r
280 VIRTIO_MMIO_DEVICE *Device;\r
281\r
282 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
283\r
284 //\r
285 // Parameter validation\r
286 //\r
287 ASSERT (FieldSize == BufferSize);\r
288\r
289 //\r
290 // Double-check fieldsize\r
291 //\r
292 if ((FieldSize != 1) && (FieldSize != 2) &&\r
293 (FieldSize != 4) && (FieldSize != 8)) {\r
294 return EFI_INVALID_PARAMETER;\r
295 }\r
296\r
297 //\r
298 // Compute base address\r
299 //\r
300 SrcBaseAddress = Device->BaseAddress +\r
301 VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_MMIO + FieldOffset;\r
302\r
303 //\r
304 // The device-specific memory area of Virtio-MMIO can only be read in\r
305 // byte reads. This is not currently in the Virtio spec.\r
306 //\r
307 MmioReadBuffer8 (SrcBaseAddress, BufferSize, Buffer);\r
308\r
309 return EFI_SUCCESS;\r
310}\r