]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c
OvmfPkg/VirtioPciDeviceDxe: Implement VIRTIO_DEVICE_PROTOCOL for VirtIo Devices over PCI
[mirror_edk2.git] / OvmfPkg / VirtioPciDeviceDxe / VirtioPciFunctions.c
diff --git a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c
new file mode 100644 (file)
index 0000000..9c40fd9
--- /dev/null
@@ -0,0 +1,283 @@
+/** @file\r
+\r
+  This driver produces Virtio Device Protocol instances for Virtio PCI 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
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
+#include "VirtioPciDevice.h"\r
+\r
+/**\r
+\r
+  Read a word from Region 0 of the device specified by VirtIo Device protocol.\r
+\r
+  The function implements the ReadDevice protocol member of\r
+  VIRTIO_DEVICE_PROTOCOL.\r
+\r
+  @param[in] This         VirtIo Device protocol.\r
+\r
+  @param[in] FieldOffset  Source offset.\r
+\r
+  @param[in] FieldSize    Source field size, must be in { 1, 2, 4, 8 }.\r
+\r
+  @param[in] BufferSize   Number of bytes available in the target buffer. Must\r
+                          equal FieldSize.\r
+\r
+  @param[out] Buffer      Target buffer.\r
+\r
+\r
+  @return  Status code returned by PciIo->Io.Read().\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioPciDeviceRead (\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
+  VIRTIO_PCI_DEVICE         *Dev;\r
+\r
+  Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);\r
+\r
+  return VirtioPciIoRead (Dev,\r
+      Dev->DeviceSpecificConfigurationOffset + FieldOffset,\r
+      FieldSize, BufferSize, Buffer);\r
+}\r
+\r
+/**\r
+\r
+  Write a word into Region 0 of the device specified by VirtIo Device protocol.\r
+\r
+  @param[in] This         VirtIo Device protocol.\r
+\r
+  @param[in] FieldOffset  Destination offset.\r
+\r
+  @param[in] FieldSize    Destination field size, must be in { 1, 2, 4, 8 }.\r
+\r
+  @param[in] Value        Little endian value to write, converted to UINT64.\r
+                          The least significant FieldSize bytes will be used.\r
+\r
+\r
+  @return  Status code returned by PciIo->Io.Write().\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioPciDeviceWrite (\r
+  IN VIRTIO_DEVICE_PROTOCOL *This,\r
+  IN UINTN                  FieldOffset,\r
+  IN UINTN                  FieldSize,\r
+  IN UINT64                 Value\r
+  )\r
+{\r
+  VIRTIO_PCI_DEVICE         *Dev;\r
+\r
+  Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);\r
+\r
+  return VirtioPciIoWrite (Dev,\r
+      Dev->DeviceSpecificConfigurationOffset + FieldOffset, FieldSize, Value);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioPciGetDeviceFeatures (\r
+  IN VIRTIO_DEVICE_PROTOCOL *This,\r
+  OUT UINT32                *DeviceFeatures\r
+  )\r
+{\r
+  VIRTIO_PCI_DEVICE         *Dev;\r
+\r
+  if (DeviceFeatures == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);\r
+\r
+  return VirtioPciIoRead (Dev, VIRTIO_PCI_OFFSET_DEVICE_FEATURES, sizeof (UINT32),\r
+      sizeof (UINT32), DeviceFeatures);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioPciGetQueueAddress (\r
+  IN  VIRTIO_DEVICE_PROTOCOL *This,\r
+  OUT UINT32                 *QueueAddress\r
+  )\r
+{\r
+  VIRTIO_PCI_DEVICE         *Dev;\r
+\r
+  if (QueueAddress == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);\r
+\r
+  return VirtioPciIoRead (Dev, VIRTIO_PCI_OFFSET_QUEUE_ADDRESS, sizeof (UINT32),\r
+      sizeof (UINT32), QueueAddress);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioPciGetQueueSize (\r
+  IN  VIRTIO_DEVICE_PROTOCOL  *This,\r
+  OUT UINT16                  *QueueNumMax\r
+  )\r
+{\r
+  VIRTIO_PCI_DEVICE         *Dev;\r
+\r
+  if (QueueNumMax == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);\r
+\r
+  return VirtioPciIoRead (Dev, VIRTIO_PCI_OFFSET_QUEUE_SIZE, sizeof (UINT16),\r
+      sizeof (UINT16), QueueNumMax);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioPciGetDeviceStatus (\r
+  IN  VIRTIO_DEVICE_PROTOCOL  *This,\r
+  OUT UINT8                   *DeviceStatus\r
+  )\r
+{\r
+  VIRTIO_PCI_DEVICE         *Dev;\r
+\r
+  if (DeviceStatus == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);\r
+\r
+  return VirtioPciIoRead (Dev, VIRTIO_PCI_OFFSET_QUEUE_DEVICE_STATUS,\r
+      sizeof (UINT8), sizeof (UINT8), DeviceStatus);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioPciSetGuestFeatures (\r
+  IN VIRTIO_DEVICE_PROTOCOL  *This,\r
+  IN UINT32                   Features\r
+  )\r
+{\r
+  VIRTIO_PCI_DEVICE *Dev;\r
+\r
+  Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);\r
+\r
+  return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_GUEST_FEATURES,\r
+      sizeof (UINT32), Features);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioPciSetQueueAddress (\r
+  VIRTIO_DEVICE_PROTOCOL    *This,\r
+  UINT32                    Address\r
+  )\r
+{\r
+  VIRTIO_PCI_DEVICE *Dev;\r
+\r
+  Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);\r
+\r
+  return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_QUEUE_ADDRESS, sizeof (UINT32),\r
+      Address);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioPciSetQueueSel (\r
+  VIRTIO_DEVICE_PROTOCOL    *This,\r
+  UINT16                    Sel\r
+  )\r
+{\r
+  VIRTIO_PCI_DEVICE *Dev;\r
+\r
+  Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);\r
+\r
+  return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_QUEUE_SELECT, sizeof (UINT16),\r
+      Sel);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioPciSetQueueAlignment (\r
+  VIRTIO_DEVICE_PROTOCOL *This,\r
+  UINT32                  Alignment\r
+  )\r
+{\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioPciSetPageSize (\r
+  VIRTIO_DEVICE_PROTOCOL *This,\r
+  UINT32                  PageSize\r
+  )\r
+{\r
+  return (PageSize == EFI_PAGE_SIZE) ? EFI_SUCCESS : EFI_UNSUPPORTED;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioPciSetQueueNotify (\r
+  VIRTIO_DEVICE_PROTOCOL *This,\r
+  UINT16                 Index\r
+  )\r
+{\r
+  VIRTIO_PCI_DEVICE *Dev;\r
+\r
+  Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);\r
+\r
+  return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_QUEUE_NOTIFY, sizeof (UINT16),\r
+      Index);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioPciSetQueueSize (\r
+  VIRTIO_DEVICE_PROTOCOL *This,\r
+  UINT16                 Size\r
+  )\r
+{\r
+  //\r
+  // This function is only applicable in Virtio-MMIO.\r
+  // (The QueueSize field is read-only in Virtio proper (PCI))\r
+  //\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioPciSetDeviceStatus (\r
+  VIRTIO_DEVICE_PROTOCOL *This,\r
+  UINT8                  DeviceStatus\r
+  )\r
+{\r
+  VIRTIO_PCI_DEVICE *Dev;\r
+\r
+  Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);\r
+\r
+  return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_QUEUE_DEVICE_STATUS,\r
+      sizeof (UINT8), DeviceStatus);\r
+}\r