//\r
#pragma pack(1)\r
typedef struct {\r
- VIRTIO_HDR Generic;\r
- UINT64 VhdrCapacity;\r
- UINT32 VhdrSizeMax;\r
- UINT32 VhdrSegMax;\r
- UINT16 VhdrCylinders;\r
- UINT8 VhdrHeads;\r
- UINT8 VhdrSectors;\r
- UINT32 VhdrBlkSize;\r
-} VBLK_HDR;\r
+ UINT64 Capacity;\r
+ UINT32 SizeMax;\r
+ UINT32 SegMax;\r
+ UINT16 Cylinders;\r
+ UINT8 Heads;\r
+ UINT8 Sectors;\r
+ UINT32 BlkSize;\r
+} VIRTIO_BLK_CONFIG;\r
#pragma pack()\r
\r
-#define OFFSET_OF_VBLK(Field) OFFSET_OF (VBLK_HDR, Field)\r
-#define SIZE_OF_VBLK(Field) (sizeof ((VBLK_HDR *) 0)->Field)\r
+#define OFFSET_OF_VBLK(Field) OFFSET_OF (VIRTIO_BLK_CONFIG, Field)\r
+#define SIZE_OF_VBLK(Field) (sizeof ((VIRTIO_BLK_CONFIG *) 0)->Field)\r
\r
#define VIRTIO_BLK_F_BARRIER BIT0\r
#define VIRTIO_BLK_F_SIZE_MAX BIT1\r
/** @file\r
-\r
Virtio Network Device specific type and macro definitions corresponding to\r
the virtio-0.9.5 specification.\r
\r
//\r
#pragma pack(1)\r
typedef struct {\r
- VIRTIO_HDR Generic;\r
- UINT8 VhdrMac[6];\r
- UINT16 VhdrLinkStatus;\r
-} VNET_HDR;\r
+ UINT8 Mac[6];\r
+ UINT16 LinkStatus;\r
+} VIRTIO_NET_CONFIG;\r
#pragma pack()\r
\r
-#define OFFSET_OF_VNET(Field) OFFSET_OF (VNET_HDR, Field)\r
-#define SIZE_OF_VNET(Field) (sizeof ((VNET_HDR *) 0)->Field)\r
+#define OFFSET_OF_VNET(Field) OFFSET_OF (VIRTIO_NET_CONFIG, Field)\r
+#define SIZE_OF_VNET(Field) (sizeof ((VIRTIO_NET_CONFIG *) 0)->Field)\r
\r
//\r
// Queue Identifiers\r
#define VIRTIO_NET_HDR_GSO_ECN BIT7\r
\r
//\r
-// Link Status Bits in VNET_HDR.VhdrLinkStatus\r
+// Link Status Bits in VIRTIO_NET_CONFIG.LinkStatus\r
//\r
#define VIRTIO_NET_S_LINK_UP BIT0\r
#define VIRTIO_NET_S_ANNOUNCE BIT1\r
//\r
#pragma pack(1)\r
typedef struct {\r
- VIRTIO_HDR Generic;\r
- UINT32 VhdrNumQueues;\r
- UINT32 VhdrSegMax;\r
- UINT32 VhdrMaxSectors;\r
- UINT32 VhdrCmdPerLun;\r
- UINT32 VhdrEventInfoSize;\r
- UINT32 VhdrSenseSize;\r
- UINT32 VhdrCdbSize;\r
- UINT16 VhdrMaxChannel;\r
- UINT16 VhdrMaxTarget;\r
- UINT32 VhdrMaxLun;\r
-} VSCSI_HDR;\r
+ UINT32 NumQueues;\r
+ UINT32 SegMax;\r
+ UINT32 MaxSectors;\r
+ UINT32 CmdPerLun;\r
+ UINT32 EventInfoSize;\r
+ UINT32 SenseSize;\r
+ UINT32 CdbSize;\r
+ UINT16 MaxChannel;\r
+ UINT16 MaxTarget;\r
+ UINT32 MaxLun;\r
+} VIRTIO_SCSI_CONFIG;\r
#pragma pack()\r
\r
-#define OFFSET_OF_VSCSI(Field) OFFSET_OF (VSCSI_HDR, Field)\r
-#define SIZE_OF_VSCSI(Field) (sizeof ((VSCSI_HDR *) 0)->Field)\r
+#define OFFSET_OF_VSCSI(Field) OFFSET_OF (VIRTIO_SCSI_CONFIG, Field)\r
+#define SIZE_OF_VSCSI(Field) (sizeof ((VIRTIO_SCSI_CONFIG *) 0)->Field)\r
\r
#define VIRTIO_SCSI_F_INOUT BIT0\r
#define VIRTIO_SCSI_F_HOTPLUG BIT1\r
#ifndef _VIRTIO_LIB_H_\r
#define _VIRTIO_LIB_H_\r
\r
-#include <Protocol/PciIo.h>\r
+#include <Protocol/VirtioDevice.h>\r
+\r
#include <IndustryStandard/Virtio.h>\r
\r
/**\r
\r
- Write a word into Region 0 of the device specified by PciIo.\r
+ Write a word into VirtIo Device Specific Region\r
\r
- Region 0 must be an iomem region. This is an internal function for the\r
- driver-specific VIRTIO_CFG_WRITE() macros.\r
+ The VirtIo Device Specific Region must be an iomem region.\r
+ This is an internal function for the driver-specific VIRTIO_CFG_WRITE()\r
+ macros.\r
\r
- @param[in] PciIo Target PCI device.\r
+ @param[in] VirtIo Target Virtio device.\r
\r
@param[in] FieldOffset Destination offset.\r
\r
The least significant FieldSize bytes will be used.\r
\r
\r
- @return Status code returned by PciIo->Io.Write().\r
+ @return Status code returned by VirtIo->WriteDevice().\r
\r
**/\r
EFI_STATUS\r
EFIAPI\r
-VirtioWrite (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN UINTN FieldOffset,\r
- IN UINTN FieldSize,\r
- IN UINT64 Value\r
+VirtioWriteDevice (\r
+ IN VIRTIO_DEVICE_PROTOCOL *VirtIo,\r
+ IN UINTN FieldOffset,\r
+ IN UINTN FieldSize,\r
+ IN UINT64 Value\r
);\r
\r
\r
/**\r
\r
- Read a word from Region 0 of the device specified by PciIo.\r
+ Read a word from VirtIo Device Specific Region\r
\r
- Region 0 must be an iomem region. This is an internal function for the\r
- driver-specific VIRTIO_CFG_READ() macros.\r
+ The VirtIo Device Specific Region must be an iomem region.\r
+ This is an internal function for the driver-specific VIRTIO_CFG_READ()\r
+ macros.\r
\r
- @param[in] PciIo Source PCI device.\r
+ @param[in] VirtIo Source Virtio device.\r
\r
@param[in] FieldOffset Source offset.\r
\r
@param[out] Buffer Target buffer.\r
\r
\r
- @return Status code returned by PciIo->Io.Read().\r
+ @return Status code returned by VirtIo->ReadDevice().\r
\r
**/\r
EFI_STATUS\r
EFIAPI\r
-VirtioRead (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN UINTN FieldOffset,\r
- IN UINTN FieldSize,\r
- IN UINTN BufferSize,\r
- OUT VOID *Buffer\r
+VirtioReadDevice (\r
+ IN VIRTIO_DEVICE_PROTOCOL *VirtIo,\r
+ IN UINTN FieldOffset,\r
+ IN UINTN FieldSize,\r
+ IN UINTN BufferSize,\r
+ OUT VOID *Buffer\r
);\r
\r
\r
Notify the host about the descriptor chain just built, and wait until the\r
host processes it.\r
\r
- @param[in] PciIo The target virtio PCI device to notify.\r
+ @param[in] VirtIo The target virtio device to notify.\r
\r
@param[in] VirtQueueId Identifies the queue for the target device.\r
\r
of the descriptor chain.\r
\r
\r
- @return Error code from VirtioWrite() if it fails.\r
+ @return Error code from VirtIo->SetQueueNotify() if it fails.\r
\r
@retval EFI_SUCCESS Otherwise, the host processed all descriptors.\r
\r
EFI_STATUS\r
EFIAPI\r
VirtioFlush (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN UINT16 VirtQueueId,\r
- IN OUT VRING *Ring,\r
- IN DESC_INDICES *Indices\r
+ IN VIRTIO_DEVICE_PROTOCOL *VirtIo,\r
+ IN UINT16 VirtQueueId,\r
+ IN OUT VRING *Ring,\r
+ IN DESC_INDICES *Indices\r
);\r
\r
#endif // _VIRTIO_LIB_H_\r
Utility functions used by virtio device drivers.\r
\r
Copyright (C) 2012, Red Hat, Inc.\r
+ Portion of 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
\r
**/\r
\r
-#include <IndustryStandard/Pci22.h>\r
#include <Library/BaseLib.h>\r
#include <Library/BaseMemoryLib.h>\r
#include <Library/DebugLib.h>\r
\r
/**\r
\r
- Write a word into Region 0 of the device specified by PciIo.\r
+ Write a word into Region 0 of the device specified by VirtIo.\r
\r
Region 0 must be an iomem region. This is an internal function for the\r
driver-specific VIRTIO_CFG_WRITE() macros.\r
\r
- @param[in] PciIo Target PCI device.\r
+ @param[in] VirtIo Target VirtIo device.\r
\r
@param[in] FieldOffset Destination offset.\r
\r
The least significant FieldSize bytes will be used.\r
\r
\r
- @return Status code returned by PciIo->Io.Write().\r
+ @return Status code returned by VirtIo->Io.Write().\r
\r
**/\r
EFI_STATUS\r
EFIAPI\r
-VirtioWrite (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN UINTN FieldOffset,\r
- IN UINTN FieldSize,\r
- IN UINT64 Value\r
+VirtioWriteDevice (\r
+ IN VIRTIO_DEVICE_PROTOCOL *VirtIo,\r
+ IN UINTN FieldOffset,\r
+ IN UINTN FieldSize,\r
+ IN UINT64 Value\r
)\r
{\r
- UINTN Count;\r
- EFI_PCI_IO_PROTOCOL_WIDTH Width;\r
-\r
- Count = 1;\r
- switch (FieldSize) {\r
- case 1:\r
- Width = EfiPciIoWidthUint8;\r
- break;\r
-\r
- case 2:\r
- Width = EfiPciIoWidthUint16;\r
- break;\r
-\r
- case 8:\r
- Count = 2;\r
- // fall through\r
-\r
- case 4:\r
- Width = EfiPciIoWidthUint32;\r
- break;\r
-\r
- default:\r
- ASSERT (FALSE);\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- return PciIo->Io.Write (\r
- PciIo,\r
- Width,\r
- PCI_BAR_IDX0,\r
- FieldOffset,\r
- Count,\r
- &Value\r
- );\r
+ return VirtIo->WriteDevice (VirtIo, FieldOffset, FieldSize, Value);\r
}\r
\r
\r
/**\r
\r
- Read a word from Region 0 of the device specified by PciIo.\r
+ Read a word from Region 0 of the device specified by VirtIo.\r
\r
Region 0 must be an iomem region. This is an internal function for the\r
driver-specific VIRTIO_CFG_READ() macros.\r
\r
- @param[in] PciIo Source PCI device.\r
+ @param[in] VirtIo Source VirtIo device.\r
\r
@param[in] FieldOffset Source offset.\r
\r
@param[out] Buffer Target buffer.\r
\r
\r
- @return Status code returned by PciIo->Io.Read().\r
+ @return Status code returned by VirtIo->Io.Read().\r
\r
**/\r
EFI_STATUS\r
EFIAPI\r
-VirtioRead (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN UINTN FieldOffset,\r
- IN UINTN FieldSize,\r
- IN UINTN BufferSize,\r
- OUT VOID *Buffer\r
+VirtioReadDevice (\r
+ IN VIRTIO_DEVICE_PROTOCOL *VirtIo,\r
+ IN UINTN FieldOffset,\r
+ IN UINTN FieldSize,\r
+ IN UINTN BufferSize,\r
+ OUT VOID *Buffer\r
)\r
{\r
- UINTN Count;\r
- EFI_PCI_IO_PROTOCOL_WIDTH Width;\r
-\r
- ASSERT (FieldSize == BufferSize);\r
-\r
- Count = 1;\r
- switch (FieldSize) {\r
- case 1:\r
- Width = EfiPciIoWidthUint8;\r
- break;\r
-\r
- case 2:\r
- Width = EfiPciIoWidthUint16;\r
- break;\r
-\r
- case 8:\r
- Count = 2;\r
- // fall through\r
-\r
- case 4:\r
- Width = EfiPciIoWidthUint32;\r
- break;\r
-\r
- default:\r
- ASSERT (FALSE);\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- return PciIo->Io.Read (\r
- PciIo,\r
- Width,\r
- PCI_BAR_IDX0,\r
- FieldOffset,\r
- Count,\r
- Buffer\r
- );\r
+ return VirtIo->ReadDevice (VirtIo, FieldOffset, FieldSize, BufferSize, Buffer);\r
}\r
\r
\r
Notify the host about the descriptor chain just built, and wait until the\r
host processes it.\r
\r
- @param[in] PciIo The target virtio PCI device to notify.\r
+ @param[in] VirtIo The target virtio device to notify.\r
\r
@param[in] VirtQueueId Identifies the queue for the target device.\r
\r
of the descriptor chain.\r
\r
\r
- @return Error code from VirtioWrite() if it fails.\r
+ @return Error code from VirtIo->SetQueueNotify() if it fails.\r
\r
@retval EFI_SUCCESS Otherwise, the host processed all descriptors.\r
\r
EFI_STATUS\r
EFIAPI\r
VirtioFlush (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN UINT16 VirtQueueId,\r
- IN OUT VRING *Ring,\r
- IN DESC_INDICES *Indices\r
+ IN VIRTIO_DEVICE_PROTOCOL *VirtIo,\r
+ IN UINT16 VirtQueueId,\r
+ IN OUT VRING *Ring,\r
+ IN DESC_INDICES *Indices\r
)\r
{\r
UINT16 NextAvailIdx;\r
// OK.\r
//\r
MemoryFence();\r
- Status = VirtioWrite (\r
- PciIo,\r
- OFFSET_OF (VIRTIO_HDR, VhdrQueueNotify),\r
- sizeof (UINT16),\r
- VirtQueueId\r
- );\r
+ Status = VirtIo->SetQueueNotify (VirtIo, VirtQueueId);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
}\r
\r
OvmfPkg/BlockMmioToBlockIoDxe/BlockIo.inf\r
+ OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf\r
OvmfPkg/VirtioBlkDxe/VirtioBlk.inf\r
OvmfPkg/VirtioScsiDxe/VirtioScsi.inf\r
OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf\r
INF PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf\r
\r
INF OvmfPkg/BlockMmioToBlockIoDxe/BlockIo.inf\r
+INF OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf\r
INF OvmfPkg/VirtioBlkDxe/VirtioBlk.inf\r
INF OvmfPkg/VirtioScsiDxe/VirtioScsi.inf\r
INF OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf\r
}\r
\r
OvmfPkg/BlockMmioToBlockIoDxe/BlockIo.inf\r
+ OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf\r
OvmfPkg/VirtioBlkDxe/VirtioBlk.inf\r
OvmfPkg/VirtioScsiDxe/VirtioScsi.inf\r
OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf\r
INF PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf\r
\r
INF OvmfPkg/BlockMmioToBlockIoDxe/BlockIo.inf\r
+INF OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf\r
INF OvmfPkg/VirtioBlkDxe/VirtioBlk.inf\r
INF OvmfPkg/VirtioScsiDxe/VirtioScsi.inf\r
INF OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf\r
}\r
\r
OvmfPkg/BlockMmioToBlockIoDxe/BlockIo.inf\r
+ OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf\r
OvmfPkg/VirtioBlkDxe/VirtioBlk.inf\r
OvmfPkg/VirtioScsiDxe/VirtioScsi.inf\r
OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf\r
INF PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf\r
\r
INF OvmfPkg/BlockMmioToBlockIoDxe/BlockIo.inf\r
+INF OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf\r
INF OvmfPkg/VirtioBlkDxe/VirtioBlk.inf\r
INF OvmfPkg/VirtioScsiDxe/VirtioScsi.inf\r
INF OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf\r
\r
**/\r
\r
-#include <IndustryStandard/Pci.h>\r
#include <IndustryStandard/VirtioBlk.h>\r
#include <Library/BaseMemoryLib.h>\r
#include <Library/DebugLib.h>\r
/**\r
\r
Convenience macros to read and write region 0 IO space elements of the\r
- virtio-blk PCI device, for configuration purposes.\r
+ virtio-blk device, for configuration purposes.\r
\r
The following macros make it possible to specify only the "core parameters"\r
for such accesses and to derive the rest. By the time VIRTIO_CFG_WRITE()\r
returns, the transaction will have been completed.\r
\r
- @param[in] Dev Pointer to the VBLK_DEV structure whose PCI IO space\r
- we're accessing. Dev->PciIo must be valid.\r
+ @param[in] Dev Pointer to the VBLK_DEV structure whose VirtIo space\r
+ we're accessing. Dev->VirtIo must be valid.\r
\r
@param[in] Field A field name from VBLK_HDR, identifying the virtio-blk\r
configuration item to access.\r
one of UINT8, UINT16, UINT32, UINT64.\r
\r
\r
- @return Status code returned by VirtioWrite() / VirtioRead().\r
+ @return Status code returned by VirtioWriteDevice() / VirtioReadDevice().\r
\r
**/\r
\r
-#define VIRTIO_CFG_WRITE(Dev, Field, Value) (VirtioWrite ( \\r
- (Dev)->PciIo, \\r
+#define VIRTIO_CFG_WRITE(Dev, Field, Value) (VirtioWriteDevice ( \\r
+ (Dev)->VirtIo, \\r
OFFSET_OF_VBLK (Field), \\r
SIZE_OF_VBLK (Field), \\r
(Value) \\r
))\r
\r
-#define VIRTIO_CFG_READ(Dev, Field, Pointer) (VirtioRead ( \\r
- (Dev)->PciIo, \\r
+#define VIRTIO_CFG_READ(Dev, Field, Pointer) (VirtioReadDevice ( \\r
+ (Dev)->VirtIo, \\r
OFFSET_OF_VBLK (Field), \\r
SIZE_OF_VBLK (Field), \\r
sizeof *(Pointer), \\r
\r
@retval EFI_SUCCESS Transfer complete.\r
\r
- @retval EFI_DEVICE_ERROR Failed to notify host side via PCI write, or\r
+ @retval EFI_DEVICE_ERROR Failed to notify host side via VirtIo write, or\r
unable to parse host response, or host response\r
is not VIRTIO_BLK_S_OK.\r
\r
//\r
// virtio-blk's only virtqueue is #0, called "requestq" (see Appendix D).\r
//\r
- if (VirtioFlush (Dev->PciIo, 0, &Dev->Ring, &Indices) == EFI_SUCCESS &&\r
+ if (VirtioFlush (Dev->VirtIo, 0, &Dev->Ring, &Indices) == EFI_SUCCESS &&\r
HostStatus == VIRTIO_BLK_S_OK) {\r
return EFI_SUCCESS;\r
}\r
underlying device\r
- 9 Driver Binding Protocol -- for exporting ourselves\r
\r
- Specs relevant in the specific sense:\r
- - UEFI Spec 2.3.1 + Errata C, 13.4 EFI PCI I/O Protocol\r
- - Driver Writer's Guide for UEFI 2.3.1 v1.01, 18 PCI Driver Design\r
- Guidelines, 18.3 PCI drivers.\r
-\r
@param[in] This The EFI_DRIVER_BINDING_PROTOCOL object\r
incorporating this driver (independently of\r
any device).\r
\r
@retval EFI_SUCCESS The driver supports the device being probed.\r
\r
- @retval EFI_UNSUPPORTED Based on virtio-blk PCI discovery, we do not support\r
+ @retval EFI_UNSUPPORTED Based on virtio-blk discovery, we do not support\r
the device.\r
\r
@return Error codes from the OpenProtocol() boot service or\r
- the PciIo protocol.\r
+ the VirtIo protocol.\r
\r
**/\r
\r
)\r
{\r
EFI_STATUS Status;\r
- EFI_PCI_IO_PROTOCOL *PciIo;\r
- PCI_TYPE00 Pci;\r
+ VIRTIO_DEVICE_PROTOCOL *VirtIo;\r
\r
//\r
- // Attempt to open the device with the PciIo set of interfaces. On success,\r
- // the protocol is "instantiated" for the PCI device. Covers duplicate open\r
+ // Attempt to open the device with the VirtIo set of interfaces. On success,\r
+ // the protocol is "instantiated" for the VirtIo device. Covers duplicate open\r
// attempts (EFI_ALREADY_STARTED).\r
//\r
Status = gBS->OpenProtocol (\r
DeviceHandle, // candidate device\r
- &gEfiPciIoProtocolGuid, // for generic PCI access\r
- (VOID **)&PciIo, // handle to instantiate\r
+ &gVirtioDeviceProtocolGuid, // for generic VirtIo access\r
+ (VOID **)&VirtIo, // handle to instantiate\r
This->DriverBindingHandle, // requestor driver identity\r
DeviceHandle, // ControllerHandle, according to\r
// the UEFI Driver Model\r
- EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive PciIo access to\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive VirtIo access to\r
// the device; to be released\r
);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
- //\r
- // Read entire PCI configuration header for more extensive check ahead.\r
- //\r
- Status = PciIo->Pci.Read (\r
- PciIo, // (protocol, device)\r
- // handle\r
- EfiPciIoWidthUint32, // access width & copy\r
- // mode\r
- 0, // Offset\r
- sizeof Pci / sizeof (UINT32), // Count\r
- &Pci // target buffer\r
- );\r
-\r
- if (Status == EFI_SUCCESS) {\r
- //\r
- // virtio-0.9.5, 2.1 PCI Discovery\r
- //\r
- Status = (Pci.Hdr.VendorId == 0x1AF4 &&\r
- Pci.Hdr.DeviceId >= 0x1000 && Pci.Hdr.DeviceId <= 0x103F &&\r
- Pci.Hdr.RevisionID == 0x00 &&\r
- Pci.Device.SubsystemID == VIRTIO_SUBSYSTEM_BLOCK_DEVICE) ? EFI_SUCCESS : EFI_UNSUPPORTED;\r
+ if (VirtIo->SubSystemDeviceId != VIRTIO_SUBSYSTEM_BLOCK_DEVICE) {\r
+ Status = EFI_UNSUPPORTED;\r
}\r
\r
//\r
- // We needed PCI IO access only transitorily, to see whether we support the\r
+ // We needed VirtIo access only transitorily, to see whether we support the\r
// device or not.\r
//\r
- gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
+ gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
This->DriverBindingHandle, DeviceHandle);\r
return Status;\r
}\r
device.\r
\r
@param[in out] Dev The driver instance to configure. The caller is\r
- responsible for Dev->PciIo's validity (ie. working IO\r
- access to the underlying virtio-blk PCI device).\r
+ responsible for Dev->VirtIo's validity (ie. working IO\r
+ access to the underlying virtio-blk device).\r
\r
@retval EFI_SUCCESS Setup complete.\r
\r
// Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence.\r
//\r
NextDevStat = 0; // step 1 -- reset device\r
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);\r
+ Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
if (EFI_ERROR (Status)) {\r
goto Failed;\r
}\r
\r
NextDevStat |= VSTAT_ACK; // step 2 -- acknowledge device presence\r
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);\r
+ Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
if (EFI_ERROR (Status)) {\r
goto Failed;\r
}\r
\r
NextDevStat |= VSTAT_DRIVER; // step 3 -- we know how to drive it\r
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);\r
+ Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Failed;\r
+ }\r
+\r
+ //\r
+ // Set Page Size - MMIO VirtIo Specific\r
+ //\r
+ Status = Dev->VirtIo->SetPageSize (Dev->VirtIo, EFI_PAGE_SIZE);\r
if (EFI_ERROR (Status)) {\r
goto Failed;\r
}\r
//\r
// step 4a -- retrieve and validate features\r
//\r
- Status = VIRTIO_CFG_READ (Dev, Generic.VhdrDeviceFeatureBits, &Features);\r
+ Status = Dev->VirtIo->GetDeviceFeatures (Dev->VirtIo, &Features);\r
if (EFI_ERROR (Status)) {\r
goto Failed;\r
}\r
- Status = VIRTIO_CFG_READ (Dev, VhdrCapacity, &NumSectors);\r
+\r
+ Status = VIRTIO_CFG_READ (Dev, Capacity, &NumSectors);\r
if (EFI_ERROR (Status)) {\r
goto Failed;\r
}\r
}\r
\r
if (Features & VIRTIO_BLK_F_BLK_SIZE) {\r
- Status = VIRTIO_CFG_READ (Dev, VhdrBlkSize, &BlockSize);\r
+ Status = VIRTIO_CFG_READ (Dev, BlkSize, &BlockSize);\r
if (EFI_ERROR (Status)) {\r
goto Failed;\r
}\r
//\r
// step 4b -- allocate virtqueue\r
//\r
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueSelect, 0);\r
+ Status = Dev->VirtIo->SetQueueSel (Dev->VirtIo, 0);\r
if (EFI_ERROR (Status)) {\r
goto Failed;\r
}\r
- Status = VIRTIO_CFG_READ (Dev, Generic.VhdrQueueSize, &QueueSize);\r
+ Status = Dev->VirtIo->GetQueueNumMax (Dev->VirtIo, &QueueSize);\r
if (EFI_ERROR (Status)) {\r
goto Failed;\r
}\r
}\r
\r
//\r
- // step 4c -- Report GPFN (guest-physical frame number) of queue. If anything\r
- // fails from here on, we must release the ring resources.\r
+ // Additional steps for MMIO: align the queue appropriately, and set the\r
+ // size. If anything fails from here on, we must release the ring resources.\r
+ //\r
+ Status = Dev->VirtIo->SetQueueNum (Dev->VirtIo, QueueSize);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ReleaseQueue;\r
+ }\r
+\r
+ Status = Dev->VirtIo->SetQueueAlign (Dev->VirtIo, EFI_PAGE_SIZE);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ReleaseQueue;\r
+ }\r
+\r
+ //\r
+ // step 4c -- Report GPFN (guest-physical frame number) of queue.\r
//\r
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueAddress,\r
- (UINTN) Dev->Ring.Base >> EFI_PAGE_SHIFT);\r
+ Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo,\r
+ (UINT32)(UINTN) Dev->Ring.Base >> EFI_PAGE_SHIFT);\r
if (EFI_ERROR (Status)) {\r
goto ReleaseQueue;\r
}\r
\r
+\r
//\r
// step 5 -- Report understood features. There are no virtio-blk specific\r
// features to negotiate in virtio-0.9.5, plus we do not want any of the\r
// device-independent (known or unknown) VIRTIO_F_* capabilities (see\r
// Appendix B).\r
//\r
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrGuestFeatureBits, 0);\r
+ Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, 0);\r
if (EFI_ERROR (Status)) {\r
goto ReleaseQueue;\r
}\r
// step 6 -- initialization complete\r
//\r
NextDevStat |= VSTAT_DRIVER_OK;\r
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);\r
+ Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
if (EFI_ERROR (Status)) {\r
goto ReleaseQueue;\r
}\r
Failed:\r
//\r
// Notify the host about our failure to setup: virtio-0.9.5, 2.2.2.1 Device\r
- // Status. PCI IO access failure here should not mask the original error.\r
+ // Status. VirtIo access failure here should not mask the original error.\r
//\r
NextDevStat |= VSTAT_FAILED;\r
- VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);\r
+ Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
\r
return Status; // reached only via Failed above\r
}\r
// VIRTIO_CFG_WRITE() returns, the host will have learned to stay away from\r
// the old comms area.\r
//\r
- VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, 0);\r
+ Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);\r
\r
VirtioRingUninit (&Dev->Ring);\r
\r
\r
\r
@retval EFI_SUCCESS Driver instance has been created and\r
- initialized for the virtio-blk PCI device, it\r
+ initialized for the virtio-blk device, it\r
is now accessibla via EFI_BLOCK_IO_PROTOCOL.\r
\r
@retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r
\r
@return Error codes from the OpenProtocol() boot\r
- service, the PciIo protocol, VirtioBlkInit(),\r
+ service, the VirtIo protocol, VirtioBlkInit(),\r
or the InstallProtocolInterface() boot service.\r
\r
**/\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
- (VOID **)&Dev->PciIo, This->DriverBindingHandle,\r
+ Status = gBS->OpenProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
+ (VOID **)&Dev->VirtIo, This->DriverBindingHandle,\r
DeviceHandle, EFI_OPEN_PROTOCOL_BY_DRIVER);\r
if (EFI_ERROR (Status)) {\r
goto FreeVirtioBlk;\r
}\r
\r
//\r
- // We must retain and ultimately restore the original PCI attributes of the\r
- // device. See Driver Writer's Guide for UEFI 2.3.1 v1.01, 18.3 PCI drivers /\r
- // 18.3.2 Start() and Stop().\r
- //\r
- // The third parameter ("Attributes", input) is ignored by the Get operation.\r
- // The fourth parameter ("Result", output) is ignored by the Enable and Set\r
- // operations.\r
- //\r
- // For virtio-blk we only need IO space access.\r
- //\r
- Status = Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationGet,\r
- 0, &Dev->OriginalPciAttributes);\r
- if (EFI_ERROR (Status)) {\r
- goto ClosePciIo;\r
- }\r
-\r
- Status = Dev->PciIo->Attributes (Dev->PciIo,\r
- EfiPciIoAttributeOperationEnable,\r
- EFI_PCI_IO_ATTRIBUTE_IO, NULL);\r
- if (EFI_ERROR (Status)) {\r
- goto ClosePciIo;\r
- }\r
-\r
- //\r
- // PCI IO access granted, configure virtio-blk device.\r
+ // VirtIo access granted, configure virtio-blk device.\r
//\r
Status = VirtioBlkInit (Dev);\r
if (EFI_ERROR (Status)) {\r
- goto RestorePciAttributes;\r
+ goto CloseVirtIo;\r
}\r
\r
//\r
UninitDev:\r
VirtioBlkUninit (Dev);\r
\r
-RestorePciAttributes:\r
- Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationSet,\r
- Dev->OriginalPciAttributes, NULL);\r
-\r
-ClosePciIo:\r
- gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
+CloseVirtIo:\r
+ gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
This->DriverBindingHandle, DeviceHandle);\r
\r
FreeVirtioBlk:\r
\r
VirtioBlkUninit (Dev);\r
\r
- Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationSet,\r
- Dev->OriginalPciAttributes, NULL);\r
-\r
- gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
+ gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
This->DriverBindingHandle, DeviceHandle);\r
\r
FreePool (Dev);\r
#include <Protocol/BlockIo.h>\r
#include <Protocol/ComponentName.h>\r
#include <Protocol/DriverBinding.h>\r
-#include <Protocol/PciIo.h>\r
\r
#include <IndustryStandard/Virtio.h>\r
\r
// at various call depths. The table to the right should make it easier to\r
// track them.\r
//\r
- // field init function init dpth\r
- // ---------------------- ------------------ ---------\r
- UINT32 Signature; // DriverBindingStart 0\r
- EFI_PCI_IO_PROTOCOL *PciIo; // DriverBindingStart 0\r
- UINT64 OriginalPciAttributes; // DriverBindingStart 0\r
- VRING Ring; // VirtioRingInit 2\r
- EFI_BLOCK_IO_PROTOCOL BlockIo; // VirtioBlkInit 1\r
- EFI_BLOCK_IO_MEDIA BlockIoMedia; // VirtioBlkInit 1\r
+ // field init function init dpth\r
+ // --------------------- ------------------ ---------\r
+ UINT32 Signature; // DriverBindingStart 0\r
+ VIRTIO_DEVICE_PROTOCOL *VirtIo; // DriverBindingStart 0\r
+ VRING Ring; // VirtioRingInit 2\r
+ EFI_BLOCK_IO_PROTOCOL BlockIo; // VirtioBlkInit 1\r
+ EFI_BLOCK_IO_MEDIA BlockIoMedia; // VirtioBlkInit 1\r
} VBLK_DEV;\r
\r
#define VIRTIO_BLK_FROM_BLOCK_IO(BlockIoPointer) \\r
underlying device\r
- 9 Driver Binding Protocol -- for exporting ourselves\r
\r
- Specs relevant in the specific sense:\r
- - UEFI Spec 2.3.1 + Errata C, 13.4 EFI PCI I/O Protocol\r
- - Driver Writer's Guide for UEFI 2.3.1 v1.01, 18 PCI Driver Design\r
- Guidelines, 18.3 PCI drivers.\r
-\r
@param[in] This The EFI_DRIVER_BINDING_PROTOCOL object\r
incorporating this driver (independently of\r
any device).\r
\r
@retval EFI_SUCCESS The driver supports the device being probed.\r
\r
- @retval EFI_UNSUPPORTED Based on virtio-blk PCI discovery, we do not support\r
+ @retval EFI_UNSUPPORTED Based on virtio-blk discovery, we do not support\r
the device.\r
\r
- @return Error codes from the OpenProtocol() boot service or\r
- the PciIo protocol.\r
+ @return Error codes from the OpenProtocol() boot service.\r
\r
**/\r
\r
\r
\r
@retval EFI_SUCCESS Driver instance has been created and\r
- initialized for the virtio-blk PCI device, it\r
+ initialized for the virtio-blk device, it\r
is now accessibla via EFI_BLOCK_IO_PROTOCOL.\r
\r
@retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r
\r
@return Error codes from the OpenProtocol() boot\r
- service, the PciIo protocol, VirtioBlkInit(),\r
- or the InstallProtocolInterface() boot service.\r
+ service, VirtioBlkInit(), or the\r
+ InstallProtocolInterface() boot service.\r
\r
**/\r
\r
VirtioLib\r
\r
[Protocols]\r
- gEfiBlockIoProtocolGuid ## BY_START\r
- gEfiPciIoProtocolGuid ## TO_START\r
+ gEfiBlockIoProtocolGuid ## BY_START\r
+ gVirtioDeviceProtocolGuid ## TO_START\r
}\r
\r
//\r
- // confirm that the device is managed by this driver, using the PCI IO\r
+ // confirm that the device is managed by this driver, using the VirtIo\r
// Protocol\r
//\r
Status = EfiTestManagedDevice (\r
ControllerHandle,\r
gVirtioNetDriverBinding.DriverBindingHandle,\r
- &gEfiPciIoProtocolGuid\r
+ &gVirtioDeviceProtocolGuid\r
);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
//\r
- // we don't give different names to the bus (= parent, = PCI) handle and the\r
+ // we don't give different names to the bus (= parent) handle and the\r
// child (= MAC) handle\r
//\r
return LookupUnicodeString2 (\r
\r
**/\r
\r
-#include <IndustryStandard/Pci.h>\r
#include <Library/BaseMemoryLib.h>\r
#include <Library/DevicePathLib.h>\r
#include <Library/MemoryAllocationLib.h>\r
unused.\r
\r
@retval EFI_UNSUPPORTED The host doesn't supply a MAC address.\r
- @return Status codes from Dev->PciIo->Io.Read(),\r
- VIRTIO_CFG_READ() and VIRTIO_CFG_WRITE().\r
+ @return Status codes from VirtIo protocol members.\r
@retval EFI_SUCCESS Configuration values retrieved.\r
*/\r
STATIC\r
EFI_STATUS Status;\r
UINT8 NextDevStat;\r
UINT32 Features;\r
+ UINTN MacIdx;\r
UINT16 LinkStatus;\r
\r
//\r
// Initialization Sequence), but don't complete setting it up.\r
//\r
NextDevStat = 0; // step 1 -- reset device\r
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);\r
+ Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
NextDevStat |= VSTAT_ACK; // step 2 -- acknowledge device presence\r
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);\r
+ Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
if (EFI_ERROR (Status)) {\r
goto YieldDevice;\r
}\r
\r
NextDevStat |= VSTAT_DRIVER; // step 3 -- we know how to drive it\r
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);\r
+ Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
if (EFI_ERROR (Status)) {\r
goto YieldDevice;\r
}\r
//\r
// step 4a -- retrieve and validate features\r
//\r
- Status = VIRTIO_CFG_READ (Dev, Generic.VhdrDeviceFeatureBits, &Features);\r
+ Status = Dev->VirtIo->GetDeviceFeatures (Dev->VirtIo, &Features);\r
if (EFI_ERROR (Status)) {\r
goto YieldDevice;\r
}\r
Status = EFI_UNSUPPORTED;\r
goto YieldDevice;\r
}\r
- Status = Dev->PciIo->Io.Read (Dev->PciIo, // PciIo\r
- EfiPciIoWidthUint8, // Width\r
- PCI_BAR_IDX0, // BarIndex\r
- OFFSET_OF_VNET (VhdrMac), // Offset\r
- SIZE_OF_VNET (VhdrMac), // Count\r
- MacAddress // Buffer\r
+ for (MacIdx = 0; MacIdx < SIZE_OF_VNET (Mac); ++MacIdx) {\r
+ Status = Dev->VirtIo->ReadDevice (Dev->VirtIo,\r
+ OFFSET_OF_VNET (Mac) + MacIdx, // Offset\r
+ 1, // FieldSize\r
+ 1, // BufferSize\r
+ &MacAddress->Addr[MacIdx] // Buffer\r
);\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto YieldDevice;\r
+ if (EFI_ERROR (Status)) {\r
+ goto YieldDevice;\r
+ }\r
}\r
\r
//\r
}\r
else {\r
*MediaPresentSupported = TRUE;\r
- Status = VIRTIO_CFG_READ (Dev, VhdrLinkStatus, &LinkStatus);\r
+ Status = VIRTIO_CFG_READ (Dev, LinkStatus, &LinkStatus);\r
if (EFI_ERROR (Status)) {\r
goto YieldDevice;\r
}\r
}\r
\r
YieldDevice:\r
- VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus,\r
+ Dev->VirtIo->SetDeviceStatus (Dev->VirtIo,\r
EFI_ERROR (Status) ? VSTAT_FAILED : 0);\r
\r
return Status;\r
Dev->Snp.Mode = &Dev->Snm;\r
\r
Dev->Snm.State = EfiSimpleNetworkStopped;\r
- Dev->Snm.HwAddressSize = SIZE_OF_VNET (VhdrMac);\r
- Dev->Snm.MediaHeaderSize = SIZE_OF_VNET (VhdrMac) + // dst MAC\r
- SIZE_OF_VNET (VhdrMac) + // src MAC\r
+ Dev->Snm.HwAddressSize = SIZE_OF_VNET (Mac);\r
+ Dev->Snm.MediaHeaderSize = SIZE_OF_VNET (Mac) + // dst MAC\r
+ SIZE_OF_VNET (Mac) + // src MAC\r
2; // Ethertype\r
Dev->Snm.MaxPacketSize = 1500;\r
Dev->Snm.NvRamSize = 0;\r
Dev->Snm.MacAddressChangeable = FALSE;\r
Dev->Snm.MultipleTxSupported = TRUE;\r
\r
- ASSERT (SIZE_OF_VNET (VhdrMac) <= sizeof (EFI_MAC_ADDRESS));\r
+ ASSERT (SIZE_OF_VNET (Mac) <= sizeof (EFI_MAC_ADDRESS));\r
\r
Status = VirtioNetGetFeatures (Dev, &Dev->Snm.CurrentAddress,\r
&Dev->Snm.MediaPresentSupported, &Dev->Snm.MediaPresent);\r
goto CloseWaitForPacket;\r
}\r
CopyMem (&Dev->Snm.PermanentAddress, &Dev->Snm.CurrentAddress,\r
- SIZE_OF_VNET (VhdrMac));\r
- SetMem (&Dev->Snm.BroadcastAddress, SIZE_OF_VNET (VhdrMac), 0xFF);\r
+ SIZE_OF_VNET (Mac));\r
+ SetMem (&Dev->Snm.BroadcastAddress, SIZE_OF_VNET (Mac), 0xFF);\r
\r
//\r
// VirtioNetExitBoot() is queued by ExitBootServices(); its purpose is to\r
)\r
{\r
EFI_STATUS Status;\r
- EFI_PCI_IO_PROTOCOL *PciIo;\r
- PCI_TYPE00 Pci;\r
-\r
- Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
- (VOID **)&PciIo, This->DriverBindingHandle, DeviceHandle,\r
- EFI_OPEN_PROTOCOL_BY_DRIVER);\r
+ VIRTIO_DEVICE_PROTOCOL *VirtIo;\r
+\r
+ //\r
+ // Attempt to open the device with the VirtIo set of interfaces. On success,\r
+ // the protocol is "instantiated" for the VirtIo device. Covers duplicate open\r
+ // attempts (EFI_ALREADY_STARTED).\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ DeviceHandle, // candidate device\r
+ &gVirtioDeviceProtocolGuid, // for generic VirtIo access\r
+ (VOID **)&VirtIo, // handle to instantiate\r
+ This->DriverBindingHandle, // requestor driver identity\r
+ DeviceHandle, // ControllerHandle, according to\r
+ // the UEFI Driver Model\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive VirtIo access to\r
+ // the device; to be released\r
+ );\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
- Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0,\r
- sizeof Pci / sizeof (UINT32), &Pci);\r
+ if (VirtIo->SubSystemDeviceId != VIRTIO_SUBSYSTEM_NETWORK_CARD) {\r
+ Status = EFI_UNSUPPORTED;\r
+ }\r
\r
//\r
- // virtio-0.9.5, 2.1 PCI Discovery:\r
- // the network device has Subsystem Device ID 1\r
+ // We needed VirtIo access only transitorily, to see whether we support the\r
+ // device or not.\r
//\r
- if (Status == EFI_SUCCESS) {\r
- Status = (Pci.Hdr.VendorId == 0x1AF4 &&\r
- Pci.Hdr.DeviceId >= 0x1000 && Pci.Hdr.DeviceId <= 0x103F &&\r
- Pci.Hdr.RevisionID == 0x00 &&\r
- Pci.Device.SubsystemID == VIRTIO_SUBSYSTEM_NETWORK_CARD) ? EFI_SUCCESS : EFI_UNSUPPORTED;\r
- }\r
-\r
- gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
+ gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
This->DriverBindingHandle, DeviceHandle);\r
return Status;\r
}\r
VNET_DEV *Dev;\r
EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
MAC_ADDR_DEVICE_PATH MacNode;\r
- VOID *ChildPciIo;\r
+ VOID *ChildVirtIo;\r
\r
//\r
// allocate space for the driver instance\r
}\r
Dev->Signature = VNET_SIG;\r
\r
- //\r
- // get PCI access to the device and keep it open\r
- //\r
- Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
- (VOID **)&Dev->PciIo, This->DriverBindingHandle,\r
+ Status = gBS->OpenProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
+ (VOID **)&Dev->VirtIo, This->DriverBindingHandle,\r
DeviceHandle, EFI_OPEN_PROTOCOL_BY_DRIVER);\r
if (EFI_ERROR (Status)) {\r
goto FreeVirtioNet;\r
}\r
\r
- //\r
- // save original PCI attributes and enable IO space access\r
- //\r
- Status = Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationGet,\r
- 0, &Dev->OrigPciAttributes);\r
- if (EFI_ERROR (Status)) {\r
- goto ClosePciIo;\r
- }\r
-\r
- Status = Dev->PciIo->Attributes (Dev->PciIo,\r
- EfiPciIoAttributeOperationEnable,\r
- EFI_PCI_IO_ATTRIBUTE_IO, NULL);\r
- if (EFI_ERROR (Status)) {\r
- goto ClosePciIo;\r
- }\r
-\r
//\r
// now we can run a basic one-shot virtio-net initialization required to\r
// retrieve the MAC address\r
//\r
Status = VirtioNetSnpPopulate (Dev);\r
if (EFI_ERROR (Status)) {\r
- goto RestorePciAttributes;\r
+ goto CloseVirtIo;\r
}\r
\r
//\r
- // get the device path of the virtio-net PCI device -- one-shot open\r
+ // get the device path of the virtio-net device -- one-shot open\r
//\r
Status = gBS->OpenProtocol (DeviceHandle, &gEfiDevicePathProtocolGuid,\r
(VOID **)&DevicePath, This->DriverBindingHandle,\r
}\r
\r
//\r
- // make a note that we keep this device open with PciIo for the sake of this\r
+ // make a note that we keep this device open with VirtIo for the sake of this\r
// child\r
//\r
- Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
- &ChildPciIo, This->DriverBindingHandle,\r
+ Status = gBS->OpenProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
+ &ChildVirtIo, This->DriverBindingHandle,\r
Dev->MacHandle, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER);\r
if (EFI_ERROR (Status)) {\r
goto UninstallMultiple;\r
Evacuate:\r
VirtioNetSnpEvacuate (Dev);\r
\r
-RestorePciAttributes:\r
- Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationSet,\r
- Dev->OrigPciAttributes, NULL);\r
-\r
-ClosePciIo:\r
- gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
+CloseVirtIo:\r
+ gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
This->DriverBindingHandle, DeviceHandle);\r
\r
FreeVirtioNet:\r
Status = EFI_DEVICE_ERROR;\r
}\r
else {\r
- gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
+ gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
This->DriverBindingHandle, Dev->MacHandle);\r
gBS->UninstallMultipleProtocolInterfaces (Dev->MacHandle,\r
&gEfiDevicePathProtocolGuid, Dev->MacDevicePath,\r
NULL);\r
FreePool (Dev->MacDevicePath);\r
VirtioNetSnpEvacuate (Dev);\r
- Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationSet,\r
- Dev->OrigPciAttributes, NULL);\r
FreePool (Dev);\r
}\r
\r
//\r
// release remaining resources, tied directly to the parent handle\r
//\r
- gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
+ gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
This->DriverBindingHandle, DeviceHandle);\r
\r
return EFI_SUCCESS;\r
\r
Dev = Context;\r
if (Dev->Snm.State == EfiSimpleNetworkInitialized) {\r
- VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, 0);\r
+ Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);\r
}\r
}\r
if (Dev->Snm.MediaPresentSupported) {\r
UINT16 LinkStatus;\r
\r
- Status = VIRTIO_CFG_READ (Dev, VhdrLinkStatus, &LinkStatus);\r
+ Status = VIRTIO_CFG_READ (Dev, LinkStatus, &LinkStatus);\r
if (EFI_ERROR (Status)) {\r
goto Exit;\r
}\r
//\r
// step 4b -- allocate selected queue\r
//\r
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueSelect, Selector);\r
+ Status = Dev->VirtIo->SetQueueSel (Dev->VirtIo, Selector);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
- Status = VIRTIO_CFG_READ (Dev, Generic.VhdrQueueSize, &QueueSize);\r
+ Status = Dev->VirtIo->GetQueueNumMax (Dev->VirtIo, &QueueSize);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
+\r
//\r
// For each packet (RX and TX alike), we need two descriptors:\r
// one for the virtio-net request header, and another one for the data\r
return Status;\r
}\r
\r
+ //\r
+ // Additional steps for MMIO: align the queue appropriately, and set the\r
+ // size. If anything fails from here on, we must release the ring resources.\r
+ //\r
+ Status = Dev->VirtIo->SetQueueNum (Dev->VirtIo, QueueSize);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ReleaseQueue;\r
+ }\r
+\r
+ Status = Dev->VirtIo->SetQueueAlign (Dev->VirtIo, EFI_PAGE_SIZE);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ReleaseQueue;\r
+ }\r
+\r
//\r
// step 4c -- report GPFN (guest-physical frame number) of queue\r
//\r
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueAddress,\r
- (UINTN) Ring->Base >> EFI_PAGE_SHIFT);\r
+ Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo,\r
+ (UINT32)(UINTN) Ring->Base >> EFI_PAGE_SHIFT);\r
if (EFI_ERROR (Status)) {\r
- VirtioRingUninit (Ring);\r
+ goto ReleaseQueue;\r
}\r
+\r
+ return EFI_SUCCESS;\r
+\r
+ReleaseQueue:\r
+ VirtioRingUninit (Ring);\r
+\r
return Status;\r
}\r
\r
// virtio-0.9.5, 2.4.1.4 Notifying the Device\r
//\r
MemoryFence ();\r
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueNotify, VIRTIO_NET_Q_RX);\r
-\r
+ Status = Dev->VirtIo->SetQueueNotify (Dev->VirtIo, VIRTIO_NET_Q_RX);\r
if (EFI_ERROR (Status)) {\r
- VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, 0);\r
+ Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);\r
FreePool (Dev->RxBuf);\r
}\r
\r
// virtio-0.9.5 spec, 2.2.1 Device Initialization Sequence.\r
//\r
NextDevStat = VSTAT_ACK; // step 2 -- acknowledge device presence\r
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);\r
+ Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
if (EFI_ERROR (Status)) {\r
goto InitFailed;\r
}\r
\r
NextDevStat |= VSTAT_DRIVER; // step 3 -- we know how to drive it\r
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);\r
+ Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
+ if (EFI_ERROR (Status)) {\r
+ goto DeviceFailed;\r
+ }\r
+\r
+ //\r
+ // Set Page Size - MMIO VirtIo Specific\r
+ //\r
+ Status = Dev->VirtIo->SetPageSize (Dev->VirtIo, EFI_PAGE_SIZE);\r
if (EFI_ERROR (Status)) {\r
goto DeviceFailed;\r
}\r
// step 4a -- retrieve features. Note that we're past validating required\r
// features in VirtioNetGetFeatures().\r
//\r
- Status = VIRTIO_CFG_READ (Dev, Generic.VhdrDeviceFeatureBits, &Features);\r
+ Status = Dev->VirtIo->GetDeviceFeatures (Dev->VirtIo, &Features);\r
if (EFI_ERROR (Status)) {\r
goto DeviceFailed;\r
}\r
+\r
ASSERT (Features & VIRTIO_NET_F_MAC);\r
ASSERT (Dev->Snm.MediaPresentSupported ==\r
!!(Features & VIRTIO_NET_F_STATUS));\r
// step 5 -- keep only the features we want\r
//\r
Features &= VIRTIO_NET_F_MAC | VIRTIO_NET_F_STATUS;\r
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrGuestFeatureBits, Features);\r
+ Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, Features);\r
if (EFI_ERROR (Status)) {\r
goto ReleaseTxRing;\r
}\r
// step 6 -- virtio-net initialization complete\r
//\r
NextDevStat |= VSTAT_DRIVER_OK;\r
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);\r
+ Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
if (EFI_ERROR (Status)) {\r
goto ReleaseTxRing;\r
}\r
VirtioNetShutdownTx (Dev);\r
\r
AbortDevice:\r
- VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, 0);\r
+ Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);\r
\r
ReleaseTxRing:\r
VirtioRingUninit (&Dev->TxRing);\r
//\r
// restore device status invariant for the EfiSimpleNetworkStarted state\r
//\r
- VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, 0);\r
+ Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);\r
\r
InitFailed:\r
gBS->RestoreTPL (OldTpl);\r
CopyMem (Buffer, RxPtr, RxLen);\r
\r
if (DestAddr != NULL) {\r
- CopyMem (DestAddr, RxPtr, SIZE_OF_VNET (VhdrMac));\r
+ CopyMem (DestAddr, RxPtr, SIZE_OF_VNET (Mac));\r
}\r
- RxPtr += SIZE_OF_VNET (VhdrMac);\r
+ RxPtr += SIZE_OF_VNET (Mac);\r
\r
if (SrcAddr != NULL) {\r
- CopyMem (SrcAddr, RxPtr, SIZE_OF_VNET (VhdrMac));\r
+ CopyMem (SrcAddr, RxPtr, SIZE_OF_VNET (Mac));\r
}\r
- RxPtr += SIZE_OF_VNET (VhdrMac);\r
+ RxPtr += SIZE_OF_VNET (Mac);\r
\r
if (Protocol != NULL) {\r
*Protocol = (UINT16) ((RxPtr[0] << 8) | RxPtr[1]);\r
*Dev->RxRing.Avail.Idx = AvailIdx;\r
\r
MemoryFence ();\r
- NotifyStatus = VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueNotify,\r
- VIRTIO_NET_Q_RX);\r
-\r
+ NotifyStatus = Dev->VirtIo->SetQueueNotify (Dev->VirtIo, VIRTIO_NET_Q_RX);\r
if (!EFI_ERROR (Status)) { // earlier error takes precedence\r
Status = NotifyStatus;\r
}\r
break;\r
}\r
\r
- VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, 0);\r
+ Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);\r
VirtioNetShutdownRx (Dev);\r
VirtioNetShutdownTx (Dev);\r
VirtioRingUninit (&Dev->TxRing);\r
goto Exit;\r
}\r
Ptr = Buffer;\r
- ASSERT (SIZE_OF_VNET (VhdrMac) <= sizeof (EFI_MAC_ADDRESS));\r
+ ASSERT (SIZE_OF_VNET (Mac) <= sizeof (EFI_MAC_ADDRESS));\r
\r
- CopyMem (Ptr, DestAddr, SIZE_OF_VNET (VhdrMac));\r
- Ptr += SIZE_OF_VNET (VhdrMac);\r
+ CopyMem (Ptr, DestAddr, SIZE_OF_VNET (Mac));\r
+ Ptr += SIZE_OF_VNET (Mac);\r
\r
CopyMem (Ptr,\r
(SrcAddr == NULL) ? &Dev->Snm.CurrentAddress : SrcAddr,\r
- SIZE_OF_VNET (VhdrMac));\r
- Ptr += SIZE_OF_VNET (VhdrMac);\r
+ SIZE_OF_VNET (Mac));\r
+ Ptr += SIZE_OF_VNET (Mac);\r
\r
*Ptr++ = (UINT8) (*Protocol >> 8);\r
*Ptr++ = (UINT8) *Protocol;\r
*Dev->TxRing.Avail.Idx = AvailIdx;\r
\r
MemoryFence ();\r
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueNotify, VIRTIO_NET_Q_TX);\r
+ Status = Dev->VirtIo->SetQueueNotify (Dev->VirtIo, VIRTIO_NET_Q_TX);\r
\r
Exit:\r
gBS->RestoreTPL (OldTpl);\r
#include <Protocol/ComponentName2.h>\r
#include <Protocol/DevicePath.h>\r
#include <Protocol/DriverBinding.h>\r
-#include <Protocol/PciIo.h>\r
#include <Protocol/SimpleNetwork.h>\r
\r
#define VNET_SIG SIGNATURE_32 ('V', 'N', 'E', 'T')\r
// field init function\r
// ------------------ ------------------------------\r
UINT32 Signature; // VirtioNetDriverBindingStart\r
- EFI_PCI_IO_PROTOCOL *PciIo; // VirtioNetDriverBindingStart\r
- UINT64 OrigPciAttributes; // VirtioNetDriverBindingStart\r
+ VIRTIO_DEVICE_PROTOCOL *VirtIo; // VirtioNetDriverBindingStart\r
EFI_SIMPLE_NETWORK_PROTOCOL Snp; // VirtioNetSnpPopulate\r
EFI_SIMPLE_NETWORK_MODE Snm; // VirtioNetSnpPopulate\r
EFI_EVENT ExitBoot; // VirtioNetSnpPopulate\r
#define VIRTIO_NET_FROM_SNP(SnpPointer) \\r
CR (SnpPointer, VNET_DEV, Snp, VNET_SIG)\r
\r
-#define VIRTIO_CFG_WRITE(Dev, Field, Value) (VirtioWrite ( \\r
- (Dev)->PciIo, \\r
+#define VIRTIO_CFG_WRITE(Dev, Field, Value) (VirtioWriteDevice ( \\r
+ (Dev)->VirtIo, \\r
OFFSET_OF_VNET (Field), \\r
SIZE_OF_VNET (Field), \\r
(Value) \\r
))\r
\r
-#define VIRTIO_CFG_READ(Dev, Field, Pointer) (VirtioRead ( \\r
- (Dev)->PciIo, \\r
+#define VIRTIO_CFG_READ(Dev, Field, Pointer) (VirtioReadDevice ( \\r
+ (Dev)->VirtIo, \\r
OFFSET_OF_VNET (Field), \\r
SIZE_OF_VNET (Field), \\r
sizeof *(Pointer), \\r
[Protocols]\r
gEfiSimpleNetworkProtocolGuid ## BY_START\r
gEfiDevicePathProtocolGuid ## BY_START\r
- gEfiPciIoProtocolGuid ## TO_START\r
+ gVirtioDeviceProtocolGuid ## TO_START\r
\r
**/\r
\r
-#include <IndustryStandard/Pci.h>\r
#include <IndustryStandard/VirtioScsi.h>\r
#include <Library/BaseMemoryLib.h>\r
#include <Library/DebugLib.h>\r
\r
/**\r
\r
- Convenience macros to read and write region 0 IO space elements of the\r
- virtio-scsi PCI device, for configuration purposes.\r
+ Convenience macros to read and write configuration elements of the\r
+ virtio-scsi VirtIo device.\r
\r
The following macros make it possible to specify only the "core parameters"\r
for such accesses and to derive the rest. By the time VIRTIO_CFG_WRITE()\r
returns, the transaction will have been completed.\r
\r
- @param[in] Dev Pointer to the VSCSI_DEV structure whose PCI IO space\r
- we're accessing. Dev->PciIo must be valid.\r
+ @param[in] Dev Pointer to the VSCSI_DEV structure.\r
\r
@param[in] Field A field name from VSCSI_HDR, identifying the virtio-scsi\r
configuration item to access.\r
one of UINT8, UINT16, UINT32, UINT64.\r
\r
\r
- @return Status codes returned by VirtioWrite() / VirtioRead().\r
+ @return Status codes returned by VirtioWriteDevice() / VirtioReadDevice().\r
\r
**/\r
\r
-#define VIRTIO_CFG_WRITE(Dev, Field, Value) (VirtioWrite ( \\r
- (Dev)->PciIo, \\r
+#define VIRTIO_CFG_WRITE(Dev, Field, Value) (VirtioWriteDevice ( \\r
+ (Dev)->VirtIo, \\r
OFFSET_OF_VSCSI (Field), \\r
SIZE_OF_VSCSI (Field), \\r
(Value) \\r
))\r
\r
-#define VIRTIO_CFG_READ(Dev, Field, Pointer) (VirtioRead ( \\r
- (Dev)->PciIo, \\r
+#define VIRTIO_CFG_READ(Dev, Field, Pointer) (VirtioReadDevice ( \\r
+ (Dev)->VirtIo, \\r
OFFSET_OF_VSCSI (Field), \\r
SIZE_OF_VSCSI (Field), \\r
sizeof *(Pointer), \\r
// EFI_NOT_READY would save us the effort, but it would also suggest that the\r
// caller retry.\r
//\r
- if (VirtioFlush (Dev->PciIo, VIRTIO_SCSI_REQUEST_QUEUE, &Dev->Ring,\r
+ if (VirtioFlush (Dev->VirtIo, VIRTIO_SCSI_REQUEST_QUEUE, &Dev->Ring,\r
&Indices) != EFI_SUCCESS) {\r
Packet->InTransferLength = 0;\r
Packet->OutTransferLength = 0;\r
// Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence.\r
//\r
NextDevStat = 0; // step 1 -- reset device\r
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);\r
+ Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
if (EFI_ERROR (Status)) {\r
goto Failed;\r
}\r
\r
NextDevStat |= VSTAT_ACK; // step 2 -- acknowledge device presence\r
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);\r
+ Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
if (EFI_ERROR (Status)) {\r
goto Failed;\r
}\r
\r
NextDevStat |= VSTAT_DRIVER; // step 3 -- we know how to drive it\r
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);\r
+ Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Failed;\r
+ }\r
+\r
+ //\r
+ // Set Page Size - MMIO VirtIo Specific\r
+ //\r
+ Status = Dev->VirtIo->SetPageSize (Dev->VirtIo, EFI_PAGE_SIZE);\r
if (EFI_ERROR (Status)) {\r
goto Failed;\r
}\r
//\r
// step 4a -- retrieve and validate features\r
//\r
- Status = VIRTIO_CFG_READ (Dev, Generic.VhdrDeviceFeatureBits, &Features);\r
+ Status = Dev->VirtIo->GetDeviceFeatures (Dev->VirtIo, &Features);\r
if (EFI_ERROR (Status)) {\r
goto Failed;\r
}\r
Dev->InOutSupported = !!(Features & VIRTIO_SCSI_F_INOUT);\r
\r
- Status = VIRTIO_CFG_READ (Dev, VhdrMaxChannel, &MaxChannel);\r
+ Status = VIRTIO_CFG_READ (Dev, MaxChannel, &MaxChannel);\r
if (EFI_ERROR (Status)) {\r
goto Failed;\r
}\r
goto Failed;\r
}\r
\r
- Status = VIRTIO_CFG_READ (Dev, VhdrNumQueues, &NumQueues);\r
+ Status = VIRTIO_CFG_READ (Dev, NumQueues, &NumQueues);\r
if (EFI_ERROR (Status)) {\r
goto Failed;\r
}\r
goto Failed;\r
}\r
\r
- Status = VIRTIO_CFG_READ (Dev, VhdrMaxTarget, &Dev->MaxTarget);\r
+ Status = VIRTIO_CFG_READ (Dev, MaxTarget, &Dev->MaxTarget);\r
if (EFI_ERROR (Status)) {\r
goto Failed;\r
}\r
Dev->MaxTarget = PcdGet16 (PcdVirtioScsiMaxTargetLimit);\r
}\r
\r
- Status = VIRTIO_CFG_READ (Dev, VhdrMaxLun, &Dev->MaxLun);\r
+ Status = VIRTIO_CFG_READ (Dev, MaxLun, &Dev->MaxLun);\r
if (EFI_ERROR (Status)) {\r
goto Failed;\r
}\r
Dev->MaxLun = PcdGet32 (PcdVirtioScsiMaxLunLimit);\r
}\r
\r
- Status = VIRTIO_CFG_READ (Dev, VhdrMaxSectors, &Dev->MaxSectors);\r
+ Status = VIRTIO_CFG_READ (Dev, MaxSectors, &Dev->MaxSectors);\r
if (EFI_ERROR (Status)) {\r
goto Failed;\r
}\r
//\r
// step 4b -- allocate request virtqueue\r
//\r
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueSelect,\r
- VIRTIO_SCSI_REQUEST_QUEUE);\r
+ Status = Dev->VirtIo->SetQueueSel (Dev->VirtIo, VIRTIO_SCSI_REQUEST_QUEUE);\r
if (EFI_ERROR (Status)) {\r
goto Failed;\r
}\r
- Status = VIRTIO_CFG_READ (Dev, Generic.VhdrQueueSize, &QueueSize);\r
+ Status = Dev->VirtIo->GetQueueNumMax (Dev->VirtIo, &QueueSize);\r
if (EFI_ERROR (Status)) {\r
goto Failed;\r
}\r
}\r
\r
//\r
- // step 4c -- Report GPFN (guest-physical frame number) of queue. If anything\r
- // fails from here on, we must release the ring resources.\r
+ // Additional steps for MMIO: align the queue appropriately, and set the\r
+ // size. If anything fails from here on, we must release the ring resources.\r
//\r
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueAddress,\r
- (UINTN) Dev->Ring.Base >> EFI_PAGE_SHIFT);\r
+ Status = Dev->VirtIo->SetQueueNum (Dev->VirtIo, QueueSize);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ReleaseQueue;\r
+ }\r
+\r
+ Status = Dev->VirtIo->SetQueueAlign (Dev->VirtIo, EFI_PAGE_SIZE);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ReleaseQueue;\r
+ }\r
+\r
+ //\r
+ // step 4c -- Report GPFN (guest-physical frame number) of queue.\r
+ //\r
+ Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo,\r
+ (UINT32)(UINTN) Dev->Ring.Base >> EFI_PAGE_SHIFT);\r
if (EFI_ERROR (Status)) {\r
goto ReleaseQueue;\r
}\r
// the known (or unknown) VIRTIO_SCSI_F_* or VIRTIO_F_* capabilities (see\r
// virtio-0.9.5, Appendices B and I), except bidirectional transfers.\r
//\r
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrGuestFeatureBits,\r
- Features & VIRTIO_SCSI_F_INOUT);\r
+ Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo,\r
+ Features & VIRTIO_SCSI_F_INOUT);\r
if (EFI_ERROR (Status)) {\r
goto ReleaseQueue;\r
}\r
// We expect these maximum sizes from the host. Since they are\r
// guest-negotiable, ask for them rather than just checking them.\r
//\r
- Status = VIRTIO_CFG_WRITE (Dev, VhdrCdbSize, VIRTIO_SCSI_CDB_SIZE);\r
+ Status = VIRTIO_CFG_WRITE (Dev, CdbSize, VIRTIO_SCSI_CDB_SIZE);\r
if (EFI_ERROR (Status)) {\r
goto ReleaseQueue;\r
}\r
- Status = VIRTIO_CFG_WRITE (Dev, VhdrSenseSize, VIRTIO_SCSI_SENSE_SIZE);\r
+ Status = VIRTIO_CFG_WRITE (Dev, SenseSize, VIRTIO_SCSI_SENSE_SIZE);\r
if (EFI_ERROR (Status)) {\r
goto ReleaseQueue;\r
}\r
// step 6 -- initialization complete\r
//\r
NextDevStat |= VSTAT_DRIVER_OK;\r
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);\r
+ Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
if (EFI_ERROR (Status)) {\r
goto ReleaseQueue;\r
}\r
Failed:\r
//\r
// Notify the host about our failure to setup: virtio-0.9.5, 2.2.2.1 Device\r
- // Status. PCI IO access failure here should not mask the original error.\r
+ // Status. VirtIo access failure here should not mask the original error.\r
//\r
NextDevStat |= VSTAT_FAILED;\r
- VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);\r
+ Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
\r
Dev->InOutSupported = FALSE;\r
Dev->MaxTarget = 0;\r
// VIRTIO_CFG_WRITE() returns, the host will have learned to stay away from\r
// the old comms area.\r
//\r
- VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, 0);\r
+ Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);\r
\r
Dev->InOutSupported = FALSE;\r
Dev->MaxTarget = 0;\r
// The implementation follows:\r
// - Driver Writer's Guide for UEFI 2.3.1 v1.01\r
// - 5.1.3.4 OpenProtocol() and CloseProtocol()\r
-// - 18 PCI Driver Design Guidelines\r
-// - 18.3 PCI drivers\r
// - UEFI Spec 2.3.1 + Errata C\r
// - 6.3 Protocol Handler Services\r
-// - 13.4 EFI PCI I/O Protocol\r
//\r
\r
EFI_STATUS\r
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
)\r
{\r
- EFI_STATUS Status;\r
- EFI_PCI_IO_PROTOCOL *PciIo;\r
- PCI_TYPE00 Pci;\r
+ EFI_STATUS Status;\r
+ VIRTIO_DEVICE_PROTOCOL *VirtIo;\r
\r
//\r
- // Attempt to open the device with the PciIo set of interfaces. On success,\r
- // the protocol is "instantiated" for the PCI device. Covers duplicate open\r
+ // Attempt to open the device with the VirtIo set of interfaces. On success,\r
+ // the protocol is "instantiated" for the VirtIo device. Covers duplicate open\r
// attempts (EFI_ALREADY_STARTED).\r
//\r
Status = gBS->OpenProtocol (\r
DeviceHandle, // candidate device\r
- &gEfiPciIoProtocolGuid, // for generic PCI access\r
- (VOID **)&PciIo, // handle to instantiate\r
+ &gVirtioDeviceProtocolGuid, // for generic VirtIo access\r
+ (VOID **)&VirtIo, // handle to instantiate\r
This->DriverBindingHandle, // requestor driver identity\r
DeviceHandle, // ControllerHandle, according to\r
// the UEFI Driver Model\r
- EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive PciIo access to\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive VirtIo access to\r
// the device; to be released\r
);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
- //\r
- // Read entire PCI configuration header for more extensive check ahead.\r
- //\r
- Status = PciIo->Pci.Read (\r
- PciIo, // (protocol, device)\r
- // handle\r
- EfiPciIoWidthUint32, // access width & copy\r
- // mode\r
- 0, // Offset\r
- sizeof Pci / sizeof (UINT32), // Count\r
- &Pci // target buffer\r
- );\r
-\r
- if (Status == EFI_SUCCESS) {\r
- //\r
- // virtio-0.9.5, 2.1 PCI Discovery\r
- //\r
- Status = (Pci.Hdr.VendorId == 0x1AF4 &&\r
- Pci.Hdr.DeviceId >= 0x1000 && Pci.Hdr.DeviceId <= 0x103F &&\r
- Pci.Hdr.RevisionID == 0x00 &&\r
- Pci.Device.SubsystemID == VIRTIO_SUBSYSTEM_SCSI_HOST) ? EFI_SUCCESS : EFI_UNSUPPORTED;\r
+ if (VirtIo->SubSystemDeviceId != VIRTIO_SUBSYSTEM_SCSI_HOST) {\r
+ Status = EFI_UNSUPPORTED;\r
}\r
\r
//\r
- // We needed PCI IO access only transitorily, to see whether we support the\r
+ // We needed VirtIo access only transitorily, to see whether we support the\r
// device or not.\r
//\r
- gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
+ gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
This->DriverBindingHandle, DeviceHandle);\r
return Status;\r
}\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
- (VOID **)&Dev->PciIo, This->DriverBindingHandle,\r
+ Status = gBS->OpenProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
+ (VOID **)&Dev->VirtIo, This->DriverBindingHandle,\r
DeviceHandle, EFI_OPEN_PROTOCOL_BY_DRIVER);\r
if (EFI_ERROR (Status)) {\r
goto FreeVirtioScsi;\r
}\r
\r
//\r
- // We must retain and ultimately restore the original PCI attributes of the\r
- // device. See Driver Writer's Guide for UEFI 2.3.1 v1.01, 18.3 PCI drivers /\r
- // 18.3.2 Start() and Stop().\r
- //\r
- // The third parameter ("Attributes", input) is ignored by the Get operation.\r
- // The fourth parameter ("Result", output) is ignored by the Enable and Set\r
- // operations.\r
- //\r
- // For virtio-scsi we only need IO space access.\r
- //\r
- Status = Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationGet,\r
- 0, &Dev->OriginalPciAttributes);\r
- if (EFI_ERROR (Status)) {\r
- goto ClosePciIo;\r
- }\r
-\r
- Status = Dev->PciIo->Attributes (Dev->PciIo,\r
- EfiPciIoAttributeOperationEnable,\r
- EFI_PCI_IO_ATTRIBUTE_IO, NULL);\r
- if (EFI_ERROR (Status)) {\r
- goto ClosePciIo;\r
- }\r
-\r
- //\r
- // PCI IO access granted, configure virtio-scsi device.\r
+ // VirtIo access granted, configure virtio-scsi device.\r
//\r
Status = VirtioScsiInit (Dev);\r
if (EFI_ERROR (Status)) {\r
- goto RestorePciAttributes;\r
+ goto CloseVirtIo;\r
}\r
\r
//\r
UninitDev:\r
VirtioScsiUninit (Dev);\r
\r
-RestorePciAttributes:\r
- Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationSet,\r
- Dev->OriginalPciAttributes, NULL);\r
-\r
-ClosePciIo:\r
- gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
+CloseVirtIo:\r
+ gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
This->DriverBindingHandle, DeviceHandle);\r
\r
FreeVirtioScsi:\r
\r
VirtioScsiUninit (Dev);\r
\r
- Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationSet,\r
- Dev->OriginalPciAttributes, NULL);\r
-\r
- gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,\r
+ gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
This->DriverBindingHandle, DeviceHandle);\r
\r
FreePool (Dev);\r
\r
#include <Protocol/ComponentName.h>\r
#include <Protocol/DriverBinding.h>\r
-#include <Protocol/PciIo.h>\r
#include <Protocol/ScsiPassThruExt.h>\r
\r
#include <IndustryStandard/Virtio.h>\r
// at various call depths. The table to the right should make it easier to\r
// track them.\r
//\r
- // field init function init depth\r
- // ---------------------- ------------------ ----------\r
- UINT32 Signature; // DriverBindingStart 0\r
- EFI_PCI_IO_PROTOCOL *PciIo; // DriverBindingStart 0\r
- UINT64 OriginalPciAttributes; // DriverBindingStart 0\r
- BOOLEAN InOutSupported; // VirtioScsiInit 1\r
- UINT16 MaxTarget; // VirtioScsiInit 1\r
- UINT32 MaxLun; // VirtioScsiInit 1\r
- UINT32 MaxSectors; // VirtioScsiInit 1\r
- VRING Ring; // VirtioRingInit 2\r
- EFI_EXT_SCSI_PASS_THRU_PROTOCOL PassThru; // VirtioScsiInit 1\r
- EFI_EXT_SCSI_PASS_THRU_MODE PassThruMode; // VirtioScsiInit 1\r
+ // field init function init depth\r
+ // ---------------- ------------------ ----------\r
+ UINT32 Signature; // DriverBindingStart 0\r
+ VIRTIO_DEVICE_PROTOCOL *VirtIo; // DriverBindingStart 0\r
+ BOOLEAN InOutSupported; // VirtioScsiInit 1\r
+ UINT16 MaxTarget; // VirtioScsiInit 1\r
+ UINT32 MaxLun; // VirtioScsiInit 1\r
+ UINT32 MaxSectors; // VirtioScsiInit 1\r
+ VRING Ring; // VirtioRingInit 2\r
+ EFI_EXT_SCSI_PASS_THRU_PROTOCOL PassThru; // VirtioScsiInit 1\r
+ EFI_EXT_SCSI_PASS_THRU_MODE PassThruMode; // VirtioScsiInit 1\r
} VSCSI_DEV;\r
\r
#define VIRTIO_SCSI_FROM_PASS_THRU(PassThruPointer) \\r
\r
[Protocols]\r
gEfiExtScsiPassThruProtocolGuid ## BY_START\r
- gEfiPciIoProtocolGuid ## TO_START\r
+ gVirtioDeviceProtocolGuid ## TO_START\r
\r
[Pcd]\r
gUefiOvmfPkgTokenSpaceGuid.PcdVirtioScsiMaxTargetLimit ## CONSUMES\r