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 <olivier.martin@arm.com>

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 <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>

git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@14966 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
Olivier Martin
2013-12-11 16:58:22 +00:00
committed by jljusten
parent 6fb4e772a0
commit 56f65ed838
27 changed files with 388 additions and 532 deletions

View File

@@ -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);