3 This driver produces Virtio Device Protocol instances for Virtio MMIO devices.
5 Copyright (C) 2012, Red Hat, Inc.
6 Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>
7 Copyright (C) 2013, ARM Ltd.
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
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.
19 #include "VirtioMmioDevice.h"
23 VirtioMmioGetDeviceFeatures (
24 IN VIRTIO_DEVICE_PROTOCOL
*This
,
25 OUT UINT64
*DeviceFeatures
28 VIRTIO_MMIO_DEVICE
*Device
;
30 if (DeviceFeatures
== NULL
) {
31 return EFI_INVALID_PARAMETER
;
34 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
36 *DeviceFeatures
= VIRTIO_CFG_READ (Device
, VIRTIO_MMIO_OFFSET_HOST_FEATURES
);
43 VirtioMmioGetQueueSize (
44 IN VIRTIO_DEVICE_PROTOCOL
*This
,
45 OUT UINT16
*QueueNumMax
48 VIRTIO_MMIO_DEVICE
*Device
;
50 if (QueueNumMax
== NULL
) {
51 return EFI_INVALID_PARAMETER
;
54 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
56 *QueueNumMax
= VIRTIO_CFG_READ (Device
, VIRTIO_MMIO_OFFSET_QUEUE_NUM_MAX
) & 0xFFFF;
63 VirtioMmioGetDeviceStatus (
64 IN VIRTIO_DEVICE_PROTOCOL
*This
,
65 OUT UINT8
*DeviceStatus
68 VIRTIO_MMIO_DEVICE
*Device
;
70 if (DeviceStatus
== NULL
) {
71 return EFI_INVALID_PARAMETER
;
74 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
76 *DeviceStatus
= VIRTIO_CFG_READ (Device
, VIRTIO_MMIO_OFFSET_STATUS
) & 0xFF;
83 VirtioMmioSetQueueSize (
84 IN VIRTIO_DEVICE_PROTOCOL
*This
,
88 VIRTIO_MMIO_DEVICE
*Device
;
90 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
92 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_QUEUE_NUM
, QueueSize
);
99 VirtioMmioSetDeviceStatus (
100 IN VIRTIO_DEVICE_PROTOCOL
*This
,
101 IN UINT8 DeviceStatus
104 VIRTIO_MMIO_DEVICE
*Device
;
106 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
108 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_STATUS
, DeviceStatus
);
115 VirtioMmioSetQueueNotify (
116 IN VIRTIO_DEVICE_PROTOCOL
*This
,
117 IN UINT16 QueueNotify
120 VIRTIO_MMIO_DEVICE
*Device
;
122 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
124 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_QUEUE_NOTIFY
, QueueNotify
);
131 VirtioMmioSetQueueAlignment (
132 IN VIRTIO_DEVICE_PROTOCOL
*This
,
136 VIRTIO_MMIO_DEVICE
*Device
;
138 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
140 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_QUEUE_ALIGN
, Alignment
);
147 VirtioMmioSetPageSize (
148 IN VIRTIO_DEVICE_PROTOCOL
*This
,
152 VIRTIO_MMIO_DEVICE
*Device
;
154 if (PageSize
!= EFI_PAGE_SIZE
) {
155 return EFI_UNSUPPORTED
;
158 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
160 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_GUEST_PAGE_SIZE
, PageSize
);
167 VirtioMmioSetQueueSel (
168 IN VIRTIO_DEVICE_PROTOCOL
*This
,
172 VIRTIO_MMIO_DEVICE
*Device
;
174 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
176 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_QUEUE_SEL
, Sel
);
182 VirtioMmioSetQueueAddress (
183 IN VIRTIO_DEVICE_PROTOCOL
*This
,
185 IN UINT64 RingBaseShift
188 VIRTIO_MMIO_DEVICE
*Device
;
190 ASSERT (RingBaseShift
== 0);
192 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
194 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_QUEUE_PFN
,
195 (UINT32
)((UINTN
)Ring
->Base
>> EFI_PAGE_SHIFT
));
202 VirtioMmioSetGuestFeatures (
203 IN VIRTIO_DEVICE_PROTOCOL
*This
,
207 VIRTIO_MMIO_DEVICE
*Device
;
209 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
211 if (Features
> MAX_UINT32
) {
212 return EFI_UNSUPPORTED
;
214 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_GUEST_FEATURES
,
222 VirtioMmioDeviceWrite (
223 IN VIRTIO_DEVICE_PROTOCOL
*This
,
224 IN UINTN FieldOffset
,
229 UINTN DstBaseAddress
;
230 VIRTIO_MMIO_DEVICE
*Device
;
232 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
235 // Double-check fieldsize
237 if ((FieldSize
!= 1) && (FieldSize
!= 2) &&
238 (FieldSize
!= 4) && (FieldSize
!= 8)) {
239 return EFI_INVALID_PARAMETER
;
243 // Compute base address
245 DstBaseAddress
= Device
->BaseAddress
+
246 VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_MMIO
+ FieldOffset
;
249 // The device-specific memory area of Virtio-MMIO can only be written in
250 // byte accesses. This is not currently in the Virtio spec.
252 MmioWriteBuffer8 (DstBaseAddress
, FieldSize
, (UINT8
*)&Value
);
259 VirtioMmioDeviceRead (
260 IN VIRTIO_DEVICE_PROTOCOL
*This
,
261 IN UINTN FieldOffset
,
267 UINTN SrcBaseAddress
;
268 VIRTIO_MMIO_DEVICE
*Device
;
270 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
273 // Parameter validation
275 ASSERT (FieldSize
== BufferSize
);
278 // Double-check fieldsize
280 if ((FieldSize
!= 1) && (FieldSize
!= 2) &&
281 (FieldSize
!= 4) && (FieldSize
!= 8)) {
282 return EFI_INVALID_PARAMETER
;
286 // Compute base address
288 SrcBaseAddress
= Device
->BaseAddress
+
289 VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_MMIO
+ FieldOffset
;
292 // The device-specific memory area of Virtio-MMIO can only be read in
293 // byte reads. This is not currently in the Virtio spec.
295 MmioReadBuffer8 (SrcBaseAddress
, BufferSize
, Buffer
);
302 VirtioMmioAllocateSharedPages (
303 IN VIRTIO_DEVICE_PROTOCOL
*This
,
305 OUT VOID
**HostAddress
310 Buffer
= AllocatePages (NumPages
);
311 if (Buffer
== NULL
) {
312 return EFI_OUT_OF_RESOURCES
;
315 *HostAddress
= Buffer
;
321 VirtioMmioFreeSharedPages (
322 IN VIRTIO_DEVICE_PROTOCOL
*This
,
327 FreePages (HostAddress
, NumPages
);
332 VirtioMmioMapSharedBuffer (
333 IN VIRTIO_DEVICE_PROTOCOL
*This
,
334 IN VIRTIO_MAP_OPERATION Operation
,
335 IN VOID
*HostAddress
,
336 IN OUT UINTN
*NumberOfBytes
,
337 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
341 *DeviceAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) HostAddress
;
349 VirtioMmioUnmapSharedBuffer (
350 IN VIRTIO_DEVICE_PROTOCOL
*This
,