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
,
187 VIRTIO_MMIO_DEVICE
*Device
;
189 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
191 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_QUEUE_PFN
,
192 (UINT32
)((UINTN
)Ring
->Base
>> EFI_PAGE_SHIFT
));
199 VirtioMmioSetGuestFeatures (
200 IN VIRTIO_DEVICE_PROTOCOL
*This
,
204 VIRTIO_MMIO_DEVICE
*Device
;
206 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
208 if (Features
> MAX_UINT32
) {
209 return EFI_UNSUPPORTED
;
211 VIRTIO_CFG_WRITE (Device
, VIRTIO_MMIO_OFFSET_GUEST_FEATURES
,
219 VirtioMmioDeviceWrite (
220 IN VIRTIO_DEVICE_PROTOCOL
*This
,
221 IN UINTN FieldOffset
,
226 UINTN DstBaseAddress
;
227 VIRTIO_MMIO_DEVICE
*Device
;
229 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
232 // Double-check fieldsize
234 if ((FieldSize
!= 1) && (FieldSize
!= 2) &&
235 (FieldSize
!= 4) && (FieldSize
!= 8)) {
236 return EFI_INVALID_PARAMETER
;
240 // Compute base address
242 DstBaseAddress
= Device
->BaseAddress
+
243 VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_MMIO
+ FieldOffset
;
246 // The device-specific memory area of Virtio-MMIO can only be written in
247 // byte accesses. This is not currently in the Virtio spec.
249 MmioWriteBuffer8 (DstBaseAddress
, FieldSize
, (UINT8
*)&Value
);
256 VirtioMmioDeviceRead (
257 IN VIRTIO_DEVICE_PROTOCOL
*This
,
258 IN UINTN FieldOffset
,
264 UINTN SrcBaseAddress
;
265 VIRTIO_MMIO_DEVICE
*Device
;
267 Device
= VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This
);
270 // Parameter validation
272 ASSERT (FieldSize
== BufferSize
);
275 // Double-check fieldsize
277 if ((FieldSize
!= 1) && (FieldSize
!= 2) &&
278 (FieldSize
!= 4) && (FieldSize
!= 8)) {
279 return EFI_INVALID_PARAMETER
;
283 // Compute base address
285 SrcBaseAddress
= Device
->BaseAddress
+
286 VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_MMIO
+ FieldOffset
;
289 // The device-specific memory area of Virtio-MMIO can only be read in
290 // byte reads. This is not currently in the Virtio spec.
292 MmioReadBuffer8 (SrcBaseAddress
, BufferSize
, Buffer
);
299 VirtioMmioAllocateSharedPages (
300 IN VIRTIO_DEVICE_PROTOCOL
*This
,
302 OUT VOID
**HostAddress
307 Buffer
= AllocatePages (NumPages
);
308 if (Buffer
== NULL
) {
309 return EFI_OUT_OF_RESOURCES
;
312 *HostAddress
= Buffer
;
318 VirtioMmioFreeSharedPages (
319 IN VIRTIO_DEVICE_PROTOCOL
*This
,
324 FreePages (HostAddress
, NumPages
);
329 VirtioMmioMapSharedBuffer (
330 IN VIRTIO_DEVICE_PROTOCOL
*This
,
331 IN VIRTIO_MAP_OPERATION Operation
,
332 IN VOID
*HostAddress
,
333 IN OUT UINTN
*NumberOfBytes
,
334 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
338 *DeviceAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) HostAddress
;
346 VirtioMmioUnmapSharedBuffer (
347 IN VIRTIO_DEVICE_PROTOCOL
*This
,