--- /dev/null
+/** @file\r
+\r
+ This driver produces Virtio Device Protocol instances for Virtio MMIO devices.\r
+\r
+ Copyright (C) 2012, Red Hat, Inc.\r
+ Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (C) 2013, ARM Ltd.\r
+\r
+ This program and the accompanying materials are licensed and made available\r
+ under the terms and conditions of the BSD License which accompanies this\r
+ distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
+ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "VirtioMmioDevice.h"\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioMmioGetDeviceFeatures (\r
+ IN VIRTIO_DEVICE_PROTOCOL *This,\r
+ OUT UINT32 *DeviceFeatures\r
+ )\r
+{\r
+ VIRTIO_MMIO_DEVICE *Device;\r
+\r
+ if (DeviceFeatures == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
+\r
+ *DeviceFeatures = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_HOST_FEATURES);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioMmioGetQueueAddress (\r
+ IN VIRTIO_DEVICE_PROTOCOL *This,\r
+ OUT UINT32 *QueueAddress\r
+ )\r
+{\r
+ VIRTIO_MMIO_DEVICE *Device;\r
+\r
+ if (QueueAddress == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
+\r
+ *QueueAddress = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_QUEUE_PFN);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioMmioGetQueueSize (\r
+ IN VIRTIO_DEVICE_PROTOCOL *This,\r
+ OUT UINT16 *QueueNumMax\r
+ )\r
+{\r
+ VIRTIO_MMIO_DEVICE *Device;\r
+\r
+ if (QueueNumMax == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
+\r
+ *QueueNumMax = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_QUEUE_NUM_MAX) & 0xFFFF;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioMmioGetDeviceStatus (\r
+ IN VIRTIO_DEVICE_PROTOCOL *This,\r
+ OUT UINT8 *DeviceStatus\r
+ )\r
+{\r
+ VIRTIO_MMIO_DEVICE *Device;\r
+\r
+ if (DeviceStatus == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
+\r
+ *DeviceStatus = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_STATUS) & 0xFF;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioMmioSetQueueSize (\r
+ VIRTIO_DEVICE_PROTOCOL *This,\r
+ UINT16 QueueSize\r
+ )\r
+{\r
+ VIRTIO_MMIO_DEVICE *Device;\r
+\r
+ Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
+\r
+ VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_NUM, QueueSize);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioMmioSetDeviceStatus (\r
+ VIRTIO_DEVICE_PROTOCOL *This,\r
+ UINT8 DeviceStatus\r
+ )\r
+{\r
+ VIRTIO_MMIO_DEVICE *Device;\r
+\r
+ Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
+\r
+ VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_STATUS, DeviceStatus);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioMmioSetQueueNotify (\r
+ VIRTIO_DEVICE_PROTOCOL *This,\r
+ UINT16 QueueNotify\r
+ )\r
+{\r
+ VIRTIO_MMIO_DEVICE *Device;\r
+\r
+ Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
+\r
+ VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_NOTIFY, QueueNotify);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioMmioSetQueueAlignment (\r
+ VIRTIO_DEVICE_PROTOCOL *This,\r
+ UINT32 Alignment\r
+ )\r
+{\r
+ VIRTIO_MMIO_DEVICE *Device;\r
+\r
+ Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
+\r
+ VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_ALIGN, Alignment);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioMmioSetPageSize (\r
+ VIRTIO_DEVICE_PROTOCOL *This,\r
+ UINT32 PageSize\r
+ )\r
+{\r
+ VIRTIO_MMIO_DEVICE *Device;\r
+\r
+ if (PageSize != EFI_PAGE_SIZE) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
+\r
+ VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_GUEST_PAGE_SIZE, PageSize);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioMmioSetQueueSel (\r
+ VIRTIO_DEVICE_PROTOCOL *This,\r
+ UINT16 Sel\r
+ )\r
+{\r
+ VIRTIO_MMIO_DEVICE *Device;\r
+\r
+ Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
+\r
+ VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_SEL, Sel);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+VirtioMmioSetQueueAddress (\r
+ VIRTIO_DEVICE_PROTOCOL *This,\r
+ UINT32 Address\r
+ )\r
+{\r
+ VIRTIO_MMIO_DEVICE *Device;\r
+\r
+ Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
+\r
+ VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_PFN, Address);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioMmioSetGuestFeatures (\r
+ VIRTIO_DEVICE_PROTOCOL *This,\r
+ UINT32 Features\r
+ )\r
+{\r
+ VIRTIO_MMIO_DEVICE *Device;\r
+\r
+ Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
+\r
+ VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_GUEST_FEATURES, Features);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioMmioDeviceWrite (\r
+ IN VIRTIO_DEVICE_PROTOCOL *This,\r
+ IN UINTN FieldOffset,\r
+ IN UINTN FieldSize,\r
+ IN UINT64 Value\r
+ )\r
+{\r
+ UINTN DstBaseAddress;\r
+ VIRTIO_MMIO_DEVICE *Device;\r
+\r
+ Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
+\r
+ //\r
+ // Double-check fieldsize\r
+ //\r
+ if ((FieldSize != 1) && (FieldSize != 2) &&\r
+ (FieldSize != 4) && (FieldSize != 8)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Compute base address\r
+ //\r
+ DstBaseAddress = Device->BaseAddress +\r
+ VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_MMIO + FieldOffset;\r
+\r
+ //\r
+ // The device-specific memory area of Virtio-MMIO can only be written in\r
+ // byte accesses. This is not currently in the Virtio spec.\r
+ //\r
+ MmioWriteBuffer8 (DstBaseAddress, FieldSize, (UINT8*)&Value);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioMmioDeviceRead (\r
+ IN VIRTIO_DEVICE_PROTOCOL *This,\r
+ IN UINTN FieldOffset,\r
+ IN UINTN FieldSize,\r
+ IN UINTN BufferSize,\r
+ OUT VOID *Buffer\r
+ )\r
+{\r
+ UINTN SrcBaseAddress;\r
+ VIRTIO_MMIO_DEVICE *Device;\r
+\r
+ Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
+\r
+ //\r
+ // Parameter validation\r
+ //\r
+ ASSERT (FieldSize == BufferSize);\r
+\r
+ //\r
+ // Double-check fieldsize\r
+ //\r
+ if ((FieldSize != 1) && (FieldSize != 2) &&\r
+ (FieldSize != 4) && (FieldSize != 8)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Compute base address\r
+ //\r
+ SrcBaseAddress = Device->BaseAddress +\r
+ VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_MMIO + FieldOffset;\r
+\r
+ //\r
+ // The device-specific memory area of Virtio-MMIO can only be read in\r
+ // byte reads. This is not currently in the Virtio spec.\r
+ //\r
+ MmioReadBuffer8 (SrcBaseAddress, BufferSize, Buffer);\r
+\r
+ return EFI_SUCCESS;\r
+}\r