From 56f65ed838e8d73e91d54a8ed984d777c936843c Mon Sep 17 00:00:00 2001 From: Olivier Martin Date: Wed, 11 Dec 2013 16:58:22 +0000 Subject: [PATCH] OvmfPkg: Make the VirtIo devices use the new VIRTIO_DEVICE_PROTOCOL This change replaces the accesses to the PCI bus from the Block, Scsi and Net drivers by the use of the new VIRTIO_DEVICE_PROTOCOL protocol that abstracts the transport layer. It means these drivers can be used on PCI and MMIO transport layer. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Olivier Martin v5: - VirtioFlush(): update comment block in VirtioLib.[hc]; error code is propagated from VirtIo->SetQueueNotify(). - VirtioBlkInit(): jump to Failed label if SetPageSize() fails - VirtioBlkInit(): fixup comment, and add error handling, near SetQueueNum() call - VirtioBlkDriverBindingStart(): remove redundant (always false) check for a subsystem device ID different from VIRTIO_SUBSYSTEM_BLOCK_DEVICE; VirtioBlkDriverBindingSupported() handles it already - VirtioNetGetFeatures(): update stale comment block - VirtioNetGetFeatures(): retrieve MAC address byte for byte (open-coded loop) - VirtioNetDriverBindingStart(): remove redundant (always false) check for a subsystem device ID different from VIRTIO_SUBSYSTEM_NETWORK_CARD; VirtioNetDriverBindingSupported() handles it already - VirtioNetInitRing(): call SetQueueNum() and SetQueueAlign() for proper MMIO operation - VirtioNetInitialize(): fix destination error label for when SetPageSize() fails - VirtioScsi.c: fix comment block of VIRTIO_CFG_WRITE()/VIRTIO_CFG_READ() - VirtioScsiInit(): fix destination error label for when SetPageSize() fails - VirtioScsiInit(): call SetQueueNum() and SetQueueAlign() for proper MMIO operation Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Laszlo Ersek Reviewed-by: Jordan Justen git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@14966 6f19259b-4bc3-4df7-8a09-765794883524 --- OvmfPkg/Include/IndustryStandard/VirtioBlk.h | 21 +- OvmfPkg/Include/IndustryStandard/VirtioNet.h | 14 +- OvmfPkg/Include/IndustryStandard/VirtioScsi.h | 27 ++- OvmfPkg/Include/Library/VirtioLib.h | 59 +++--- OvmfPkg/Library/VirtioLib/VirtioLib.c | 127 +++--------- OvmfPkg/OvmfPkgIa32.dsc | 1 + OvmfPkg/OvmfPkgIa32.fdf | 1 + OvmfPkg/OvmfPkgIa32X64.dsc | 1 + OvmfPkg/OvmfPkgIa32X64.fdf | 1 + OvmfPkg/OvmfPkgX64.dsc | 1 + OvmfPkg/OvmfPkgX64.fdf | 1 + OvmfPkg/VirtioBlkDxe/VirtioBlk.c | 180 +++++++----------- OvmfPkg/VirtioBlkDxe/VirtioBlk.h | 32 ++-- OvmfPkg/VirtioBlkDxe/VirtioBlk.inf | 4 +- OvmfPkg/VirtioNetDxe/ComponentName.c | 6 +- OvmfPkg/VirtioNetDxe/DriverBinding.c | 137 ++++++------- OvmfPkg/VirtioNetDxe/Events.c | 2 +- OvmfPkg/VirtioNetDxe/SnpGetStatus.c | 2 +- OvmfPkg/VirtioNetDxe/SnpInitialize.c | 59 ++++-- OvmfPkg/VirtioNetDxe/SnpReceive.c | 12 +- OvmfPkg/VirtioNetDxe/SnpShutdown.c | 2 +- OvmfPkg/VirtioNetDxe/SnpTransmit.c | 12 +- OvmfPkg/VirtioNetDxe/VirtioNet.h | 12 +- OvmfPkg/VirtioNetDxe/VirtioNet.inf | 2 +- OvmfPkg/VirtioScsiDxe/VirtioScsi.c | 178 +++++++---------- OvmfPkg/VirtioScsiDxe/VirtioScsi.h | 24 ++- OvmfPkg/VirtioScsiDxe/VirtioScsi.inf | 2 +- 27 files changed, 388 insertions(+), 532 deletions(-) diff --git a/OvmfPkg/Include/IndustryStandard/VirtioBlk.h b/OvmfPkg/Include/IndustryStandard/VirtioBlk.h index b71f224b65..ab11e6c855 100644 --- a/OvmfPkg/Include/IndustryStandard/VirtioBlk.h +++ b/OvmfPkg/Include/IndustryStandard/VirtioBlk.h @@ -26,19 +26,18 @@ // #pragma pack(1) typedef struct { - VIRTIO_HDR Generic; - UINT64 VhdrCapacity; - UINT32 VhdrSizeMax; - UINT32 VhdrSegMax; - UINT16 VhdrCylinders; - UINT8 VhdrHeads; - UINT8 VhdrSectors; - UINT32 VhdrBlkSize; -} VBLK_HDR; + UINT64 Capacity; + UINT32 SizeMax; + UINT32 SegMax; + UINT16 Cylinders; + UINT8 Heads; + UINT8 Sectors; + UINT32 BlkSize; +} VIRTIO_BLK_CONFIG; #pragma pack() -#define OFFSET_OF_VBLK(Field) OFFSET_OF (VBLK_HDR, Field) -#define SIZE_OF_VBLK(Field) (sizeof ((VBLK_HDR *) 0)->Field) +#define OFFSET_OF_VBLK(Field) OFFSET_OF (VIRTIO_BLK_CONFIG, Field) +#define SIZE_OF_VBLK(Field) (sizeof ((VIRTIO_BLK_CONFIG *) 0)->Field) #define VIRTIO_BLK_F_BARRIER BIT0 #define VIRTIO_BLK_F_SIZE_MAX BIT1 diff --git a/OvmfPkg/Include/IndustryStandard/VirtioNet.h b/OvmfPkg/Include/IndustryStandard/VirtioNet.h index 03dfeb2c59..34bf15a588 100644 --- a/OvmfPkg/Include/IndustryStandard/VirtioNet.h +++ b/OvmfPkg/Include/IndustryStandard/VirtioNet.h @@ -1,5 +1,4 @@ /** @file - Virtio Network Device specific type and macro definitions corresponding to the virtio-0.9.5 specification. @@ -25,14 +24,13 @@ // #pragma pack(1) typedef struct { - VIRTIO_HDR Generic; - UINT8 VhdrMac[6]; - UINT16 VhdrLinkStatus; -} VNET_HDR; + UINT8 Mac[6]; + UINT16 LinkStatus; +} VIRTIO_NET_CONFIG; #pragma pack() -#define OFFSET_OF_VNET(Field) OFFSET_OF (VNET_HDR, Field) -#define SIZE_OF_VNET(Field) (sizeof ((VNET_HDR *) 0)->Field) +#define OFFSET_OF_VNET(Field) OFFSET_OF (VIRTIO_NET_CONFIG, Field) +#define SIZE_OF_VNET(Field) (sizeof ((VIRTIO_NET_CONFIG *) 0)->Field) // // Queue Identifiers @@ -91,7 +89,7 @@ typedef struct { #define VIRTIO_NET_HDR_GSO_ECN BIT7 // -// Link Status Bits in VNET_HDR.VhdrLinkStatus +// Link Status Bits in VIRTIO_NET_CONFIG.LinkStatus // #define VIRTIO_NET_S_LINK_UP BIT0 #define VIRTIO_NET_S_ANNOUNCE BIT1 diff --git a/OvmfPkg/Include/IndustryStandard/VirtioScsi.h b/OvmfPkg/Include/IndustryStandard/VirtioScsi.h index 59ce97e070..0c9b520904 100644 --- a/OvmfPkg/Include/IndustryStandard/VirtioScsi.h +++ b/OvmfPkg/Include/IndustryStandard/VirtioScsi.h @@ -26,22 +26,21 @@ // #pragma pack(1) typedef struct { - VIRTIO_HDR Generic; - UINT32 VhdrNumQueues; - UINT32 VhdrSegMax; - UINT32 VhdrMaxSectors; - UINT32 VhdrCmdPerLun; - UINT32 VhdrEventInfoSize; - UINT32 VhdrSenseSize; - UINT32 VhdrCdbSize; - UINT16 VhdrMaxChannel; - UINT16 VhdrMaxTarget; - UINT32 VhdrMaxLun; -} VSCSI_HDR; + UINT32 NumQueues; + UINT32 SegMax; + UINT32 MaxSectors; + UINT32 CmdPerLun; + UINT32 EventInfoSize; + UINT32 SenseSize; + UINT32 CdbSize; + UINT16 MaxChannel; + UINT16 MaxTarget; + UINT32 MaxLun; +} VIRTIO_SCSI_CONFIG; #pragma pack() -#define OFFSET_OF_VSCSI(Field) OFFSET_OF (VSCSI_HDR, Field) -#define SIZE_OF_VSCSI(Field) (sizeof ((VSCSI_HDR *) 0)->Field) +#define OFFSET_OF_VSCSI(Field) OFFSET_OF (VIRTIO_SCSI_CONFIG, Field) +#define SIZE_OF_VSCSI(Field) (sizeof ((VIRTIO_SCSI_CONFIG *) 0)->Field) #define VIRTIO_SCSI_F_INOUT BIT0 #define VIRTIO_SCSI_F_HOTPLUG BIT1 diff --git a/OvmfPkg/Include/Library/VirtioLib.h b/OvmfPkg/Include/Library/VirtioLib.h index 51303491d0..8c043369c3 100644 --- a/OvmfPkg/Include/Library/VirtioLib.h +++ b/OvmfPkg/Include/Library/VirtioLib.h @@ -17,17 +17,19 @@ #ifndef _VIRTIO_LIB_H_ #define _VIRTIO_LIB_H_ -#include +#include + #include /** - Write a word into Region 0 of the device specified by PciIo. + Write a word into VirtIo Device Specific Region - Region 0 must be an iomem region. This is an internal function for the - driver-specific VIRTIO_CFG_WRITE() macros. + The VirtIo Device Specific Region must be an iomem region. + This is an internal function for the driver-specific VIRTIO_CFG_WRITE() + macros. - @param[in] PciIo Target PCI device. + @param[in] VirtIo Target Virtio device. @param[in] FieldOffset Destination offset. @@ -37,27 +39,28 @@ The least significant FieldSize bytes will be used. - @return Status code returned by PciIo->Io.Write(). + @return Status code returned by VirtIo->WriteDevice(). **/ EFI_STATUS EFIAPI -VirtioWrite ( - IN EFI_PCI_IO_PROTOCOL *PciIo, - IN UINTN FieldOffset, - IN UINTN FieldSize, - IN UINT64 Value +VirtioWriteDevice ( + IN VIRTIO_DEVICE_PROTOCOL *VirtIo, + IN UINTN FieldOffset, + IN UINTN FieldSize, + IN UINT64 Value ); /** - Read a word from Region 0 of the device specified by PciIo. + Read a word from VirtIo Device Specific Region - Region 0 must be an iomem region. This is an internal function for the - driver-specific VIRTIO_CFG_READ() macros. + The VirtIo Device Specific Region must be an iomem region. + This is an internal function for the driver-specific VIRTIO_CFG_READ() + macros. - @param[in] PciIo Source PCI device. + @param[in] VirtIo Source Virtio device. @param[in] FieldOffset Source offset. @@ -69,17 +72,17 @@ VirtioWrite ( @param[out] Buffer Target buffer. - @return Status code returned by PciIo->Io.Read(). + @return Status code returned by VirtIo->ReadDevice(). **/ EFI_STATUS EFIAPI -VirtioRead ( - IN EFI_PCI_IO_PROTOCOL *PciIo, - IN UINTN FieldOffset, - IN UINTN FieldSize, - IN UINTN BufferSize, - OUT VOID *Buffer +VirtioReadDevice ( + IN VIRTIO_DEVICE_PROTOCOL *VirtIo, + IN UINTN FieldOffset, + IN UINTN FieldSize, + IN UINTN BufferSize, + OUT VOID *Buffer ); @@ -218,7 +221,7 @@ VirtioAppendDesc ( Notify the host about the descriptor chain just built, and wait until the host processes it. - @param[in] PciIo The target virtio PCI device to notify. + @param[in] VirtIo The target virtio device to notify. @param[in] VirtQueueId Identifies the queue for the target device. @@ -229,7 +232,7 @@ VirtioAppendDesc ( of the descriptor chain. - @return Error code from VirtioWrite() if it fails. + @return Error code from VirtIo->SetQueueNotify() if it fails. @retval EFI_SUCCESS Otherwise, the host processed all descriptors. @@ -237,10 +240,10 @@ VirtioAppendDesc ( EFI_STATUS EFIAPI VirtioFlush ( - IN EFI_PCI_IO_PROTOCOL *PciIo, - IN UINT16 VirtQueueId, - IN OUT VRING *Ring, - IN DESC_INDICES *Indices + IN VIRTIO_DEVICE_PROTOCOL *VirtIo, + IN UINT16 VirtQueueId, + IN OUT VRING *Ring, + IN DESC_INDICES *Indices ); #endif // _VIRTIO_LIB_H_ diff --git a/OvmfPkg/Library/VirtioLib/VirtioLib.c b/OvmfPkg/Library/VirtioLib/VirtioLib.c index 959bc5da87..503d4adffc 100644 --- a/OvmfPkg/Library/VirtioLib/VirtioLib.c +++ b/OvmfPkg/Library/VirtioLib/VirtioLib.c @@ -3,6 +3,7 @@ Utility functions used by virtio device drivers. Copyright (C) 2012, Red Hat, Inc. + Portion of Copyright (C) 2013, ARM Ltd. This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this @@ -14,7 +15,6 @@ **/ -#include #include #include #include @@ -26,12 +26,12 @@ /** - Write a word into Region 0 of the device specified by PciIo. + Write a word into Region 0 of the device specified by VirtIo. Region 0 must be an iomem region. This is an internal function for the driver-specific VIRTIO_CFG_WRITE() macros. - @param[in] PciIo Target PCI device. + @param[in] VirtIo Target VirtIo device. @param[in] FieldOffset Destination offset. @@ -41,63 +41,30 @@ The least significant FieldSize bytes will be used. - @return Status code returned by PciIo->Io.Write(). + @return Status code returned by VirtIo->Io.Write(). **/ EFI_STATUS EFIAPI -VirtioWrite ( - IN EFI_PCI_IO_PROTOCOL *PciIo, - IN UINTN FieldOffset, - IN UINTN FieldSize, - IN UINT64 Value +VirtioWriteDevice ( + IN VIRTIO_DEVICE_PROTOCOL *VirtIo, + IN UINTN FieldOffset, + IN UINTN FieldSize, + IN UINT64 Value ) { - UINTN Count; - EFI_PCI_IO_PROTOCOL_WIDTH Width; - - Count = 1; - switch (FieldSize) { - case 1: - Width = EfiPciIoWidthUint8; - break; - - case 2: - Width = EfiPciIoWidthUint16; - break; - - case 8: - Count = 2; - // fall through - - case 4: - Width = EfiPciIoWidthUint32; - break; - - default: - ASSERT (FALSE); - return EFI_INVALID_PARAMETER; - } - - return PciIo->Io.Write ( - PciIo, - Width, - PCI_BAR_IDX0, - FieldOffset, - Count, - &Value - ); + return VirtIo->WriteDevice (VirtIo, FieldOffset, FieldSize, Value); } /** - Read a word from Region 0 of the device specified by PciIo. + Read a word from Region 0 of the device specified by VirtIo. Region 0 must be an iomem region. This is an internal function for the driver-specific VIRTIO_CFG_READ() macros. - @param[in] PciIo Source PCI device. + @param[in] VirtIo Source VirtIo device. @param[in] FieldOffset Source offset. @@ -109,55 +76,20 @@ VirtioWrite ( @param[out] Buffer Target buffer. - @return Status code returned by PciIo->Io.Read(). + @return Status code returned by VirtIo->Io.Read(). **/ EFI_STATUS EFIAPI -VirtioRead ( - IN EFI_PCI_IO_PROTOCOL *PciIo, - IN UINTN FieldOffset, - IN UINTN FieldSize, - IN UINTN BufferSize, - OUT VOID *Buffer +VirtioReadDevice ( + IN VIRTIO_DEVICE_PROTOCOL *VirtIo, + IN UINTN FieldOffset, + IN UINTN FieldSize, + IN UINTN BufferSize, + OUT VOID *Buffer ) { - UINTN Count; - EFI_PCI_IO_PROTOCOL_WIDTH Width; - - ASSERT (FieldSize == BufferSize); - - Count = 1; - switch (FieldSize) { - case 1: - Width = EfiPciIoWidthUint8; - break; - - case 2: - Width = EfiPciIoWidthUint16; - break; - - case 8: - Count = 2; - // fall through - - case 4: - Width = EfiPciIoWidthUint32; - break; - - default: - ASSERT (FALSE); - return EFI_INVALID_PARAMETER; - } - - return PciIo->Io.Read ( - PciIo, - Width, - PCI_BAR_IDX0, - FieldOffset, - Count, - Buffer - ); + return VirtIo->ReadDevice (VirtIo, FieldOffset, FieldSize, BufferSize, Buffer); } @@ -376,7 +308,7 @@ VirtioAppendDesc ( Notify the host about the descriptor chain just built, and wait until the host processes it. - @param[in] PciIo The target virtio PCI device to notify. + @param[in] VirtIo The target virtio device to notify. @param[in] VirtQueueId Identifies the queue for the target device. @@ -387,7 +319,7 @@ VirtioAppendDesc ( of the descriptor chain. - @return Error code from VirtioWrite() if it fails. + @return Error code from VirtIo->SetQueueNotify() if it fails. @retval EFI_SUCCESS Otherwise, the host processed all descriptors. @@ -395,10 +327,10 @@ VirtioAppendDesc ( EFI_STATUS EFIAPI VirtioFlush ( - IN EFI_PCI_IO_PROTOCOL *PciIo, - IN UINT16 VirtQueueId, - IN OUT VRING *Ring, - IN DESC_INDICES *Indices + IN VIRTIO_DEVICE_PROTOCOL *VirtIo, + IN UINT16 VirtQueueId, + IN OUT VRING *Ring, + IN DESC_INDICES *Indices ) { UINT16 NextAvailIdx; @@ -427,12 +359,7 @@ VirtioFlush ( // OK. // MemoryFence(); - Status = VirtioWrite ( - PciIo, - OFFSET_OF (VIRTIO_HDR, VhdrQueueNotify), - sizeof (UINT16), - VirtQueueId - ); + Status = VirtIo->SetQueueNotify (VirtIo, VirtQueueId); if (EFI_ERROR (Status)) { return Status; } diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc index 6647302a0e..2e13e0ed5d 100644 --- a/OvmfPkg/OvmfPkgIa32.dsc +++ b/OvmfPkg/OvmfPkgIa32.dsc @@ -411,6 +411,7 @@ } OvmfPkg/BlockMmioToBlockIoDxe/BlockIo.inf + OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf OvmfPkg/VirtioBlkDxe/VirtioBlk.inf OvmfPkg/VirtioScsiDxe/VirtioScsi.inf OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf diff --git a/OvmfPkg/OvmfPkgIa32.fdf b/OvmfPkg/OvmfPkgIa32.fdf index c50709cf50..c6e186f26d 100644 --- a/OvmfPkg/OvmfPkgIa32.fdf +++ b/OvmfPkg/OvmfPkgIa32.fdf @@ -266,6 +266,7 @@ INF MdeModulePkg/Universal/Metronome/Metronome.inf INF PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf INF OvmfPkg/BlockMmioToBlockIoDxe/BlockIo.inf +INF OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf INF OvmfPkg/VirtioBlkDxe/VirtioBlk.inf INF OvmfPkg/VirtioScsiDxe/VirtioScsi.inf INF OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc index 7d521b14e3..64404a6647 100644 --- a/OvmfPkg/OvmfPkgIa32X64.dsc +++ b/OvmfPkg/OvmfPkgIa32X64.dsc @@ -418,6 +418,7 @@ } OvmfPkg/BlockMmioToBlockIoDxe/BlockIo.inf + OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf OvmfPkg/VirtioBlkDxe/VirtioBlk.inf OvmfPkg/VirtioScsiDxe/VirtioScsi.inf OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf diff --git a/OvmfPkg/OvmfPkgIa32X64.fdf b/OvmfPkg/OvmfPkgIa32X64.fdf index d65f40f373..615451dbec 100644 --- a/OvmfPkg/OvmfPkgIa32X64.fdf +++ b/OvmfPkg/OvmfPkgIa32X64.fdf @@ -266,6 +266,7 @@ INF MdeModulePkg/Universal/Metronome/Metronome.inf INF PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf INF OvmfPkg/BlockMmioToBlockIoDxe/BlockIo.inf +INF OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf INF OvmfPkg/VirtioBlkDxe/VirtioBlk.inf INF OvmfPkg/VirtioScsiDxe/VirtioScsi.inf INF OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc index 7c232c4d8e..467260717e 100644 --- a/OvmfPkg/OvmfPkgX64.dsc +++ b/OvmfPkg/OvmfPkgX64.dsc @@ -416,6 +416,7 @@ } OvmfPkg/BlockMmioToBlockIoDxe/BlockIo.inf + OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf OvmfPkg/VirtioBlkDxe/VirtioBlk.inf OvmfPkg/VirtioScsiDxe/VirtioScsi.inf OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf index 751b94bcd0..911fe0898b 100644 --- a/OvmfPkg/OvmfPkgX64.fdf +++ b/OvmfPkg/OvmfPkgX64.fdf @@ -266,6 +266,7 @@ INF MdeModulePkg/Universal/Metronome/Metronome.inf INF PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf INF OvmfPkg/BlockMmioToBlockIoDxe/BlockIo.inf +INF OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf INF OvmfPkg/VirtioBlkDxe/VirtioBlk.inf INF OvmfPkg/VirtioScsiDxe/VirtioScsi.inf INF OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c index 17b9f71d63..f09b0d1118 100644 --- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c +++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c @@ -23,7 +23,6 @@ **/ -#include #include #include #include @@ -37,14 +36,14 @@ /** Convenience macros to read and write region 0 IO space elements of the - virtio-blk PCI device, for configuration purposes. + virtio-blk device, for configuration purposes. The following macros make it possible to specify only the "core parameters" for such accesses and to derive the rest. By the time VIRTIO_CFG_WRITE() returns, the transaction will have been completed. - @param[in] Dev Pointer to the VBLK_DEV structure whose PCI IO space - we're accessing. Dev->PciIo must be valid. + @param[in] Dev Pointer to the VBLK_DEV structure whose VirtIo space + we're accessing. Dev->VirtIo must be valid. @param[in] Field A field name from VBLK_HDR, identifying the virtio-blk configuration item to access. @@ -57,19 +56,19 @@ one of UINT8, UINT16, UINT32, UINT64. - @return Status code returned by VirtioWrite() / VirtioRead(). + @return Status code returned by VirtioWriteDevice() / VirtioReadDevice(). **/ -#define VIRTIO_CFG_WRITE(Dev, Field, Value) (VirtioWrite ( \ - (Dev)->PciIo, \ +#define VIRTIO_CFG_WRITE(Dev, Field, Value) (VirtioWriteDevice ( \ + (Dev)->VirtIo, \ OFFSET_OF_VBLK (Field), \ SIZE_OF_VBLK (Field), \ (Value) \ )) -#define VIRTIO_CFG_READ(Dev, Field, Pointer) (VirtioRead ( \ - (Dev)->PciIo, \ +#define VIRTIO_CFG_READ(Dev, Field, Pointer) (VirtioReadDevice ( \ + (Dev)->VirtIo, \ OFFSET_OF_VBLK (Field), \ SIZE_OF_VBLK (Field), \ sizeof *(Pointer), \ @@ -229,7 +228,7 @@ VerifyReadWriteRequest ( @retval EFI_SUCCESS Transfer complete. - @retval EFI_DEVICE_ERROR Failed to notify host side via PCI write, or + @retval EFI_DEVICE_ERROR Failed to notify host side via VirtIo write, or unable to parse host response, or host response is not VIRTIO_BLK_S_OK. @@ -324,7 +323,7 @@ SynchronousRequest ( // // virtio-blk's only virtqueue is #0, called "requestq" (see Appendix D). // - if (VirtioFlush (Dev->PciIo, 0, &Dev->Ring, &Indices) == EFI_SUCCESS && + if (VirtioFlush (Dev->VirtIo, 0, &Dev->Ring, &Indices) == EFI_SUCCESS && HostStatus == VIRTIO_BLK_S_OK) { return EFI_SUCCESS; } @@ -500,11 +499,6 @@ VirtioBlkFlushBlocks ( underlying device - 9 Driver Binding Protocol -- for exporting ourselves - Specs relevant in the specific sense: - - UEFI Spec 2.3.1 + Errata C, 13.4 EFI PCI I/O Protocol - - Driver Writer's Guide for UEFI 2.3.1 v1.01, 18 PCI Driver Design - Guidelines, 18.3 PCI drivers. - @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object incorporating this driver (independently of any device). @@ -516,11 +510,11 @@ VirtioBlkFlushBlocks ( @retval EFI_SUCCESS The driver supports the device being probed. - @retval EFI_UNSUPPORTED Based on virtio-blk PCI discovery, we do not support + @retval EFI_UNSUPPORTED Based on virtio-blk discovery, we do not support the device. @return Error codes from the OpenProtocol() boot service or - the PciIo protocol. + the VirtIo protocol. **/ @@ -533,56 +527,36 @@ VirtioBlkDriverBindingSupported ( ) { EFI_STATUS Status; - EFI_PCI_IO_PROTOCOL *PciIo; - PCI_TYPE00 Pci; + VIRTIO_DEVICE_PROTOCOL *VirtIo; // - // Attempt to open the device with the PciIo set of interfaces. On success, - // the protocol is "instantiated" for the PCI device. Covers duplicate open + // Attempt to open the device with the VirtIo set of interfaces. On success, + // the protocol is "instantiated" for the VirtIo device. Covers duplicate open // attempts (EFI_ALREADY_STARTED). // Status = gBS->OpenProtocol ( DeviceHandle, // candidate device - &gEfiPciIoProtocolGuid, // for generic PCI access - (VOID **)&PciIo, // handle to instantiate + &gVirtioDeviceProtocolGuid, // for generic VirtIo access + (VOID **)&VirtIo, // handle to instantiate This->DriverBindingHandle, // requestor driver identity DeviceHandle, // ControllerHandle, according to // the UEFI Driver Model - EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive PciIo access to + EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive VirtIo access to // the device; to be released ); if (EFI_ERROR (Status)) { return Status; } - // - // Read entire PCI configuration header for more extensive check ahead. - // - Status = PciIo->Pci.Read ( - PciIo, // (protocol, device) - // handle - EfiPciIoWidthUint32, // access width & copy - // mode - 0, // Offset - sizeof Pci / sizeof (UINT32), // Count - &Pci // target buffer - ); - - if (Status == EFI_SUCCESS) { - // - // virtio-0.9.5, 2.1 PCI Discovery - // - Status = (Pci.Hdr.VendorId == 0x1AF4 && - Pci.Hdr.DeviceId >= 0x1000 && Pci.Hdr.DeviceId <= 0x103F && - Pci.Hdr.RevisionID == 0x00 && - Pci.Device.SubsystemID == VIRTIO_SUBSYSTEM_BLOCK_DEVICE) ? EFI_SUCCESS : EFI_UNSUPPORTED; + if (VirtIo->SubSystemDeviceId != VIRTIO_SUBSYSTEM_BLOCK_DEVICE) { + Status = EFI_UNSUPPORTED; } // - // We needed PCI IO access only transitorily, to see whether we support the + // We needed VirtIo access only transitorily, to see whether we support the // device or not. // - gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid, + gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid, This->DriverBindingHandle, DeviceHandle); return Status; } @@ -594,8 +568,8 @@ VirtioBlkDriverBindingSupported ( device. @param[in out] Dev The driver instance to configure. The caller is - responsible for Dev->PciIo's validity (ie. working IO - access to the underlying virtio-blk PCI device). + responsible for Dev->VirtIo's validity (ie. working IO + access to the underlying virtio-blk device). @retval EFI_SUCCESS Setup complete. @@ -626,19 +600,27 @@ VirtioBlkInit ( // Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence. // NextDevStat = 0; // step 1 -- reset device - Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat); + Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); if (EFI_ERROR (Status)) { goto Failed; } NextDevStat |= VSTAT_ACK; // step 2 -- acknowledge device presence - Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat); + Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); if (EFI_ERROR (Status)) { goto Failed; } NextDevStat |= VSTAT_DRIVER; // step 3 -- we know how to drive it - Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat); + Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); + if (EFI_ERROR (Status)) { + goto Failed; + } + + // + // Set Page Size - MMIO VirtIo Specific + // + Status = Dev->VirtIo->SetPageSize (Dev->VirtIo, EFI_PAGE_SIZE); if (EFI_ERROR (Status)) { goto Failed; } @@ -646,11 +628,12 @@ VirtioBlkInit ( // // step 4a -- retrieve and validate features // - Status = VIRTIO_CFG_READ (Dev, Generic.VhdrDeviceFeatureBits, &Features); + Status = Dev->VirtIo->GetDeviceFeatures (Dev->VirtIo, &Features); if (EFI_ERROR (Status)) { goto Failed; } - Status = VIRTIO_CFG_READ (Dev, VhdrCapacity, &NumSectors); + + Status = VIRTIO_CFG_READ (Dev, Capacity, &NumSectors); if (EFI_ERROR (Status)) { goto Failed; } @@ -660,7 +643,7 @@ VirtioBlkInit ( } if (Features & VIRTIO_BLK_F_BLK_SIZE) { - Status = VIRTIO_CFG_READ (Dev, VhdrBlkSize, &BlockSize); + Status = VIRTIO_CFG_READ (Dev, BlkSize, &BlockSize); if (EFI_ERROR (Status)) { goto Failed; } @@ -681,11 +664,11 @@ VirtioBlkInit ( // // step 4b -- allocate virtqueue // - Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueSelect, 0); + Status = Dev->VirtIo->SetQueueSel (Dev->VirtIo, 0); if (EFI_ERROR (Status)) { goto Failed; } - Status = VIRTIO_CFG_READ (Dev, Generic.VhdrQueueSize, &QueueSize); + Status = Dev->VirtIo->GetQueueNumMax (Dev->VirtIo, &QueueSize); if (EFI_ERROR (Status)) { goto Failed; } @@ -700,22 +683,36 @@ VirtioBlkInit ( } // - // step 4c -- Report GPFN (guest-physical frame number) of queue. If anything - // fails from here on, we must release the ring resources. + // Additional steps for MMIO: align the queue appropriately, and set the + // size. If anything fails from here on, we must release the ring resources. // - Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueAddress, - (UINTN) Dev->Ring.Base >> EFI_PAGE_SHIFT); + Status = Dev->VirtIo->SetQueueNum (Dev->VirtIo, QueueSize); if (EFI_ERROR (Status)) { goto ReleaseQueue; } + Status = Dev->VirtIo->SetQueueAlign (Dev->VirtIo, EFI_PAGE_SIZE); + if (EFI_ERROR (Status)) { + goto ReleaseQueue; + } + + // + // step 4c -- Report GPFN (guest-physical frame number) of queue. + // + Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, + (UINT32)(UINTN) Dev->Ring.Base >> EFI_PAGE_SHIFT); + if (EFI_ERROR (Status)) { + goto ReleaseQueue; + } + + // // step 5 -- Report understood features. There are no virtio-blk specific // features to negotiate in virtio-0.9.5, plus we do not want any of the // device-independent (known or unknown) VIRTIO_F_* capabilities (see // Appendix B). // - Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrGuestFeatureBits, 0); + Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, 0); if (EFI_ERROR (Status)) { goto ReleaseQueue; } @@ -724,7 +721,7 @@ VirtioBlkInit ( // step 6 -- initialization complete // NextDevStat |= VSTAT_DRIVER_OK; - Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat); + Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); if (EFI_ERROR (Status)) { goto ReleaseQueue; } @@ -758,10 +755,10 @@ ReleaseQueue: Failed: // // Notify the host about our failure to setup: virtio-0.9.5, 2.2.2.1 Device - // Status. PCI IO access failure here should not mask the original error. + // Status. VirtIo access failure here should not mask the original error. // NextDevStat |= VSTAT_FAILED; - VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat); + Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); return Status; // reached only via Failed above } @@ -788,7 +785,7 @@ VirtioBlkUninit ( // VIRTIO_CFG_WRITE() returns, the host will have learned to stay away from // the old comms area. // - VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, 0); + Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0); VirtioRingUninit (&Dev->Ring); @@ -815,13 +812,13 @@ VirtioBlkUninit ( @retval EFI_SUCCESS Driver instance has been created and - initialized for the virtio-blk PCI device, it + initialized for the virtio-blk device, it is now accessibla via EFI_BLOCK_IO_PROTOCOL. @retval EFI_OUT_OF_RESOURCES Memory allocation failed. @return Error codes from the OpenProtocol() boot - service, the PciIo protocol, VirtioBlkInit(), + service, the VirtIo protocol, VirtioBlkInit(), or the InstallProtocolInterface() boot service. **/ @@ -842,43 +839,19 @@ VirtioBlkDriverBindingStart ( return EFI_OUT_OF_RESOURCES; } - Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid, - (VOID **)&Dev->PciIo, This->DriverBindingHandle, + Status = gBS->OpenProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid, + (VOID **)&Dev->VirtIo, This->DriverBindingHandle, DeviceHandle, EFI_OPEN_PROTOCOL_BY_DRIVER); if (EFI_ERROR (Status)) { goto FreeVirtioBlk; } // - // We must retain and ultimately restore the original PCI attributes of the - // device. See Driver Writer's Guide for UEFI 2.3.1 v1.01, 18.3 PCI drivers / - // 18.3.2 Start() and Stop(). - // - // The third parameter ("Attributes", input) is ignored by the Get operation. - // The fourth parameter ("Result", output) is ignored by the Enable and Set - // operations. - // - // For virtio-blk we only need IO space access. - // - Status = Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationGet, - 0, &Dev->OriginalPciAttributes); - if (EFI_ERROR (Status)) { - goto ClosePciIo; - } - - Status = Dev->PciIo->Attributes (Dev->PciIo, - EfiPciIoAttributeOperationEnable, - EFI_PCI_IO_ATTRIBUTE_IO, NULL); - if (EFI_ERROR (Status)) { - goto ClosePciIo; - } - - // - // PCI IO access granted, configure virtio-blk device. + // VirtIo access granted, configure virtio-blk device. // Status = VirtioBlkInit (Dev); if (EFI_ERROR (Status)) { - goto RestorePciAttributes; + goto CloseVirtIo; } // @@ -897,12 +870,8 @@ VirtioBlkDriverBindingStart ( UninitDev: VirtioBlkUninit (Dev); -RestorePciAttributes: - Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationSet, - Dev->OriginalPciAttributes, NULL); - -ClosePciIo: - gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid, +CloseVirtIo: + gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid, This->DriverBindingHandle, DeviceHandle); FreeVirtioBlk: @@ -973,10 +942,7 @@ VirtioBlkDriverBindingStop ( VirtioBlkUninit (Dev); - Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationSet, - Dev->OriginalPciAttributes, NULL); - - gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid, + gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid, This->DriverBindingHandle, DeviceHandle); FreePool (Dev); diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.h b/OvmfPkg/VirtioBlkDxe/VirtioBlk.h index d22570def9..789caf9a37 100644 --- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.h +++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.h @@ -21,7 +21,6 @@ #include #include #include -#include #include @@ -34,14 +33,13 @@ typedef struct { // at various call depths. The table to the right should make it easier to // track them. // - // field init function init dpth - // ---------------------- ------------------ --------- - UINT32 Signature; // DriverBindingStart 0 - EFI_PCI_IO_PROTOCOL *PciIo; // DriverBindingStart 0 - UINT64 OriginalPciAttributes; // DriverBindingStart 0 - VRING Ring; // VirtioRingInit 2 - EFI_BLOCK_IO_PROTOCOL BlockIo; // VirtioBlkInit 1 - EFI_BLOCK_IO_MEDIA BlockIoMedia; // VirtioBlkInit 1 + // field init function init dpth + // --------------------- ------------------ --------- + UINT32 Signature; // DriverBindingStart 0 + VIRTIO_DEVICE_PROTOCOL *VirtIo; // DriverBindingStart 0 + VRING Ring; // VirtioRingInit 2 + EFI_BLOCK_IO_PROTOCOL BlockIo; // VirtioBlkInit 1 + EFI_BLOCK_IO_MEDIA BlockIoMedia; // VirtioBlkInit 1 } VBLK_DEV; #define VIRTIO_BLK_FROM_BLOCK_IO(BlockIoPointer) \ @@ -66,11 +64,6 @@ typedef struct { underlying device - 9 Driver Binding Protocol -- for exporting ourselves - Specs relevant in the specific sense: - - UEFI Spec 2.3.1 + Errata C, 13.4 EFI PCI I/O Protocol - - Driver Writer's Guide for UEFI 2.3.1 v1.01, 18 PCI Driver Design - Guidelines, 18.3 PCI drivers. - @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object incorporating this driver (independently of any device). @@ -82,11 +75,10 @@ typedef struct { @retval EFI_SUCCESS The driver supports the device being probed. - @retval EFI_UNSUPPORTED Based on virtio-blk PCI discovery, we do not support + @retval EFI_UNSUPPORTED Based on virtio-blk discovery, we do not support the device. - @return Error codes from the OpenProtocol() boot service or - the PciIo protocol. + @return Error codes from the OpenProtocol() boot service. **/ @@ -117,14 +109,14 @@ VirtioBlkDriverBindingSupported ( @retval EFI_SUCCESS Driver instance has been created and - initialized for the virtio-blk PCI device, it + initialized for the virtio-blk device, it is now accessibla via EFI_BLOCK_IO_PROTOCOL. @retval EFI_OUT_OF_RESOURCES Memory allocation failed. @return Error codes from the OpenProtocol() boot - service, the PciIo protocol, VirtioBlkInit(), - or the InstallProtocolInterface() boot service. + service, VirtioBlkInit(), or the + InstallProtocolInterface() boot service. **/ diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.inf b/OvmfPkg/VirtioBlkDxe/VirtioBlk.inf index 6dffc3a22a..d5975b74eb 100644 --- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.inf +++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.inf @@ -38,5 +38,5 @@ VirtioLib [Protocols] - gEfiBlockIoProtocolGuid ## BY_START - gEfiPciIoProtocolGuid ## TO_START + gEfiBlockIoProtocolGuid ## BY_START + gVirtioDeviceProtocolGuid ## TO_START diff --git a/OvmfPkg/VirtioNetDxe/ComponentName.c b/OvmfPkg/VirtioNetDxe/ComponentName.c index a291405ee6..2c96adbcbd 100644 --- a/OvmfPkg/VirtioNetDxe/ComponentName.c +++ b/OvmfPkg/VirtioNetDxe/ComponentName.c @@ -139,20 +139,20 @@ VirtioNetGetControllerName ( } // - // confirm that the device is managed by this driver, using the PCI IO + // confirm that the device is managed by this driver, using the VirtIo // Protocol // Status = EfiTestManagedDevice ( ControllerHandle, gVirtioNetDriverBinding.DriverBindingHandle, - &gEfiPciIoProtocolGuid + &gVirtioDeviceProtocolGuid ); if (EFI_ERROR (Status)) { return Status; } // - // we don't give different names to the bus (= parent, = PCI) handle and the + // we don't give different names to the bus (= parent) handle and the // child (= MAC) handle // return LookupUnicodeString2 ( diff --git a/OvmfPkg/VirtioNetDxe/DriverBinding.c b/OvmfPkg/VirtioNetDxe/DriverBinding.c index c9259ab339..93995c6359 100644 --- a/OvmfPkg/VirtioNetDxe/DriverBinding.c +++ b/OvmfPkg/VirtioNetDxe/DriverBinding.c @@ -15,7 +15,6 @@ **/ -#include #include #include #include @@ -50,8 +49,7 @@ unused. @retval EFI_UNSUPPORTED The host doesn't supply a MAC address. - @return Status codes from Dev->PciIo->Io.Read(), - VIRTIO_CFG_READ() and VIRTIO_CFG_WRITE(). + @return Status codes from VirtIo protocol members. @retval EFI_SUCCESS Configuration values retrieved. */ STATIC @@ -67,6 +65,7 @@ VirtioNetGetFeatures ( EFI_STATUS Status; UINT8 NextDevStat; UINT32 Features; + UINTN MacIdx; UINT16 LinkStatus; // @@ -74,19 +73,19 @@ VirtioNetGetFeatures ( // Initialization Sequence), but don't complete setting it up. // NextDevStat = 0; // step 1 -- reset device - Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat); + Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); if (EFI_ERROR (Status)) { return Status; } NextDevStat |= VSTAT_ACK; // step 2 -- acknowledge device presence - Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat); + Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); if (EFI_ERROR (Status)) { goto YieldDevice; } NextDevStat |= VSTAT_DRIVER; // step 3 -- we know how to drive it - Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat); + Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); if (EFI_ERROR (Status)) { goto YieldDevice; } @@ -94,7 +93,7 @@ VirtioNetGetFeatures ( // // step 4a -- retrieve and validate features // - Status = VIRTIO_CFG_READ (Dev, Generic.VhdrDeviceFeatureBits, &Features); + Status = Dev->VirtIo->GetDeviceFeatures (Dev->VirtIo, &Features); if (EFI_ERROR (Status)) { goto YieldDevice; } @@ -106,16 +105,16 @@ VirtioNetGetFeatures ( Status = EFI_UNSUPPORTED; goto YieldDevice; } - Status = Dev->PciIo->Io.Read (Dev->PciIo, // PciIo - EfiPciIoWidthUint8, // Width - PCI_BAR_IDX0, // BarIndex - OFFSET_OF_VNET (VhdrMac), // Offset - SIZE_OF_VNET (VhdrMac), // Count - MacAddress // Buffer + for (MacIdx = 0; MacIdx < SIZE_OF_VNET (Mac); ++MacIdx) { + Status = Dev->VirtIo->ReadDevice (Dev->VirtIo, + OFFSET_OF_VNET (Mac) + MacIdx, // Offset + 1, // FieldSize + 1, // BufferSize + &MacAddress->Addr[MacIdx] // Buffer ); - - if (EFI_ERROR (Status)) { - goto YieldDevice; + if (EFI_ERROR (Status)) { + goto YieldDevice; + } } // @@ -126,7 +125,7 @@ VirtioNetGetFeatures ( } else { *MediaPresentSupported = TRUE; - Status = VIRTIO_CFG_READ (Dev, VhdrLinkStatus, &LinkStatus); + Status = VIRTIO_CFG_READ (Dev, LinkStatus, &LinkStatus); if (EFI_ERROR (Status)) { goto YieldDevice; } @@ -134,7 +133,7 @@ VirtioNetGetFeatures ( } YieldDevice: - VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, + Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, EFI_ERROR (Status) ? VSTAT_FAILED : 0); return Status; @@ -207,9 +206,9 @@ VirtioNetSnpPopulate ( Dev->Snp.Mode = &Dev->Snm; Dev->Snm.State = EfiSimpleNetworkStopped; - Dev->Snm.HwAddressSize = SIZE_OF_VNET (VhdrMac); - Dev->Snm.MediaHeaderSize = SIZE_OF_VNET (VhdrMac) + // dst MAC - SIZE_OF_VNET (VhdrMac) + // src MAC + Dev->Snm.HwAddressSize = SIZE_OF_VNET (Mac); + Dev->Snm.MediaHeaderSize = SIZE_OF_VNET (Mac) + // dst MAC + SIZE_OF_VNET (Mac) + // src MAC 2; // Ethertype Dev->Snm.MaxPacketSize = 1500; Dev->Snm.NvRamSize = 0; @@ -222,7 +221,7 @@ VirtioNetSnpPopulate ( Dev->Snm.MacAddressChangeable = FALSE; Dev->Snm.MultipleTxSupported = TRUE; - ASSERT (SIZE_OF_VNET (VhdrMac) <= sizeof (EFI_MAC_ADDRESS)); + ASSERT (SIZE_OF_VNET (Mac) <= sizeof (EFI_MAC_ADDRESS)); Status = VirtioNetGetFeatures (Dev, &Dev->Snm.CurrentAddress, &Dev->Snm.MediaPresentSupported, &Dev->Snm.MediaPresent); @@ -230,8 +229,8 @@ VirtioNetSnpPopulate ( goto CloseWaitForPacket; } CopyMem (&Dev->Snm.PermanentAddress, &Dev->Snm.CurrentAddress, - SIZE_OF_VNET (VhdrMac)); - SetMem (&Dev->Snm.BroadcastAddress, SIZE_OF_VNET (VhdrMac), 0xFF); + SIZE_OF_VNET (Mac)); + SetMem (&Dev->Snm.BroadcastAddress, SIZE_OF_VNET (Mac), 0xFF); // // VirtioNetExitBoot() is queued by ExitBootServices(); its purpose is to @@ -348,31 +347,36 @@ VirtioNetDriverBindingSupported ( ) { EFI_STATUS Status; - EFI_PCI_IO_PROTOCOL *PciIo; - PCI_TYPE00 Pci; + VIRTIO_DEVICE_PROTOCOL *VirtIo; - Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid, - (VOID **)&PciIo, This->DriverBindingHandle, DeviceHandle, - EFI_OPEN_PROTOCOL_BY_DRIVER); + // + // Attempt to open the device with the VirtIo set of interfaces. On success, + // the protocol is "instantiated" for the VirtIo device. Covers duplicate open + // attempts (EFI_ALREADY_STARTED). + // + Status = gBS->OpenProtocol ( + DeviceHandle, // candidate device + &gVirtioDeviceProtocolGuid, // for generic VirtIo access + (VOID **)&VirtIo, // handle to instantiate + This->DriverBindingHandle, // requestor driver identity + DeviceHandle, // ControllerHandle, according to + // the UEFI Driver Model + EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive VirtIo access to + // the device; to be released + ); if (EFI_ERROR (Status)) { return Status; } - Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0, - sizeof Pci / sizeof (UINT32), &Pci); - - // - // virtio-0.9.5, 2.1 PCI Discovery: - // the network device has Subsystem Device ID 1 - // - if (Status == EFI_SUCCESS) { - Status = (Pci.Hdr.VendorId == 0x1AF4 && - Pci.Hdr.DeviceId >= 0x1000 && Pci.Hdr.DeviceId <= 0x103F && - Pci.Hdr.RevisionID == 0x00 && - Pci.Device.SubsystemID == VIRTIO_SUBSYSTEM_NETWORK_CARD) ? EFI_SUCCESS : EFI_UNSUPPORTED; + if (VirtIo->SubSystemDeviceId != VIRTIO_SUBSYSTEM_NETWORK_CARD) { + Status = EFI_UNSUPPORTED; } - gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid, + // + // We needed VirtIo access only transitorily, to see whether we support the + // device or not. + // + gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid, This->DriverBindingHandle, DeviceHandle); return Status; } @@ -438,7 +442,7 @@ VirtioNetDriverBindingStart ( VNET_DEV *Dev; EFI_DEVICE_PATH_PROTOCOL *DevicePath; MAC_ADDR_DEVICE_PATH MacNode; - VOID *ChildPciIo; + VOID *ChildVirtIo; // // allocate space for the driver instance @@ -449,43 +453,24 @@ VirtioNetDriverBindingStart ( } Dev->Signature = VNET_SIG; - // - // get PCI access to the device and keep it open - // - Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid, - (VOID **)&Dev->PciIo, This->DriverBindingHandle, + Status = gBS->OpenProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid, + (VOID **)&Dev->VirtIo, This->DriverBindingHandle, DeviceHandle, EFI_OPEN_PROTOCOL_BY_DRIVER); if (EFI_ERROR (Status)) { goto FreeVirtioNet; } - // - // save original PCI attributes and enable IO space access - // - Status = Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationGet, - 0, &Dev->OrigPciAttributes); - if (EFI_ERROR (Status)) { - goto ClosePciIo; - } - - Status = Dev->PciIo->Attributes (Dev->PciIo, - EfiPciIoAttributeOperationEnable, - EFI_PCI_IO_ATTRIBUTE_IO, NULL); - if (EFI_ERROR (Status)) { - goto ClosePciIo; - } - // // now we can run a basic one-shot virtio-net initialization required to // retrieve the MAC address // Status = VirtioNetSnpPopulate (Dev); if (EFI_ERROR (Status)) { - goto RestorePciAttributes; + goto CloseVirtIo; } // - // get the device path of the virtio-net PCI device -- one-shot open + // get the device path of the virtio-net device -- one-shot open // Status = gBS->OpenProtocol (DeviceHandle, &gEfiDevicePathProtocolGuid, (VOID **)&DevicePath, This->DriverBindingHandle, @@ -523,11 +508,11 @@ VirtioNetDriverBindingStart ( } // - // make a note that we keep this device open with PciIo for the sake of this + // make a note that we keep this device open with VirtIo for the sake of this // child // - Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid, - &ChildPciIo, This->DriverBindingHandle, + Status = gBS->OpenProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid, + &ChildVirtIo, This->DriverBindingHandle, Dev->MacHandle, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER); if (EFI_ERROR (Status)) { goto UninstallMultiple; @@ -547,12 +532,8 @@ FreeMacDevicePath: Evacuate: VirtioNetSnpEvacuate (Dev); -RestorePciAttributes: - Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationSet, - Dev->OrigPciAttributes, NULL); - -ClosePciIo: - gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid, +CloseVirtIo: + gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid, This->DriverBindingHandle, DeviceHandle); FreeVirtioNet: @@ -637,7 +618,7 @@ VirtioNetDriverBindingStop ( Status = EFI_DEVICE_ERROR; } else { - gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid, + gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid, This->DriverBindingHandle, Dev->MacHandle); gBS->UninstallMultipleProtocolInterfaces (Dev->MacHandle, &gEfiDevicePathProtocolGuid, Dev->MacDevicePath, @@ -645,8 +626,6 @@ VirtioNetDriverBindingStop ( NULL); FreePool (Dev->MacDevicePath); VirtioNetSnpEvacuate (Dev); - Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationSet, - Dev->OrigPciAttributes, NULL); FreePool (Dev); } @@ -657,7 +636,7 @@ VirtioNetDriverBindingStop ( // // release remaining resources, tied directly to the parent handle // - gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid, + gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid, This->DriverBindingHandle, DeviceHandle); return EFI_SUCCESS; diff --git a/OvmfPkg/VirtioNetDxe/Events.c b/OvmfPkg/VirtioNetDxe/Events.c index b9d7bbf6c6..5be1af6ffb 100644 --- a/OvmfPkg/VirtioNetDxe/Events.c +++ b/OvmfPkg/VirtioNetDxe/Events.c @@ -86,6 +86,6 @@ VirtioNetExitBoot ( Dev = Context; if (Dev->Snm.State == EfiSimpleNetworkInitialized) { - VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, 0); + Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0); } } diff --git a/OvmfPkg/VirtioNetDxe/SnpGetStatus.c b/OvmfPkg/VirtioNetDxe/SnpGetStatus.c index adb57cf8fe..4393d243a2 100644 --- a/OvmfPkg/VirtioNetDxe/SnpGetStatus.c +++ b/OvmfPkg/VirtioNetDxe/SnpGetStatus.c @@ -90,7 +90,7 @@ VirtioNetGetStatus ( if (Dev->Snm.MediaPresentSupported) { UINT16 LinkStatus; - Status = VIRTIO_CFG_READ (Dev, VhdrLinkStatus, &LinkStatus); + Status = VIRTIO_CFG_READ (Dev, LinkStatus, &LinkStatus); if (EFI_ERROR (Status)) { goto Exit; } diff --git a/OvmfPkg/VirtioNetDxe/SnpInitialize.c b/OvmfPkg/VirtioNetDxe/SnpInitialize.c index 6cee014072..4203fbd6c1 100644 --- a/OvmfPkg/VirtioNetDxe/SnpInitialize.c +++ b/OvmfPkg/VirtioNetDxe/SnpInitialize.c @@ -57,14 +57,15 @@ VirtioNetInitRing ( // // step 4b -- allocate selected queue // - Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueSelect, Selector); + Status = Dev->VirtIo->SetQueueSel (Dev->VirtIo, Selector); if (EFI_ERROR (Status)) { return Status; } - Status = VIRTIO_CFG_READ (Dev, Generic.VhdrQueueSize, &QueueSize); + Status = Dev->VirtIo->GetQueueNumMax (Dev->VirtIo, &QueueSize); if (EFI_ERROR (Status)) { return Status; } + // // For each packet (RX and TX alike), we need two descriptors: // one for the virtio-net request header, and another one for the data @@ -77,14 +78,34 @@ VirtioNetInitRing ( return Status; } + // + // Additional steps for MMIO: align the queue appropriately, and set the + // size. If anything fails from here on, we must release the ring resources. + // + Status = Dev->VirtIo->SetQueueNum (Dev->VirtIo, QueueSize); + if (EFI_ERROR (Status)) { + goto ReleaseQueue; + } + + Status = Dev->VirtIo->SetQueueAlign (Dev->VirtIo, EFI_PAGE_SIZE); + if (EFI_ERROR (Status)) { + goto ReleaseQueue; + } + // // step 4c -- report GPFN (guest-physical frame number) of queue // - Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueAddress, - (UINTN) Ring->Base >> EFI_PAGE_SHIFT); + Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, + (UINT32)(UINTN) Ring->Base >> EFI_PAGE_SHIFT); if (EFI_ERROR (Status)) { - VirtioRingUninit (Ring); + goto ReleaseQueue; } + + return EFI_SUCCESS; + +ReleaseQueue: + VirtioRingUninit (Ring); + return Status; } @@ -287,10 +308,9 @@ VirtioNetInitRx ( // virtio-0.9.5, 2.4.1.4 Notifying the Device // MemoryFence (); - Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueNotify, VIRTIO_NET_Q_RX); - + Status = Dev->VirtIo->SetQueueNotify (Dev->VirtIo, VIRTIO_NET_Q_RX); if (EFI_ERROR (Status)) { - VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, 0); + Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0); FreePool (Dev->RxBuf); } @@ -366,13 +386,21 @@ VirtioNetInitialize ( // virtio-0.9.5 spec, 2.2.1 Device Initialization Sequence. // NextDevStat = VSTAT_ACK; // step 2 -- acknowledge device presence - Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat); + Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); if (EFI_ERROR (Status)) { goto InitFailed; } NextDevStat |= VSTAT_DRIVER; // step 3 -- we know how to drive it - Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat); + Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); + if (EFI_ERROR (Status)) { + goto DeviceFailed; + } + + // + // Set Page Size - MMIO VirtIo Specific + // + Status = Dev->VirtIo->SetPageSize (Dev->VirtIo, EFI_PAGE_SIZE); if (EFI_ERROR (Status)) { goto DeviceFailed; } @@ -381,10 +409,11 @@ VirtioNetInitialize ( // step 4a -- retrieve features. Note that we're past validating required // features in VirtioNetGetFeatures(). // - Status = VIRTIO_CFG_READ (Dev, Generic.VhdrDeviceFeatureBits, &Features); + Status = Dev->VirtIo->GetDeviceFeatures (Dev->VirtIo, &Features); if (EFI_ERROR (Status)) { goto DeviceFailed; } + ASSERT (Features & VIRTIO_NET_F_MAC); ASSERT (Dev->Snm.MediaPresentSupported == !!(Features & VIRTIO_NET_F_STATUS)); @@ -406,7 +435,7 @@ VirtioNetInitialize ( // step 5 -- keep only the features we want // Features &= VIRTIO_NET_F_MAC | VIRTIO_NET_F_STATUS; - Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrGuestFeatureBits, Features); + Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, Features); if (EFI_ERROR (Status)) { goto ReleaseTxRing; } @@ -415,7 +444,7 @@ VirtioNetInitialize ( // step 6 -- virtio-net initialization complete // NextDevStat |= VSTAT_DRIVER_OK; - Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat); + Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); if (EFI_ERROR (Status)) { goto ReleaseTxRing; } @@ -441,7 +470,7 @@ ReleaseTxAux: VirtioNetShutdownTx (Dev); AbortDevice: - VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, 0); + Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0); ReleaseTxRing: VirtioRingUninit (&Dev->TxRing); @@ -453,7 +482,7 @@ DeviceFailed: // // restore device status invariant for the EfiSimpleNetworkStarted state // - VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, 0); + Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0); InitFailed: gBS->RestoreTPL (OldTpl); diff --git a/OvmfPkg/VirtioNetDxe/SnpReceive.c b/OvmfPkg/VirtioNetDxe/SnpReceive.c index 87c6ca9b4b..99abd7ebe4 100644 --- a/OvmfPkg/VirtioNetDxe/SnpReceive.c +++ b/OvmfPkg/VirtioNetDxe/SnpReceive.c @@ -147,14 +147,14 @@ VirtioNetReceive ( CopyMem (Buffer, RxPtr, RxLen); if (DestAddr != NULL) { - CopyMem (DestAddr, RxPtr, SIZE_OF_VNET (VhdrMac)); + CopyMem (DestAddr, RxPtr, SIZE_OF_VNET (Mac)); } - RxPtr += SIZE_OF_VNET (VhdrMac); + RxPtr += SIZE_OF_VNET (Mac); if (SrcAddr != NULL) { - CopyMem (SrcAddr, RxPtr, SIZE_OF_VNET (VhdrMac)); + CopyMem (SrcAddr, RxPtr, SIZE_OF_VNET (Mac)); } - RxPtr += SIZE_OF_VNET (VhdrMac); + RxPtr += SIZE_OF_VNET (Mac); if (Protocol != NULL) { *Protocol = (UINT16) ((RxPtr[0] << 8) | RxPtr[1]); @@ -177,9 +177,7 @@ RecycleDesc: *Dev->RxRing.Avail.Idx = AvailIdx; MemoryFence (); - NotifyStatus = VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueNotify, - VIRTIO_NET_Q_RX); - + NotifyStatus = Dev->VirtIo->SetQueueNotify (Dev->VirtIo, VIRTIO_NET_Q_RX); if (!EFI_ERROR (Status)) { // earlier error takes precedence Status = NotifyStatus; } diff --git a/OvmfPkg/VirtioNetDxe/SnpShutdown.c b/OvmfPkg/VirtioNetDxe/SnpShutdown.c index 42aeca1676..01409c0ce7 100644 --- a/OvmfPkg/VirtioNetDxe/SnpShutdown.c +++ b/OvmfPkg/VirtioNetDxe/SnpShutdown.c @@ -63,7 +63,7 @@ VirtioNetShutdown ( break; } - VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, 0); + Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0); VirtioNetShutdownRx (Dev); VirtioNetShutdownTx (Dev); VirtioRingUninit (&Dev->TxRing); diff --git a/OvmfPkg/VirtioNetDxe/SnpTransmit.c b/OvmfPkg/VirtioNetDxe/SnpTransmit.c index ff922ca021..7ca40d5d06 100644 --- a/OvmfPkg/VirtioNetDxe/SnpTransmit.c +++ b/OvmfPkg/VirtioNetDxe/SnpTransmit.c @@ -127,15 +127,15 @@ VirtioNetTransmit ( goto Exit; } Ptr = Buffer; - ASSERT (SIZE_OF_VNET (VhdrMac) <= sizeof (EFI_MAC_ADDRESS)); + ASSERT (SIZE_OF_VNET (Mac) <= sizeof (EFI_MAC_ADDRESS)); - CopyMem (Ptr, DestAddr, SIZE_OF_VNET (VhdrMac)); - Ptr += SIZE_OF_VNET (VhdrMac); + CopyMem (Ptr, DestAddr, SIZE_OF_VNET (Mac)); + Ptr += SIZE_OF_VNET (Mac); CopyMem (Ptr, (SrcAddr == NULL) ? &Dev->Snm.CurrentAddress : SrcAddr, - SIZE_OF_VNET (VhdrMac)); - Ptr += SIZE_OF_VNET (VhdrMac); + SIZE_OF_VNET (Mac)); + Ptr += SIZE_OF_VNET (Mac); *Ptr++ = (UINT8) (*Protocol >> 8); *Ptr++ = (UINT8) *Protocol; @@ -161,7 +161,7 @@ VirtioNetTransmit ( *Dev->TxRing.Avail.Idx = AvailIdx; MemoryFence (); - Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueNotify, VIRTIO_NET_Q_TX); + Status = Dev->VirtIo->SetQueueNotify (Dev->VirtIo, VIRTIO_NET_Q_TX); Exit: gBS->RestoreTPL (OldTpl); diff --git a/OvmfPkg/VirtioNetDxe/VirtioNet.h b/OvmfPkg/VirtioNetDxe/VirtioNet.h index 8c21bcdfa2..31fca79b84 100644 --- a/OvmfPkg/VirtioNetDxe/VirtioNet.h +++ b/OvmfPkg/VirtioNetDxe/VirtioNet.h @@ -24,7 +24,6 @@ #include #include #include -#include #include #define VNET_SIG SIGNATURE_32 ('V', 'N', 'E', 'T') @@ -75,8 +74,7 @@ typedef struct { // field init function // ------------------ ------------------------------ UINT32 Signature; // VirtioNetDriverBindingStart - EFI_PCI_IO_PROTOCOL *PciIo; // VirtioNetDriverBindingStart - UINT64 OrigPciAttributes; // VirtioNetDriverBindingStart + VIRTIO_DEVICE_PROTOCOL *VirtIo; // VirtioNetDriverBindingStart EFI_SIMPLE_NETWORK_PROTOCOL Snp; // VirtioNetSnpPopulate EFI_SIMPLE_NETWORK_MODE Snm; // VirtioNetSnpPopulate EFI_EVENT ExitBoot; // VirtioNetSnpPopulate @@ -109,15 +107,15 @@ typedef struct { #define VIRTIO_NET_FROM_SNP(SnpPointer) \ CR (SnpPointer, VNET_DEV, Snp, VNET_SIG) -#define VIRTIO_CFG_WRITE(Dev, Field, Value) (VirtioWrite ( \ - (Dev)->PciIo, \ +#define VIRTIO_CFG_WRITE(Dev, Field, Value) (VirtioWriteDevice ( \ + (Dev)->VirtIo, \ OFFSET_OF_VNET (Field), \ SIZE_OF_VNET (Field), \ (Value) \ )) -#define VIRTIO_CFG_READ(Dev, Field, Pointer) (VirtioRead ( \ - (Dev)->PciIo, \ +#define VIRTIO_CFG_READ(Dev, Field, Pointer) (VirtioReadDevice ( \ + (Dev)->VirtIo, \ OFFSET_OF_VNET (Field), \ SIZE_OF_VNET (Field), \ sizeof *(Pointer), \ diff --git a/OvmfPkg/VirtioNetDxe/VirtioNet.inf b/OvmfPkg/VirtioNetDxe/VirtioNet.inf index 408a54112a..a855ad4ac1 100644 --- a/OvmfPkg/VirtioNetDxe/VirtioNet.inf +++ b/OvmfPkg/VirtioNetDxe/VirtioNet.inf @@ -57,4 +57,4 @@ [Protocols] gEfiSimpleNetworkProtocolGuid ## BY_START gEfiDevicePathProtocolGuid ## BY_START - gEfiPciIoProtocolGuid ## TO_START + gVirtioDeviceProtocolGuid ## TO_START diff --git a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c index b836fb3e6a..2223c9c33e 100644 --- a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c +++ b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c @@ -38,7 +38,6 @@ **/ -#include #include #include #include @@ -51,15 +50,14 @@ /** - Convenience macros to read and write region 0 IO space elements of the - virtio-scsi PCI device, for configuration purposes. + Convenience macros to read and write configuration elements of the + virtio-scsi VirtIo device. The following macros make it possible to specify only the "core parameters" for such accesses and to derive the rest. By the time VIRTIO_CFG_WRITE() returns, the transaction will have been completed. - @param[in] Dev Pointer to the VSCSI_DEV structure whose PCI IO space - we're accessing. Dev->PciIo must be valid. + @param[in] Dev Pointer to the VSCSI_DEV structure. @param[in] Field A field name from VSCSI_HDR, identifying the virtio-scsi configuration item to access. @@ -72,19 +70,19 @@ one of UINT8, UINT16, UINT32, UINT64. - @return Status codes returned by VirtioWrite() / VirtioRead(). + @return Status codes returned by VirtioWriteDevice() / VirtioReadDevice(). **/ -#define VIRTIO_CFG_WRITE(Dev, Field, Value) (VirtioWrite ( \ - (Dev)->PciIo, \ +#define VIRTIO_CFG_WRITE(Dev, Field, Value) (VirtioWriteDevice ( \ + (Dev)->VirtIo, \ OFFSET_OF_VSCSI (Field), \ SIZE_OF_VSCSI (Field), \ (Value) \ )) -#define VIRTIO_CFG_READ(Dev, Field, Pointer) (VirtioRead ( \ - (Dev)->PciIo, \ +#define VIRTIO_CFG_READ(Dev, Field, Pointer) (VirtioReadDevice ( \ + (Dev)->VirtIo, \ OFFSET_OF_VSCSI (Field), \ SIZE_OF_VSCSI (Field), \ sizeof *(Pointer), \ @@ -471,7 +469,7 @@ VirtioScsiPassThru ( // EFI_NOT_READY would save us the effort, but it would also suggest that the // caller retry. // - if (VirtioFlush (Dev->PciIo, VIRTIO_SCSI_REQUEST_QUEUE, &Dev->Ring, + if (VirtioFlush (Dev->VirtIo, VIRTIO_SCSI_REQUEST_QUEUE, &Dev->Ring, &Indices) != EFI_SUCCESS) { Packet->InTransferLength = 0; Packet->OutTransferLength = 0; @@ -718,19 +716,27 @@ VirtioScsiInit ( // Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence. // NextDevStat = 0; // step 1 -- reset device - Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat); + Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); if (EFI_ERROR (Status)) { goto Failed; } NextDevStat |= VSTAT_ACK; // step 2 -- acknowledge device presence - Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat); + Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); if (EFI_ERROR (Status)) { goto Failed; } NextDevStat |= VSTAT_DRIVER; // step 3 -- we know how to drive it - Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat); + Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); + if (EFI_ERROR (Status)) { + goto Failed; + } + + // + // Set Page Size - MMIO VirtIo Specific + // + Status = Dev->VirtIo->SetPageSize (Dev->VirtIo, EFI_PAGE_SIZE); if (EFI_ERROR (Status)) { goto Failed; } @@ -738,13 +744,13 @@ VirtioScsiInit ( // // step 4a -- retrieve and validate features // - Status = VIRTIO_CFG_READ (Dev, Generic.VhdrDeviceFeatureBits, &Features); + Status = Dev->VirtIo->GetDeviceFeatures (Dev->VirtIo, &Features); if (EFI_ERROR (Status)) { goto Failed; } Dev->InOutSupported = !!(Features & VIRTIO_SCSI_F_INOUT); - Status = VIRTIO_CFG_READ (Dev, VhdrMaxChannel, &MaxChannel); + Status = VIRTIO_CFG_READ (Dev, MaxChannel, &MaxChannel); if (EFI_ERROR (Status)) { goto Failed; } @@ -756,7 +762,7 @@ VirtioScsiInit ( goto Failed; } - Status = VIRTIO_CFG_READ (Dev, VhdrNumQueues, &NumQueues); + Status = VIRTIO_CFG_READ (Dev, NumQueues, &NumQueues); if (EFI_ERROR (Status)) { goto Failed; } @@ -765,7 +771,7 @@ VirtioScsiInit ( goto Failed; } - Status = VIRTIO_CFG_READ (Dev, VhdrMaxTarget, &Dev->MaxTarget); + Status = VIRTIO_CFG_READ (Dev, MaxTarget, &Dev->MaxTarget); if (EFI_ERROR (Status)) { goto Failed; } @@ -773,7 +779,7 @@ VirtioScsiInit ( Dev->MaxTarget = PcdGet16 (PcdVirtioScsiMaxTargetLimit); } - Status = VIRTIO_CFG_READ (Dev, VhdrMaxLun, &Dev->MaxLun); + Status = VIRTIO_CFG_READ (Dev, MaxLun, &Dev->MaxLun); if (EFI_ERROR (Status)) { goto Failed; } @@ -781,7 +787,7 @@ VirtioScsiInit ( Dev->MaxLun = PcdGet32 (PcdVirtioScsiMaxLunLimit); } - Status = VIRTIO_CFG_READ (Dev, VhdrMaxSectors, &Dev->MaxSectors); + Status = VIRTIO_CFG_READ (Dev, MaxSectors, &Dev->MaxSectors); if (EFI_ERROR (Status)) { goto Failed; } @@ -797,12 +803,11 @@ VirtioScsiInit ( // // step 4b -- allocate request virtqueue // - Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueSelect, - VIRTIO_SCSI_REQUEST_QUEUE); + Status = Dev->VirtIo->SetQueueSel (Dev->VirtIo, VIRTIO_SCSI_REQUEST_QUEUE); if (EFI_ERROR (Status)) { goto Failed; } - Status = VIRTIO_CFG_READ (Dev, Generic.VhdrQueueSize, &QueueSize); + Status = Dev->VirtIo->GetQueueNumMax (Dev->VirtIo, &QueueSize); if (EFI_ERROR (Status)) { goto Failed; } @@ -820,11 +825,24 @@ VirtioScsiInit ( } // - // step 4c -- Report GPFN (guest-physical frame number) of queue. If anything - // fails from here on, we must release the ring resources. + // Additional steps for MMIO: align the queue appropriately, and set the + // size. If anything fails from here on, we must release the ring resources. // - Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueAddress, - (UINTN) Dev->Ring.Base >> EFI_PAGE_SHIFT); + Status = Dev->VirtIo->SetQueueNum (Dev->VirtIo, QueueSize); + if (EFI_ERROR (Status)) { + goto ReleaseQueue; + } + + Status = Dev->VirtIo->SetQueueAlign (Dev->VirtIo, EFI_PAGE_SIZE); + if (EFI_ERROR (Status)) { + goto ReleaseQueue; + } + + // + // step 4c -- Report GPFN (guest-physical frame number) of queue. + // + Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, + (UINT32)(UINTN) Dev->Ring.Base >> EFI_PAGE_SHIFT); if (EFI_ERROR (Status)) { goto ReleaseQueue; } @@ -834,8 +852,8 @@ VirtioScsiInit ( // the known (or unknown) VIRTIO_SCSI_F_* or VIRTIO_F_* capabilities (see // virtio-0.9.5, Appendices B and I), except bidirectional transfers. // - Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrGuestFeatureBits, - Features & VIRTIO_SCSI_F_INOUT); + Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, + Features & VIRTIO_SCSI_F_INOUT); if (EFI_ERROR (Status)) { goto ReleaseQueue; } @@ -844,11 +862,11 @@ VirtioScsiInit ( // We expect these maximum sizes from the host. Since they are // guest-negotiable, ask for them rather than just checking them. // - Status = VIRTIO_CFG_WRITE (Dev, VhdrCdbSize, VIRTIO_SCSI_CDB_SIZE); + Status = VIRTIO_CFG_WRITE (Dev, CdbSize, VIRTIO_SCSI_CDB_SIZE); if (EFI_ERROR (Status)) { goto ReleaseQueue; } - Status = VIRTIO_CFG_WRITE (Dev, VhdrSenseSize, VIRTIO_SCSI_SENSE_SIZE); + Status = VIRTIO_CFG_WRITE (Dev, SenseSize, VIRTIO_SCSI_SENSE_SIZE); if (EFI_ERROR (Status)) { goto ReleaseQueue; } @@ -857,7 +875,7 @@ VirtioScsiInit ( // step 6 -- initialization complete // NextDevStat |= VSTAT_DRIVER_OK; - Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat); + Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); if (EFI_ERROR (Status)) { goto ReleaseQueue; } @@ -901,10 +919,10 @@ ReleaseQueue: Failed: // // Notify the host about our failure to setup: virtio-0.9.5, 2.2.2.1 Device - // Status. PCI IO access failure here should not mask the original error. + // Status. VirtIo access failure here should not mask the original error. // NextDevStat |= VSTAT_FAILED; - VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat); + Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); Dev->InOutSupported = FALSE; Dev->MaxTarget = 0; @@ -928,7 +946,7 @@ VirtioScsiUninit ( // VIRTIO_CFG_WRITE() returns, the host will have learned to stay away from // the old comms area. // - VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, 0); + Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0); Dev->InOutSupported = FALSE; Dev->MaxTarget = 0; @@ -953,11 +971,8 @@ VirtioScsiUninit ( // The implementation follows: // - Driver Writer's Guide for UEFI 2.3.1 v1.01 // - 5.1.3.4 OpenProtocol() and CloseProtocol() -// - 18 PCI Driver Design Guidelines -// - 18.3 PCI drivers // - UEFI Spec 2.3.1 + Errata C // - 6.3 Protocol Handler Services -// - 13.4 EFI PCI I/O Protocol // EFI_STATUS @@ -968,57 +983,37 @@ VirtioScsiDriverBindingSupported ( IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { - EFI_STATUS Status; - EFI_PCI_IO_PROTOCOL *PciIo; - PCI_TYPE00 Pci; + EFI_STATUS Status; + VIRTIO_DEVICE_PROTOCOL *VirtIo; // - // Attempt to open the device with the PciIo set of interfaces. On success, - // the protocol is "instantiated" for the PCI device. Covers duplicate open + // Attempt to open the device with the VirtIo set of interfaces. On success, + // the protocol is "instantiated" for the VirtIo device. Covers duplicate open // attempts (EFI_ALREADY_STARTED). // Status = gBS->OpenProtocol ( DeviceHandle, // candidate device - &gEfiPciIoProtocolGuid, // for generic PCI access - (VOID **)&PciIo, // handle to instantiate + &gVirtioDeviceProtocolGuid, // for generic VirtIo access + (VOID **)&VirtIo, // handle to instantiate This->DriverBindingHandle, // requestor driver identity DeviceHandle, // ControllerHandle, according to // the UEFI Driver Model - EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive PciIo access to + EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive VirtIo access to // the device; to be released ); if (EFI_ERROR (Status)) { return Status; } - // - // Read entire PCI configuration header for more extensive check ahead. - // - Status = PciIo->Pci.Read ( - PciIo, // (protocol, device) - // handle - EfiPciIoWidthUint32, // access width & copy - // mode - 0, // Offset - sizeof Pci / sizeof (UINT32), // Count - &Pci // target buffer - ); - - if (Status == EFI_SUCCESS) { - // - // virtio-0.9.5, 2.1 PCI Discovery - // - Status = (Pci.Hdr.VendorId == 0x1AF4 && - Pci.Hdr.DeviceId >= 0x1000 && Pci.Hdr.DeviceId <= 0x103F && - Pci.Hdr.RevisionID == 0x00 && - Pci.Device.SubsystemID == VIRTIO_SUBSYSTEM_SCSI_HOST) ? EFI_SUCCESS : EFI_UNSUPPORTED; + if (VirtIo->SubSystemDeviceId != VIRTIO_SUBSYSTEM_SCSI_HOST) { + Status = EFI_UNSUPPORTED; } // - // We needed PCI IO access only transitorily, to see whether we support the + // We needed VirtIo access only transitorily, to see whether we support the // device or not. // - gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid, + gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid, This->DriverBindingHandle, DeviceHandle); return Status; } @@ -1040,43 +1035,19 @@ VirtioScsiDriverBindingStart ( return EFI_OUT_OF_RESOURCES; } - Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid, - (VOID **)&Dev->PciIo, This->DriverBindingHandle, + Status = gBS->OpenProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid, + (VOID **)&Dev->VirtIo, This->DriverBindingHandle, DeviceHandle, EFI_OPEN_PROTOCOL_BY_DRIVER); if (EFI_ERROR (Status)) { goto FreeVirtioScsi; } // - // We must retain and ultimately restore the original PCI attributes of the - // device. See Driver Writer's Guide for UEFI 2.3.1 v1.01, 18.3 PCI drivers / - // 18.3.2 Start() and Stop(). - // - // The third parameter ("Attributes", input) is ignored by the Get operation. - // The fourth parameter ("Result", output) is ignored by the Enable and Set - // operations. - // - // For virtio-scsi we only need IO space access. - // - Status = Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationGet, - 0, &Dev->OriginalPciAttributes); - if (EFI_ERROR (Status)) { - goto ClosePciIo; - } - - Status = Dev->PciIo->Attributes (Dev->PciIo, - EfiPciIoAttributeOperationEnable, - EFI_PCI_IO_ATTRIBUTE_IO, NULL); - if (EFI_ERROR (Status)) { - goto ClosePciIo; - } - - // - // PCI IO access granted, configure virtio-scsi device. + // VirtIo access granted, configure virtio-scsi device. // Status = VirtioScsiInit (Dev); if (EFI_ERROR (Status)) { - goto RestorePciAttributes; + goto CloseVirtIo; } // @@ -1096,12 +1067,8 @@ VirtioScsiDriverBindingStart ( UninitDev: VirtioScsiUninit (Dev); -RestorePciAttributes: - Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationSet, - Dev->OriginalPciAttributes, NULL); - -ClosePciIo: - gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid, +CloseVirtIo: + gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid, This->DriverBindingHandle, DeviceHandle); FreeVirtioScsi: @@ -1149,10 +1116,7 @@ VirtioScsiDriverBindingStop ( VirtioScsiUninit (Dev); - Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationSet, - Dev->OriginalPciAttributes, NULL); - - gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid, + gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid, This->DriverBindingHandle, DeviceHandle); FreePool (Dev); diff --git a/OvmfPkg/VirtioScsiDxe/VirtioScsi.h b/OvmfPkg/VirtioScsiDxe/VirtioScsi.h index f5220b2215..0d3181d140 100644 --- a/OvmfPkg/VirtioScsiDxe/VirtioScsi.h +++ b/OvmfPkg/VirtioScsiDxe/VirtioScsi.h @@ -20,7 +20,6 @@ #include #include -#include #include #include @@ -49,18 +48,17 @@ typedef struct { // at various call depths. The table to the right should make it easier to // track them. // - // field init function init depth - // ---------------------- ------------------ ---------- - UINT32 Signature; // DriverBindingStart 0 - EFI_PCI_IO_PROTOCOL *PciIo; // DriverBindingStart 0 - UINT64 OriginalPciAttributes; // DriverBindingStart 0 - BOOLEAN InOutSupported; // VirtioScsiInit 1 - UINT16 MaxTarget; // VirtioScsiInit 1 - UINT32 MaxLun; // VirtioScsiInit 1 - UINT32 MaxSectors; // VirtioScsiInit 1 - VRING Ring; // VirtioRingInit 2 - EFI_EXT_SCSI_PASS_THRU_PROTOCOL PassThru; // VirtioScsiInit 1 - EFI_EXT_SCSI_PASS_THRU_MODE PassThruMode; // VirtioScsiInit 1 + // field init function init depth + // ---------------- ------------------ ---------- + UINT32 Signature; // DriverBindingStart 0 + VIRTIO_DEVICE_PROTOCOL *VirtIo; // DriverBindingStart 0 + BOOLEAN InOutSupported; // VirtioScsiInit 1 + UINT16 MaxTarget; // VirtioScsiInit 1 + UINT32 MaxLun; // VirtioScsiInit 1 + UINT32 MaxSectors; // VirtioScsiInit 1 + VRING Ring; // VirtioRingInit 2 + EFI_EXT_SCSI_PASS_THRU_PROTOCOL PassThru; // VirtioScsiInit 1 + EFI_EXT_SCSI_PASS_THRU_MODE PassThruMode; // VirtioScsiInit 1 } VSCSI_DEV; #define VIRTIO_SCSI_FROM_PASS_THRU(PassThruPointer) \ diff --git a/OvmfPkg/VirtioScsiDxe/VirtioScsi.inf b/OvmfPkg/VirtioScsiDxe/VirtioScsi.inf index 8209c50275..7558112393 100644 --- a/OvmfPkg/VirtioScsiDxe/VirtioScsi.inf +++ b/OvmfPkg/VirtioScsiDxe/VirtioScsi.inf @@ -40,7 +40,7 @@ [Protocols] gEfiExtScsiPassThruProtocolGuid ## BY_START - gEfiPciIoProtocolGuid ## TO_START + gVirtioDeviceProtocolGuid ## TO_START [Pcd] gUefiOvmfPkgTokenSpaceGuid.PcdVirtioScsiMaxTargetLimit ## CONSUMES