]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c
OvmfPkg/VirtioMmioDeviceLib: Implement VIRTIO_DEVICE_PROTOCOL for VirtIo Devices...
[mirror_edk2.git] / OvmfPkg / Library / VirtioMmioDeviceLib / VirtioMmioDeviceFunctions.c
diff --git a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c
new file mode 100644 (file)
index 0000000..3950c07
--- /dev/null
@@ -0,0 +1,310 @@
+/** @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