X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=OvmfPkg%2FVirtioScsiDxe%2FVirtioScsi.c;h=c080404330e55a941507a488b61e08626bab7601;hb=fed691a6f9138c3c22d075a9597435be43e660d0;hp=0bcceecab113ae38b31eeadd50ef7c0071c3843f;hpb=ece77e4047c36ddd177949e81d548bda244ea8a7;p=mirror_edk2.git
diff --git a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
index 0bcceecab1..c080404330 100644
--- a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
+++ b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
@@ -26,7 +26,7 @@
unreasonable for now.
Copyright (C) 2012, Red Hat, Inc.
- Copyright (c) 2012, Intel Corporation. All rights reserved.
+ Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available
under the terms and conditions of the BSD License which accompanies this
@@ -253,7 +253,7 @@ PopulateRequest (
//
Request->Lun[0] = 1;
Request->Lun[1] = (UINT8) Target;
- Request->Lun[2] = (UINT8) ((Lun >> 8) | 0x40);
+ Request->Lun[2] = (UINT8) (((UINT32)Lun >> 8) | 0x40);
Request->Lun[3] = (UINT8) Lun;
//
@@ -470,7 +470,7 @@ VirtioScsiPassThru (
// caller retry.
//
if (VirtioFlush (Dev->VirtIo, VIRTIO_SCSI_REQUEST_QUEUE, &Dev->Ring,
- &Indices) != EFI_SUCCESS) {
+ &Indices, NULL) != EFI_SUCCESS) {
Packet->InTransferLength = 0;
Packet->OutTransferLength = 0;
Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;
@@ -707,7 +707,7 @@ VirtioScsiInit (
UINT8 NextDevStat;
EFI_STATUS Status;
- UINT32 Features;
+ UINT64 Features;
UINT16 MaxChannel; // for validation only
UINT32 NumQueues; // for validation only
UINT16 QueueSize;
@@ -748,7 +748,7 @@ VirtioScsiInit (
if (EFI_ERROR (Status)) {
goto Failed;
}
- Dev->InOutSupported = !!(Features & VIRTIO_SCSI_F_INOUT);
+ Dev->InOutSupported = (BOOLEAN) ((Features & VIRTIO_SCSI_F_INOUT) != 0);
Status = VIRTIO_CFG_READ (Dev, MaxChannel, &MaxChannel);
if (EFI_ERROR (Status)) {
@@ -800,6 +800,19 @@ VirtioScsiInit (
goto Failed;
}
+ Features &= VIRTIO_SCSI_F_INOUT | VIRTIO_F_VERSION_1;
+
+ //
+ // In virtio-1.0, feature negotiation is expected to complete before queue
+ // discovery, and the device can also reject the selected set of features.
+ //
+ if (Dev->VirtIo->Revision >= VIRTIO_SPEC_REVISION (1, 0, 0)) {
+ Status = Virtio10WriteFeatures (Dev->VirtIo, Features, &NextDevStat);
+ if (EFI_ERROR (Status)) {
+ goto Failed;
+ }
+ }
+
//
// step 4b -- allocate request virtqueue
//
@@ -841,21 +854,20 @@ VirtioScsiInit (
//
// step 4c -- Report GPFN (guest-physical frame number) of queue.
//
- Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo,
- (UINT32)(UINTN) Dev->Ring.Base >> EFI_PAGE_SHIFT);
+ Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, &Dev->Ring);
if (EFI_ERROR (Status)) {
goto ReleaseQueue;
}
//
- // step 5 -- Report understood features and guest-tuneables. We want none of
- // the known (or unknown) VIRTIO_SCSI_F_* or VIRTIO_F_* capabilities (see
- // virtio-0.9.5, Appendices B and I), except bidirectional transfers.
+ // step 5 -- Report understood features and guest-tuneables.
//
- Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo,
- Features & VIRTIO_SCSI_F_INOUT);
- if (EFI_ERROR (Status)) {
- goto ReleaseQueue;
+ if (Dev->VirtIo->Revision < VIRTIO_SPEC_REVISION (1, 0, 0)) {
+ Features &= ~(UINT64)VIRTIO_F_VERSION_1;
+ Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, Features);
+ if (EFI_ERROR (Status)) {
+ goto ReleaseQueue;
+ }
}
//
@@ -933,7 +945,6 @@ Failed:
}
-
STATIC
VOID
EFIAPI
@@ -960,6 +971,32 @@ VirtioScsiUninit (
}
+//
+// Event notification function enqueued by ExitBootServices().
+//
+
+STATIC
+VOID
+EFIAPI
+VirtioScsiExitBoot (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ VSCSI_DEV *Dev;
+
+ //
+ // Reset the device. This causes the hypervisor to forget about the virtio
+ // ring.
+ //
+ // We allocated said ring in EfiBootServicesData type memory, and code
+ // executing after ExitBootServices() is permitted to overwrite it.
+ //
+ Dev = Context;
+ Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
+}
+
+
//
// Probe, start and stop functions of this driver, called by the DXE core for
// specific devices.
@@ -1050,6 +1087,12 @@ VirtioScsiDriverBindingStart (
goto CloseVirtIo;
}
+ Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK,
+ &VirtioScsiExitBoot, Dev, &Dev->ExitBoot);
+ if (EFI_ERROR (Status)) {
+ goto UninitDev;
+ }
+
//
// Setup complete, attempt to export the driver instance's PassThru
// interface.
@@ -1059,11 +1102,14 @@ VirtioScsiDriverBindingStart (
&gEfiExtScsiPassThruProtocolGuid, EFI_NATIVE_INTERFACE,
&Dev->PassThru);
if (EFI_ERROR (Status)) {
- goto UninitDev;
+ goto CloseExitBoot;
}
return EFI_SUCCESS;
+CloseExitBoot:
+ gBS->CloseEvent (Dev->ExitBoot);
+
UninitDev:
VirtioScsiUninit (Dev);
@@ -1114,6 +1160,8 @@ VirtioScsiDriverBindingStop (
return Status;
}
+ gBS->CloseEvent (Dev->ExitBoot);
+
VirtioScsiUninit (Dev);
gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,