From: "Nikita Leshenko" <nikita.leshchenko@oracle.com>
To: devel@edk2.groups.io
Cc: Nikita Leshenko <nikita.leshchenko@oracle.com>,
liran.alon@oracle.com, aaron.young@oracle.com,
Jordan Justen <jordan.l.justen@intel.com>,
Laszlo Ersek <lersek@redhat.com>,
Ard Biesheuvel <ard.biesheuvel@arm.com>
Subject: [PATCH v4 11/13] OvmfPkg/MptScsiDxe: Implement the PassThru method
Date: Tue, 14 Apr 2020 20:38:11 +0300 [thread overview]
Message-ID: <20200414173813.7715-12-nikita.leshchenko@oracle.com> (raw)
In-Reply-To: <20200414173813.7715-1-nikita.leshchenko@oracle.com>
Machines should be able to boot after this commit. Tested with different
Linux distributions (Ubuntu, CentOS) and different Windows
versions (Windows 7, Windows 10, Server 2016).
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2390
Signed-off-by: Nikita Leshenko <nikita.leshchenko@oracle.com>
---
.../Include/IndustryStandard/FusionMptScsi.h | 19 +-
OvmfPkg/MptScsiDxe/MptScsi.c | 369 +++++++++++++++++-
OvmfPkg/MptScsiDxe/MptScsiDxe.inf | 3 +
OvmfPkg/OvmfPkg.dec | 3 +
4 files changed, 390 insertions(+), 4 deletions(-)
diff --git a/OvmfPkg/Include/IndustryStandard/FusionMptScsi.h b/OvmfPkg/Include/IndustryStandard/FusionMptScsi.h
index d00a9e6db0bf..4be36adedd8f 100644
--- a/OvmfPkg/Include/IndustryStandard/FusionMptScsi.h
+++ b/OvmfPkg/Include/IndustryStandard/FusionMptScsi.h
@@ -44,6 +44,15 @@
#define MPT_IOC_WHOINIT_ROM_BIOS 0x02
+#define MPT_SCSIIO_REQUEST_CONTROL_TXDIR_NONE (0x00 << 24)
+#define MPT_SCSIIO_REQUEST_CONTROL_TXDIR_WRITE (0x01 << 24)
+#define MPT_SCSIIO_REQUEST_CONTROL_TXDIR_READ (0x02 << 24)
+
+#define MPT_SCSI_IOCSTATUS_SUCCESS 0x0000
+#define MPT_SCSI_IOCSTATUS_DEVICE_NOT_THERE 0x0043
+#define MPT_SCSI_IOCSTATUS_DATA_OVERRUN 0x0044
+#define MPT_SCSI_IOCSTATUS_DATA_UNDERRUN 0x0045
+
//
// Device structures
//
@@ -141,6 +150,14 @@ typedef union {
} Data;
#pragma pack ()
UINT64 Uint64; // 8 byte alignment required by HW
-} MPT_SCSI_IO_ERROR_REPLY;
+} MPT_SCSI_IO_REPLY;
+
+typedef union {
+ struct {
+ MPT_SCSI_IO_REQUEST Header;
+ MPT_SG_ENTRY_SIMPLE Sg;
+ } Data;
+ UINT64 Uint64; // 8 byte alignment required by HW
+} MPT_SCSI_REQUEST_WITH_SG;
#endif // __FUSION_MPT_SCSI_H__
diff --git a/OvmfPkg/MptScsiDxe/MptScsi.c b/OvmfPkg/MptScsiDxe/MptScsi.c
index 9c3bdc430e1a..fcdaa4c338a4 100644
--- a/OvmfPkg/MptScsiDxe/MptScsi.c
+++ b/OvmfPkg/MptScsiDxe/MptScsi.c
@@ -17,6 +17,7 @@
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
#include <Protocol/PciIo.h>
+#include <Protocol/PciRootBridgeIo.h>
#include <Protocol/ScsiPassThruExt.h>
#include <Uefi/UefiSpec.h>
@@ -30,6 +31,13 @@
// Runtime Structures
//
+typedef struct {
+ MPT_SCSI_REQUEST_WITH_SG IoRequest;
+ MPT_SCSI_IO_REPLY IoReply;
+ UINT8 Sense[MAX_UINT8];
+ UINT8 Data[0x2000];
+} MPT_SCSI_DMA_BUFFER;
+
#define MPT_SCSI_DEV_SIGNATURE SIGNATURE_32 ('M','P','T','S')
typedef struct {
UINT32 Signature;
@@ -37,11 +45,19 @@ typedef struct {
EFI_EXT_SCSI_PASS_THRU_MODE PassThruMode;
EFI_PCI_IO_PROTOCOL *PciIo;
UINT64 OriginalPciAttributes;
+ UINT32 StallPerPollUsec;
+ MPT_SCSI_DMA_BUFFER *Dma;
+ EFI_PHYSICAL_ADDRESS DmaPhysical;
+ VOID *DmaMapping;
+ BOOLEAN IoReplyEnqueued;
} MPT_SCSI_DEV;
#define MPT_SCSI_FROM_PASS_THRU(PassThruPtr) \
CR (PassThruPtr, MPT_SCSI_DEV, PassThru, MPT_SCSI_DEV_SIGNATURE)
+#define MPT_SCSI_DMA_ADDR(Dev, MemberName) \
+ (Dev->DmaPhysical + OFFSET_OF(MPT_SCSI_DMA_BUFFER, MemberName))
+
//
// Hardware functions
//
@@ -142,6 +158,8 @@ MptScsiInit (
UINT8 *ReplyBytes;
UINT32 ReplyWord;
+ Dev->StallPerPollUsec = PcdGet32 (PcdMptScsiStallPerPollUsec);
+
Status = MptScsiReset (Dev);
if (EFI_ERROR (Status)) {
return Status;
@@ -153,7 +171,7 @@ MptScsiInit (
Req.Data.Function = MPT_MESSAGE_HDR_FUNCTION_IOC_INIT;
Req.Data.MaxDevices = 1;
Req.Data.MaxBuses = 1;
- Req.Data.ReplyFrameSize = sizeof (MPT_SCSI_IO_ERROR_REPLY);
+ Req.Data.ReplyFrameSize = sizeof (MPT_SCSI_IO_REPLY);
//
// Send controller init through doorbell
@@ -203,6 +221,257 @@ MptScsiInit (
return EFI_SUCCESS;
}
+STATIC
+EFI_STATUS
+MptScsiPopulateRequest (
+ IN MPT_SCSI_DEV *Dev,
+ IN UINT8 Target,
+ IN UINT64 Lun,
+ IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
+ )
+{
+ MPT_SCSI_REQUEST_WITH_SG *Request;
+
+ Request = &Dev->Dma->IoRequest;
+
+ if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_BIDIRECTIONAL ||
+ (Packet->InTransferLength > 0 && Packet->OutTransferLength > 0) ||
+ Packet->CdbLength > sizeof (Request->Data.Header.CDB)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (Target > 0 || Lun > 0 ||
+ Packet->DataDirection > EFI_EXT_SCSI_DATA_DIRECTION_BIDIRECTIONAL ||
+ //
+ // Trying to receive, but destination pointer is NULL, or contradicting
+ // transfer direction
+ //
+ (Packet->InTransferLength > 0 &&
+ (Packet->InDataBuffer == NULL ||
+ Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_WRITE
+ )
+ ) ||
+
+ //
+ // Trying to send, but source pointer is NULL, or contradicting transfer
+ // direction
+ //
+ (Packet->OutTransferLength > 0 &&
+ (Packet->OutDataBuffer == NULL ||
+ Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ
+ )
+ )
+ ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Packet->InTransferLength > sizeof (Dev->Dma->Data)) {
+ Packet->InTransferLength = sizeof (Dev->Dma->Data);
+ return EFI_BAD_BUFFER_SIZE;
+ }
+ if (Packet->OutTransferLength > sizeof (Dev->Dma->Data)) {
+ Packet->OutTransferLength = sizeof (Dev->Dma->Data);
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ ZeroMem (Request, sizeof (*Request));
+ Request->Data.Header.TargetID = Target;
+ //
+ // It's 1 and not 0, for some reason...
+ //
+ Request->Data.Header.LUN[1] = Lun;
+ Request->Data.Header.Function = MPT_MESSAGE_HDR_FUNCTION_SCSI_IO_REQUEST;
+ Request->Data.Header.MessageContext = 1; // We handle one request at a time
+
+ Request->Data.Header.CDBLength = Packet->CdbLength;
+ CopyMem (Request->Data.Header.CDB, Packet->Cdb, Packet->CdbLength);
+
+ //
+ // SenseDataLength is UINT8, Sense[] is MAX_UINT8, so we can't overflow
+ //
+ ZeroMem (&Dev->Dma->Sense, Packet->SenseDataLength);
+ Request->Data.Header.SenseBufferLength = Packet->SenseDataLength;
+ Request->Data.Header.SenseBufferLowAddress = MPT_SCSI_DMA_ADDR (Dev, Sense);
+
+ Request->Data.Sg.EndOfList = 1;
+ Request->Data.Sg.EndOfBuffer = 1;
+ Request->Data.Sg.LastElement = 1;
+ Request->Data.Sg.ElementType = MPT_SG_ENTRY_TYPE_SIMPLE;
+ Request->Data.Sg.DataBufferAddress = MPT_SCSI_DMA_ADDR (Dev, Data);
+
+ Request->Data.Header.Control = MPT_SCSIIO_REQUEST_CONTROL_TXDIR_NONE;
+ switch (Packet->DataDirection)
+ {
+ case EFI_EXT_SCSI_DATA_DIRECTION_READ:
+ if (Packet->InTransferLength == 0) {
+ break;
+ }
+ Request->Data.Header.DataLength = Packet->InTransferLength;
+ Request->Data.Sg.Length = Packet->InTransferLength;
+ Request->Data.Header.Control = MPT_SCSIIO_REQUEST_CONTROL_TXDIR_READ;
+ break;
+ case EFI_EXT_SCSI_DATA_DIRECTION_WRITE:
+ if (Packet->OutTransferLength == 0) {
+ break;
+ }
+ Request->Data.Header.DataLength = Packet->OutTransferLength;
+ Request->Data.Sg.Length = Packet->OutTransferLength;
+ Request->Data.Header.Control = MPT_SCSIIO_REQUEST_CONTROL_TXDIR_WRITE;
+
+ CopyMem (Dev->Dma->Data, Packet->OutDataBuffer, Packet->OutTransferLength);
+ Request->Data.Sg.BufferContainsData = 1;
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+MptScsiSendRequest (
+ IN MPT_SCSI_DEV *Dev,
+ IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
+ )
+{
+ EFI_STATUS Status;
+
+ if (!Dev->IoReplyEnqueued) {
+ //
+ // Put one free reply frame on the reply queue, the hardware may use it to
+ // report an error to us.
+ //
+ Status = Out32 (Dev, MPT_REG_REP_Q, MPT_SCSI_DMA_ADDR (Dev, IoReply));
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ Dev->IoReplyEnqueued = TRUE;
+ }
+
+ Status = Out32 (Dev, MPT_REG_REQ_Q, MPT_SCSI_DMA_ADDR (Dev, IoRequest));
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+MptScsiGetReply (
+ IN MPT_SCSI_DEV *Dev,
+ OUT UINT32 *Reply
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Istatus;
+ UINT32 EmptyReply;
+
+ //
+ // Timeouts are not supported for
+ // EFI_EXT_SCSI_PASS_THRU_PROTOCOL.PassThru() in this implementation.
+ //
+ for (;;) {
+ Status = In32 (Dev, MPT_REG_ISTATUS, &Istatus);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Interrupt raised
+ //
+ if (Istatus & MPT_IMASK_REPLY) {
+ break;
+ }
+
+ gBS->Stall (Dev->StallPerPollUsec);
+ }
+
+ Status = In32 (Dev, MPT_REG_REP_Q, Reply);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // The driver is supposed to fetch replies until 0xffffffff is returned, which
+ // will reset the interrupt status. We put only one request, so we expect the
+ // next read reply to be the last.
+ //
+ Status = In32 (Dev, MPT_REG_REP_Q, &EmptyReply);
+ if (EFI_ERROR (Status) || EmptyReply != MAX_UINT32) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+MptScsiHandleReply (
+ IN MPT_SCSI_DEV *Dev,
+ IN UINT32 Reply,
+ OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
+ )
+{
+ CopyMem (Packet->SenseData, Dev->Dma->Sense, Packet->SenseDataLength);
+ if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
+ CopyMem (Packet->InDataBuffer, Dev->Dma->Data, Packet->InTransferLength);
+ }
+
+ if (Reply == Dev->Dma->IoRequest.Data.Header.MessageContext) {
+ //
+ // This is a turbo reply, everything is good
+ //
+ Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK;
+ Packet->TargetStatus = EFI_EXT_SCSI_STATUS_TARGET_GOOD;
+
+ } else if (Reply & (1 << 31)) {
+ DEBUG ((DEBUG_ERROR, "%a: request failed\n", __FUNCTION__));
+ //
+ // When reply MSB is set, we got a full reply. Since we submitted only one
+ // reply frame, we know it's IoReply.
+ //
+ Dev->IoReplyEnqueued = FALSE;
+
+ Packet->TargetStatus = Dev->Dma->IoReply.Data.SCSIStatus;
+ Packet->SenseDataLength = Dev->Dma->IoReply.Data.SenseCount;
+
+ switch (Dev->Dma->IoReply.Data.IOCStatus) {
+ case MPT_SCSI_IOCSTATUS_SUCCESS:
+ Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK;
+ break;
+ case MPT_SCSI_IOCSTATUS_DEVICE_NOT_THERE:
+ Packet->HostAdapterStatus =
+ EFI_EXT_SCSI_STATUS_HOST_ADAPTER_SELECTION_TIMEOUT;
+ return EFI_TIMEOUT;
+ case MPT_SCSI_IOCSTATUS_DATA_UNDERRUN:
+ if (Packet->TargetStatus == EFI_EXT_SCSI_STATUS_TARGET_GOOD) {
+ if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
+ Packet->InTransferLength = Dev->Dma->IoReply.Data.TransferCount;
+ } else {
+ Packet->OutTransferLength = Dev->Dma->IoReply.Data.TransferCount;
+ }
+ }
+ Packet->HostAdapterStatus =
+ EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN;
+ return EFI_SUCCESS;
+ case MPT_SCSI_IOCSTATUS_DATA_OVERRUN:
+ Packet->HostAdapterStatus =
+ EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN;
+ return EFI_SUCCESS;
+ default:
+ Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;
+ return EFI_DEVICE_ERROR;
+ }
+
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a: unexpected reply\n", __FUNCTION__));
+ Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
//
// Ext SCSI Pass Thru
//
@@ -218,7 +487,44 @@ MptScsiPassThru (
IN EFI_EVENT Event OPTIONAL
)
{
- return EFI_UNSUPPORTED;
+ EFI_STATUS Status;
+ MPT_SCSI_DEV *Dev;
+ UINT32 Reply;
+
+ Dev = MPT_SCSI_FROM_PASS_THRU (This);
+ Status = MptScsiPopulateRequest (Dev, *Target, Lun, Packet);
+ if (EFI_ERROR (Status)) {
+ //
+ // MptScsiPopulateRequest modified packet according to the error
+ //
+ return Status;
+ }
+
+ Status = MptScsiSendRequest (Dev, Packet);
+ if (EFI_ERROR (Status)) {
+ goto Fatal;
+ }
+
+ Status = MptScsiGetReply (Dev, &Reply);
+ if (EFI_ERROR (Status)) {
+ goto Fatal;
+ }
+
+ return MptScsiHandleReply (Dev, Reply, Packet);
+
+Fatal:
+ //
+ // We erred in the middle of a transaction, a very serious problem has occured
+ // and it's not clear if it's possible to recover without leaving the hardware
+ // in an inconsistent state. Perhaps we would want to reset the device...
+ //
+ DEBUG ((DEBUG_ERROR, "%a: fatal error in scsi request\n", __FUNCTION__));
+ Packet->InTransferLength = 0;
+ Packet->OutTransferLength = 0;
+ Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;
+ Packet->TargetStatus = EFI_EXT_SCSI_STATUS_TARGET_TASK_ABORTED;
+ Packet->SenseDataLength = 0;
+ return EFI_DEVICE_ERROR;
}
STATIC
@@ -450,6 +756,7 @@ MptScsiControllerStart (
{
EFI_STATUS Status;
MPT_SCSI_DEV *Dev;
+ UINTN BytesMapped;
Dev = AllocateZeroPool (sizeof (*Dev));
if (Dev == NULL) {
@@ -494,9 +801,42 @@ MptScsiControllerStart (
goto CloseProtocol;
}
+ //
+ // Create buffers for data transfer
+ //
+ Status = Dev->PciIo->AllocateBuffer (
+ Dev->PciIo,
+ AllocateAnyPages,
+ EfiBootServicesData,
+ EFI_SIZE_TO_PAGES (sizeof (*Dev->Dma)),
+ (VOID **)&Dev->Dma,
+ EFI_PCI_ATTRIBUTE_MEMORY_CACHED
+ );
+ if (EFI_ERROR (Status)) {
+ goto RestoreAttributes;
+ }
+
+ BytesMapped = sizeof (*Dev->Dma);
+ Status = Dev->PciIo->Map (
+ Dev->PciIo,
+ EfiPciIoOperationBusMasterCommonBuffer,
+ Dev->Dma,
+ &BytesMapped,
+ &Dev->DmaPhysical,
+ &Dev->DmaMapping
+ );
+ if (EFI_ERROR (Status)) {
+ goto FreeBuffer;
+ }
+
+ if (BytesMapped != sizeof (*Dev->Dma)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Unmap;
+ }
+
Status = MptScsiInit (Dev);
if (EFI_ERROR (Status)) {
- goto RestorePciAttributes;
+ goto Unmap;
}
//
@@ -531,6 +871,18 @@ MptScsiControllerStart (
UninitDev:
MptScsiReset (Dev);
+Unmap:
+ Dev->PciIo->Unmap (
+ Dev->PciIo,
+ Dev->DmaMapping
+ );
+
+FreeBuffer:
+ Dev->PciIo->FreeBuffer (
+ Dev->PciIo,
+ EFI_SIZE_TO_PAGES (sizeof (*Dev->Dma)),
+ Dev->Dma
+ );
RestoreAttributes:
Dev->PciIo->Attributes (
Dev->PciIo,
@@ -592,6 +944,17 @@ MptScsiControllerStop (
MptScsiReset (Dev);
+ Dev->PciIo->Unmap (
+ Dev->PciIo,
+ Dev->DmaMapping
+ );
+
+ Dev->PciIo->FreeBuffer (
+ Dev->PciIo,
+ EFI_SIZE_TO_PAGES (sizeof (*Dev->Dma)),
+ Dev->Dma
+ );
+
Dev->PciIo->Attributes (
Dev->PciIo,
EfiPciIoAttributeOperationEnable,
diff --git a/OvmfPkg/MptScsiDxe/MptScsiDxe.inf b/OvmfPkg/MptScsiDxe/MptScsiDxe.inf
index 809f12173bb8..ef1f6a5ebb3a 100644
--- a/OvmfPkg/MptScsiDxe/MptScsiDxe.inf
+++ b/OvmfPkg/MptScsiDxe/MptScsiDxe.inf
@@ -34,3 +34,6 @@ [LibraryClasses]
[Protocols]
gEfiPciIoProtocolGuid ## TO_START
gEfiExtScsiPassThruProtocolGuid ## BY_START
+
+[Pcd]
+ gUefiOvmfPkgTokenSpaceGuid.PcdMptScsiStallPerPollUsec ## CONSUMES
diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index 28030391cff2..7fa1581f2101 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -270,6 +270,9 @@ [PcdsFixedAtBuild]
## Number of page frames to use for storing grant table entries.
gUefiOvmfPkgTokenSpaceGuid.PcdXenGrantFrames|4|UINT32|0x33
+ ## Microseconds to stall between polling for MptScsi request result
+ gUefiOvmfPkgTokenSpaceGuid.PcdMptScsiStallPerPollUsec|5|UINT32|0x39
+
[PcdsDynamic, PcdsDynamicEx]
gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|2
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable|FALSE|BOOLEAN|0x10
--
2.20.1
next prev parent reply other threads:[~2020-04-14 17:35 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-04-14 17:38 [PATCH v4 00/13] OvmfPkg: Support booting from Fusion-MPT SCSI controllers Nikita Leshenko
2020-04-14 17:38 ` [PATCH v4 01/13] OvmfPkg/MptScsiDxe: Create empty driver Nikita Leshenko
2020-04-15 6:31 ` [edk2-devel] " Laszlo Ersek
2020-04-14 17:38 ` [PATCH v4 02/13] OvmfPkg/MptScsiDxe: Install DriverBinding Protocol Nikita Leshenko
2020-04-14 17:38 ` [PATCH v4 03/13] OvmfPkg/MptScsiDxe: Report name of driver Nikita Leshenko
2020-04-14 17:38 ` [PATCH v4 04/13] OvmfPkg/MptScsiDxe: Probe PCI devices and look for MptScsi Nikita Leshenko
2020-04-14 17:38 ` [PATCH v4 05/13] OvmfPkg/MptScsiDxe: Install stubbed EXT_SCSI_PASS_THRU Nikita Leshenko
2020-04-15 6:54 ` [edk2-devel] " Laszlo Ersek
2020-04-14 17:38 ` [PATCH v4 06/13] OvmfPkg/MptScsiDxe: Report one Target and one LUN Nikita Leshenko
2020-04-14 17:38 ` [PATCH v4 07/13] OvmfPkg/MptScsiDxe: Build and decode DevicePath Nikita Leshenko
2020-04-15 12:03 ` [edk2-devel] " Laszlo Ersek
2020-04-14 17:38 ` [PATCH v4 08/13] OvmfPkg/MptScsiDxe: Open PciIo protocol for later use Nikita Leshenko
2020-04-16 8:05 ` [edk2-devel] " Laszlo Ersek
2020-04-14 17:38 ` [PATCH v4 09/13] OvmfPkg/MptScsiDxe: Set and restore PCI attributes Nikita Leshenko
2020-04-16 8:11 ` [edk2-devel] " Laszlo Ersek
2020-04-14 17:38 ` [PATCH v4 10/13] OvmfPkg/MptScsiDxe: Initialize hardware Nikita Leshenko
2020-04-16 9:53 ` [edk2-devel] " Laszlo Ersek
2020-04-16 16:00 ` Nikita Leshenko
2020-04-20 11:58 ` Laszlo Ersek
2020-04-20 14:10 ` Laszlo Ersek
2020-04-14 17:38 ` Nikita Leshenko [this message]
2020-04-20 17:30 ` [edk2-devel] [PATCH v4 11/13] OvmfPkg/MptScsiDxe: Implement the PassThru method Laszlo Ersek
2020-04-24 17:03 ` Nikita Leshenko
2020-04-14 17:38 ` [PATCH v4 12/13] OvmfPkg/MptScsiDxe: Report multiple targets Nikita Leshenko
2020-04-20 18:31 ` [edk2-devel] " Laszlo Ersek
2020-04-14 17:38 ` [PATCH v4 13/13] OvmfPkg/MptScsiDxe: Reset device on ExitBootServices() Nikita Leshenko
2020-04-20 19:02 ` [edk2-devel] " Laszlo Ersek
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200414173813.7715-12-nikita.leshchenko@oracle.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox