summaryrefslogtreecommitdiff
path: root/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'OvmfPkg/VirtioScsiDxe/VirtioScsi.c')
-rw-r--r--OvmfPkg/VirtioScsiDxe/VirtioScsi.c143
1 files changed, 78 insertions, 65 deletions
diff --git a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
index 3b6c3ade8..e6154cd22 100644
--- a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
+++ b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
@@ -50,14 +50,14 @@
/**
- Convenience macros to read and write region 0 IO space elements of the
- virtio-scsi VirtIo 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 VirtIo Device Protocol
+ @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.
@@ -70,23 +70,23 @@
one of UINT8, UINT16, UINT32, UINT64.
- @return Status codes returned by Virtio->WriteDevice() / Virtio->ReadDevice().
+ @return Status codes returned by Virtio->WriteDevice() / Virtio->ReadDevice().
**/
-#define VIRTIO_CFG_WRITE(Dev, Field, Value) ((Dev)->VirtIo->WriteDevice ( \
- (Dev)->VirtIo, \
- OFFSET_OF_VSCSI (Field), \
- SIZE_OF_VSCSI (Field), \
- (Value) \
+#define VIRTIO_CFG_WRITE(Dev, Field, Value) ((Dev)->VirtIo->WriteDevice ( \
+ (Dev)->VirtIo, \
+ OFFSET_OF_VSCSI (Field), \
+ SIZE_OF_VSCSI (Field), \
+ (Value) \
))
-#define VIRTIO_CFG_READ(Dev, Field, Pointer) ((Dev)->VirtIo->ReadDevice ( \
- (Dev)->VirtIo, \
- OFFSET_OF_VSCSI (Field), \
- SIZE_OF_VSCSI (Field), \
- sizeof *(Pointer), \
- (Pointer) \
+#define VIRTIO_CFG_READ(Dev, Field, Pointer) ((Dev)->VirtIo->ReadDevice ( \
+ (Dev)->VirtIo, \
+ OFFSET_OF_VSCSI (Field), \
+ SIZE_OF_VSCSI (Field), \
+ sizeof *(Pointer), \
+ (Pointer) \
))
@@ -469,7 +469,7 @@ VirtioScsiPassThru (
// EFI_NOT_READY would save us the effort, but it would also suggest that the
// caller retry.
//
- if (VirtioFlush (Dev->VirtIo, 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;
@@ -716,41 +716,41 @@ VirtioScsiInit (
// Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence.
//
NextDevStat = 0; // step 1 -- reset device
- Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
+ Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
if (EFI_ERROR (Status)) {
goto Failed;
}
NextDevStat |= VSTAT_ACK; // step 2 -- acknowledge device presence
- Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 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 = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 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;
}
//
- // Set Page Size - MMIO VirtIo Specific
- //
- Status = Dev->VirtIo->SetPageSize (Dev->VirtIo, EFI_PAGE_SIZE);
- if (EFI_ERROR (Status)) {
- goto ReleaseQueue;
- }
-
- //
// step 4a -- retrieve and validate features
//
- Status = Dev->VirtIo->GetDeviceFeatures (Dev->VirtIo, &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, MaxChannel, &MaxChannel);
+ Status = VIRTIO_CFG_READ (Dev, MaxChannel, &MaxChannel);
if (EFI_ERROR (Status)) {
goto Failed;
}
@@ -762,7 +762,7 @@ VirtioScsiInit (
goto Failed;
}
- Status = VIRTIO_CFG_READ (Dev, NumQueues, &NumQueues);
+ Status = VIRTIO_CFG_READ (Dev, NumQueues, &NumQueues);
if (EFI_ERROR (Status)) {
goto Failed;
}
@@ -771,7 +771,7 @@ VirtioScsiInit (
goto Failed;
}
- Status = VIRTIO_CFG_READ (Dev, MaxTarget, &Dev->MaxTarget);
+ Status = VIRTIO_CFG_READ (Dev, MaxTarget, &Dev->MaxTarget);
if (EFI_ERROR (Status)) {
goto Failed;
}
@@ -779,7 +779,7 @@ VirtioScsiInit (
Dev->MaxTarget = PcdGet16 (PcdVirtioScsiMaxTargetLimit);
}
- Status = VIRTIO_CFG_READ (Dev, MaxLun, &Dev->MaxLun);
+ Status = VIRTIO_CFG_READ (Dev, MaxLun, &Dev->MaxLun);
if (EFI_ERROR (Status)) {
goto Failed;
}
@@ -787,7 +787,7 @@ VirtioScsiInit (
Dev->MaxLun = PcdGet32 (PcdVirtioScsiMaxLunLimit);
}
- Status = VIRTIO_CFG_READ (Dev, MaxSectors, &Dev->MaxSectors);
+ Status = VIRTIO_CFG_READ (Dev, MaxSectors, &Dev->MaxSectors);
if (EFI_ERROR (Status)) {
goto Failed;
}
@@ -803,11 +803,11 @@ VirtioScsiInit (
//
// step 4b -- allocate request virtqueue
//
- Status = Dev->VirtIo->SetQueueSel (Dev->VirtIo, VIRTIO_SCSI_REQUEST_QUEUE);
+ Status = Dev->VirtIo->SetQueueSel (Dev->VirtIo, VIRTIO_SCSI_REQUEST_QUEUE);
if (EFI_ERROR (Status)) {
goto Failed;
}
- Status = Dev->VirtIo->GetQueueNumMax (Dev->VirtIo, &QueueSize);
+ Status = Dev->VirtIo->GetQueueNumMax (Dev->VirtIo, &QueueSize);
if (EFI_ERROR (Status)) {
goto Failed;
}
@@ -825,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 = Dev->VirtIo->SetQueueAddress (Dev->VirtIo,
- (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;
}
@@ -839,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 = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo,
- Features & VIRTIO_SCSI_F_INOUT);
+ Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo,
+ Features & VIRTIO_SCSI_F_INOUT);
if (EFI_ERROR (Status)) {
goto ReleaseQueue;
}
@@ -849,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, CdbSize, 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, SenseSize, VIRTIO_SCSI_SENSE_SIZE);
+ Status = VIRTIO_CFG_WRITE (Dev, SenseSize, VIRTIO_SCSI_SENSE_SIZE);
if (EFI_ERROR (Status)) {
goto ReleaseQueue;
}
@@ -862,7 +875,7 @@ VirtioScsiInit (
// step 6 -- initialization complete
//
NextDevStat |= VSTAT_DRIVER_OK;
- Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
+ Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
if (EFI_ERROR (Status)) {
goto ReleaseQueue;
}
@@ -906,10 +919,10 @@ ReleaseQueue:
Failed:
//
// Notify the host about our failure to setup: virtio-0.9.5, 2.2.2.1 Device
- // Status. VirtIo access failure here should not mask the original error.
+ // Status. VirtIo access failure here should not mask the original error.
//
NextDevStat |= VSTAT_FAILED;
- Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
+ Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
Dev->InOutSupported = FALSE;
Dev->MaxTarget = 0;
@@ -933,7 +946,7 @@ VirtioScsiUninit (
// VIRTIO_CFG_WRITE() returns, the host will have learned to stay away from
// the old comms area.
//
- Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
+ Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
Dev->InOutSupported = FALSE;
Dev->MaxTarget = 0;
@@ -970,37 +983,37 @@ VirtioScsiDriverBindingSupported (
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
)
{
- EFI_STATUS Status;
- VIRTIO_DEVICE_PROTOCOL *VirtIo;
+ EFI_STATUS Status;
+ 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
+ // 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
+ &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
+ EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive VirtIo access to
// the device; to be released
);
if (EFI_ERROR (Status)) {
return Status;
}
- if (VirtIo->SubSystemDeviceId != VIRTIO_SUBSYSTEM_SCSI_HOST) {
- Status = EFI_UNSUPPORTED;
+ if (VirtIo->SubSystemDeviceId != VIRTIO_SUBSYSTEM_SCSI_HOST) {
+ Status = EFI_UNSUPPORTED;
}
//
- // We needed VirtIo 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, &gVirtioDeviceProtocolGuid,
+ gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
This->DriverBindingHandle, DeviceHandle);
return Status;
}
@@ -1022,19 +1035,19 @@ VirtioScsiDriverBindingStart (
return EFI_OUT_OF_RESOURCES;
}
- Status = gBS->OpenProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
- (VOID **)&Dev->VirtIo, This->DriverBindingHandle,
+ Status = gBS->OpenProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
+ (VOID **)&Dev->VirtIo, This->DriverBindingHandle,
DeviceHandle, EFI_OPEN_PROTOCOL_BY_DRIVER);
if (EFI_ERROR (Status)) {
goto FreeVirtioScsi;
}
//
- // VirtIo access granted, configure virtio-scsi device.
+ // VirtIo access granted, configure virtio-scsi device.
//
Status = VirtioScsiInit (Dev);
if (EFI_ERROR (Status)) {
- goto CloseVirtIo;
+ goto CloseVirtIo;
}
//
@@ -1054,8 +1067,8 @@ VirtioScsiDriverBindingStart (
UninitDev:
VirtioScsiUninit (Dev);
-CloseVirtIo:
- gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
+CloseVirtIo:
+ gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
This->DriverBindingHandle, DeviceHandle);
FreeVirtioScsi:
@@ -1103,7 +1116,7 @@ VirtioScsiDriverBindingStop (
VirtioScsiUninit (Dev);
- gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
+ gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
This->DriverBindingHandle, DeviceHandle);
FreePool (Dev);