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
VirtioMmioGetDeviceFeatures(IN VIRTIO_DEVICE_PROTOCOL * This,OUT UINT32 * DeviceFeatures)23 VirtioMmioGetDeviceFeatures (
24 IN VIRTIO_DEVICE_PROTOCOL *This,
25 OUT UINT32 *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
VirtioMmioGetQueueAddress(IN VIRTIO_DEVICE_PROTOCOL * This,OUT UINT32 * QueueAddress)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
VirtioMmioGetQueueSize(IN VIRTIO_DEVICE_PROTOCOL * This,OUT UINT16 * QueueNumMax)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
VirtioMmioGetDeviceStatus(IN VIRTIO_DEVICE_PROTOCOL * This,OUT UINT8 * DeviceStatus)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
VirtioMmioSetQueueSize(VIRTIO_DEVICE_PROTOCOL * This,UINT16 QueueSize)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
VirtioMmioSetDeviceStatus(VIRTIO_DEVICE_PROTOCOL * This,UINT8 DeviceStatus)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
VirtioMmioSetQueueNotify(VIRTIO_DEVICE_PROTOCOL * This,UINT16 QueueNotify)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
VirtioMmioSetQueueAlignment(VIRTIO_DEVICE_PROTOCOL * This,UINT32 Alignment)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
VirtioMmioSetPageSize(VIRTIO_DEVICE_PROTOCOL * This,UINT32 PageSize)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
VirtioMmioSetQueueSel(VIRTIO_DEVICE_PROTOCOL * This,UINT16 Sel)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
VirtioMmioSetQueueAddress(VIRTIO_DEVICE_PROTOCOL * This,UINT32 Address)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
VirtioMmioSetGuestFeatures(VIRTIO_DEVICE_PROTOCOL * This,UINT32 Features)218 VirtioMmioSetGuestFeatures (
219 VIRTIO_DEVICE_PROTOCOL *This,
220 UINT32 Features
221 )
222 {
223 VIRTIO_MMIO_DEVICE *Device;
224
225 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
226
227 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_GUEST_FEATURES, Features);
228
229 return EFI_SUCCESS;
230 }
231
232 EFI_STATUS
233 EFIAPI
VirtioMmioDeviceWrite(IN VIRTIO_DEVICE_PROTOCOL * This,IN UINTN FieldOffset,IN UINTN FieldSize,IN UINT64 Value)234 VirtioMmioDeviceWrite (
235 IN VIRTIO_DEVICE_PROTOCOL *This,
236 IN UINTN FieldOffset,
237 IN UINTN FieldSize,
238 IN UINT64 Value
239 )
240 {
241 UINTN DstBaseAddress;
242 VIRTIO_MMIO_DEVICE *Device;
243
244 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
245
246 //
247 // Double-check fieldsize
248 //
249 if ((FieldSize != 1) && (FieldSize != 2) &&
250 (FieldSize != 4) && (FieldSize != 8)) {
251 return EFI_INVALID_PARAMETER;
252 }
253
254 //
255 // Compute base address
256 //
257 DstBaseAddress = Device->BaseAddress +
258 VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_MMIO + FieldOffset;
259
260 //
261 // The device-specific memory area of Virtio-MMIO can only be written in
262 // byte accesses. This is not currently in the Virtio spec.
263 //
264 MmioWriteBuffer8 (DstBaseAddress, FieldSize, (UINT8*)&Value);
265
266 return EFI_SUCCESS;
267 }
268
269 EFI_STATUS
270 EFIAPI
VirtioMmioDeviceRead(IN VIRTIO_DEVICE_PROTOCOL * This,IN UINTN FieldOffset,IN UINTN FieldSize,IN UINTN BufferSize,OUT VOID * Buffer)271 VirtioMmioDeviceRead (
272 IN VIRTIO_DEVICE_PROTOCOL *This,
273 IN UINTN FieldOffset,
274 IN UINTN FieldSize,
275 IN UINTN BufferSize,
276 OUT VOID *Buffer
277 )
278 {
279 UINTN SrcBaseAddress;
280 VIRTIO_MMIO_DEVICE *Device;
281
282 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
283
284 //
285 // Parameter validation
286 //
287 ASSERT (FieldSize == BufferSize);
288
289 //
290 // Double-check fieldsize
291 //
292 if ((FieldSize != 1) && (FieldSize != 2) &&
293 (FieldSize != 4) && (FieldSize != 8)) {
294 return EFI_INVALID_PARAMETER;
295 }
296
297 //
298 // Compute base address
299 //
300 SrcBaseAddress = Device->BaseAddress +
301 VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_MMIO + FieldOffset;
302
303 //
304 // The device-specific memory area of Virtio-MMIO can only be read in
305 // byte reads. This is not currently in the Virtio spec.
306 //
307 MmioReadBuffer8 (SrcBaseAddress, BufferSize, Buffer);
308
309 return EFI_SUCCESS;
310 }
311