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