--- /dev/null
+/** @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