unreasonable for now.\r
\r
Copyright (C) 2012, Red Hat, Inc.\r
- Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved.<BR>\r
\r
This program and the accompanying materials are licensed and made available\r
under the terms and conditions of the BSD License which accompanies this\r
one of UINT8, UINT16, UINT32, UINT64.\r
\r
\r
- @return Status codes returned by VirtioWriteDevice() / VirtioReadDevice().\r
+ @return Status codes returned by Virtio->WriteDevice() / Virtio->ReadDevice().\r
\r
**/\r
\r
-#define VIRTIO_CFG_WRITE(Dev, Field, Value) (VirtioWriteDevice ( \\r
- (Dev)->VirtIo, \\r
- OFFSET_OF_VSCSI (Field), \\r
- SIZE_OF_VSCSI (Field), \\r
- (Value) \\r
+#define VIRTIO_CFG_WRITE(Dev, Field, Value) ((Dev)->VirtIo->WriteDevice ( \\r
+ (Dev)->VirtIo, \\r
+ OFFSET_OF_VSCSI (Field), \\r
+ SIZE_OF_VSCSI (Field), \\r
+ (Value) \\r
))\r
\r
-#define VIRTIO_CFG_READ(Dev, Field, Pointer) (VirtioReadDevice ( \\r
- (Dev)->VirtIo, \\r
- OFFSET_OF_VSCSI (Field), \\r
- SIZE_OF_VSCSI (Field), \\r
- sizeof *(Pointer), \\r
- (Pointer) \\r
+#define VIRTIO_CFG_READ(Dev, Field, Pointer) ((Dev)->VirtIo->ReadDevice ( \\r
+ (Dev)->VirtIo, \\r
+ OFFSET_OF_VSCSI (Field), \\r
+ SIZE_OF_VSCSI (Field), \\r
+ sizeof *(Pointer), \\r
+ (Pointer) \\r
))\r
\r
\r
//\r
Request->Lun[0] = 1;\r
Request->Lun[1] = (UINT8) Target;\r
- Request->Lun[2] = (UINT8) ((Lun >> 8) | 0x40);\r
+ Request->Lun[2] = (UINT8) (((UINT32)Lun >> 8) | 0x40);\r
Request->Lun[3] = (UINT8) Lun;\r
\r
//\r
// caller retry.\r
//\r
if (VirtioFlush (Dev->VirtIo, VIRTIO_SCSI_REQUEST_QUEUE, &Dev->Ring,\r
- &Indices) != EFI_SUCCESS) {\r
+ &Indices, NULL) != EFI_SUCCESS) {\r
Packet->InTransferLength = 0;\r
Packet->OutTransferLength = 0;\r
Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;\r
UINT8 NextDevStat;\r
EFI_STATUS Status;\r
\r
- UINT32 Features;\r
+ UINT64 Features;\r
UINT16 MaxChannel; // for validation only\r
UINT32 NumQueues; // for validation only\r
UINT16 QueueSize;\r
if (EFI_ERROR (Status)) {\r
goto Failed;\r
}\r
- Dev->InOutSupported = !!(Features & VIRTIO_SCSI_F_INOUT);\r
+ Dev->InOutSupported = (BOOLEAN) ((Features & VIRTIO_SCSI_F_INOUT) != 0);\r
\r
Status = VIRTIO_CFG_READ (Dev, MaxChannel, &MaxChannel);\r
if (EFI_ERROR (Status)) {\r
goto Failed;\r
}\r
\r
+ Features &= VIRTIO_SCSI_F_INOUT | VIRTIO_F_VERSION_1;\r
+\r
+ //\r
+ // In virtio-1.0, feature negotiation is expected to complete before queue\r
+ // discovery, and the device can also reject the selected set of features.\r
+ //\r
+ if (Dev->VirtIo->Revision >= VIRTIO_SPEC_REVISION (1, 0, 0)) {\r
+ Status = Virtio10WriteFeatures (Dev->VirtIo, Features, &NextDevStat);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Failed;\r
+ }\r
+ }\r
+\r
//\r
// step 4b -- allocate request virtqueue\r
//\r
//\r
// step 4c -- Report GPFN (guest-physical frame number) of queue.\r
//\r
- Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo,\r
- (UINT32)(UINTN) Dev->Ring.Base >> EFI_PAGE_SHIFT);\r
+ Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, &Dev->Ring);\r
if (EFI_ERROR (Status)) {\r
goto ReleaseQueue;\r
}\r
\r
//\r
- // step 5 -- Report understood features and guest-tuneables. We want none of\r
- // the known (or unknown) VIRTIO_SCSI_F_* or VIRTIO_F_* capabilities (see\r
- // virtio-0.9.5, Appendices B and I), except bidirectional transfers.\r
+ // step 5 -- Report understood features and guest-tuneables.\r
//\r
- Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo,\r
- Features & VIRTIO_SCSI_F_INOUT);\r
- if (EFI_ERROR (Status)) {\r
- goto ReleaseQueue;\r
+ if (Dev->VirtIo->Revision < VIRTIO_SPEC_REVISION (1, 0, 0)) {\r
+ Features &= ~(UINT64)VIRTIO_F_VERSION_1;\r
+ Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, Features);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ReleaseQueue;\r
+ }\r
}\r
\r
//\r
}\r
\r
\r
-\r
STATIC\r
VOID\r
EFIAPI\r
}\r
\r
\r
+//\r
+// Event notification function enqueued by ExitBootServices().\r
+//\r
+\r
+STATIC\r
+VOID\r
+EFIAPI\r
+VirtioScsiExitBoot (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ VSCSI_DEV *Dev;\r
+\r
+ //\r
+ // Reset the device. This causes the hypervisor to forget about the virtio\r
+ // ring.\r
+ //\r
+ // We allocated said ring in EfiBootServicesData type memory, and code\r
+ // executing after ExitBootServices() is permitted to overwrite it.\r
+ //\r
+ Dev = Context;\r
+ Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);\r
+}\r
+\r
+\r
//\r
// Probe, start and stop functions of this driver, called by the DXE core for\r
// specific devices.\r
goto CloseVirtIo;\r
}\r
\r
+ Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK,\r
+ &VirtioScsiExitBoot, Dev, &Dev->ExitBoot);\r
+ if (EFI_ERROR (Status)) {\r
+ goto UninitDev;\r
+ }\r
+\r
//\r
// Setup complete, attempt to export the driver instance's PassThru\r
// interface.\r
&gEfiExtScsiPassThruProtocolGuid, EFI_NATIVE_INTERFACE,\r
&Dev->PassThru);\r
if (EFI_ERROR (Status)) {\r
- goto UninitDev;\r
+ goto CloseExitBoot;\r
}\r
\r
return EFI_SUCCESS;\r
\r
+CloseExitBoot:\r
+ gBS->CloseEvent (Dev->ExitBoot);\r
+\r
UninitDev:\r
VirtioScsiUninit (Dev);\r
\r
return Status;\r
}\r
\r
+ gBS->CloseEvent (Dev->ExitBoot);\r
+\r
VirtioScsiUninit (Dev);\r
\r
gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r