[edk2] [PATCH v3 07/11] OvmfPkg: Make the VirtIo devices use the new VIRTIO_DEVICE_PROTOCOL

Subject: [edk2] [PATCH v3 07/11] OvmfPkg: Make the VirtIo devices use the new VIRTIO_DEVICE_PROTOCOL

From: Olivier Martin <olivier.martin@arm.com>

To: edk2-devel@lists.sourceforge.net

Date: 2013-09-23 20:17:37

  • 2013-09-23 20:17:37  Olivier Martin   [edk2] [PATCH v3 07/11] OvmfPkg: Make the VirtIo devices use the new VIRTIO_DEVICE_PROTOCOL
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Olivier Martin 
---
 OvmfPkg/Include/IndustryStandard/VirtioBlk.h  |   21 ++--
 OvmfPkg/Include/IndustryStandard/VirtioNet.h  |   14 +--
 OvmfPkg/Include/IndustryStandard/VirtioScsi.h |   27 ++--
 OvmfPkg/Include/Library/VirtioLib.h           |   49 ++++----
 OvmfPkg/Library/VirtioLib/VirtioLib.c         |  126 ++++---------------
 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              |  165 +++++++++----------------
 OvmfPkg/VirtioBlkDxe/VirtioBlk.h              |   15 +--
 OvmfPkg/VirtioBlkDxe/VirtioBlk.inf            |    4 +-
 OvmfPkg/VirtioNetDxe/ComponentName.c          |    4 +-
 OvmfPkg/VirtioNetDxe/DriverBinding.c          |  145 ++++++++++------------
 OvmfPkg/VirtioNetDxe/Events.c                 |    2 +-
 OvmfPkg/VirtioNetDxe/SnpGetStatus.c           |    2 +-
 OvmfPkg/VirtioNetDxe/SnpInitialize.c          |   33 ++---
 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            |  151 +++++++----------------
 OvmfPkg/VirtioScsiDxe/VirtioScsi.h            |   24 ++--
 OvmfPkg/VirtioScsiDxe/VirtioScsi.inf          |    2 +-
 27 files changed, 315 insertions(+), 515 deletions(-)

diff --git a/OvmfPkg/Include/IndustryStandard/VirtioBlk.h b/OvmfPkg/Include/IndustryStandard/VirtioBlk.h
index b71f224..ab11e6c 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 03dfeb2..54255df 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 VNET_HDR.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 59ce97e..0c9b520 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 5130349..722cdb1 100644
--- a/OvmfPkg/Include/Library/VirtioLib.h
+++ b/OvmfPkg/Include/Library/VirtioLib.h
@@ -17,17 +17,18 @@
 #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 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 PCI device.
 
   @param[in] FieldOffset  Destination offset.
 
@@ -37,27 +38,27 @@
                           The least significant FieldSize bytes will be used.
 
 
-  @return  Status code returned by PciIo->Io.Write().
+  @return  Status code returned by VirtIo->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
   );
 
 
 /**
 
-  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 PCI device.
 
   @param[in] FieldOffset  Source offset.
 
@@ -69,17 +70,17 @@ VirtioWrite (
   @param[out] Buffer      Target buffer.
 
 
-  @return  Status code returned by PciIo->Io.Read().
+  @return  Status code returned by VirtIo->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
   );
 
 
@@ -218,7 +219,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 PCI device to notify.
 
   @param[in] VirtQueueId  Identifies the queue for the target device.
 
@@ -229,7 +230,7 @@ VirtioAppendDesc (
                           of the descriptor chain.
 
 
-  @return              Error code from VirtioWrite() if it fails.
+  @return              Error code from VirtioWriteDevice() if it fails.
 
   @retval EFI_SUCCESS  Otherwise, the host processed all descriptors.
 
@@ -237,10 +238,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 959bc5d..e4d5bd8 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
@@ -26,12 +27,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 PCI device.
 
   @param[in] FieldOffset  Destination offset.
 
@@ -41,63 +42,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 PCI device.
 
   @param[in] FieldOffset  Source offset.
 
@@ -109,55 +77,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 +309,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 PCI device to notify.
 
   @param[in] VirtQueueId  Identifies the queue for the target device.
 
@@ -387,7 +320,7 @@ VirtioAppendDesc (
                           of the descriptor chain.
 
 
-  @return              Error code from VirtioWrite() if it fails.
+  @return              Error code from VirtioWriteDevice() if it fails.
 
   @retval EFI_SUCCESS  Otherwise, the host processed all descriptors.
 
@@ -395,10 +328,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 +360,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 41c104c..5f3c6eb 100644
--- a/OvmfPkg/OvmfPkgIa32.dsc
+++ b/OvmfPkg/OvmfPkgIa32.dsc
@@ -407,6 +407,7 @@
   }
 
   OvmfPkg/BlockMmioToBlockIoDxe/BlockIo.inf
+  OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf
   OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
   OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
   OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf {
diff --git a/OvmfPkg/OvmfPkgIa32.fdf b/OvmfPkg/OvmfPkgIa32.fdf
index df4f227..1965e99 100644
--- a/OvmfPkg/OvmfPkgIa32.fdf
+++ b/OvmfPkg/OvmfPkgIa32.fdf
@@ -181,6 +181,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/EmuVariableFvbRuntimeDxe/Fvb.inf
diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
index 2c7b457..d883ba0 100644
--- a/OvmfPkg/OvmfPkgIa32X64.dsc
+++ b/OvmfPkg/OvmfPkgIa32X64.dsc
@@ -414,6 +414,7 @@
   }
 
   OvmfPkg/BlockMmioToBlockIoDxe/BlockIo.inf
+  OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf
   OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
   OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
   OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf {
diff --git a/OvmfPkg/OvmfPkgIa32X64.fdf b/OvmfPkg/OvmfPkgIa32X64.fdf
index d93a7ff..323e431 100644
--- a/OvmfPkg/OvmfPkgIa32X64.fdf
+++ b/OvmfPkg/OvmfPkgIa32X64.fdf
@@ -181,6 +181,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/EmuVariableFvbRuntimeDxe/Fvb.inf
diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
index 9fc0183..27dc6db 100644
--- a/OvmfPkg/OvmfPkgX64.dsc
+++ b/OvmfPkg/OvmfPkgX64.dsc
@@ -412,6 +412,7 @@
   }
 
   OvmfPkg/BlockMmioToBlockIoDxe/BlockIo.inf
+  OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf
   OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
   OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
   OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf {
diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
index a7c9bcd..11de481 100644
--- a/OvmfPkg/OvmfPkgX64.fdf
+++ b/OvmfPkg/OvmfPkgX64.fdf
@@ -181,6 +181,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/EmuVariableFvbRuntimeDxe/Fvb.inf
diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
index b2bfcdf..2b65fc4 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 == 0x02) ? EFI_SUCCESS : EFI_UNSUPPORTED;
+  if (VirtIo->SubSystemDeviceId != 0x02) {
+    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,19 @@ 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;
   }
@@ -646,11 +620,9 @@ VirtioBlkInit (
   //
   // step 4a -- retrieve and validate features
   //
-  Status = VIRTIO_CFG_READ (Dev, Generic.VhdrDeviceFeatureBits, &Features);
-  if (EFI_ERROR (Status)) {
-    goto Failed;
-  }
-  Status = VIRTIO_CFG_READ (Dev, VhdrCapacity, &NumSectors);
+  Features = Dev->VirtIo->GetDeviceFeatures (Dev->VirtIo);
+
+  Status = VIRTIO_CFG_READ (Dev, Capacity, &NumSectors);
   if (EFI_ERROR (Status)) {
     goto Failed;
   }
@@ -660,7 +632,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 +653,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);
+  QueueSize = Dev->VirtIo->GetQueueNumMax (Dev->VirtIo);
   if (EFI_ERROR (Status)) {
     goto Failed;
   }
@@ -700,11 +672,19 @@ VirtioBlkInit (
   }
 
   //
+  // Additional steps for MMIO: align the queue appropriately, and set the size
+  Dev->VirtIo->SetQueueNum (Dev->VirtIo, QueueSize);
+  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. 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->SetQueueAddress (Dev->VirtIo,
+      (UINTN) Dev->Ring.Base >> EFI_PAGE_SHIFT);
   if (EFI_ERROR (Status)) {
     goto ReleaseQueue;
   }
@@ -715,7 +695,7 @@ VirtioBlkInit (
   // 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 +704,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 +738,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 +768,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 +795,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 +822,23 @@ 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;
+  if (Dev->VirtIo->SubSystemDeviceId != 0x02) {
+    return EFI_UNSUPPORTED;
   }
 
   //
-  // 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 +857,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 +929,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 d22570d..af77d4b 100644
--- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.h
+++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.h
@@ -34,14 +34,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) \
diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.inf b/OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
index 6dffc3a..d5975b7 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 a291405..91d573c 100644
--- a/OvmfPkg/VirtioNetDxe/ComponentName.c
+++ b/OvmfPkg/VirtioNetDxe/ComponentName.c
@@ -139,13 +139,13 @@ 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;
diff --git a/OvmfPkg/VirtioNetDxe/DriverBinding.c b/OvmfPkg/VirtioNetDxe/DriverBinding.c
index d9c0096..cf92d78 100644
--- a/OvmfPkg/VirtioNetDxe/DriverBinding.c
+++ b/OvmfPkg/VirtioNetDxe/DriverBinding.c
@@ -15,7 +15,6 @@
 
 **/
 
-#include 
 #include 
 #include 
 #include 
@@ -50,7 +49,7 @@
                                     unused.
 
   @retval EFI_UNSUPPORTED           The host doesn't supply a MAC address.
-  @return                           Status codes from Dev->PciIo->Io.Read(),
+  @return                           Status codes from Dev->VirtIo->Io.Read(),
                                     VIRTIO_CFG_READ() and VIRTIO_CFG_WRITE().
   @retval EFI_SUCCESS               Configuration values retrieved.
 */
@@ -68,25 +67,26 @@ VirtioNetGetFeatures (
   UINT8      NextDevStat;
   UINT32     Features;
   UINT16     LinkStatus;
+  UINT8      TempMacBuffer[8];
 
   //
   // Interrogate the device for features (virtio-0.9.5, 2.2.1 Device
   // 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,10 +94,7 @@ VirtioNetGetFeatures (
   //
   // step 4a -- retrieve and validate features
   //
-  Status = VIRTIO_CFG_READ (Dev, Generic.VhdrDeviceFeatureBits, &Features);
-  if (EFI_ERROR (Status)) {
-    goto YieldDevice;
-  }
+  Features = Dev->VirtIo->GetDeviceFeatures (Dev->VirtIo);
 
   //
   // get MAC address byte-wise
@@ -106,13 +103,19 @@ 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
-                            );
+
+  //
+  // Virtio->ReadDevice only supports read sizes of 1, 2, 4 and 8 bytes.
+  // Mac Addresses are 6 bytes. So Read into a temporary 8 byte buffer,
+  // then copy to the output parameter.
+  //
+  Status = Dev->VirtIo->ReadDevice (Dev->VirtIo,              // VirtIo
+                                    OFFSET_OF_VNET (Mac),     // Offset
+                                    sizeof (TempMacBuffer),   // FieldSize
+                                    sizeof (TempMacBuffer),   // Count
+                                    &TempMacBuffer            // Buffer
+                                    );
+  CopyMem (MacAddress, &TempMacBuffer, SIZE_OF_VNET(Mac));
 
   if (EFI_ERROR (Status)) {
     goto YieldDevice;
@@ -126,7 +129,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 +137,7 @@ VirtioNetGetFeatures (
   }
 
 YieldDevice:
-  VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus,
+  Dev->VirtIo->SetDeviceStatus (Dev->VirtIo,
     EFI_ERROR (Status) ? VSTAT_FAILED : 0);
 
   return Status;
@@ -207,9 +210,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 +225,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 +233,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 +351,36 @@ VirtioNetDriverBindingSupported (
   )
 {
   EFI_STATUS          Status;
-  EFI_PCI_IO_PROTOCOL *PciIo;
-  PCI_TYPE00          Pci;
-
-  Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
-                  (VOID **)&PciIo, This->DriverBindingHandle, DeviceHandle,
-                  EFI_OPEN_PROTOCOL_BY_DRIVER);
+  VIRTIO_DEVICE_PROTOCOL *VirtIo;
+
+  //
+  // 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);
+  if (VirtIo->SubSystemDeviceId != 0x01) {
+    Status = EFI_UNSUPPORTED;
+  }
 
   //
-  // virtio-0.9.5, 2.1 PCI Discovery:
-  // the network device has Subsystem Device ID 1
+  // We needed VirtIo access only transitorily, to see whether we support the
+  // device or not.
   //
-  if (Status == EFI_SUCCESS) {
-    Status = (Pci.Hdr.VendorId == 0x1AF4 &&
-              Pci.Hdr.DeviceId >= 0x1000 && Pci.Hdr.DeviceId <= 0x103F &&
-              Pci.Hdr.RevisionID == 0x00 &&
-              Pci.Device.SubsystemID == 0x01) ? EFI_SUCCESS : EFI_UNSUPPORTED;
-  }
-
-  gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
+  gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
          This->DriverBindingHandle, DeviceHandle);
   return Status;
 }
@@ -438,7 +446,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,30 +457,15 @@ 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;
+    goto FreeVirtioBlk;
   }
 
-  Status = Dev->PciIo->Attributes (Dev->PciIo,
-                         EfiPciIoAttributeOperationEnable,
-                         EFI_PCI_IO_ATTRIBUTE_IO, NULL);
-  if (EFI_ERROR (Status)) {
-    goto ClosePciIo;
+  if (Dev->VirtIo->SubSystemDeviceId != 0x01) {
+    return EFI_UNSUPPORTED;
   }
 
   //
@@ -481,11 +474,11 @@ VirtioNetDriverBindingStart (
   //
   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 +516,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,15 +540,11 @@ 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:
+FreeVirtioBlk:
   FreePool (Dev);
 
   return Status;
@@ -637,7 +626,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 +634,6 @@ VirtioNetDriverBindingStop (
              NULL);
       FreePool (Dev->MacDevicePath);
       VirtioNetSnpEvacuate (Dev);
-      Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationSet,
-                    Dev->OrigPciAttributes, NULL);
       FreePool (Dev);
     }
 
@@ -657,7 +644,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 b9d7bbf..5be1af6 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 adb57cf..4393d24 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 6cee014..5d91b50 100644
--- a/OvmfPkg/VirtioNetDxe/SnpInitialize.c
+++ b/OvmfPkg/VirtioNetDxe/SnpInitialize.c
@@ -57,14 +57,11 @@ VirtioNetInitRing (
   //
   // step 4b -- allocate selected queue
   //
-  Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueSelect, Selector);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-  Status = VIRTIO_CFG_READ (Dev, Generic.VhdrQueueSize, &QueueSize);
+  Status = Dev->VirtIo->SetQueueSel (Dev->VirtIo, Selector);
   if (EFI_ERROR (Status)) {
     return Status;
   }
+  QueueSize = Dev->VirtIo->GetQueueNumMax (Dev->VirtIo);
   //
   // For each packet (RX and TX alike), we need two descriptors:
   // one for the virtio-net request header, and another one for the data
@@ -80,8 +77,8 @@ VirtioNetInitRing (
   //
   // 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,
+      (UINTN) Ring->Base >> EFI_PAGE_SHIFT);
   if (EFI_ERROR (Status)) {
     VirtioRingUninit (Ring);
   }
@@ -287,10 +284,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 +362,13 @@ 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;
   }
@@ -381,10 +377,7 @@ VirtioNetInitialize (
   // step 4a -- retrieve features. Note that we're past validating required
   // features in VirtioNetGetFeatures().
   //
-  Status = VIRTIO_CFG_READ (Dev, Generic.VhdrDeviceFeatureBits, &Features);
-  if (EFI_ERROR (Status)) {
-    goto DeviceFailed;
-  }
+  Features = Dev->VirtIo->GetDeviceFeatures (Dev->VirtIo);
   ASSERT (Features & VIRTIO_NET_F_MAC);
   ASSERT (Dev->Snm.MediaPresentSupported ==
     !!(Features & VIRTIO_NET_F_STATUS));
@@ -406,7 +399,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 +408,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 +434,7 @@ ReleaseTxAux:
   VirtioNetShutdownTx (Dev);
 
 AbortDevice:
-  VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, 0);
+  Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
 
 ReleaseTxRing:
   VirtioRingUninit (&Dev->TxRing);
@@ -453,7 +446,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 87c6ca9..99abd7e 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 42aeca1..01409c0 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 ff922ca..7ca40d5 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 8c21bcd..31fca79 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 408a541..a855ad4 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 e58dd80..fe56532 100644
--- a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
+++ b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
@@ -38,7 +38,6 @@
 
 **/
 
-#include 
 #include 
 #include 
 #include 
@@ -52,14 +51,13 @@
 /**
 
   Convenience macros to read and write region 0 IO space elements of the
-  virtio-scsi PCI device, for configuration purposes.
+  virtio-scsi VirtIo 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 VSCSI_DEV structure whose PCI IO space
-                       we're accessing. Dev->PciIo must be valid.
+  @param[in] Dev       Pointer to the VirtIo Device Protocol
 
   @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,19 @@ 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;
   }
@@ -738,13 +736,13 @@ VirtioScsiInit (
   //
   // step 4a -- retrieve and validate features
   //
-  Status = VIRTIO_CFG_READ (Dev, Generic.VhdrDeviceFeatureBits, &Features);
+  Features = Dev->VirtIo->GetDeviceFeatures (Dev->VirtIo);
   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 +754,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 +763,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 +771,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 +779,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 +795,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);
+  QueueSize = Dev->VirtIo->GetQueueNumMax (Dev->VirtIo);
   if (EFI_ERROR (Status)) {
     goto Failed;
   }
@@ -823,8 +820,8 @@ VirtioScsiInit (
   // step 4c -- Report GPFN (guest-physical frame number) of queue. 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->SetQueueAddress (Dev->VirtIo,
+      (UINTN) Dev->Ring.Base >> EFI_PAGE_SHIFT);
   if (EFI_ERROR (Status)) {
     goto ReleaseQueue;
   }
@@ -834,8 +831,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 +841,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 +854,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 +898,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 +925,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 +950,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 +962,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 == 0x08) ? EFI_SUCCESS : EFI_UNSUPPORTED;
+  if (VirtIo->SubSystemDeviceId != 0x08) {
+    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 +1014,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 +1046,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 +1095,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 f5220b2..0d3181d 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 8209c50..7558112 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
-- 
1.7.0.4


------------------------------------------------------------------------------
LIMITED TIME SALE - Full Year of Microsoft Training For Just $49.99!
1,500+ hours of tutorials including VisualStudio 2012, Windows 8, SharePoint
2013, SQL 2012, MVC 4, more. BEST VALUE: New Multi-Library Power Pack includes
Mobile, Cloud, Java, and UX Design. Lowest price ever! Ends 9/20/13. 
http://pubads.g.doubleclick.net/gampad/clk?id=58041151&iu=/4140/ostg.clktrk
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/edk2-devel