public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH 00/11] Introduce LsiScsi driver to OvmfPkg
@ 2020-07-01  4:04 Gary Lin
  2020-07-01  4:04 ` [PATCH 01/11] OvmfPkg/LsiScsiDxe: Create the empty driver Gary Lin
                   ` (11 more replies)
  0 siblings, 12 replies; 35+ messages in thread
From: Gary Lin @ 2020-07-01  4:04 UTC (permalink / raw)
  To: devel; +Cc: Jordan Justen, Laszlo Ersek, Ard Biesheuvel

This patch series implement the driver for LSI 53C895A SCSI controller
for OVMF so that the user can access the storage devices connected to
QEMU "lsi" controller. The driver is disabled by default since LSI
53C895A is considered as a legacy device. To enable the driver, please
add "-D LSI_SCSI_ENABLE" when building OvmfPkg.

The patch series is also available in my git branch:
https://github.com/lcp/edk2/tree/ovmf-lsi-v1

Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>

Gary Lin (11):
  OvmfPkg/LsiScsiDxe: Create the empty driver
  OvmfPkg/LsiScsiDxe: Install the skeleton of driver binding
  OvmfPkg/LsiScsiDxe: Report the name of the driver
  OvmfPkg/LsiScsiDxe: Probe PCI devices and look for LsiScsi
  OvmfPkg/LsiScsiDxe: Install stubbed EXT_SCSI_PASS_THRU
  OvmfPkg/LsiScsiDxe: Report Targets and LUNs
  OvmfPkg/LsiScsiDxe: Open PciIo protocol and initialize the device
  OvmfPkg/LsiScsiDxe: Map DMA buffer
  OvmfPkg/LsiScsiDxe: Examine the incoming SCSI Request Packet
  OvmfPkg/LsiScsiDxe: Process the SCSI Request Packet
  Maintainers.txt: Add myself as the reviewer for LsiScsi driver

 Maintainers.txt                            |    4 +
 OvmfPkg/Include/IndustryStandard/LsiScsi.h |   80 ++
 OvmfPkg/LsiScsiDxe/LsiScsi.c               | 1130 ++++++++++++++++++++
 OvmfPkg/LsiScsiDxe/LsiScsi.h               |  199 ++++
 OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf          |   46 +
 OvmfPkg/OvmfPkg.dec                        |    8 +
 OvmfPkg/OvmfPkgIa32.dsc                    |    4 +
 OvmfPkg/OvmfPkgIa32.fdf                    |    3 +
 OvmfPkg/OvmfPkgIa32X64.dsc                 |    4 +
 OvmfPkg/OvmfPkgIa32X64.fdf                 |    3 +
 OvmfPkg/OvmfPkgX64.dsc                     |    4 +
 OvmfPkg/OvmfPkgX64.fdf                     |    3 +
 12 files changed, 1488 insertions(+)
 create mode 100644 OvmfPkg/Include/IndustryStandard/LsiScsi.h
 create mode 100644 OvmfPkg/LsiScsiDxe/LsiScsi.c
 create mode 100644 OvmfPkg/LsiScsiDxe/LsiScsi.h
 create mode 100644 OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf

-- 
2.25.1


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH 01/11] OvmfPkg/LsiScsiDxe: Create the empty driver
  2020-07-01  4:04 [PATCH 00/11] Introduce LsiScsi driver to OvmfPkg Gary Lin
@ 2020-07-01  4:04 ` Gary Lin
  2020-07-07  7:59   ` Laszlo Ersek
  2020-07-01  4:04 ` [PATCH 02/11] OvmfPkg/LsiScsiDxe: Install the skeleton of driver binding Gary Lin
                   ` (10 subsequent siblings)
  11 siblings, 1 reply; 35+ messages in thread
From: Gary Lin @ 2020-07-01  4:04 UTC (permalink / raw)
  To: devel; +Cc: Jordan Justen, Laszlo Ersek, Ard Biesheuvel

Create the driver with only a dummy LsiScsiEntryPoint() for the further
implementation of the driver for LSI 53C895A SCSI controller.

Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Signed-off-by: Gary Lin <glin@suse.com>
---
 OvmfPkg/LsiScsiDxe/LsiScsi.c      | 25 +++++++++++++++++++++++++
 OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf | 26 ++++++++++++++++++++++++++
 OvmfPkg/OvmfPkgIa32.dsc           |  4 ++++
 OvmfPkg/OvmfPkgIa32.fdf           |  3 +++
 OvmfPkg/OvmfPkgIa32X64.dsc        |  4 ++++
 OvmfPkg/OvmfPkgIa32X64.fdf        |  3 +++
 OvmfPkg/OvmfPkgX64.dsc            |  4 ++++
 OvmfPkg/OvmfPkgX64.fdf            |  3 +++
 8 files changed, 72 insertions(+)
 create mode 100644 OvmfPkg/LsiScsiDxe/LsiScsi.c
 create mode 100644 OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf

diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.c b/OvmfPkg/LsiScsiDxe/LsiScsi.c
new file mode 100644
index 000000000000..9c90941688ed
--- /dev/null
+++ b/OvmfPkg/LsiScsiDxe/LsiScsi.c
@@ -0,0 +1,25 @@
+/** @file
+
+  This driver produces Extended SCSI Pass Thru Protocol instances for
+  LSI 53C895A SCSI devices.
+
+  Copyright (C) 2020, SUSE LLC.
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi/UefiSpec.h>
+
+//
+// Entry point of this driver
+//
+EFI_STATUS
+EFIAPI
+LsiScsiEntryPoint (
+  IN EFI_HANDLE       ImageHandle,
+  IN EFI_SYSTEM_TABLE *SystemTable
+  )
+{
+  return EFI_UNSUPPORTED;
+}
diff --git a/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf b/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
new file mode 100644
index 000000000000..55b483c2fa20
--- /dev/null
+++ b/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
@@ -0,0 +1,26 @@
+## @file
+# This driver produces Extended SCSI Pass Thru Protocol instances for
+# LSI 53C895A SCSI devices.
+#
+# Copyright (C) 2020, SUSE LLC.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 1.29
+  BASE_NAME                      = LsiScsiDxe
+  FILE_GUID                      = EB4EB21f-5A3D-40BE-8BD2-F1B0E38E5744
+  MODULE_TYPE                    = UEFI_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = LsiScsiEntryPoint
+
+[Sources]
+  LsiScsi.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  UefiDriverEntryPoint
diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
index b4ee7376791b..9178ffeb71cb 100644
--- a/OvmfPkg/OvmfPkgIa32.dsc
+++ b/OvmfPkg/OvmfPkgIa32.dsc
@@ -50,6 +50,7 @@ [Defines]
   #
   DEFINE PVSCSI_ENABLE           = TRUE
   DEFINE MPT_SCSI_ENABLE         = TRUE
+  DEFINE LSI_SCSI_ENABLE         = FALSE
 
   #
   # Flash size selection. Setting FD_SIZE_IN_KB on the command line directly to
@@ -771,6 +772,9 @@ [Components]
 !endif
 !if $(MPT_SCSI_ENABLE) == TRUE
   OvmfPkg/MptScsiDxe/MptScsiDxe.inf
+!endif
+!if $(LSI_SCSI_ENABLE) == TRUE
+  OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
 !endif
   MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
   MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
diff --git a/OvmfPkg/OvmfPkgIa32.fdf b/OvmfPkg/OvmfPkgIa32.fdf
index e2b759aa8d05..2b9a6b58015f 100644
--- a/OvmfPkg/OvmfPkgIa32.fdf
+++ b/OvmfPkg/OvmfPkgIa32.fdf
@@ -236,6 +236,9 @@ [FV.DXEFV]
 !if $(MPT_SCSI_ENABLE) == TRUE
 INF  OvmfPkg/MptScsiDxe/MptScsiDxe.inf
 !endif
+!if $(LSI_SCSI_ENABLE) == TRUE
+INF  OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
+!endif
 
 !if $(SECURE_BOOT_ENABLE) == TRUE
   INF  SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
index ed68b080f2a2..a665f78f0dc7 100644
--- a/OvmfPkg/OvmfPkgIa32X64.dsc
+++ b/OvmfPkg/OvmfPkgIa32X64.dsc
@@ -49,6 +49,7 @@ [Defines]
   #
   DEFINE PVSCSI_ENABLE           = TRUE
   DEFINE MPT_SCSI_ENABLE         = TRUE
+  DEFINE LSI_SCSI_ENABLE         = FALSE
 
   #
   # Flash size selection. Setting FD_SIZE_IN_KB on the command line directly to
@@ -785,6 +786,9 @@ [Components.X64]
 !endif
 !if $(MPT_SCSI_ENABLE) == TRUE
   OvmfPkg/MptScsiDxe/MptScsiDxe.inf
+!endif
+!if $(LSI_SCSI_ENABLE) == TRUE
+  OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
 !endif
   MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
   MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
diff --git a/OvmfPkg/OvmfPkgIa32X64.fdf b/OvmfPkg/OvmfPkgIa32X64.fdf
index bfca1eff9e83..83ff6aef2e8c 100644
--- a/OvmfPkg/OvmfPkgIa32X64.fdf
+++ b/OvmfPkg/OvmfPkgIa32X64.fdf
@@ -237,6 +237,9 @@ [FV.DXEFV]
 !if $(MPT_SCSI_ENABLE) == TRUE
 INF  OvmfPkg/MptScsiDxe/MptScsiDxe.inf
 !endif
+!if $(LSI_SCSI_ENABLE) == TRUE
+INF  OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
+!endif
 
 !if $(SECURE_BOOT_ENABLE) == TRUE
   INF  SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
index cb7e8068a3d8..17f345acf4ee 100644
--- a/OvmfPkg/OvmfPkgX64.dsc
+++ b/OvmfPkg/OvmfPkgX64.dsc
@@ -49,6 +49,7 @@ [Defines]
   #
   DEFINE PVSCSI_ENABLE           = TRUE
   DEFINE MPT_SCSI_ENABLE         = TRUE
+  DEFINE LSI_SCSI_ENABLE         = FALSE
 
   #
   # Flash size selection. Setting FD_SIZE_IN_KB on the command line directly to
@@ -781,6 +782,9 @@ [Components]
 !endif
 !if $(MPT_SCSI_ENABLE) == TRUE
   OvmfPkg/MptScsiDxe/MptScsiDxe.inf
+!endif
+!if $(LSI_SCSI_ENABLE) == TRUE
+  OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
 !endif
   MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
   MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
index bfca1eff9e83..83ff6aef2e8c 100644
--- a/OvmfPkg/OvmfPkgX64.fdf
+++ b/OvmfPkg/OvmfPkgX64.fdf
@@ -237,6 +237,9 @@ [FV.DXEFV]
 !if $(MPT_SCSI_ENABLE) == TRUE
 INF  OvmfPkg/MptScsiDxe/MptScsiDxe.inf
 !endif
+!if $(LSI_SCSI_ENABLE) == TRUE
+INF  OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
+!endif
 
 !if $(SECURE_BOOT_ENABLE) == TRUE
   INF  SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 02/11] OvmfPkg/LsiScsiDxe: Install the skeleton of driver binding
  2020-07-01  4:04 [PATCH 00/11] Introduce LsiScsi driver to OvmfPkg Gary Lin
  2020-07-01  4:04 ` [PATCH 01/11] OvmfPkg/LsiScsiDxe: Create the empty driver Gary Lin
@ 2020-07-01  4:04 ` Gary Lin
  2020-07-07  8:06   ` Laszlo Ersek
  2020-07-01  4:04 ` [PATCH 03/11] OvmfPkg/LsiScsiDxe: Report the name of the driver Gary Lin
                   ` (9 subsequent siblings)
  11 siblings, 1 reply; 35+ messages in thread
From: Gary Lin @ 2020-07-01  4:04 UTC (permalink / raw)
  To: devel; +Cc: Jordan Justen, Laszlo Ersek, Ard Biesheuvel

Implement the dummy functions for EFI Driver Binding protocol.

Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Signed-off-by: Gary Lin <glin@suse.com>
---
 OvmfPkg/LsiScsiDxe/LsiScsi.c      | 72 ++++++++++++++++++++++++++++++-
 OvmfPkg/LsiScsiDxe/LsiScsi.h      | 50 +++++++++++++++++++++
 OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf |  2 +
 3 files changed, 123 insertions(+), 1 deletion(-)
 create mode 100644 OvmfPkg/LsiScsiDxe/LsiScsi.h

diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.c b/OvmfPkg/LsiScsiDxe/LsiScsi.c
index 9c90941688ed..79a2af4fee73 100644
--- a/OvmfPkg/LsiScsiDxe/LsiScsi.c
+++ b/OvmfPkg/LsiScsiDxe/LsiScsi.c
@@ -9,8 +9,71 @@
 
 **/
 
+#include <Library/UefiLib.h>
 #include <Uefi/UefiSpec.h>
 
+#include "LsiScsi.h"
+
+//
+// Probe, start and stop functions of this driver, called by the DXE core for
+// specific devices.
+//
+// The following specifications document these interfaces:
+// - Driver Writer's Guide for UEFI 2.3.1 v1.01, 9 Driver Binding Protocol
+// - UEFI Spec 2.3.1 + Errata C, 10.1 EFI Driver Binding Protocol
+//
+
+EFI_STATUS
+EFIAPI
+LsiScsiControllerSupported (
+  IN EFI_DRIVER_BINDING_PROTOCOL *This,
+  IN EFI_HANDLE                  ControllerHandle,
+  IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath OPTIONAL
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EFIAPI
+LsiScsiControllerStart (
+  IN EFI_DRIVER_BINDING_PROTOCOL *This,
+  IN EFI_HANDLE                  ControllerHandle,
+  IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath OPTIONAL
+  )
+{
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+LsiScsiControllerStop (
+  IN EFI_DRIVER_BINDING_PROTOCOL *This,
+  IN EFI_HANDLE                  ControllerHandle,
+  IN UINTN                       NumberOfChildren,
+  IN EFI_HANDLE                  *ChildHandleBuffer
+  )
+{
+  return EFI_SUCCESS;
+}
+
+//
+// The static object that groups the Supported() (ie. probe), Start() and
+// Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata
+// C, 10.1 EFI Driver Binding Protocol.
+//
+STATIC
+EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {
+  &LsiScsiControllerSupported,
+  &LsiScsiControllerStart,
+  &LsiScsiControllerStop,
+  0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers
+  NULL, // ImageHandle, to be overwritten by
+        // EfiLibInstallDriverBindingComponentName2() in LsiScsiEntryPoint()
+  NULL  // DriverBindingHandle, ditto
+};
+
+
 //
 // Entry point of this driver
 //
@@ -21,5 +84,12 @@ LsiScsiEntryPoint (
   IN EFI_SYSTEM_TABLE *SystemTable
   )
 {
-  return EFI_UNSUPPORTED;
+  return EfiLibInstallDriverBindingComponentName2 (
+           ImageHandle,
+           SystemTable,
+           &gDriverBinding,
+           ImageHandle, // The handle to install onto
+           NULL, // TODO Component name
+           NULL  // TODO Component name
+           );
 }
diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.h b/OvmfPkg/LsiScsiDxe/LsiScsi.h
new file mode 100644
index 000000000000..17738442fd5f
--- /dev/null
+++ b/OvmfPkg/LsiScsiDxe/LsiScsi.h
@@ -0,0 +1,50 @@
+/** @file
+
+  Internal definitions for the LSI 53C895A SCSI driver, which produces
+  Extended SCSI Pass Thru Protocol instances for LSI 53C895A SCSI devices.
+
+  Copyright (C) 2020, SUSE LLC.
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _LSI_SCSI_DXE_H_
+#define _LSI_SCSI_DXE_H_
+
+//
+// Probe, start and stop functions of this driver, called by the DXE core for
+// specific devices.
+//
+// The following specifications document these interfaces:
+// - Driver Writer's Guide for UEFI 2.3.1 v1.01, 9 Driver Binding Protocol
+// - UEFI Spec 2.3.1 + Errata C, 10.1 EFI Driver Binding Protocol
+//
+
+STATIC
+EFI_STATUS
+EFIAPI
+LsiScsiControllerSupported (
+  IN EFI_DRIVER_BINDING_PROTOCOL *This,
+  IN EFI_HANDLE                  ControllerHandle,
+  IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath OPTIONAL
+  );
+
+EFI_STATUS
+EFIAPI
+LsiScsiControllerStart (
+  IN EFI_DRIVER_BINDING_PROTOCOL *This,
+  IN EFI_HANDLE                  ControllerHandle,
+  IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath OPTIONAL
+  );
+
+EFI_STATUS
+EFIAPI
+LsiScsiControllerStop (
+  IN EFI_DRIVER_BINDING_PROTOCOL *This,
+  IN EFI_HANDLE                  ControllerHandle,
+  IN UINTN                       NumberOfChildren,
+  IN EFI_HANDLE                  *ChildHandleBuffer
+  );
+
+#endif // _LSI_SCSI_DXE_H_
diff --git a/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf b/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
index 55b483c2fa20..444ceb78e9ca 100644
--- a/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
+++ b/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
@@ -18,9 +18,11 @@ [Defines]
 
 [Sources]
   LsiScsi.c
+  LsiScsi.h
 
 [Packages]
   MdePkg/MdePkg.dec
 
 [LibraryClasses]
   UefiDriverEntryPoint
+  UefiLib
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 03/11] OvmfPkg/LsiScsiDxe: Report the name of the driver
  2020-07-01  4:04 [PATCH 00/11] Introduce LsiScsi driver to OvmfPkg Gary Lin
  2020-07-01  4:04 ` [PATCH 01/11] OvmfPkg/LsiScsiDxe: Create the empty driver Gary Lin
  2020-07-01  4:04 ` [PATCH 02/11] OvmfPkg/LsiScsiDxe: Install the skeleton of driver binding Gary Lin
@ 2020-07-01  4:04 ` Gary Lin
  2020-07-07  8:09   ` Laszlo Ersek
  2020-07-01  4:04 ` [PATCH 04/11] OvmfPkg/LsiScsiDxe: Probe PCI devices and look for LsiScsi Gary Lin
                   ` (8 subsequent siblings)
  11 siblings, 1 reply; 35+ messages in thread
From: Gary Lin @ 2020-07-01  4:04 UTC (permalink / raw)
  To: devel; +Cc: Jordan Justen, Laszlo Ersek, Ard Biesheuvel

Implement LsiScsiGetDriverName() and LsiScsiGetDeviceName()
to report the name of the driver.

Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Signed-off-by: Gary Lin <glin@suse.com>
---
 OvmfPkg/LsiScsiDxe/LsiScsi.c | 69 ++++++++++++++++++++++++++++++++++--
 OvmfPkg/LsiScsiDxe/LsiScsi.h | 31 ++++++++++++++++
 2 files changed, 98 insertions(+), 2 deletions(-)

diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.c b/OvmfPkg/LsiScsiDxe/LsiScsi.c
index 79a2af4fee73..62daa3ab99bf 100644
--- a/OvmfPkg/LsiScsiDxe/LsiScsi.c
+++ b/OvmfPkg/LsiScsiDxe/LsiScsi.c
@@ -74,6 +74,71 @@ EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {
 };
 
 
+//
+// The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and
+// EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name
+// in English, for display on standard console devices. This is recommended for
+// UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's
+// Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.
+//
+// Device type names ("LSI 53C895A SCSI Controller") are not formatted because
+// the driver supports only that device type. Therefore the driver name
+// suffices for unambiguous identification.
+//
+
+STATIC
+EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {
+  { "eng;en", L"LSI 53C895A SCSI Controller Driver" },
+  { NULL,     NULL                                  }
+};
+
+STATIC
+EFI_COMPONENT_NAME_PROTOCOL gComponentName;
+
+EFI_STATUS
+EFIAPI
+LsiScsiGetDriverName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL *This,
+  IN  CHAR8                       *Language,
+  OUT CHAR16                      **DriverName
+  )
+{
+  return LookupUnicodeString2 (
+           Language,
+           This->SupportedLanguages,
+           mDriverNameTable,
+           DriverName,
+           (BOOLEAN)(This == &gComponentName) // Iso639Language
+           );
+}
+
+EFI_STATUS
+EFIAPI
+LsiScsiGetDeviceName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL *This,
+  IN  EFI_HANDLE                  DeviceHandle,
+  IN  EFI_HANDLE                  ChildHandle,
+  IN  CHAR8                       *Language,
+  OUT CHAR16                      **ControllerName
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+STATIC
+EFI_COMPONENT_NAME_PROTOCOL gComponentName = {
+  &LsiScsiGetDriverName,
+  &LsiScsiGetDeviceName,
+  "eng" // SupportedLanguages, ISO 639-2 language codes
+};
+
+STATIC
+EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = {
+  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)     &LsiScsiGetDriverName,
+  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) &LsiScsiGetDeviceName,
+  "en" // SupportedLanguages, RFC 4646 language codes
+};
+
 //
 // Entry point of this driver
 //
@@ -89,7 +154,7 @@ LsiScsiEntryPoint (
            SystemTable,
            &gDriverBinding,
            ImageHandle, // The handle to install onto
-           NULL, // TODO Component name
-           NULL  // TODO Component name
+           &gComponentName,
+           &gComponentName2
            );
 }
diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.h b/OvmfPkg/LsiScsiDxe/LsiScsi.h
index 17738442fd5f..00db9ada12d2 100644
--- a/OvmfPkg/LsiScsiDxe/LsiScsi.h
+++ b/OvmfPkg/LsiScsiDxe/LsiScsi.h
@@ -47,4 +47,35 @@ LsiScsiControllerStop (
   IN EFI_HANDLE                  *ChildHandleBuffer
   );
 
+
+//
+// The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and
+// EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name
+// in English, for display on standard console devices. This is recommended for
+// UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's
+// Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.
+//
+// Device type names ("LSI 53C895A SCSI Controller") are not formatted because
+// the driver supports only that device type. Therefore the driver name
+// suffices for unambiguous identification.
+//
+
+EFI_STATUS
+EFIAPI
+LsiScsiGetDriverName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL *This,
+  IN  CHAR8                       *Language,
+  OUT CHAR16                      **DriverName
+  );
+
+EFI_STATUS
+EFIAPI
+LsiScsiGetDeviceName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL *This,
+  IN  EFI_HANDLE                  DeviceHandle,
+  IN  EFI_HANDLE                  ChildHandle,
+  IN  CHAR8                       *Language,
+  OUT CHAR16                      **ControllerName
+  );
+
 #endif // _LSI_SCSI_DXE_H_
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 04/11] OvmfPkg/LsiScsiDxe: Probe PCI devices and look for LsiScsi
  2020-07-01  4:04 [PATCH 00/11] Introduce LsiScsi driver to OvmfPkg Gary Lin
                   ` (2 preceding siblings ...)
  2020-07-01  4:04 ` [PATCH 03/11] OvmfPkg/LsiScsiDxe: Report the name of the driver Gary Lin
@ 2020-07-01  4:04 ` Gary Lin
  2020-07-07  8:15   ` Laszlo Ersek
  2020-07-01  4:04 ` [PATCH 05/11] OvmfPkg/LsiScsiDxe: Install stubbed EXT_SCSI_PASS_THRU Gary Lin
                   ` (7 subsequent siblings)
  11 siblings, 1 reply; 35+ messages in thread
From: Gary Lin @ 2020-07-01  4:04 UTC (permalink / raw)
  To: devel; +Cc: Jordan Justen, Laszlo Ersek, Ard Biesheuvel

Implement LsiScsiControllerSupported() to probe the PCI ID and look for
LSI 53C895A.

Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Signed-off-by: Gary Lin <glin@suse.com>
---
 OvmfPkg/Include/IndustryStandard/LsiScsi.h | 20 +++++++++
 OvmfPkg/LsiScsiDxe/LsiScsi.c               | 48 +++++++++++++++++++++-
 OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf          |  6 +++
 3 files changed, 73 insertions(+), 1 deletion(-)
 create mode 100644 OvmfPkg/Include/IndustryStandard/LsiScsi.h

diff --git a/OvmfPkg/Include/IndustryStandard/LsiScsi.h b/OvmfPkg/Include/IndustryStandard/LsiScsi.h
new file mode 100644
index 000000000000..c09e864a1f39
--- /dev/null
+++ b/OvmfPkg/Include/IndustryStandard/LsiScsi.h
@@ -0,0 +1,20 @@
+/** @file
+
+  Macros and type definitions for LSI 53C895A SCSI devices.
+
+  Copyright (C) 2020, SUSE LLC.
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _LSI_SCSI_H_
+#define _LSI_SCSI_H_
+
+//
+// Device ID
+//
+#define LSI_LOGIC_PCI_VENDOR_ID   0x1000
+#define LSI_53C895A_PCI_DEVICE_ID 0x0012
+
+#endif // _LSI_SCSI_H_
diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.c b/OvmfPkg/LsiScsiDxe/LsiScsi.c
index 62daa3ab99bf..5bca85bd75eb 100644
--- a/OvmfPkg/LsiScsiDxe/LsiScsi.c
+++ b/OvmfPkg/LsiScsiDxe/LsiScsi.c
@@ -9,7 +9,12 @@
 
 **/
 
+#include <IndustryStandard/LsiScsi.h>
+#include <IndustryStandard/Pci.h>
+#include <Library/UefiBootServicesTableLib.h>
 #include <Library/UefiLib.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/PciRootBridgeIo.h>
 #include <Uefi/UefiSpec.h>
 
 #include "LsiScsi.h"
@@ -31,7 +36,48 @@ LsiScsiControllerSupported (
   IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath OPTIONAL
   )
 {
-  return EFI_UNSUPPORTED;
+  EFI_STATUS          Status;
+  EFI_PCI_IO_PROTOCOL *PciIo;
+  PCI_TYPE00          Pci;
+
+  Status = gBS->OpenProtocol (
+                  ControllerHandle,
+                  &gEfiPciIoProtocolGuid,
+                  (VOID **)&PciIo,
+                  This->DriverBindingHandle,
+                  ControllerHandle,
+                  EFI_OPEN_PROTOCOL_BY_DRIVER
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = PciIo->Pci.Read (
+                        PciIo,
+                        EfiPciIoWidthUint32,
+                        0,
+                        sizeof (Pci) / sizeof (UINT32),
+                        &Pci
+                        );
+  if (EFI_ERROR (Status)) {
+    goto Done;
+  }
+
+  if (Pci.Hdr.VendorId == LSI_LOGIC_PCI_VENDOR_ID &&
+      Pci.Hdr.DeviceId == LSI_53C895A_PCI_DEVICE_ID) {
+    Status = EFI_SUCCESS;
+  } else {
+    Status = EFI_UNSUPPORTED;
+  }
+
+Done:
+  gBS->CloseProtocol (
+         ControllerHandle,
+         &gEfiPciIoProtocolGuid,
+         This->DriverBindingHandle,
+         ControllerHandle
+         );
+  return Status;
 }
 
 EFI_STATUS
diff --git a/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf b/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
index 444ceb78e9ca..e86c626a61aa 100644
--- a/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
+++ b/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
@@ -22,7 +22,13 @@ [Sources]
 
 [Packages]
   MdePkg/MdePkg.dec
+  OvmfPkg/OvmfPkg.dec
 
 [LibraryClasses]
+  BaseLib
+  UefiBootServicesTableLib
   UefiDriverEntryPoint
   UefiLib
+
+[Protocols]
+  gEfiPciIoProtocolGuid                  ## TO_START
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 05/11] OvmfPkg/LsiScsiDxe: Install stubbed EXT_SCSI_PASS_THRU
  2020-07-01  4:04 [PATCH 00/11] Introduce LsiScsi driver to OvmfPkg Gary Lin
                   ` (3 preceding siblings ...)
  2020-07-01  4:04 ` [PATCH 04/11] OvmfPkg/LsiScsiDxe: Probe PCI devices and look for LsiScsi Gary Lin
@ 2020-07-01  4:04 ` Gary Lin
  2020-07-07  8:28   ` Laszlo Ersek
  2020-07-01  4:04 ` [PATCH 06/11] OvmfPkg/LsiScsiDxe: Report Targets and LUNs Gary Lin
                   ` (6 subsequent siblings)
  11 siblings, 1 reply; 35+ messages in thread
From: Gary Lin @ 2020-07-01  4:04 UTC (permalink / raw)
  To: devel; +Cc: Jordan Justen, Laszlo Ersek, Ard Biesheuvel

Partially implement LsiScsiControllerStart() and LsiScsiControllerStop()
to insert the scaffolding of EXT_SCSI_PASS_THRU functions.

Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Signed-off-by: Gary Lin <glin@suse.com>
---
 OvmfPkg/LsiScsiDxe/LsiScsi.c      | 171 +++++++++++++++++++++++++++++-
 OvmfPkg/LsiScsiDxe/LsiScsi.h      |  77 ++++++++++++++
 OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf |   3 +
 3 files changed, 250 insertions(+), 1 deletion(-)

diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.c b/OvmfPkg/LsiScsiDxe/LsiScsi.c
index 5bca85bd75eb..f633c6793298 100644
--- a/OvmfPkg/LsiScsiDxe/LsiScsi.c
+++ b/OvmfPkg/LsiScsiDxe/LsiScsi.c
@@ -11,14 +11,105 @@
 
 #include <IndustryStandard/LsiScsi.h>
 #include <IndustryStandard/Pci.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
 #include <Library/UefiBootServicesTableLib.h>
 #include <Library/UefiLib.h>
 #include <Protocol/PciIo.h>
 #include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/ScsiPassThruExt.h>
 #include <Uefi/UefiSpec.h>
 
 #include "LsiScsi.h"
 
+//
+// The next seven functions implement EFI_EXT_SCSI_PASS_THRU_PROTOCOL
+// for the LSI 53C895A SCSI Controller. Refer to UEFI Spec 2.3.1 + Errata C,
+// sections
+// - 14.1 SCSI Driver Model Overview,
+// - 14.7 Extended SCSI Pass Thru Protocol.
+//
+
+EFI_STATUS
+EFIAPI
+LsiScsiPassThru (
+  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL                *This,
+  IN UINT8                                          *Target,
+  IN UINT64                                         Lun,
+  IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,
+  IN EFI_EVENT                                      Event     OPTIONAL
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EFIAPI
+LsiScsiGetNextTargetLun (
+  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
+  IN OUT UINT8                       **TargetPointer,
+  IN OUT UINT64                      *Lun
+  )
+{
+  return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+EFIAPI
+LsiScsiBuildDevicePath (
+  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
+  IN UINT8                           *Target,
+  IN UINT64                          Lun,
+  IN OUT EFI_DEVICE_PATH_PROTOCOL    **DevicePath
+  )
+{
+  return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+EFIAPI
+LsiScsiGetTargetLun (
+  IN  EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
+  IN  EFI_DEVICE_PATH_PROTOCOL        *DevicePath,
+  OUT UINT8                           **TargetPointer,
+  OUT UINT64                          *Lun
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EFIAPI
+LsiScsiResetChannel (
+  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EFIAPI
+LsiScsiResetTargetLun (
+  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
+  IN UINT8                           *Target,
+  IN UINT64                          Lun
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EFIAPI
+LsiScsiGetNextTarget (
+  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
+  IN OUT UINT8                       **TargetPointer
+  )
+{
+  return EFI_NOT_FOUND;
+}
+
 //
 // Probe, start and stop functions of this driver, called by the DXE core for
 // specific devices.
@@ -88,7 +179,49 @@ LsiScsiControllerStart (
   IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath OPTIONAL
   )
 {
+  EFI_STATUS           Status;
+  LSI_SCSI_DEV         *Dev;
+
+  Dev = AllocateZeroPool (sizeof (*Dev));
+  if (Dev == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Dev->Signature = LSI_SCSI_DEV_SIGNATURE;
+
+  //
+  // Host adapter channel, doesn't exist
+  //
+  Dev->PassThruMode.AdapterId = MAX_UINT32;
+  Dev->PassThruMode.Attributes =
+    EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL |
+    EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL;
+
+  Dev->PassThru.Mode = &Dev->PassThruMode;
+  Dev->PassThru.PassThru = &LsiScsiPassThru;
+  Dev->PassThru.GetNextTargetLun = &LsiScsiGetNextTargetLun;
+  Dev->PassThru.BuildDevicePath = &LsiScsiBuildDevicePath;
+  Dev->PassThru.GetTargetLun = &LsiScsiGetTargetLun;
+  Dev->PassThru.ResetChannel = &LsiScsiResetChannel;
+  Dev->PassThru.ResetTargetLun = &LsiScsiResetTargetLun;
+  Dev->PassThru.GetNextTarget = &LsiScsiGetNextTarget;
+
+  Status = gBS->InstallProtocolInterface (
+                  &ControllerHandle,
+                  &gEfiExtScsiPassThruProtocolGuid,
+                  EFI_NATIVE_INTERFACE,
+                  &Dev->PassThru
+                  );
+  if (EFI_ERROR (Status)) {
+    goto FreePool;
+  }
+
   return EFI_SUCCESS;
+
+FreePool:
+  FreePool (Dev);
+
+  return Status;
 }
 
 EFI_STATUS
@@ -100,7 +233,43 @@ LsiScsiControllerStop (
   IN EFI_HANDLE                  *ChildHandleBuffer
   )
 {
-  return EFI_SUCCESS;
+  EFI_STATUS                      Status;
+  EFI_EXT_SCSI_PASS_THRU_PROTOCOL *PassThru;
+  LSI_SCSI_DEV                    *Dev;
+
+  Status = gBS->OpenProtocol (
+                  ControllerHandle,
+                  &gEfiExtScsiPassThruProtocolGuid,
+                  (VOID **)&PassThru,
+                  This->DriverBindingHandle,
+                  ControllerHandle,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL // Lookup only
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Dev = LSI_SCSI_FROM_PASS_THRU (PassThru);
+
+  Status = gBS->UninstallProtocolInterface (
+                  ControllerHandle,
+                  &gEfiExtScsiPassThruProtocolGuid,
+                  &Dev->PassThru
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  gBS->CloseProtocol (
+         ControllerHandle,
+         &gEfiPciIoProtocolGuid,
+         This->DriverBindingHandle,
+         ControllerHandle
+         );
+
+  FreePool (Dev);
+
+  return Status;
 }
 
 //
diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.h b/OvmfPkg/LsiScsiDxe/LsiScsi.h
index 00db9ada12d2..fca1007f9b98 100644
--- a/OvmfPkg/LsiScsiDxe/LsiScsi.h
+++ b/OvmfPkg/LsiScsiDxe/LsiScsi.h
@@ -12,6 +12,17 @@
 #ifndef _LSI_SCSI_DXE_H_
 #define _LSI_SCSI_DXE_H_
 
+typedef struct {
+  UINT32                          Signature;
+  EFI_EXT_SCSI_PASS_THRU_MODE     PassThruMode;
+  EFI_EXT_SCSI_PASS_THRU_PROTOCOL PassThru;
+} LSI_SCSI_DEV;
+
+#define LSI_SCSI_DEV_SIGNATURE SIGNATURE_32 ('L','S','I','S')
+
+#define LSI_SCSI_FROM_PASS_THRU(PassThruPtr) \
+  CR (PassThruPtr, LSI_SCSI_DEV, PassThru, LSI_SCSI_DEV_SIGNATURE)
+
 //
 // Probe, start and stop functions of this driver, called by the DXE core for
 // specific devices.
@@ -48,6 +59,72 @@ LsiScsiControllerStop (
   );
 
 
+//
+// The next seven functions implement EFI_EXT_SCSI_PASS_THRU_PROTOCOL
+// for the LSI 53C895A SCSI Controller. Refer to UEFI Spec 2.3.1 + Errata C,
+// sections
+// - 14.1 SCSI Driver Model Overview,
+// - 14.7 Extended SCSI Pass Thru Protocol.
+//
+
+EFI_STATUS
+EFIAPI
+LsiScsiPassThru (
+  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL                *This,
+  IN UINT8                                          *Target,
+  IN UINT64                                         Lun,
+  IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,
+  IN EFI_EVENT                                      Event     OPTIONAL
+  );
+
+EFI_STATUS
+EFIAPI
+LsiScsiGetNextTargetLun (
+  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
+  IN OUT UINT8                       **TargetPointer,
+  IN OUT UINT64                      *Lun
+  );
+
+EFI_STATUS
+EFIAPI
+LsiScsiBuildDevicePath (
+  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
+  IN UINT8                           *Target,
+  IN UINT64                          Lun,
+  IN OUT EFI_DEVICE_PATH_PROTOCOL    **DevicePath
+  );
+
+EFI_STATUS
+EFIAPI
+LsiScsiGetTargetLun (
+  IN  EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
+  IN  EFI_DEVICE_PATH_PROTOCOL        *DevicePath,
+  OUT UINT8                           **TargetPointer,
+  OUT UINT64                          *Lun
+  );
+
+EFI_STATUS
+EFIAPI
+LsiScsiResetChannel (
+  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This
+  );
+
+EFI_STATUS
+EFIAPI
+LsiScsiResetTargetLun (
+  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
+  IN UINT8                           *Target,
+  IN UINT64                          Lun
+  );
+
+EFI_STATUS
+EFIAPI
+LsiScsiGetNextTarget (
+  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
+  IN OUT UINT8                       **TargetPointer
+  );
+
+
 //
 // The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and
 // EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name
diff --git a/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf b/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
index e86c626a61aa..8660513e2ffd 100644
--- a/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
+++ b/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
@@ -26,9 +26,12 @@ [Packages]
 
 [LibraryClasses]
   BaseLib
+  BaseMemoryLib
+  MemoryAllocationLib
   UefiBootServicesTableLib
   UefiDriverEntryPoint
   UefiLib
 
 [Protocols]
+  gEfiExtScsiPassThruProtocolGuid        ## BY_START
   gEfiPciIoProtocolGuid                  ## TO_START
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 06/11] OvmfPkg/LsiScsiDxe: Report Targets and LUNs
  2020-07-01  4:04 [PATCH 00/11] Introduce LsiScsi driver to OvmfPkg Gary Lin
                   ` (4 preceding siblings ...)
  2020-07-01  4:04 ` [PATCH 05/11] OvmfPkg/LsiScsiDxe: Install stubbed EXT_SCSI_PASS_THRU Gary Lin
@ 2020-07-01  4:04 ` Gary Lin
  2020-07-07  9:04   ` Laszlo Ersek
  2020-07-01  4:04 ` [PATCH 07/11] OvmfPkg/LsiScsiDxe: Open PciIo protocol and initialize the device Gary Lin
                   ` (5 subsequent siblings)
  11 siblings, 1 reply; 35+ messages in thread
From: Gary Lin @ 2020-07-01  4:04 UTC (permalink / raw)
  To: devel; +Cc: Jordan Justen, Laszlo Ersek, Ard Biesheuvel

Implement LsiScsiGetNextTargetLun(), LsiScsiBuildDevicePath(),
LsiScsiGetTargetLun(), and LsiScsiGetNextTarget() to report Targets and
LUNs and build the device path.

This commit also introduces two PCD value: PcdLsiScsiMaxTargetLimit and
PcdLsiScsiMaxLunLimit as the limits for Targets and LUNs.

Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Signed-off-by: Gary Lin <glin@suse.com>
---
 OvmfPkg/LsiScsiDxe/LsiScsi.c      | 143 +++++++++++++++++++++++++++++-
 OvmfPkg/LsiScsiDxe/LsiScsi.h      |   3 +
 OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf |   6 ++
 OvmfPkg/OvmfPkg.dec               |   5 ++
 4 files changed, 155 insertions(+), 2 deletions(-)

diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.c b/OvmfPkg/LsiScsiDxe/LsiScsi.c
index f633c6793298..e10a81a5f9f7 100644
--- a/OvmfPkg/LsiScsiDxe/LsiScsi.c
+++ b/OvmfPkg/LsiScsiDxe/LsiScsi.c
@@ -15,6 +15,7 @@
 #include <Library/BaseMemoryLib.h>
 #include <Library/DebugLib.h>
 #include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
 #include <Library/UefiBootServicesTableLib.h>
 #include <Library/UefiLib.h>
 #include <Protocol/PciIo.h>
@@ -53,6 +54,49 @@ LsiScsiGetNextTargetLun (
   IN OUT UINT64                      *Lun
   )
 {
+  LSI_SCSI_DEV *Dev;
+  UINTN        Idx;
+  UINT8        *Target;
+  UINT16       LastTarget;
+
+  //
+  // the TargetPointer input parameter is unnecessarily a pointer-to-pointer
+  //
+  Target = *TargetPointer;
+
+  //
+  // Search for first non-0xFF byte. If not found, return first target & LUN.
+  //
+  for (Idx = 0; Idx < TARGET_MAX_BYTES && Target[Idx] == 0xFF; ++Idx)
+    ;
+  if (Idx == TARGET_MAX_BYTES) {
+    SetMem (Target, TARGET_MAX_BYTES, 0x00);
+    *Lun = 0;
+    return EFI_SUCCESS;
+  }
+
+  CopyMem (&LastTarget, Target, sizeof LastTarget);
+
+  //
+  // increment (target, LUN) pair if valid on input
+  //
+  Dev = LSI_SCSI_FROM_PASS_THRU (This);
+  if (LastTarget > Dev->MaxTarget || *Lun > Dev->MaxLun) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (*Lun < Dev->MaxLun) {
+    ++*Lun;
+    return EFI_SUCCESS;
+  }
+
+  if (LastTarget < Dev->MaxTarget) {
+    *Lun = 0;
+    ++LastTarget;
+    CopyMem (Target, &LastTarget, sizeof LastTarget);
+    return EFI_SUCCESS;
+  }
+
   return EFI_NOT_FOUND;
 }
 
@@ -65,7 +109,34 @@ LsiScsiBuildDevicePath (
   IN OUT EFI_DEVICE_PATH_PROTOCOL    **DevicePath
   )
 {
-  return EFI_NOT_FOUND;
+  UINT16           TargetValue;
+  LSI_SCSI_DEV     *Dev;
+  SCSI_DEVICE_PATH *ScsiDevicePath;
+
+  if (DevicePath == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  CopyMem (&TargetValue, Target, sizeof TargetValue);
+  Dev = LSI_SCSI_FROM_PASS_THRU (This);
+  if (TargetValue > Dev->MaxTarget || Lun > Dev->MaxLun || Lun > 0xFFFF) {
+    return EFI_NOT_FOUND;
+  }
+
+  ScsiDevicePath = AllocatePool (sizeof *ScsiDevicePath);
+  if (ScsiDevicePath == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  ScsiDevicePath->Header.Type      = MESSAGING_DEVICE_PATH;
+  ScsiDevicePath->Header.SubType   = MSG_SCSI_DP;
+  ScsiDevicePath->Header.Length[0] = (UINT8)  sizeof *ScsiDevicePath;
+  ScsiDevicePath->Header.Length[1] = (UINT8) (sizeof *ScsiDevicePath >> 8);
+  ScsiDevicePath->Pun              = TargetValue;
+  ScsiDevicePath->Lun              = (UINT16) Lun;
+
+  *DevicePath = &ScsiDevicePath->Header;
+  return EFI_SUCCESS;
 }
 
 EFI_STATUS
@@ -77,7 +148,36 @@ LsiScsiGetTargetLun (
   OUT UINT64                          *Lun
   )
 {
-  return EFI_UNSUPPORTED;
+  SCSI_DEVICE_PATH *ScsiDevicePath;
+  LSI_SCSI_DEV     *Dev;
+  UINT8            *Target;
+
+  if (DevicePath == NULL || TargetPointer == NULL || *TargetPointer == NULL ||
+      Lun == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (DevicePath->Type    != MESSAGING_DEVICE_PATH ||
+      DevicePath->SubType != MSG_SCSI_DP) {
+    return EFI_UNSUPPORTED;
+  }
+
+  ScsiDevicePath = (SCSI_DEVICE_PATH *) DevicePath;
+  Dev = LSI_SCSI_FROM_PASS_THRU (This);
+  if (ScsiDevicePath->Pun > Dev->MaxTarget ||
+      ScsiDevicePath->Lun > Dev->MaxLun) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // This device support 8 targets only, so it's enough to set the LSB
+  // of Target.
+  //
+  Target = *TargetPointer;
+  *Target = (UINT8)ScsiDevicePath->Pun;
+  *Lun = ScsiDevicePath->Lun;
+
+  return EFI_SUCCESS;
 }
 
 EFI_STATUS
@@ -107,6 +207,42 @@ LsiScsiGetNextTarget (
   IN OUT UINT8                       **TargetPointer
   )
 {
+  LSI_SCSI_DEV *Dev;
+  UINTN        Idx;
+  UINT8        *Target;
+  UINT16       LastTarget;
+
+  //
+  // the TargetPointer input parameter is unnecessarily a pointer-to-pointer
+  //
+  Target = *TargetPointer;
+
+  //
+  // Search for first non-0xFF byte. If not found, return first target.
+  //
+  for (Idx = 0; Idx < TARGET_MAX_BYTES && Target[Idx] == 0xFF; ++Idx)
+    ;
+  if (Idx == TARGET_MAX_BYTES) {
+    SetMem (Target, TARGET_MAX_BYTES, 0x00);
+    return EFI_SUCCESS;
+  }
+
+  CopyMem (&LastTarget, Target, sizeof LastTarget);
+
+  //
+  // increment target if valid on input
+  //
+  Dev = LSI_SCSI_FROM_PASS_THRU (This);
+  if (LastTarget > Dev->MaxTarget) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (LastTarget < Dev->MaxTarget) {
+    ++LastTarget;
+    CopyMem (Target, &LastTarget, sizeof LastTarget);
+    return EFI_SUCCESS;
+  }
+
   return EFI_NOT_FOUND;
 }
 
@@ -189,6 +325,9 @@ LsiScsiControllerStart (
 
   Dev->Signature = LSI_SCSI_DEV_SIGNATURE;
 
+  Dev->MaxTarget = PcdGet8 (PcdLsiScsiMaxTargetLimit);
+  Dev->MaxLun = PcdGet8 (PcdLsiScsiMaxLunLimit);
+
   //
   // Host adapter channel, doesn't exist
   //
diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.h b/OvmfPkg/LsiScsiDxe/LsiScsi.h
index fca1007f9b98..a3d51d8f2386 100644
--- a/OvmfPkg/LsiScsiDxe/LsiScsi.h
+++ b/OvmfPkg/LsiScsiDxe/LsiScsi.h
@@ -14,6 +14,8 @@
 
 typedef struct {
   UINT32                          Signature;
+  UINT8                           MaxTarget;
+  UINT8                           MaxLun;
   EFI_EXT_SCSI_PASS_THRU_MODE     PassThruMode;
   EFI_EXT_SCSI_PASS_THRU_PROTOCOL PassThru;
 } LSI_SCSI_DEV;
@@ -23,6 +25,7 @@ typedef struct {
 #define LSI_SCSI_FROM_PASS_THRU(PassThruPtr) \
   CR (PassThruPtr, LSI_SCSI_DEV, PassThru, LSI_SCSI_DEV_SIGNATURE)
 
+
 //
 // Probe, start and stop functions of this driver, called by the DXE core for
 // specific devices.
diff --git a/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf b/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
index 8660513e2ffd..68844c6772e3 100644
--- a/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
+++ b/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
@@ -27,7 +27,9 @@ [Packages]
 [LibraryClasses]
   BaseLib
   BaseMemoryLib
+  DebugLib
   MemoryAllocationLib
+  PcdLib
   UefiBootServicesTableLib
   UefiDriverEntryPoint
   UefiLib
@@ -35,3 +37,7 @@ [LibraryClasses]
 [Protocols]
   gEfiExtScsiPassThruProtocolGuid        ## BY_START
   gEfiPciIoProtocolGuid                  ## TO_START
+
+[FixedPcd]
+  gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiMaxTargetLimit   ## CONSUMES
+  gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiMaxLunLimit      ## CONSUMES
diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index 65bb2bb0eb4c..ae7d1d648d22 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -174,6 +174,11 @@ [PcdsFixedAtBuild]
   ## Microseconds to stall between polling for MptScsi request result
   gUefiOvmfPkgTokenSpaceGuid.PcdMptScsiStallPerPollUsec|5|UINT32|0x40
 
+  ## Set the *inclusive* number of targets and LUNs that LsiScsi exposes for
+  #  scan by ScsiBusDxe.
+  gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiMaxTargetLimit|7|UINT8|0x3b
+  gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiMaxLunLimit|0|UINT8|0x3c
+
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogBase|0x0|UINT32|0x8
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogSize|0x0|UINT32|0x9
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareFdSize|0x0|UINT32|0xa
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 07/11] OvmfPkg/LsiScsiDxe: Open PciIo protocol and initialize the device
  2020-07-01  4:04 [PATCH 00/11] Introduce LsiScsi driver to OvmfPkg Gary Lin
                   ` (5 preceding siblings ...)
  2020-07-01  4:04 ` [PATCH 06/11] OvmfPkg/LsiScsiDxe: Report Targets and LUNs Gary Lin
@ 2020-07-01  4:04 ` Gary Lin
  2020-07-07  9:46   ` Laszlo Ersek
  2020-07-01  4:04 ` [PATCH 08/11] OvmfPkg/LsiScsiDxe: Map DMA buffer Gary Lin
                   ` (4 subsequent siblings)
  11 siblings, 1 reply; 35+ messages in thread
From: Gary Lin @ 2020-07-01  4:04 UTC (permalink / raw)
  To: devel; +Cc: Jordan Justen, Laszlo Ersek, Ard Biesheuvel

Open PciIo protocol and use it to initialize the device. The
initialization of LSI 53C895A is simple: just set the SRST bit in
Interrupt Status Zero register to reset the device.

Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Signed-off-by: Gary Lin <glin@suse.com>
---
 OvmfPkg/Include/IndustryStandard/LsiScsi.h |  21 ++++
 OvmfPkg/LsiScsiDxe/LsiScsi.c               | 129 ++++++++++++++++++++-
 OvmfPkg/LsiScsiDxe/LsiScsi.h               |   3 +
 3 files changed, 152 insertions(+), 1 deletion(-)

diff --git a/OvmfPkg/Include/IndustryStandard/LsiScsi.h b/OvmfPkg/Include/IndustryStandard/LsiScsi.h
index c09e864a1f39..60e527f1c6a7 100644
--- a/OvmfPkg/Include/IndustryStandard/LsiScsi.h
+++ b/OvmfPkg/Include/IndustryStandard/LsiScsi.h
@@ -17,4 +17,25 @@
 #define LSI_LOGIC_PCI_VENDOR_ID   0x1000
 #define LSI_53C895A_PCI_DEVICE_ID 0x0012
 
+//
+// LSI 53C895A Registers
+//
+#define LSI_REG_DSTAT             0x0C
+#define LSI_REG_ISTAT0            0x14
+#define LSI_REG_DSP               0x2C
+#define LSI_REG_SIST0             0x42
+#define LSI_REG_SIST1             0x43
+
+//
+// The status bits for Interrupt Status Zero (ISTAT0)
+//
+#define LSI_ISTAT0_DIP            0x01
+#define LSI_ISTAT0_SIP            0x02
+#define LSI_ISTAT0_INTF           0x04
+#define LSI_ISTAT0_CON            0x08
+#define LSI_ISTAT0_SEM            0x10
+#define LSI_ISTAT0_SIGP           0x20
+#define LSI_ISTAT0_SRST           0x40
+#define LSI_ISTAT0_ABRT           0x80
+
 #endif // _LSI_SCSI_H_
diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.c b/OvmfPkg/LsiScsiDxe/LsiScsi.c
index e10a81a5f9f7..f03774cc4ced 100644
--- a/OvmfPkg/LsiScsiDxe/LsiScsi.c
+++ b/OvmfPkg/LsiScsiDxe/LsiScsi.c
@@ -25,6 +25,33 @@
 
 #include "LsiScsi.h"
 
+STATIC
+EFI_STATUS
+Out8 (
+  IN LSI_SCSI_DEV *Dev,
+  IN UINT32       Addr,
+  IN UINT8        Data
+  )
+{
+  return Dev->PciIo->Io.Write (
+                          Dev->PciIo,
+                          EfiPciIoWidthUint8,
+                          PCI_BAR_IDX0,
+                          Addr,
+                          1,
+                          &Data
+                          );
+}
+
+STATIC
+EFI_STATUS
+LsiScsiReset (
+  IN LSI_SCSI_DEV *Dev
+  )
+{
+  return Out8 (Dev, LSI_REG_ISTAT0, LSI_ISTAT0_SRST);
+}
+
 //
 // The next seven functions implement EFI_EXT_SCSI_PASS_THRU_PROTOCOL
 // for the LSI 53C895A SCSI Controller. Refer to UEFI Spec 2.3.1 + Errata C,
@@ -246,6 +273,21 @@ LsiScsiGetNextTarget (
   return EFI_NOT_FOUND;
 }
 
+STATIC
+VOID
+EFIAPI
+LsiScsiExitBoot (
+  IN  EFI_EVENT Event,
+  IN  VOID      *Context
+  )
+{
+  LSI_SCSI_DEV *Dev;
+
+  Dev = Context;
+  DEBUG ((DEBUG_VERBOSE, "%a: Context=0x%p\n", __FUNCTION__, Context));
+  LsiScsiReset (Dev);
+}
+
 //
 // Probe, start and stop functions of this driver, called by the DXE core for
 // specific devices.
@@ -328,6 +370,58 @@ LsiScsiControllerStart (
   Dev->MaxTarget = PcdGet8 (PcdLsiScsiMaxTargetLimit);
   Dev->MaxLun = PcdGet8 (PcdLsiScsiMaxLunLimit);
 
+  Status = gBS->OpenProtocol (
+                  ControllerHandle,
+                  &gEfiPciIoProtocolGuid,
+                  (VOID **)&Dev->PciIo,
+                  This->DriverBindingHandle,
+                  ControllerHandle,
+                  EFI_OPEN_PROTOCOL_BY_DRIVER
+                  );
+  if (EFI_ERROR (Status)) {
+    goto FreePool;
+  }
+
+  Status = Dev->PciIo->Attributes (
+                         Dev->PciIo,
+                         EfiPciIoAttributeOperationGet,
+                         0,
+                         &Dev->OrigPciAttrs
+                         );
+  if (EFI_ERROR (Status)) {
+    goto CloseProtocol;
+  }
+
+  //
+  // Enable I/O Space & Bus-Mastering
+  //
+  Status = Dev->PciIo->Attributes (
+                         Dev->PciIo,
+                         EfiPciIoAttributeOperationEnable,
+                         (EFI_PCI_IO_ATTRIBUTE_IO |
+                          EFI_PCI_IO_ATTRIBUTE_BUS_MASTER),
+                         NULL
+                         );
+  if (EFI_ERROR (Status)) {
+    goto CloseProtocol;
+  }
+
+  Status = LsiScsiReset (Dev);
+  if (EFI_ERROR (Status)) {
+    goto RestoreAttributes;
+  }
+
+  Status = gBS->CreateEvent (
+                  EVT_SIGNAL_EXIT_BOOT_SERVICES,
+                  TPL_CALLBACK,
+                  &LsiScsiExitBoot,
+                  Dev,
+                  &Dev->ExitBoot
+                  );
+  if (EFI_ERROR (Status)) {
+    goto UninitDev;
+  }
+
   //
   // Host adapter channel, doesn't exist
   //
@@ -352,11 +446,33 @@ LsiScsiControllerStart (
                   &Dev->PassThru
                   );
   if (EFI_ERROR (Status)) {
-    goto FreePool;
+    goto CloseExitBoot;
   }
 
   return EFI_SUCCESS;
 
+CloseExitBoot:
+  gBS->CloseEvent (Dev->ExitBoot);
+
+UninitDev:
+  LsiScsiReset (Dev);
+
+RestoreAttributes:
+  Dev->PciIo->Attributes (
+                Dev->PciIo,
+                EfiPciIoAttributeOperationSet,
+                Dev->OrigPciAttrs,
+                NULL
+                );
+
+CloseProtocol:
+  gBS->CloseProtocol (
+         ControllerHandle,
+         &gEfiPciIoProtocolGuid,
+         This->DriverBindingHandle,
+         ControllerHandle
+         );
+
 FreePool:
   FreePool (Dev);
 
@@ -399,6 +515,17 @@ LsiScsiControllerStop (
     return Status;
   }
 
+  gBS->CloseEvent (Dev->ExitBoot);
+
+  LsiScsiReset (Dev);
+
+  Dev->PciIo->Attributes (
+                Dev->PciIo,
+                EfiPciIoAttributeOperationSet,
+                Dev->OrigPciAttrs,
+                NULL
+                );
+
   gBS->CloseProtocol (
          ControllerHandle,
          &gEfiPciIoProtocolGuid,
diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.h b/OvmfPkg/LsiScsiDxe/LsiScsi.h
index a3d51d8f2386..ffaee6188536 100644
--- a/OvmfPkg/LsiScsiDxe/LsiScsi.h
+++ b/OvmfPkg/LsiScsiDxe/LsiScsi.h
@@ -14,6 +14,9 @@
 
 typedef struct {
   UINT32                          Signature;
+  UINT64                          OrigPciAttrs;
+  EFI_EVENT                       ExitBoot;
+  EFI_PCI_IO_PROTOCOL             *PciIo;
   UINT8                           MaxTarget;
   UINT8                           MaxLun;
   EFI_EXT_SCSI_PASS_THRU_MODE     PassThruMode;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 08/11] OvmfPkg/LsiScsiDxe: Map DMA buffer
  2020-07-01  4:04 [PATCH 00/11] Introduce LsiScsi driver to OvmfPkg Gary Lin
                   ` (6 preceding siblings ...)
  2020-07-01  4:04 ` [PATCH 07/11] OvmfPkg/LsiScsiDxe: Open PciIo protocol and initialize the device Gary Lin
@ 2020-07-01  4:04 ` Gary Lin
  2020-07-07  9:59   ` Laszlo Ersek
  2020-07-01  4:04 ` [PATCH 09/11] OvmfPkg/LsiScsiDxe: Examine the incoming SCSI Request Packet Gary Lin
                   ` (3 subsequent siblings)
  11 siblings, 1 reply; 35+ messages in thread
From: Gary Lin @ 2020-07-01  4:04 UTC (permalink / raw)
  To: devel; +Cc: Jordan Justen, Laszlo Ersek, Ard Biesheuvel

Map DMA buffer and perpare for the implementation of LsiScsiPassThru().

Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Signed-off-by: Gary Lin <glin@suse.com>
---
 OvmfPkg/LsiScsiDxe/LsiScsi.c | 85 +++++++++++++++++++++++++++++++++++-
 OvmfPkg/LsiScsiDxe/LsiScsi.h | 10 +++++
 2 files changed, 94 insertions(+), 1 deletion(-)

diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.c b/OvmfPkg/LsiScsiDxe/LsiScsi.c
index f03774cc4ced..b728d18d51df 100644
--- a/OvmfPkg/LsiScsiDxe/LsiScsi.c
+++ b/OvmfPkg/LsiScsiDxe/LsiScsi.c
@@ -359,6 +359,8 @@ LsiScsiControllerStart (
 {
   EFI_STATUS           Status;
   LSI_SCSI_DEV         *Dev;
+  UINTN                Pages;
+  UINTN                BytesMapped;
 
   Dev = AllocateZeroPool (sizeof (*Dev));
   if (Dev == NULL) {
@@ -406,11 +408,68 @@ LsiScsiControllerStart (
     goto CloseProtocol;
   }
 
-  Status = LsiScsiReset (Dev);
+  //
+  // Signal device supports 64-bit DMA addresses
+  //
+  Status = Dev->PciIo->Attributes (
+                         Dev->PciIo,
+                         EfiPciIoAttributeOperationEnable,
+                         EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE,
+                         NULL
+                         );
+  if (EFI_ERROR (Status)) {
+    //
+    // Warn user that device will only be using 32-bit DMA addresses.
+    //
+    // Note that this does not prevent the device/driver from working
+    // and therefore we only warn and continue as usual.
+    //
+    DEBUG ((
+      DEBUG_WARN,
+      "%a: failed to enable 64-bit DMA addresses\n",
+      __FUNCTION__
+      ));
+  }
+
+  //
+  // Create buffers for data transfer
+  //
+  Pages = EFI_SIZE_TO_PAGES (sizeof (*Dev->Dma));
+  Status = Dev->PciIo->AllocateBuffer (
+                         Dev->PciIo,
+                         AllocateAnyPages,
+                         EfiBootServicesData,
+                         Pages,
+                         (VOID **)&Dev->Dma,
+                         EFI_PCI_ATTRIBUTE_MEMORY_CACHED
+                         );
   if (EFI_ERROR (Status)) {
     goto RestoreAttributes;
   }
 
+  BytesMapped = EFI_PAGES_TO_SIZE (Pages);
+  Status = Dev->PciIo->Map (
+                         Dev->PciIo,
+                         EfiPciIoOperationBusMasterCommonBuffer,
+                         Dev->Dma,
+                         &BytesMapped,
+                         &Dev->DmaPhysical,
+                         &Dev->DmaMapping
+                         );
+  if (EFI_ERROR (Status)) {
+    goto FreeBuffer;
+  }
+
+  if (BytesMapped != EFI_PAGES_TO_SIZE (Pages)) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Unmap;
+  }
+
+  Status = LsiScsiReset (Dev);
+  if (EFI_ERROR (Status)) {
+    goto Unmap;
+  }
+
   Status = gBS->CreateEvent (
                   EVT_SIGNAL_EXIT_BOOT_SERVICES,
                   TPL_CALLBACK,
@@ -457,6 +516,19 @@ CloseExitBoot:
 UninitDev:
   LsiScsiReset (Dev);
 
+Unmap:
+  Dev->PciIo->Unmap (
+                Dev->PciIo,
+                Dev->DmaMapping
+                );
+
+FreeBuffer:
+  Dev->PciIo->FreeBuffer (
+                Dev->PciIo,
+                Pages,
+                Dev->Dma
+                );
+
 RestoreAttributes:
   Dev->PciIo->Attributes (
                 Dev->PciIo,
@@ -519,6 +591,17 @@ LsiScsiControllerStop (
 
   LsiScsiReset (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,
                 EfiPciIoAttributeOperationSet,
diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.h b/OvmfPkg/LsiScsiDxe/LsiScsi.h
index ffaee6188536..1e4bbc56f933 100644
--- a/OvmfPkg/LsiScsiDxe/LsiScsi.h
+++ b/OvmfPkg/LsiScsiDxe/LsiScsi.h
@@ -12,6 +12,13 @@
 #ifndef _LSI_SCSI_DXE_H_
 #define _LSI_SCSI_DXE_H_
 
+typedef struct {
+  //
+  // Allocate 64KB for read/write buffer.
+  //
+  UINT8                           Data[0x10000];
+} LSI_SCSI_DMA_BUFFER;
+
 typedef struct {
   UINT32                          Signature;
   UINT64                          OrigPciAttrs;
@@ -19,6 +26,9 @@ typedef struct {
   EFI_PCI_IO_PROTOCOL             *PciIo;
   UINT8                           MaxTarget;
   UINT8                           MaxLun;
+  LSI_SCSI_DMA_BUFFER             *Dma;
+  EFI_PHYSICAL_ADDRESS            DmaPhysical;
+  VOID                            *DmaMapping;
   EFI_EXT_SCSI_PASS_THRU_MODE     PassThruMode;
   EFI_EXT_SCSI_PASS_THRU_PROTOCOL PassThru;
 } LSI_SCSI_DEV;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 09/11] OvmfPkg/LsiScsiDxe: Examine the incoming SCSI Request Packet
  2020-07-01  4:04 [PATCH 00/11] Introduce LsiScsi driver to OvmfPkg Gary Lin
                   ` (7 preceding siblings ...)
  2020-07-01  4:04 ` [PATCH 08/11] OvmfPkg/LsiScsiDxe: Map DMA buffer Gary Lin
@ 2020-07-01  4:04 ` Gary Lin
  2020-07-07 10:17   ` Laszlo Ersek
  2020-07-01  4:04 ` [PATCH 10/11] OvmfPkg/LsiScsiDxe: Process the " Gary Lin
                   ` (2 subsequent siblings)
  11 siblings, 1 reply; 35+ messages in thread
From: Gary Lin @ 2020-07-01  4:04 UTC (permalink / raw)
  To: devel; +Cc: Jordan Justen, Laszlo Ersek, Ard Biesheuvel

This is the first part of LsiScsiPassThru(). Before processing the SCSI
Request packet, we have to make sure whether the packet is valid or not.

Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Signed-off-by: Gary Lin <glin@suse.com>
---
 OvmfPkg/LsiScsiDxe/LsiScsi.c | 100 ++++++++++++++++++++++++++++++++++-
 OvmfPkg/LsiScsiDxe/LsiScsi.h |   4 ++
 2 files changed, 103 insertions(+), 1 deletion(-)

diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.c b/OvmfPkg/LsiScsiDxe/LsiScsi.c
index b728d18d51df..1bcebd92e455 100644
--- a/OvmfPkg/LsiScsiDxe/LsiScsi.c
+++ b/OvmfPkg/LsiScsiDxe/LsiScsi.c
@@ -52,6 +52,95 @@ LsiScsiReset (
   return Out8 (Dev, LSI_REG_ISTAT0, LSI_ISTAT0_SRST);
 }
 
+STATIC
+EFI_STATUS
+ReportHostAdapterOverrunError (
+  OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
+  )
+{
+  Packet->SenseDataLength = 0;
+  Packet->HostAdapterStatus =
+            EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN;
+  Packet->TargetStatus = EFI_EXT_SCSI_STATUS_TARGET_GOOD;
+  return EFI_BAD_BUFFER_SIZE;
+}
+
+/**
+
+  Check the request packet from the Extended SCSI Pass Thru Protocol. The
+  request packet is modified, to be forwarded outwards by LsiScsiPassThru(),
+  if invalid or unsupported parameters are detected.
+
+  @param[in] Dev          The LSI 53C895A SCSI device the packet targets.
+
+  @param[in] Target       The SCSI target controlled by the LSI 53C895A SCSI
+                          device.
+
+  @param[in] Lun          The Logical Unit Number under the SCSI target.
+
+  @param[in out] Packet   The Extended SCSI Pass Thru Protocol packet.
+
+
+  @retval EFI_SUCCESS  The Extended SCSI Pass Thru Protocol packet was valid.
+
+  @return              Otherwise, invalid or unsupported parameters were
+                       detected. Status codes are meant for direct forwarding
+                       by the EFI_EXT_SCSI_PASS_THRU_PROTOCOL.PassThru()
+                       implementation.
+
+ **/
+STATIC
+EFI_STATUS
+LsiScsiCheckRequest (
+  IN LSI_SCSI_DEV                                   *Dev,
+  IN UINT8                                          Target,
+  IN UINT64                                         Lun,
+  IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
+  )
+{
+  if (Target > Dev->MaxTarget || Lun > Dev->MaxLun ||
+      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->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_BIDIRECTIONAL ||
+      (Packet->InTransferLength > 0 && Packet->OutTransferLength > 0) ||
+      Packet->CdbLength > sizeof Dev->Dma->Cdb) {
+    return EFI_UNSUPPORTED;
+  }
+
+  if (Packet->InTransferLength > sizeof Dev->Dma->Data) {
+    Packet->InTransferLength = sizeof Dev->Dma->Data;
+    return ReportHostAdapterOverrunError (Packet);
+  }
+  if (Packet->OutTransferLength > sizeof Dev->Dma->Data) {
+    Packet->OutTransferLength = sizeof Dev->Dma->Data;
+    return ReportHostAdapterOverrunError (Packet);
+  }
+
+  return EFI_SUCCESS;
+}
+
 //
 // The next seven functions implement EFI_EXT_SCSI_PASS_THRU_PROTOCOL
 // for the LSI 53C895A SCSI Controller. Refer to UEFI Spec 2.3.1 + Errata C,
@@ -70,7 +159,16 @@ LsiScsiPassThru (
   IN EFI_EVENT                                      Event     OPTIONAL
   )
 {
-  return EFI_UNSUPPORTED;
+  EFI_STATUS   Status;
+  LSI_SCSI_DEV *Dev;
+
+  Dev = LSI_SCSI_FROM_PASS_THRU (This);
+  Status = LsiScsiCheckRequest (Dev, *Target, Lun, Packet);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  return EFI_SUCCESS;
 }
 
 EFI_STATUS
diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.h b/OvmfPkg/LsiScsiDxe/LsiScsi.h
index 1e4bbc56f933..9272eb7506c7 100644
--- a/OvmfPkg/LsiScsiDxe/LsiScsi.h
+++ b/OvmfPkg/LsiScsiDxe/LsiScsi.h
@@ -13,6 +13,10 @@
 #define _LSI_SCSI_DXE_H_
 
 typedef struct {
+  //
+  // The max size of CDB is 32.
+  //
+  UINT8                           Cdb[32];
   //
   // Allocate 64KB for read/write buffer.
   //
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 10/11] OvmfPkg/LsiScsiDxe: Process the SCSI Request Packet
  2020-07-01  4:04 [PATCH 00/11] Introduce LsiScsi driver to OvmfPkg Gary Lin
                   ` (8 preceding siblings ...)
  2020-07-01  4:04 ` [PATCH 09/11] OvmfPkg/LsiScsiDxe: Examine the incoming SCSI Request Packet Gary Lin
@ 2020-07-01  4:04 ` Gary Lin
  2020-07-07 12:46   ` Laszlo Ersek
  2020-07-01  4:04 ` [PATCH 11/11] Maintainers.txt: Add myself as the reviewer for LsiScsi driver Gary Lin
  2020-07-03 14:08 ` [edk2-devel] [PATCH 00/11] Introduce LsiScsi driver to OvmfPkg Laszlo Ersek
  11 siblings, 1 reply; 35+ messages in thread
From: Gary Lin @ 2020-07-01  4:04 UTC (permalink / raw)
  To: devel; +Cc: Jordan Justen, Laszlo Ersek, Ard Biesheuvel

This is the second part of LsiScsiPassThru(). LsiScsiProcessRequest() is
added to translate the SCSI Request Packet into the LSI 53C895A
commands. This function utilizes the so-called Script buffer to transmit
a series of commands to the chip and then polls the DMA Status (DSTAT)
register until the Scripts Interrupt Instruction Received (SIR) bit
sets. Once the script is done, the SCSI Request Packet will be modified
to reflect the result of the script.

Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Signed-off-by: Gary Lin <glin@suse.com>
---
 OvmfPkg/Include/IndustryStandard/LsiScsi.h |  39 +++
 OvmfPkg/LsiScsiDxe/LsiScsi.c               | 308 +++++++++++++++++++++
 OvmfPkg/LsiScsiDxe/LsiScsi.h               |  21 ++
 OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf          |   3 +
 OvmfPkg/OvmfPkg.dec                        |   3 +
 5 files changed, 374 insertions(+)

diff --git a/OvmfPkg/Include/IndustryStandard/LsiScsi.h b/OvmfPkg/Include/IndustryStandard/LsiScsi.h
index 60e527f1c6a7..cbf049c18310 100644
--- a/OvmfPkg/Include/IndustryStandard/LsiScsi.h
+++ b/OvmfPkg/Include/IndustryStandard/LsiScsi.h
@@ -26,6 +26,18 @@
 #define LSI_REG_SIST0             0x42
 #define LSI_REG_SIST1             0x43
 
+//
+// The status bits for DMA Status (DSTAT)
+//
+#define LSI_DSTAT_IID             0x01
+#define LSI_DSTAT_R               0x02
+#define LSI_DSTAT_SIR             0x04
+#define LSI_DSTAT_SSI             0x08
+#define LSI_DSTAT_ABRT            0x10
+#define LSI_DSTAT_BF              0x20
+#define LSI_DSTAT_MDPE            0x40
+#define LSI_DSTAT_DFE             0x80
+
 //
 // The status bits for Interrupt Status Zero (ISTAT0)
 //
@@ -38,4 +50,31 @@
 #define LSI_ISTAT0_SRST           0x40
 #define LSI_ISTAT0_ABRT           0x80
 
+//
+// LSI 53C895A Script Instructions
+//
+#define LSI_INS_TYPE_BLK          0x00000000
+#define LSI_INS_TYPE_IO           0x40000000
+#define LSI_INS_TYPE_TC           0x80000000
+
+#define LSI_INS_BLK_SCSIP_DAT_OUT 0x00000000
+#define LSI_INS_BLK_SCSIP_DAT_IN  0x01000000
+#define LSI_INS_BLK_SCSIP_CMD     0x02000000
+#define LSI_INS_BLK_SCSIP_STAT    0x03000000
+#define LSI_INS_BLK_SCSIP_MSG_OUT 0x06000000
+#define LSI_INS_BLK_SCSIP_MSG_IN  0x07000000
+
+#define LSI_INS_IO_OPC_SEL        0x00000000
+#define LSI_INS_IO_OPC_WAIT_RESEL 0x10000000
+
+#define LSI_INS_TC_CP             0x00020000
+#define LSI_INS_TC_JMP            0x00080000
+#define LSI_INS_TC_RA             0x00800000
+
+#define LSI_INS_TC_OPC_JMP        0x00000000
+#define LSI_INS_TC_OPC_INT        0x18000000
+
+#define LSI_INS_TC_SCSIP_DAT_OUT  0x00000000
+#define LSI_INS_TC_SCSIP_MSG_IN   0x07000000
+
 #endif // _LSI_SCSI_H_
diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.c b/OvmfPkg/LsiScsiDxe/LsiScsi.c
index 1bcebd92e455..090d7df15b34 100644
--- a/OvmfPkg/LsiScsiDxe/LsiScsi.c
+++ b/OvmfPkg/LsiScsiDxe/LsiScsi.c
@@ -43,6 +43,42 @@ Out8 (
                           );
 }
 
+STATIC
+EFI_STATUS
+Out32 (
+  IN LSI_SCSI_DEV       *Dev,
+  IN UINT32             Addr,
+  IN UINT32             Data
+  )
+{
+  return Dev->PciIo->Io.Write (
+                          Dev->PciIo,
+                          EfiPciIoWidthUint32,
+                          PCI_BAR_IDX0,
+                          Addr,
+                          1,
+                          &Data
+                          );
+}
+
+STATIC
+EFI_STATUS
+In8 (
+  IN  LSI_SCSI_DEV *Dev,
+  IN  UINT32       Addr,
+  OUT UINT8        *Data
+  )
+{
+  return Dev->PciIo->Io.Read (
+                          Dev->PciIo,
+                          EfiPciIoWidthUint8,
+                          PCI_BAR_IDX0,
+                          Addr,
+                          1,
+                          Data
+                          );
+}
+
 STATIC
 EFI_STATUS
 LsiScsiReset (
@@ -141,6 +177,272 @@ LsiScsiCheckRequest (
   return EFI_SUCCESS;
 }
 
+/**
+
+  Interpret the request packet from the Extended SCSI Pass Thru Protocol and
+  compose the script to submit the command and data to the contorller.
+
+  @param[in] Dev          The LSI 53C895A SCSI device the packet targets.
+
+  @param[in] Target       The SCSI target controlled by the LSI 53C895A SCSI
+                          device.
+
+  @param[in] Lun          The Logical Unit Number under the SCSI target.
+
+  @param[in out] Packet   The Extended SCSI Pass Thru Protocol packet.
+
+
+  @retval EFI_SUCCESS  The Extended SCSI Pass Thru Protocol packet was valid.
+
+  @return              Otherwise, invalid or unsupported parameters were
+                       detected. Status codes are meant for direct forwarding
+                       by the EFI_EXT_SCSI_PASS_THRU_PROTOCOL.PassThru()
+                       implementation.
+
+ **/
+STATIC
+EFI_STATUS
+LsiScsiProcessRequest (
+  IN LSI_SCSI_DEV                                   *Dev,
+  IN UINT8                                          Target,
+  IN UINT64                                         Lun,
+  IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
+  )
+{
+  EFI_STATUS Status;
+  UINT32     *Script;
+  UINT8      *Cdb;
+  UINT8      *MsgOut;
+  UINT8      *MsgIn;
+  UINT8      *ScsiStatus;
+  UINT8      *Data;
+  UINT8      DStat;
+  UINT8      SIst0;
+  UINT8      SIst1;
+
+  Script      = Dev->Dma->Script;
+  Cdb         = Dev->Dma->Cdb;
+  Data        = Dev->Dma->Data;
+  MsgIn       = Dev->Dma->MsgIn;
+  MsgOut      = &Dev->Dma->MsgOut;
+  ScsiStatus  = &Dev->Dma->Status;
+
+  *ScsiStatus = 0xFF;
+
+  SetMem (Cdb, sizeof Dev->Dma->Cdb, 0x00);
+  CopyMem (Cdb, Packet->Cdb, Packet->CdbLength);
+
+  //
+  // Clean up the DMA buffer for the script.
+  //
+  SetMem (Script, sizeof Dev->Dma->Script, 0x00);
+
+  //
+  // Compose the script to transfer data between the host and the device.
+  //
+  // Reference:
+  //   LSI53C895A PCI to Ultra2 SCSI Controller Version 2.2
+  //   - Chapter 5 SCSI SCRIPT Instruction Set
+  //
+  // All instructions used here consist of 2 32bit words. The first word
+  // contains the command to execute. The second word is loaded into the
+  // DMA SCRIPTS Pointer Save (DSPS) register as either the DMA address
+  // for data transmission or the address/offset for the jump command.
+  // Some commands, such as the selection of the target, don't need to
+  // transfer data through DMA or jump to another instruction, then DSPS
+  // has to be zero.
+  //
+  // There are 3 major parts in this script. The first part (1~3) contains
+  // the instructions to select target and LUN and send the SCSI command
+  // from the request packet. The second part (4~7) is to handle the
+  // potential disconnection and prepare for the data transmission. The
+  // instructions in the third part (8~10) transmit the given data and
+  // collect the result. Instruction 11 raises the interrupt and marks the
+  // end of the script.
+  //
+
+  //
+  // 1. Select target.
+  //
+  *Script++ = LSI_INS_TYPE_IO | LSI_INS_IO_OPC_SEL | (UINT32)Target << 16;
+  *Script++ = 0x00000000;
+
+  //
+  // 2. Select LUN.
+  //
+  *MsgOut   = 0x80 | (UINT8) Lun; // 0x80: Identify bit
+  *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_MSG_OUT | \
+              sizeof Dev->Dma->MsgOut;
+  *Script++ = LSI_SCSI_DMA_ADDR_LOW (Dev, MsgOut);
+
+  //
+  // 3. Send the SCSI Command.
+  //
+  *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_CMD | \
+              sizeof Dev->Dma->Cdb;
+  *Script++ = LSI_SCSI_DMA_ADDR_LOW (Dev, Cdb);
+
+  //
+  // 4. Check whether the current SCSI phase is "Message In" or not
+  //    and jump to 8 if it is.
+  //
+  *Script++ = LSI_INS_TYPE_TC | LSI_INS_TC_OPC_JMP | \
+              LSI_INS_TC_SCSIP_MSG_IN | LSI_INS_TC_RA | \
+              LSI_INS_TC_CP;
+  *Script++ = 0x00000018;
+
+  //
+  // 5. Read "Message" from the initiator to trigger reselect.
+  //
+  *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_MSG_IN | \
+              sizeof Dev->Dma->MsgIn;
+  *Script++ = LSI_SCSI_DMA_ADDR_LOW (Dev, MsgIn);
+
+  //
+  // 6. Wait reselect.
+  //
+  *Script++ = LSI_INS_TYPE_IO | LSI_INS_IO_OPC_WAIT_RESEL;
+  *Script++ = 0x00000000;
+
+  //
+  // 7. Read "Message" from the initiator again
+  //
+  *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_MSG_IN | \
+              sizeof Dev->Dma->MsgIn;
+  *Script++ = LSI_SCSI_DMA_ADDR_LOW (Dev, MsgIn);
+
+  //
+  // 8. Set the DMA command for the read/write operations.
+  //
+  if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ &&
+      Packet->InTransferLength > 0) {
+    *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_DAT_IN | \
+                Packet->InTransferLength;
+    *Script++ = LSI_SCSI_DMA_ADDR_LOW (Dev, Data);
+  } else if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_WRITE &&
+             Packet->OutTransferLength > 0) {
+    // LsiScsiCheckRequest() guarantees that OutTransferLength is no
+    // larger than sizeof Dev->Dma->Data, so we can safely copy the
+    // the data to Dev->Dma->Data.
+    CopyMem (Data, Packet->OutDataBuffer, Packet->OutTransferLength);
+    *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_DAT_OUT | \
+                Packet->OutTransferLength;
+    *Script++ = LSI_SCSI_DMA_ADDR_LOW (Dev, Data);
+  }
+
+  //
+  // 9. Get the SCSI status.
+  //
+  *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_STAT | \
+              sizeof Dev->Dma->Status;
+  *Script++ = LSI_SCSI_DMA_ADDR_LOW (Dev, Status);
+
+  //
+  // 10. Get the SCSI message.
+  //
+  *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_MSG_IN | \
+              sizeof Dev->Dma->MsgIn;
+  *Script++ = LSI_SCSI_DMA_ADDR_LOW (Dev, MsgIn);
+
+  //
+  // 11. Raise the interrupt to end the script.
+  //
+  *Script++ = LSI_INS_TYPE_TC | LSI_INS_TC_OPC_INT | \
+              LSI_INS_TC_SCSIP_DAT_OUT | LSI_INS_TC_JMP;
+  *Script++ = 0x00000000;
+
+  //
+  // Make sure the size of the script doesn't exceed the buffer.
+  //
+  ASSERT (Script < Dev->Dma->Script + sizeof Dev->Dma->Script);
+
+  //
+  // The controller starts to execute the script once the DMA Script
+  // Pointer (DSP) register is set.
+  //
+  Status = Out32 (Dev, LSI_REG_DSP, LSI_SCSI_DMA_ADDR_LOW(Dev, Script));
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Poll the device registers (DSTAT, SIST0, and SIST1) until the SIR
+  // bit sets.
+  //
+  for(;;) {
+    Status = In8 (Dev, LSI_REG_DSTAT, &DStat);
+    if (EFI_ERROR (Status)) {
+      goto Error;
+    }
+    Status = In8 (Dev, LSI_REG_SIST0, &SIst0);
+    if (EFI_ERROR (Status)) {
+      goto Error;
+    }
+    Status = In8 (Dev, LSI_REG_SIST1, &SIst1);
+    if (EFI_ERROR (Status)) {
+      goto Error;
+    }
+
+    if (SIst0 != 0 || SIst1 != 0) {
+      goto Error;
+    }
+
+    //
+    // Check the SIR (SCRIPTS Interrupt Instruction Received) bit.
+    //
+    if (DStat & LSI_DSTAT_SIR) {
+      break;
+    }
+
+    gBS->Stall (Dev->StallPerPollUsec);
+  }
+
+  //
+  // Check if everything is good.
+  //   SCSI Message Code 0x00: COMMAND COMPLETE
+  //   SCSI Status  Code 0x00: Good
+  //
+  if (MsgIn[0] == 0 && *ScsiStatus == 0) {
+    //
+    // Copy Data to InDataBuffer if necessary.
+    //
+    if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
+      CopyMem (Packet->InDataBuffer, Data, Packet->InTransferLength);
+    }
+
+    //
+    // The controller doesn't return sense data when replying "TEST UNIT READY",
+    // so we have to set SenseDataLength to 0 to notify ScsiIo to issue
+    // "REQUEST SENSE" for the sense data.
+    //
+    if (Cdb[0] == 0x00) {
+      Packet->SenseDataLength = 0;
+    }
+    Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK;
+    Packet->TargetStatus      = EFI_EXT_SCSI_STATUS_TARGET_GOOD;
+
+    return EFI_SUCCESS;
+  }
+
+Error:
+  DEBUG((DEBUG_VERBOSE, "%a: dstat: %02X, sist0: %02X, sist1: %02X\n",
+         __FUNCTION__, DStat, SIst0, SIst1));
+  //
+  // Update the request packet to reflect the status.
+  //
+  if (*ScsiStatus != 0xFF) {
+    Packet->TargetStatus    = *ScsiStatus;
+  } else {
+    Packet->TargetStatus    = EFI_EXT_SCSI_STATUS_TARGET_TASK_ABORTED;
+  }
+  Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;
+  Packet->InTransferLength  = 0;
+  Packet->OutTransferLength = 0;
+  Packet->SenseDataLength   = 0;
+
+  return EFI_DEVICE_ERROR;
+}
+
 //
 // The next seven functions implement EFI_EXT_SCSI_PASS_THRU_PROTOCOL
 // for the LSI 53C895A SCSI Controller. Refer to UEFI Spec 2.3.1 + Errata C,
@@ -168,6 +470,11 @@ LsiScsiPassThru (
     return Status;
   }
 
+  Status = LsiScsiProcessRequest (Dev, *Target, Lun, Packet);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
   return EFI_SUCCESS;
 }
 
@@ -469,6 +776,7 @@ LsiScsiControllerStart (
 
   Dev->MaxTarget = PcdGet8 (PcdLsiScsiMaxTargetLimit);
   Dev->MaxLun = PcdGet8 (PcdLsiScsiMaxLunLimit);
+  Dev->StallPerPollUsec = PcdGet32 (PcdLsiScsiStallPerPollUsec);
 
   Status = gBS->OpenProtocol (
                   ControllerHandle,
diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.h b/OvmfPkg/LsiScsiDxe/LsiScsi.h
index 9272eb7506c7..1a16ef9f7795 100644
--- a/OvmfPkg/LsiScsiDxe/LsiScsi.h
+++ b/OvmfPkg/LsiScsiDxe/LsiScsi.h
@@ -13,6 +13,11 @@
 #define _LSI_SCSI_DXE_H_
 
 typedef struct {
+  //
+  // Allocate 32 UINT32 entries for the script and it's sufficient for
+  // 16 instructions.
+  //
+  UINT32                          Script[32];
   //
   // The max size of CDB is 32.
   //
@@ -21,6 +26,18 @@ typedef struct {
   // Allocate 64KB for read/write buffer.
   //
   UINT8                           Data[0x10000];
+  //
+  // For SCSI Message In phase
+  //
+  UINT8                           MsgIn[2];
+  //
+  // For SCSI Message Out phase
+  //
+  UINT8                           MsgOut;
+  //
+  // For SCSI Status phase
+  //
+  UINT8                           Status;
 } LSI_SCSI_DMA_BUFFER;
 
 typedef struct {
@@ -30,6 +47,7 @@ typedef struct {
   EFI_PCI_IO_PROTOCOL             *PciIo;
   UINT8                           MaxTarget;
   UINT8                           MaxLun;
+  UINT32                          StallPerPollUsec;
   LSI_SCSI_DMA_BUFFER             *Dma;
   EFI_PHYSICAL_ADDRESS            DmaPhysical;
   VOID                            *DmaMapping;
@@ -42,6 +60,9 @@ typedef struct {
 #define LSI_SCSI_FROM_PASS_THRU(PassThruPtr) \
   CR (PassThruPtr, LSI_SCSI_DEV, PassThru, LSI_SCSI_DEV_SIGNATURE)
 
+#define LSI_SCSI_DMA_ADDR_LOW(Dev, MemberName) \
+  ((UINT32)(Dev->DmaPhysical + OFFSET_OF (LSI_SCSI_DMA_BUFFER, MemberName)))
+
 
 //
 // Probe, start and stop functions of this driver, called by the DXE core for
diff --git a/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf b/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
index 68844c6772e3..cbd7294573ac 100644
--- a/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
+++ b/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
@@ -41,3 +41,6 @@ [Protocols]
 [FixedPcd]
   gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiMaxTargetLimit   ## CONSUMES
   gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiMaxLunLimit      ## CONSUMES
+
+[Pcd]
+  gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiStallPerPollUsec ## CONSUMES
diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index ae7d1d648d22..57e418d4b8a9 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -179,6 +179,9 @@ [PcdsFixedAtBuild]
   gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiMaxTargetLimit|7|UINT8|0x3b
   gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiMaxLunLimit|0|UINT8|0x3c
 
+  ## Microseconds to stall between polling for LsiScsi request result
+  gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiStallPerPollUsec|5|UINT32|0x3d
+
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogBase|0x0|UINT32|0x8
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogSize|0x0|UINT32|0x9
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareFdSize|0x0|UINT32|0xa
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 11/11] Maintainers.txt: Add myself as the reviewer for LsiScsi driver
  2020-07-01  4:04 [PATCH 00/11] Introduce LsiScsi driver to OvmfPkg Gary Lin
                   ` (9 preceding siblings ...)
  2020-07-01  4:04 ` [PATCH 10/11] OvmfPkg/LsiScsiDxe: Process the " Gary Lin
@ 2020-07-01  4:04 ` Gary Lin
  2020-07-07 12:49   ` Laszlo Ersek
  2020-07-03 14:08 ` [edk2-devel] [PATCH 00/11] Introduce LsiScsi driver to OvmfPkg Laszlo Ersek
  11 siblings, 1 reply; 35+ messages in thread
From: Gary Lin @ 2020-07-01  4:04 UTC (permalink / raw)
  To: devel; +Cc: Jordan Justen, Laszlo Ersek, Ard Biesheuvel

Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Signed-off-by: Gary Lin <glin@suse.com>
---
 Maintainers.txt | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Maintainers.txt b/Maintainers.txt
index 32c9003a6209..666d3af4d76a 100644
--- a/Maintainers.txt
+++ b/Maintainers.txt
@@ -400,6 +400,10 @@ OvmfPkg: CSM modules
 F: OvmfPkg/Csm/
 R: David Woodhouse <dwmw2@infradead.org>
 
+OvmfPkg: LsiScsi Driver
+F: OvmfPkg/LsiScsiDxe/
+R: Gary Lin <glin@suse.com>
+
 OvmfPkg: MptScsi and PVSCSI driver
 F: OvmfPkg/MptScsiDxe/
 F: OvmfPkg/PvScsiDxe/
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* Re: [edk2-devel] [PATCH 00/11] Introduce LsiScsi driver to OvmfPkg
  2020-07-01  4:04 [PATCH 00/11] Introduce LsiScsi driver to OvmfPkg Gary Lin
                   ` (10 preceding siblings ...)
  2020-07-01  4:04 ` [PATCH 11/11] Maintainers.txt: Add myself as the reviewer for LsiScsi driver Gary Lin
@ 2020-07-03 14:08 ` Laszlo Ersek
  11 siblings, 0 replies; 35+ messages in thread
From: Laszlo Ersek @ 2020-07-03 14:08 UTC (permalink / raw)
  To: devel, glin; +Cc: Jordan Justen, Ard Biesheuvel

Hi Gary,

On 07/01/20 06:04, Gary Lin wrote:
> This patch series implement the driver for LSI 53C895A SCSI controller
> for OVMF so that the user can access the storage devices connected to
> QEMU "lsi" controller. The driver is disabled by default since LSI
> 53C895A is considered as a legacy device. To enable the driver, please
> add "-D LSI_SCSI_ENABLE" when building OvmfPkg.
> 
> The patch series is also available in my git branch:
> https://github.com/lcp/edk2/tree/ovmf-lsi-v1
> 
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>

I've queued your series for review; please give me some time to get to
it. I hope I can review the patches next week.

Thanks
Laszlo

> 
> Gary Lin (11):
>   OvmfPkg/LsiScsiDxe: Create the empty driver
>   OvmfPkg/LsiScsiDxe: Install the skeleton of driver binding
>   OvmfPkg/LsiScsiDxe: Report the name of the driver
>   OvmfPkg/LsiScsiDxe: Probe PCI devices and look for LsiScsi
>   OvmfPkg/LsiScsiDxe: Install stubbed EXT_SCSI_PASS_THRU
>   OvmfPkg/LsiScsiDxe: Report Targets and LUNs
>   OvmfPkg/LsiScsiDxe: Open PciIo protocol and initialize the device
>   OvmfPkg/LsiScsiDxe: Map DMA buffer
>   OvmfPkg/LsiScsiDxe: Examine the incoming SCSI Request Packet
>   OvmfPkg/LsiScsiDxe: Process the SCSI Request Packet
>   Maintainers.txt: Add myself as the reviewer for LsiScsi driver
> 
>  Maintainers.txt                            |    4 +
>  OvmfPkg/Include/IndustryStandard/LsiScsi.h |   80 ++
>  OvmfPkg/LsiScsiDxe/LsiScsi.c               | 1130 ++++++++++++++++++++
>  OvmfPkg/LsiScsiDxe/LsiScsi.h               |  199 ++++
>  OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf          |   46 +
>  OvmfPkg/OvmfPkg.dec                        |    8 +
>  OvmfPkg/OvmfPkgIa32.dsc                    |    4 +
>  OvmfPkg/OvmfPkgIa32.fdf                    |    3 +
>  OvmfPkg/OvmfPkgIa32X64.dsc                 |    4 +
>  OvmfPkg/OvmfPkgIa32X64.fdf                 |    3 +
>  OvmfPkg/OvmfPkgX64.dsc                     |    4 +
>  OvmfPkg/OvmfPkgX64.fdf                     |    3 +
>  12 files changed, 1488 insertions(+)
>  create mode 100644 OvmfPkg/Include/IndustryStandard/LsiScsi.h
>  create mode 100644 OvmfPkg/LsiScsiDxe/LsiScsi.c
>  create mode 100644 OvmfPkg/LsiScsiDxe/LsiScsi.h
>  create mode 100644 OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> 


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 01/11] OvmfPkg/LsiScsiDxe: Create the empty driver
  2020-07-01  4:04 ` [PATCH 01/11] OvmfPkg/LsiScsiDxe: Create the empty driver Gary Lin
@ 2020-07-07  7:59   ` Laszlo Ersek
  2020-07-07  8:24     ` Gary Lin
  0 siblings, 1 reply; 35+ messages in thread
From: Laszlo Ersek @ 2020-07-07  7:59 UTC (permalink / raw)
  To: Gary Lin, devel; +Cc: Jordan Justen, Ard Biesheuvel

On 07/01/20 06:04, Gary Lin wrote:
> Create the driver with only a dummy LsiScsiEntryPoint() for the further
> implementation of the driver for LSI 53C895A SCSI controller.
> 
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
> Signed-off-by: Gary Lin <glin@suse.com>
> ---
>  OvmfPkg/LsiScsiDxe/LsiScsi.c      | 25 +++++++++++++++++++++++++
>  OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf | 26 ++++++++++++++++++++++++++
>  OvmfPkg/OvmfPkgIa32.dsc           |  4 ++++
>  OvmfPkg/OvmfPkgIa32.fdf           |  3 +++
>  OvmfPkg/OvmfPkgIa32X64.dsc        |  4 ++++
>  OvmfPkg/OvmfPkgIa32X64.fdf        |  3 +++
>  OvmfPkg/OvmfPkgX64.dsc            |  4 ++++
>  OvmfPkg/OvmfPkgX64.fdf            |  3 +++
>  8 files changed, 72 insertions(+)
>  create mode 100644 OvmfPkg/LsiScsiDxe/LsiScsi.c
>  create mode 100644 OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> 
> diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.c b/OvmfPkg/LsiScsiDxe/LsiScsi.c
> new file mode 100644
> index 000000000000..9c90941688ed
> --- /dev/null
> +++ b/OvmfPkg/LsiScsiDxe/LsiScsi.c
> @@ -0,0 +1,25 @@
> +/** @file
> +
> +  This driver produces Extended SCSI Pass Thru Protocol instances for
> +  LSI 53C895A SCSI devices.
> +
> +  Copyright (C) 2020, SUSE LLC.
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <Uefi/UefiSpec.h>
> +
> +//
> +// Entry point of this driver
> +//
> +EFI_STATUS
> +EFIAPI
> +LsiScsiEntryPoint (
> +  IN EFI_HANDLE       ImageHandle,
> +  IN EFI_SYSTEM_TABLE *SystemTable
> +  )
> +{
> +  return EFI_UNSUPPORTED;
> +}
> diff --git a/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf b/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> new file mode 100644
> index 000000000000..55b483c2fa20
> --- /dev/null
> +++ b/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> @@ -0,0 +1,26 @@
> +## @file
> +# This driver produces Extended SCSI Pass Thru Protocol instances for
> +# LSI 53C895A SCSI devices.
> +#
> +# Copyright (C) 2020, SUSE LLC.
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 1.29
> +  BASE_NAME                      = LsiScsiDxe
> +  FILE_GUID                      = EB4EB21f-5A3D-40BE-8BD2-F1B0E38E5744

(1) The GUID should not be written in mixed case. Please pick upper case
or lower case for the whole GUID string.

(I wonder how you created the current (mixed-case) GUID string...
uuidgen outputs lower case, and I wonder how one can translate
everything except the *first* "f" from that to upper case. I hope you
didn't manually update a previously generated GUID!)

with the spelling fixed, or the GUID regenerated:

Reviewed-by: Laszlo Ersek <lersek@redhat.com>

Thanks
Laszlo

> +  MODULE_TYPE                    = UEFI_DRIVER
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = LsiScsiEntryPoint
> +
> +[Sources]
> +  LsiScsi.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +
> +[LibraryClasses]
> +  UefiDriverEntryPoint
> diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
> index b4ee7376791b..9178ffeb71cb 100644
> --- a/OvmfPkg/OvmfPkgIa32.dsc
> +++ b/OvmfPkg/OvmfPkgIa32.dsc
> @@ -50,6 +50,7 @@ [Defines]
>    #
>    DEFINE PVSCSI_ENABLE           = TRUE
>    DEFINE MPT_SCSI_ENABLE         = TRUE
> +  DEFINE LSI_SCSI_ENABLE         = FALSE
>  
>    #
>    # Flash size selection. Setting FD_SIZE_IN_KB on the command line directly to
> @@ -771,6 +772,9 @@ [Components]
>  !endif
>  !if $(MPT_SCSI_ENABLE) == TRUE
>    OvmfPkg/MptScsiDxe/MptScsiDxe.inf
> +!endif
> +!if $(LSI_SCSI_ENABLE) == TRUE
> +  OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
>  !endif
>    MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
>    MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
> diff --git a/OvmfPkg/OvmfPkgIa32.fdf b/OvmfPkg/OvmfPkgIa32.fdf
> index e2b759aa8d05..2b9a6b58015f 100644
> --- a/OvmfPkg/OvmfPkgIa32.fdf
> +++ b/OvmfPkg/OvmfPkgIa32.fdf
> @@ -236,6 +236,9 @@ [FV.DXEFV]
>  !if $(MPT_SCSI_ENABLE) == TRUE
>  INF  OvmfPkg/MptScsiDxe/MptScsiDxe.inf
>  !endif
> +!if $(LSI_SCSI_ENABLE) == TRUE
> +INF  OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> +!endif
>  
>  !if $(SECURE_BOOT_ENABLE) == TRUE
>    INF  SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
> diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
> index ed68b080f2a2..a665f78f0dc7 100644
> --- a/OvmfPkg/OvmfPkgIa32X64.dsc
> +++ b/OvmfPkg/OvmfPkgIa32X64.dsc
> @@ -49,6 +49,7 @@ [Defines]
>    #
>    DEFINE PVSCSI_ENABLE           = TRUE
>    DEFINE MPT_SCSI_ENABLE         = TRUE
> +  DEFINE LSI_SCSI_ENABLE         = FALSE
>  
>    #
>    # Flash size selection. Setting FD_SIZE_IN_KB on the command line directly to
> @@ -785,6 +786,9 @@ [Components.X64]
>  !endif
>  !if $(MPT_SCSI_ENABLE) == TRUE
>    OvmfPkg/MptScsiDxe/MptScsiDxe.inf
> +!endif
> +!if $(LSI_SCSI_ENABLE) == TRUE
> +  OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
>  !endif
>    MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
>    MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
> diff --git a/OvmfPkg/OvmfPkgIa32X64.fdf b/OvmfPkg/OvmfPkgIa32X64.fdf
> index bfca1eff9e83..83ff6aef2e8c 100644
> --- a/OvmfPkg/OvmfPkgIa32X64.fdf
> +++ b/OvmfPkg/OvmfPkgIa32X64.fdf
> @@ -237,6 +237,9 @@ [FV.DXEFV]
>  !if $(MPT_SCSI_ENABLE) == TRUE
>  INF  OvmfPkg/MptScsiDxe/MptScsiDxe.inf
>  !endif
> +!if $(LSI_SCSI_ENABLE) == TRUE
> +INF  OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> +!endif
>  
>  !if $(SECURE_BOOT_ENABLE) == TRUE
>    INF  SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
> diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
> index cb7e8068a3d8..17f345acf4ee 100644
> --- a/OvmfPkg/OvmfPkgX64.dsc
> +++ b/OvmfPkg/OvmfPkgX64.dsc
> @@ -49,6 +49,7 @@ [Defines]
>    #
>    DEFINE PVSCSI_ENABLE           = TRUE
>    DEFINE MPT_SCSI_ENABLE         = TRUE
> +  DEFINE LSI_SCSI_ENABLE         = FALSE
>  
>    #
>    # Flash size selection. Setting FD_SIZE_IN_KB on the command line directly to
> @@ -781,6 +782,9 @@ [Components]
>  !endif
>  !if $(MPT_SCSI_ENABLE) == TRUE
>    OvmfPkg/MptScsiDxe/MptScsiDxe.inf
> +!endif
> +!if $(LSI_SCSI_ENABLE) == TRUE
> +  OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
>  !endif
>    MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
>    MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
> diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
> index bfca1eff9e83..83ff6aef2e8c 100644
> --- a/OvmfPkg/OvmfPkgX64.fdf
> +++ b/OvmfPkg/OvmfPkgX64.fdf
> @@ -237,6 +237,9 @@ [FV.DXEFV]
>  !if $(MPT_SCSI_ENABLE) == TRUE
>  INF  OvmfPkg/MptScsiDxe/MptScsiDxe.inf
>  !endif
> +!if $(LSI_SCSI_ENABLE) == TRUE
> +INF  OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> +!endif
>  
>  !if $(SECURE_BOOT_ENABLE) == TRUE
>    INF  SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
> 


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 02/11] OvmfPkg/LsiScsiDxe: Install the skeleton of driver binding
  2020-07-01  4:04 ` [PATCH 02/11] OvmfPkg/LsiScsiDxe: Install the skeleton of driver binding Gary Lin
@ 2020-07-07  8:06   ` Laszlo Ersek
  2020-07-07  8:34     ` Gary Lin
  0 siblings, 1 reply; 35+ messages in thread
From: Laszlo Ersek @ 2020-07-07  8:06 UTC (permalink / raw)
  To: Gary Lin, devel; +Cc: Jordan Justen, Ard Biesheuvel

On 07/01/20 06:04, Gary Lin wrote:
> Implement the dummy functions for EFI Driver Binding protocol.
> 
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
> Signed-off-by: Gary Lin <glin@suse.com>
> ---
>  OvmfPkg/LsiScsiDxe/LsiScsi.c      | 72 ++++++++++++++++++++++++++++++-
>  OvmfPkg/LsiScsiDxe/LsiScsi.h      | 50 +++++++++++++++++++++
>  OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf |  2 +
>  3 files changed, 123 insertions(+), 1 deletion(-)
>  create mode 100644 OvmfPkg/LsiScsiDxe/LsiScsi.h
> 
> diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.c b/OvmfPkg/LsiScsiDxe/LsiScsi.c
> index 9c90941688ed..79a2af4fee73 100644
> --- a/OvmfPkg/LsiScsiDxe/LsiScsi.c
> +++ b/OvmfPkg/LsiScsiDxe/LsiScsi.c
> @@ -9,8 +9,71 @@
>  
>  **/
>  
> +#include <Library/UefiLib.h>
>  #include <Uefi/UefiSpec.h>
>  
> +#include "LsiScsi.h"
> +
> +//
> +// Probe, start and stop functions of this driver, called by the DXE core for
> +// specific devices.
> +//
> +// The following specifications document these interfaces:
> +// - Driver Writer's Guide for UEFI 2.3.1 v1.01, 9 Driver Binding Protocol
> +// - UEFI Spec 2.3.1 + Errata C, 10.1 EFI Driver Binding Protocol
> +//
> +
> +EFI_STATUS
> +EFIAPI
> +LsiScsiControllerSupported (
> +  IN EFI_DRIVER_BINDING_PROTOCOL *This,
> +  IN EFI_HANDLE                  ControllerHandle,
> +  IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath OPTIONAL
> +  )
> +{
> +  return EFI_UNSUPPORTED;
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +LsiScsiControllerStart (
> +  IN EFI_DRIVER_BINDING_PROTOCOL *This,
> +  IN EFI_HANDLE                  ControllerHandle,
> +  IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath OPTIONAL
> +  )
> +{
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +LsiScsiControllerStop (
> +  IN EFI_DRIVER_BINDING_PROTOCOL *This,
> +  IN EFI_HANDLE                  ControllerHandle,
> +  IN UINTN                       NumberOfChildren,
> +  IN EFI_HANDLE                  *ChildHandleBuffer
> +  )
> +{
> +  return EFI_SUCCESS;
> +}
> +
> +//
> +// The static object that groups the Supported() (ie. probe), Start() and
> +// Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata
> +// C, 10.1 EFI Driver Binding Protocol.
> +//
> +STATIC
> +EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {
> +  &LsiScsiControllerSupported,
> +  &LsiScsiControllerStart,
> +  &LsiScsiControllerStop,
> +  0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers
> +  NULL, // ImageHandle, to be overwritten by
> +        // EfiLibInstallDriverBindingComponentName2() in LsiScsiEntryPoint()
> +  NULL  // DriverBindingHandle, ditto
> +};
> +
> +
>  //
>  // Entry point of this driver
>  //
> @@ -21,5 +84,12 @@ LsiScsiEntryPoint (
>    IN EFI_SYSTEM_TABLE *SystemTable
>    )
>  {
> -  return EFI_UNSUPPORTED;
> +  return EfiLibInstallDriverBindingComponentName2 (
> +           ImageHandle,
> +           SystemTable,
> +           &gDriverBinding,
> +           ImageHandle, // The handle to install onto
> +           NULL, // TODO Component name
> +           NULL  // TODO Component name
> +           );
>  }
> diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.h b/OvmfPkg/LsiScsiDxe/LsiScsi.h
> new file mode 100644
> index 000000000000..17738442fd5f
> --- /dev/null
> +++ b/OvmfPkg/LsiScsiDxe/LsiScsi.h
> @@ -0,0 +1,50 @@
> +/** @file
> +
> +  Internal definitions for the LSI 53C895A SCSI driver, which produces
> +  Extended SCSI Pass Thru Protocol instances for LSI 53C895A SCSI devices.
> +
> +  Copyright (C) 2020, SUSE LLC.
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef _LSI_SCSI_DXE_H_
> +#define _LSI_SCSI_DXE_H_
> +
> +//
> +// Probe, start and stop functions of this driver, called by the DXE core for
> +// specific devices.
> +//
> +// The following specifications document these interfaces:
> +// - Driver Writer's Guide for UEFI 2.3.1 v1.01, 9 Driver Binding Protocol
> +// - UEFI Spec 2.3.1 + Errata C, 10.1 EFI Driver Binding Protocol
> +//
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +LsiScsiControllerSupported (
> +  IN EFI_DRIVER_BINDING_PROTOCOL *This,
> +  IN EFI_HANDLE                  ControllerHandle,
> +  IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath OPTIONAL
> +  );

(1) Please drop "STATIC", to be consistent with the definition of
LsiScsiControllerSupported(), in the .c file.

(I think the patch is not invalid C as-is, but it's confusing for the
reader.)

With that fixed

Reviewed-by: Laszlo Ersek <lersek@redhat.com>

Thanks
Laszlo

> +
> +EFI_STATUS
> +EFIAPI
> +LsiScsiControllerStart (
> +  IN EFI_DRIVER_BINDING_PROTOCOL *This,
> +  IN EFI_HANDLE                  ControllerHandle,
> +  IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath OPTIONAL
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +LsiScsiControllerStop (
> +  IN EFI_DRIVER_BINDING_PROTOCOL *This,
> +  IN EFI_HANDLE                  ControllerHandle,
> +  IN UINTN                       NumberOfChildren,
> +  IN EFI_HANDLE                  *ChildHandleBuffer
> +  );
> +
> +#endif // _LSI_SCSI_DXE_H_
> diff --git a/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf b/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> index 55b483c2fa20..444ceb78e9ca 100644
> --- a/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> +++ b/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> @@ -18,9 +18,11 @@ [Defines]
>  
>  [Sources]
>    LsiScsi.c
> +  LsiScsi.h
>  
>  [Packages]
>    MdePkg/MdePkg.dec
>  
>  [LibraryClasses]
>    UefiDriverEntryPoint
> +  UefiLib
> 


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 03/11] OvmfPkg/LsiScsiDxe: Report the name of the driver
  2020-07-01  4:04 ` [PATCH 03/11] OvmfPkg/LsiScsiDxe: Report the name of the driver Gary Lin
@ 2020-07-07  8:09   ` Laszlo Ersek
  0 siblings, 0 replies; 35+ messages in thread
From: Laszlo Ersek @ 2020-07-07  8:09 UTC (permalink / raw)
  To: Gary Lin, devel; +Cc: Jordan Justen, Ard Biesheuvel

On 07/01/20 06:04, Gary Lin wrote:
> Implement LsiScsiGetDriverName() and LsiScsiGetDeviceName()
> to report the name of the driver.
> 
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
> Signed-off-by: Gary Lin <glin@suse.com>
> ---
>  OvmfPkg/LsiScsiDxe/LsiScsi.c | 69 ++++++++++++++++++++++++++++++++++--
>  OvmfPkg/LsiScsiDxe/LsiScsi.h | 31 ++++++++++++++++
>  2 files changed, 98 insertions(+), 2 deletions(-)
> 
> diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.c b/OvmfPkg/LsiScsiDxe/LsiScsi.c
> index 79a2af4fee73..62daa3ab99bf 100644
> --- a/OvmfPkg/LsiScsiDxe/LsiScsi.c
> +++ b/OvmfPkg/LsiScsiDxe/LsiScsi.c
> @@ -74,6 +74,71 @@ EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {
>  };
>  
>  
> +//
> +// The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and
> +// EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name
> +// in English, for display on standard console devices. This is recommended for
> +// UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's
> +// Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.
> +//
> +// Device type names ("LSI 53C895A SCSI Controller") are not formatted because
> +// the driver supports only that device type. Therefore the driver name
> +// suffices for unambiguous identification.
> +//
> +
> +STATIC
> +EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {
> +  { "eng;en", L"LSI 53C895A SCSI Controller Driver" },
> +  { NULL,     NULL                                  }
> +};
> +
> +STATIC
> +EFI_COMPONENT_NAME_PROTOCOL gComponentName;
> +
> +EFI_STATUS
> +EFIAPI
> +LsiScsiGetDriverName (
> +  IN  EFI_COMPONENT_NAME_PROTOCOL *This,
> +  IN  CHAR8                       *Language,
> +  OUT CHAR16                      **DriverName
> +  )
> +{
> +  return LookupUnicodeString2 (
> +           Language,
> +           This->SupportedLanguages,
> +           mDriverNameTable,
> +           DriverName,
> +           (BOOLEAN)(This == &gComponentName) // Iso639Language
> +           );
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +LsiScsiGetDeviceName (
> +  IN  EFI_COMPONENT_NAME_PROTOCOL *This,
> +  IN  EFI_HANDLE                  DeviceHandle,
> +  IN  EFI_HANDLE                  ChildHandle,
> +  IN  CHAR8                       *Language,
> +  OUT CHAR16                      **ControllerName
> +  )
> +{
> +  return EFI_UNSUPPORTED;
> +}
> +
> +STATIC
> +EFI_COMPONENT_NAME_PROTOCOL gComponentName = {
> +  &LsiScsiGetDriverName,
> +  &LsiScsiGetDeviceName,
> +  "eng" // SupportedLanguages, ISO 639-2 language codes
> +};
> +
> +STATIC
> +EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = {
> +  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)     &LsiScsiGetDriverName,
> +  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) &LsiScsiGetDeviceName,
> +  "en" // SupportedLanguages, RFC 4646 language codes
> +};
> +
>  //
>  // Entry point of this driver
>  //
> @@ -89,7 +154,7 @@ LsiScsiEntryPoint (
>             SystemTable,
>             &gDriverBinding,
>             ImageHandle, // The handle to install onto
> -           NULL, // TODO Component name
> -           NULL  // TODO Component name
> +           &gComponentName,
> +           &gComponentName2
>             );
>  }
> diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.h b/OvmfPkg/LsiScsiDxe/LsiScsi.h
> index 17738442fd5f..00db9ada12d2 100644
> --- a/OvmfPkg/LsiScsiDxe/LsiScsi.h
> +++ b/OvmfPkg/LsiScsiDxe/LsiScsi.h
> @@ -47,4 +47,35 @@ LsiScsiControllerStop (
>    IN EFI_HANDLE                  *ChildHandleBuffer
>    );
>  
> +
> +//
> +// The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and
> +// EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name
> +// in English, for display on standard console devices. This is recommended for
> +// UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's
> +// Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.
> +//
> +// Device type names ("LSI 53C895A SCSI Controller") are not formatted because
> +// the driver supports only that device type. Therefore the driver name
> +// suffices for unambiguous identification.
> +//
> +
> +EFI_STATUS
> +EFIAPI
> +LsiScsiGetDriverName (
> +  IN  EFI_COMPONENT_NAME_PROTOCOL *This,
> +  IN  CHAR8                       *Language,
> +  OUT CHAR16                      **DriverName
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +LsiScsiGetDeviceName (
> +  IN  EFI_COMPONENT_NAME_PROTOCOL *This,
> +  IN  EFI_HANDLE                  DeviceHandle,
> +  IN  EFI_HANDLE                  ChildHandle,
> +  IN  CHAR8                       *Language,
> +  OUT CHAR16                      **ControllerName
> +  );
> +
>  #endif // _LSI_SCSI_DXE_H_
> 

Reviewed-by: Laszlo Ersek <lersek@redhat.com>


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 04/11] OvmfPkg/LsiScsiDxe: Probe PCI devices and look for LsiScsi
  2020-07-01  4:04 ` [PATCH 04/11] OvmfPkg/LsiScsiDxe: Probe PCI devices and look for LsiScsi Gary Lin
@ 2020-07-07  8:15   ` Laszlo Ersek
  2020-07-07  8:16     ` Laszlo Ersek
  0 siblings, 1 reply; 35+ messages in thread
From: Laszlo Ersek @ 2020-07-07  8:15 UTC (permalink / raw)
  To: Gary Lin, devel; +Cc: Jordan Justen, Ard Biesheuvel

On 07/01/20 06:04, Gary Lin wrote:
> Implement LsiScsiControllerSupported() to probe the PCI ID and look for
> LSI 53C895A.
> 
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
> Signed-off-by: Gary Lin <glin@suse.com>
> ---
>  OvmfPkg/Include/IndustryStandard/LsiScsi.h | 20 +++++++++
>  OvmfPkg/LsiScsiDxe/LsiScsi.c               | 48 +++++++++++++++++++++-
>  OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf          |  6 +++
>  3 files changed, 73 insertions(+), 1 deletion(-)
>  create mode 100644 OvmfPkg/Include/IndustryStandard/LsiScsi.h
> 
> diff --git a/OvmfPkg/Include/IndustryStandard/LsiScsi.h b/OvmfPkg/Include/IndustryStandard/LsiScsi.h
> new file mode 100644
> index 000000000000..c09e864a1f39
> --- /dev/null
> +++ b/OvmfPkg/Include/IndustryStandard/LsiScsi.h
> @@ -0,0 +1,20 @@
> +/** @file
> +
> +  Macros and type definitions for LSI 53C895A SCSI devices.
> +
> +  Copyright (C) 2020, SUSE LLC.
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef _LSI_SCSI_H_
> +#define _LSI_SCSI_H_
> +
> +//
> +// Device ID
> +//
> +#define LSI_LOGIC_PCI_VENDOR_ID   0x1000
> +#define LSI_53C895A_PCI_DEVICE_ID 0x0012
> +
> +#endif // _LSI_SCSI_H_
> diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.c b/OvmfPkg/LsiScsiDxe/LsiScsi.c
> index 62daa3ab99bf..5bca85bd75eb 100644
> --- a/OvmfPkg/LsiScsiDxe/LsiScsi.c
> +++ b/OvmfPkg/LsiScsiDxe/LsiScsi.c
> @@ -9,7 +9,12 @@
>  
>  **/
>  
> +#include <IndustryStandard/LsiScsi.h>
> +#include <IndustryStandard/Pci.h>
> +#include <Library/UefiBootServicesTableLib.h>
>  #include <Library/UefiLib.h>
> +#include <Protocol/PciIo.h>
> +#include <Protocol/PciRootBridgeIo.h>
>  #include <Uefi/UefiSpec.h>
>  
>  #include "LsiScsi.h"
> @@ -31,7 +36,48 @@ LsiScsiControllerSupported (
>    IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath OPTIONAL
>    )
>  {
> -  return EFI_UNSUPPORTED;
> +  EFI_STATUS          Status;
> +  EFI_PCI_IO_PROTOCOL *PciIo;
> +  PCI_TYPE00          Pci;
> +
> +  Status = gBS->OpenProtocol (
> +                  ControllerHandle,
> +                  &gEfiPciIoProtocolGuid,
> +                  (VOID **)&PciIo,
> +                  This->DriverBindingHandle,
> +                  ControllerHandle,
> +                  EFI_OPEN_PROTOCOL_BY_DRIVER
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  Status = PciIo->Pci.Read (
> +                        PciIo,
> +                        EfiPciIoWidthUint32,
> +                        0,
> +                        sizeof (Pci) / sizeof (UINT32),
> +                        &Pci
> +                        );
> +  if (EFI_ERROR (Status)) {
> +    goto Done;
> +  }
> +
> +  if (Pci.Hdr.VendorId == LSI_LOGIC_PCI_VENDOR_ID &&
> +      Pci.Hdr.DeviceId == LSI_53C895A_PCI_DEVICE_ID) {
> +    Status = EFI_SUCCESS;
> +  } else {
> +    Status = EFI_UNSUPPORTED;
> +  }
> +
> +Done:
> +  gBS->CloseProtocol (
> +         ControllerHandle,
> +         &gEfiPciIoProtocolGuid,
> +         This->DriverBindingHandle,
> +         ControllerHandle
> +         );
> +  return Status;
>  }
>  
>  EFI_STATUS
> diff --git a/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf b/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> index 444ceb78e9ca..e86c626a61aa 100644
> --- a/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> +++ b/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> @@ -22,7 +22,13 @@ [Sources]
>  
>  [Packages]
>    MdePkg/MdePkg.dec
> +  OvmfPkg/OvmfPkg.dec
>  
>  [LibraryClasses]
> +  BaseLib
> +  UefiBootServicesTableLib
>    UefiDriverEntryPoint
>    UefiLib
> +
> +[Protocols]
> +  gEfiPciIoProtocolGuid                  ## TO_START
> 

Reviewed-by: Laszlo Ersek <lersek@redhat.com>


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 04/11] OvmfPkg/LsiScsiDxe: Probe PCI devices and look for LsiScsi
  2020-07-07  8:15   ` Laszlo Ersek
@ 2020-07-07  8:16     ` Laszlo Ersek
  0 siblings, 0 replies; 35+ messages in thread
From: Laszlo Ersek @ 2020-07-07  8:16 UTC (permalink / raw)
  To: Gary Lin, devel; +Cc: Jordan Justen, Ard Biesheuvel

On 07/07/20 10:15, Laszlo Ersek wrote:
> On 07/01/20 06:04, Gary Lin wrote:
>> Implement LsiScsiControllerSupported() to probe the PCI ID and look for
>> LSI 53C895A.
>>
>> Cc: Jordan Justen <jordan.l.justen@intel.com>
>> Cc: Laszlo Ersek <lersek@redhat.com>
>> Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
>> Signed-off-by: Gary Lin <glin@suse.com>
>> ---
>>  OvmfPkg/Include/IndustryStandard/LsiScsi.h | 20 +++++++++
>>  OvmfPkg/LsiScsiDxe/LsiScsi.c               | 48 +++++++++++++++++++++-
>>  OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf          |  6 +++
>>  3 files changed, 73 insertions(+), 1 deletion(-)
>>  create mode 100644 OvmfPkg/Include/IndustryStandard/LsiScsi.h
>>
>> diff --git a/OvmfPkg/Include/IndustryStandard/LsiScsi.h b/OvmfPkg/Include/IndustryStandard/LsiScsi.h
>> new file mode 100644
>> index 000000000000..c09e864a1f39
>> --- /dev/null
>> +++ b/OvmfPkg/Include/IndustryStandard/LsiScsi.h
>> @@ -0,0 +1,20 @@
>> +/** @file
>> +
>> +  Macros and type definitions for LSI 53C895A SCSI devices.
>> +
>> +  Copyright (C) 2020, SUSE LLC.
>> +
>> +  SPDX-License-Identifier: BSD-2-Clause-Patent
>> +
>> +**/
>> +
>> +#ifndef _LSI_SCSI_H_
>> +#define _LSI_SCSI_H_
>> +
>> +//
>> +// Device ID
>> +//
>> +#define LSI_LOGIC_PCI_VENDOR_ID   0x1000
>> +#define LSI_53C895A_PCI_DEVICE_ID 0x0012
>> +
>> +#endif // _LSI_SCSI_H_
>> diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.c b/OvmfPkg/LsiScsiDxe/LsiScsi.c
>> index 62daa3ab99bf..5bca85bd75eb 100644
>> --- a/OvmfPkg/LsiScsiDxe/LsiScsi.c
>> +++ b/OvmfPkg/LsiScsiDxe/LsiScsi.c
>> @@ -9,7 +9,12 @@
>>  
>>  **/
>>  
>> +#include <IndustryStandard/LsiScsi.h>
>> +#include <IndustryStandard/Pci.h>
>> +#include <Library/UefiBootServicesTableLib.h>
>>  #include <Library/UefiLib.h>
>> +#include <Protocol/PciIo.h>
>> +#include <Protocol/PciRootBridgeIo.h>
>>  #include <Uefi/UefiSpec.h>
>>  
>>  #include "LsiScsi.h"
>> @@ -31,7 +36,48 @@ LsiScsiControllerSupported (
>>    IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath OPTIONAL
>>    )
>>  {
>> -  return EFI_UNSUPPORTED;
>> +  EFI_STATUS          Status;
>> +  EFI_PCI_IO_PROTOCOL *PciIo;
>> +  PCI_TYPE00          Pci;
>> +
>> +  Status = gBS->OpenProtocol (
>> +                  ControllerHandle,
>> +                  &gEfiPciIoProtocolGuid,
>> +                  (VOID **)&PciIo,
>> +                  This->DriverBindingHandle,
>> +                  ControllerHandle,
>> +                  EFI_OPEN_PROTOCOL_BY_DRIVER
>> +                  );
>> +  if (EFI_ERROR (Status)) {
>> +    return Status;
>> +  }
>> +
>> +  Status = PciIo->Pci.Read (
>> +                        PciIo,
>> +                        EfiPciIoWidthUint32,
>> +                        0,
>> +                        sizeof (Pci) / sizeof (UINT32),
>> +                        &Pci
>> +                        );
>> +  if (EFI_ERROR (Status)) {
>> +    goto Done;
>> +  }
>> +
>> +  if (Pci.Hdr.VendorId == LSI_LOGIC_PCI_VENDOR_ID &&
>> +      Pci.Hdr.DeviceId == LSI_53C895A_PCI_DEVICE_ID) {
>> +    Status = EFI_SUCCESS;
>> +  } else {
>> +    Status = EFI_UNSUPPORTED;
>> +  }
>> +
>> +Done:
>> +  gBS->CloseProtocol (
>> +         ControllerHandle,
>> +         &gEfiPciIoProtocolGuid,
>> +         This->DriverBindingHandle,
>> +         ControllerHandle
>> +         );
>> +  return Status;
>>  }
>>  
>>  EFI_STATUS
>> diff --git a/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf b/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
>> index 444ceb78e9ca..e86c626a61aa 100644
>> --- a/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
>> +++ b/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
>> @@ -22,7 +22,13 @@ [Sources]
>>  
>>  [Packages]
>>    MdePkg/MdePkg.dec
>> +  OvmfPkg/OvmfPkg.dec
>>  
>>  [LibraryClasses]
>> +  BaseLib
>> +  UefiBootServicesTableLib
>>    UefiDriverEntryPoint
>>    UefiLib
>> +
>> +[Protocols]
>> +  gEfiPciIoProtocolGuid                  ## TO_START
>>
> 
> Reviewed-by: Laszlo Ersek <lersek@redhat.com>
> 

(I've checked PCI_VENDOR_ID_LSI_LOGIC in QEMU's
"include/hw/pci/pci_ids.h" and "hw/scsi/lsi53c895a.c". Also checked
PCI_DEVICE_ID_LSI_53C895A in the QEMU source.)


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 01/11] OvmfPkg/LsiScsiDxe: Create the empty driver
  2020-07-07  7:59   ` Laszlo Ersek
@ 2020-07-07  8:24     ` Gary Lin
  0 siblings, 0 replies; 35+ messages in thread
From: Gary Lin @ 2020-07-07  8:24 UTC (permalink / raw)
  To: Laszlo Ersek; +Cc: devel, Jordan Justen, Ard Biesheuvel

On Tue, Jul 07, 2020 at 09:59:04AM +0200, Laszlo Ersek wrote:
> On 07/01/20 06:04, Gary Lin wrote:
> > Create the driver with only a dummy LsiScsiEntryPoint() for the further
> > implementation of the driver for LSI 53C895A SCSI controller.
> > 
> > Cc: Jordan Justen <jordan.l.justen@intel.com>
> > Cc: Laszlo Ersek <lersek@redhat.com>
> > Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
> > Signed-off-by: Gary Lin <glin@suse.com>
> > ---
> >  OvmfPkg/LsiScsiDxe/LsiScsi.c      | 25 +++++++++++++++++++++++++
> >  OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf | 26 ++++++++++++++++++++++++++
> >  OvmfPkg/OvmfPkgIa32.dsc           |  4 ++++
> >  OvmfPkg/OvmfPkgIa32.fdf           |  3 +++
> >  OvmfPkg/OvmfPkgIa32X64.dsc        |  4 ++++
> >  OvmfPkg/OvmfPkgIa32X64.fdf        |  3 +++
> >  OvmfPkg/OvmfPkgX64.dsc            |  4 ++++
> >  OvmfPkg/OvmfPkgX64.fdf            |  3 +++
> >  8 files changed, 72 insertions(+)
> >  create mode 100644 OvmfPkg/LsiScsiDxe/LsiScsi.c
> >  create mode 100644 OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> > 
> > diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.c b/OvmfPkg/LsiScsiDxe/LsiScsi.c
> > new file mode 100644
> > index 000000000000..9c90941688ed
> > --- /dev/null
> > +++ b/OvmfPkg/LsiScsiDxe/LsiScsi.c
> > @@ -0,0 +1,25 @@
> > +/** @file
> > +
> > +  This driver produces Extended SCSI Pass Thru Protocol instances for
> > +  LSI 53C895A SCSI devices.
> > +
> > +  Copyright (C) 2020, SUSE LLC.
> > +
> > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#include <Uefi/UefiSpec.h>
> > +
> > +//
> > +// Entry point of this driver
> > +//
> > +EFI_STATUS
> > +EFIAPI
> > +LsiScsiEntryPoint (
> > +  IN EFI_HANDLE       ImageHandle,
> > +  IN EFI_SYSTEM_TABLE *SystemTable
> > +  )
> > +{
> > +  return EFI_UNSUPPORTED;
> > +}
> > diff --git a/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf b/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> > new file mode 100644
> > index 000000000000..55b483c2fa20
> > --- /dev/null
> > +++ b/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> > @@ -0,0 +1,26 @@
> > +## @file
> > +# This driver produces Extended SCSI Pass Thru Protocol instances for
> > +# LSI 53C895A SCSI devices.
> > +#
> > +# Copyright (C) 2020, SUSE LLC.
> > +#
> > +# SPDX-License-Identifier: BSD-2-Clause-Patent
> > +#
> > +##
> > +
> > +[Defines]
> > +  INF_VERSION                    = 1.29
> > +  BASE_NAME                      = LsiScsiDxe
> > +  FILE_GUID                      = EB4EB21f-5A3D-40BE-8BD2-F1B0E38E5744
> 
> (1) The GUID should not be written in mixed case. Please pick upper case
> or lower case for the whole GUID string.
> 
> (I wonder how you created the current (mixed-case) GUID string...
> uuidgen outputs lower case, and I wonder how one can translate
> everything except the *first* "f" from that to upper case. I hope you
> didn't manually update a previously generated GUID!)
Oops, I generated the GUID with uuidgen and converted it to upper case
manually (facepalm). Will fix it.

Gary Lin

> 
> with the spelling fixed, or the GUID regenerated:
> 
> Reviewed-by: Laszlo Ersek <lersek@redhat.com>
> 
> Thanks
> Laszlo
> 
> > +  MODULE_TYPE                    = UEFI_DRIVER
> > +  VERSION_STRING                 = 1.0
> > +  ENTRY_POINT                    = LsiScsiEntryPoint
> > +
> > +[Sources]
> > +  LsiScsi.c
> > +
> > +[Packages]
> > +  MdePkg/MdePkg.dec
> > +
> > +[LibraryClasses]
> > +  UefiDriverEntryPoint
> > diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
> > index b4ee7376791b..9178ffeb71cb 100644
> > --- a/OvmfPkg/OvmfPkgIa32.dsc
> > +++ b/OvmfPkg/OvmfPkgIa32.dsc
> > @@ -50,6 +50,7 @@ [Defines]
> >    #
> >    DEFINE PVSCSI_ENABLE           = TRUE
> >    DEFINE MPT_SCSI_ENABLE         = TRUE
> > +  DEFINE LSI_SCSI_ENABLE         = FALSE
> >  
> >    #
> >    # Flash size selection. Setting FD_SIZE_IN_KB on the command line directly to
> > @@ -771,6 +772,9 @@ [Components]
> >  !endif
> >  !if $(MPT_SCSI_ENABLE) == TRUE
> >    OvmfPkg/MptScsiDxe/MptScsiDxe.inf
> > +!endif
> > +!if $(LSI_SCSI_ENABLE) == TRUE
> > +  OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> >  !endif
> >    MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
> >    MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
> > diff --git a/OvmfPkg/OvmfPkgIa32.fdf b/OvmfPkg/OvmfPkgIa32.fdf
> > index e2b759aa8d05..2b9a6b58015f 100644
> > --- a/OvmfPkg/OvmfPkgIa32.fdf
> > +++ b/OvmfPkg/OvmfPkgIa32.fdf
> > @@ -236,6 +236,9 @@ [FV.DXEFV]
> >  !if $(MPT_SCSI_ENABLE) == TRUE
> >  INF  OvmfPkg/MptScsiDxe/MptScsiDxe.inf
> >  !endif
> > +!if $(LSI_SCSI_ENABLE) == TRUE
> > +INF  OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> > +!endif
> >  
> >  !if $(SECURE_BOOT_ENABLE) == TRUE
> >    INF  SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
> > diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
> > index ed68b080f2a2..a665f78f0dc7 100644
> > --- a/OvmfPkg/OvmfPkgIa32X64.dsc
> > +++ b/OvmfPkg/OvmfPkgIa32X64.dsc
> > @@ -49,6 +49,7 @@ [Defines]
> >    #
> >    DEFINE PVSCSI_ENABLE           = TRUE
> >    DEFINE MPT_SCSI_ENABLE         = TRUE
> > +  DEFINE LSI_SCSI_ENABLE         = FALSE
> >  
> >    #
> >    # Flash size selection. Setting FD_SIZE_IN_KB on the command line directly to
> > @@ -785,6 +786,9 @@ [Components.X64]
> >  !endif
> >  !if $(MPT_SCSI_ENABLE) == TRUE
> >    OvmfPkg/MptScsiDxe/MptScsiDxe.inf
> > +!endif
> > +!if $(LSI_SCSI_ENABLE) == TRUE
> > +  OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> >  !endif
> >    MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
> >    MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
> > diff --git a/OvmfPkg/OvmfPkgIa32X64.fdf b/OvmfPkg/OvmfPkgIa32X64.fdf
> > index bfca1eff9e83..83ff6aef2e8c 100644
> > --- a/OvmfPkg/OvmfPkgIa32X64.fdf
> > +++ b/OvmfPkg/OvmfPkgIa32X64.fdf
> > @@ -237,6 +237,9 @@ [FV.DXEFV]
> >  !if $(MPT_SCSI_ENABLE) == TRUE
> >  INF  OvmfPkg/MptScsiDxe/MptScsiDxe.inf
> >  !endif
> > +!if $(LSI_SCSI_ENABLE) == TRUE
> > +INF  OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> > +!endif
> >  
> >  !if $(SECURE_BOOT_ENABLE) == TRUE
> >    INF  SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
> > diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
> > index cb7e8068a3d8..17f345acf4ee 100644
> > --- a/OvmfPkg/OvmfPkgX64.dsc
> > +++ b/OvmfPkg/OvmfPkgX64.dsc
> > @@ -49,6 +49,7 @@ [Defines]
> >    #
> >    DEFINE PVSCSI_ENABLE           = TRUE
> >    DEFINE MPT_SCSI_ENABLE         = TRUE
> > +  DEFINE LSI_SCSI_ENABLE         = FALSE
> >  
> >    #
> >    # Flash size selection. Setting FD_SIZE_IN_KB on the command line directly to
> > @@ -781,6 +782,9 @@ [Components]
> >  !endif
> >  !if $(MPT_SCSI_ENABLE) == TRUE
> >    OvmfPkg/MptScsiDxe/MptScsiDxe.inf
> > +!endif
> > +!if $(LSI_SCSI_ENABLE) == TRUE
> > +  OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> >  !endif
> >    MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
> >    MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
> > diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
> > index bfca1eff9e83..83ff6aef2e8c 100644
> > --- a/OvmfPkg/OvmfPkgX64.fdf
> > +++ b/OvmfPkg/OvmfPkgX64.fdf
> > @@ -237,6 +237,9 @@ [FV.DXEFV]
> >  !if $(MPT_SCSI_ENABLE) == TRUE
> >  INF  OvmfPkg/MptScsiDxe/MptScsiDxe.inf
> >  !endif
> > +!if $(LSI_SCSI_ENABLE) == TRUE
> > +INF  OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> > +!endif
> >  
> >  !if $(SECURE_BOOT_ENABLE) == TRUE
> >    INF  SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
> > 
> 


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 05/11] OvmfPkg/LsiScsiDxe: Install stubbed EXT_SCSI_PASS_THRU
  2020-07-01  4:04 ` [PATCH 05/11] OvmfPkg/LsiScsiDxe: Install stubbed EXT_SCSI_PASS_THRU Gary Lin
@ 2020-07-07  8:28   ` Laszlo Ersek
  0 siblings, 0 replies; 35+ messages in thread
From: Laszlo Ersek @ 2020-07-07  8:28 UTC (permalink / raw)
  To: Gary Lin, devel; +Cc: Jordan Justen, Ard Biesheuvel

On 07/01/20 06:04, Gary Lin wrote:
> Partially implement LsiScsiControllerStart() and LsiScsiControllerStop()
> to insert the scaffolding of EXT_SCSI_PASS_THRU functions.
> 
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
> Signed-off-by: Gary Lin <glin@suse.com>
> ---
>  OvmfPkg/LsiScsiDxe/LsiScsi.c      | 171 +++++++++++++++++++++++++++++-
>  OvmfPkg/LsiScsiDxe/LsiScsi.h      |  77 ++++++++++++++
>  OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf |   3 +
>  3 files changed, 250 insertions(+), 1 deletion(-)
> 
> diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.c b/OvmfPkg/LsiScsiDxe/LsiScsi.c
> index 5bca85bd75eb..f633c6793298 100644
> --- a/OvmfPkg/LsiScsiDxe/LsiScsi.c
> +++ b/OvmfPkg/LsiScsiDxe/LsiScsi.c
> @@ -11,14 +11,105 @@
>  
>  #include <IndustryStandard/LsiScsi.h>
>  #include <IndustryStandard/Pci.h>
> +#include <Library/BaseLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/MemoryAllocationLib.h>
>  #include <Library/UefiBootServicesTableLib.h>
>  #include <Library/UefiLib.h>
>  #include <Protocol/PciIo.h>
>  #include <Protocol/PciRootBridgeIo.h>
> +#include <Protocol/ScsiPassThruExt.h>
>  #include <Uefi/UefiSpec.h>
>  
>  #include "LsiScsi.h"
>  
> +//
> +// The next seven functions implement EFI_EXT_SCSI_PASS_THRU_PROTOCOL
> +// for the LSI 53C895A SCSI Controller. Refer to UEFI Spec 2.3.1 + Errata C,
> +// sections
> +// - 14.1 SCSI Driver Model Overview,
> +// - 14.7 Extended SCSI Pass Thru Protocol.
> +//
> +
> +EFI_STATUS
> +EFIAPI
> +LsiScsiPassThru (
> +  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL                *This,
> +  IN UINT8                                          *Target,
> +  IN UINT64                                         Lun,
> +  IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,
> +  IN EFI_EVENT                                      Event     OPTIONAL
> +  )
> +{
> +  return EFI_UNSUPPORTED;
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +LsiScsiGetNextTargetLun (
> +  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
> +  IN OUT UINT8                       **TargetPointer,
> +  IN OUT UINT64                      *Lun
> +  )
> +{
> +  return EFI_NOT_FOUND;
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +LsiScsiBuildDevicePath (
> +  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
> +  IN UINT8                           *Target,
> +  IN UINT64                          Lun,
> +  IN OUT EFI_DEVICE_PATH_PROTOCOL    **DevicePath
> +  )
> +{
> +  return EFI_NOT_FOUND;
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +LsiScsiGetTargetLun (
> +  IN  EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
> +  IN  EFI_DEVICE_PATH_PROTOCOL        *DevicePath,
> +  OUT UINT8                           **TargetPointer,
> +  OUT UINT64                          *Lun
> +  )
> +{
> +  return EFI_UNSUPPORTED;
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +LsiScsiResetChannel (
> +  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This
> +  )
> +{
> +  return EFI_UNSUPPORTED;
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +LsiScsiResetTargetLun (
> +  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
> +  IN UINT8                           *Target,
> +  IN UINT64                          Lun
> +  )
> +{
> +  return EFI_UNSUPPORTED;
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +LsiScsiGetNextTarget (
> +  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
> +  IN OUT UINT8                       **TargetPointer
> +  )
> +{
> +  return EFI_NOT_FOUND;
> +}
> +
>  //
>  // Probe, start and stop functions of this driver, called by the DXE core for
>  // specific devices.
> @@ -88,7 +179,49 @@ LsiScsiControllerStart (
>    IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath OPTIONAL
>    )
>  {
> +  EFI_STATUS           Status;
> +  LSI_SCSI_DEV         *Dev;
> +
> +  Dev = AllocateZeroPool (sizeof (*Dev));
> +  if (Dev == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  Dev->Signature = LSI_SCSI_DEV_SIGNATURE;
> +
> +  //
> +  // Host adapter channel, doesn't exist
> +  //
> +  Dev->PassThruMode.AdapterId = MAX_UINT32;
> +  Dev->PassThruMode.Attributes =
> +    EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL |
> +    EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL;
> +
> +  Dev->PassThru.Mode = &Dev->PassThruMode;
> +  Dev->PassThru.PassThru = &LsiScsiPassThru;
> +  Dev->PassThru.GetNextTargetLun = &LsiScsiGetNextTargetLun;
> +  Dev->PassThru.BuildDevicePath = &LsiScsiBuildDevicePath;
> +  Dev->PassThru.GetTargetLun = &LsiScsiGetTargetLun;
> +  Dev->PassThru.ResetChannel = &LsiScsiResetChannel;
> +  Dev->PassThru.ResetTargetLun = &LsiScsiResetTargetLun;
> +  Dev->PassThru.GetNextTarget = &LsiScsiGetNextTarget;
> +
> +  Status = gBS->InstallProtocolInterface (
> +                  &ControllerHandle,
> +                  &gEfiExtScsiPassThruProtocolGuid,
> +                  EFI_NATIVE_INTERFACE,
> +                  &Dev->PassThru
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    goto FreePool;
> +  }
> +
>    return EFI_SUCCESS;
> +
> +FreePool:
> +  FreePool (Dev);
> +
> +  return Status;
>  }
>  
>  EFI_STATUS
> @@ -100,7 +233,43 @@ LsiScsiControllerStop (
>    IN EFI_HANDLE                  *ChildHandleBuffer
>    )
>  {
> -  return EFI_SUCCESS;
> +  EFI_STATUS                      Status;
> +  EFI_EXT_SCSI_PASS_THRU_PROTOCOL *PassThru;
> +  LSI_SCSI_DEV                    *Dev;
> +
> +  Status = gBS->OpenProtocol (
> +                  ControllerHandle,
> +                  &gEfiExtScsiPassThruProtocolGuid,
> +                  (VOID **)&PassThru,
> +                  This->DriverBindingHandle,
> +                  ControllerHandle,
> +                  EFI_OPEN_PROTOCOL_GET_PROTOCOL // Lookup only
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  Dev = LSI_SCSI_FROM_PASS_THRU (PassThru);
> +
> +  Status = gBS->UninstallProtocolInterface (
> +                  ControllerHandle,
> +                  &gEfiExtScsiPassThruProtocolGuid,
> +                  &Dev->PassThru
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  gBS->CloseProtocol (
> +         ControllerHandle,
> +         &gEfiPciIoProtocolGuid,
> +         This->DriverBindingHandle,
> +         ControllerHandle
> +         );

(1) This CloseProtocol() call does not belong in this patch. In this
patch, the Start() function doesn't open the PCI IO protocol yet. Please
move the CloseProtocol() call to the following patch:

  [PATCH 07/11]
  OvmfPkg/LsiScsiDxe: Open PciIo protocol and initialize the device

with that:

Reviewed-by: Laszlo Ersek <lersek@redhat.com>

Thanks
Laszlo


> +
> +  FreePool (Dev);
> +
> +  return Status;
>  }
>  
>  //
> diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.h b/OvmfPkg/LsiScsiDxe/LsiScsi.h
> index 00db9ada12d2..fca1007f9b98 100644
> --- a/OvmfPkg/LsiScsiDxe/LsiScsi.h
> +++ b/OvmfPkg/LsiScsiDxe/LsiScsi.h
> @@ -12,6 +12,17 @@
>  #ifndef _LSI_SCSI_DXE_H_
>  #define _LSI_SCSI_DXE_H_
>  
> +typedef struct {
> +  UINT32                          Signature;
> +  EFI_EXT_SCSI_PASS_THRU_MODE     PassThruMode;
> +  EFI_EXT_SCSI_PASS_THRU_PROTOCOL PassThru;
> +} LSI_SCSI_DEV;
> +
> +#define LSI_SCSI_DEV_SIGNATURE SIGNATURE_32 ('L','S','I','S')
> +
> +#define LSI_SCSI_FROM_PASS_THRU(PassThruPtr) \
> +  CR (PassThruPtr, LSI_SCSI_DEV, PassThru, LSI_SCSI_DEV_SIGNATURE)
> +
>  //
>  // Probe, start and stop functions of this driver, called by the DXE core for
>  // specific devices.
> @@ -48,6 +59,72 @@ LsiScsiControllerStop (
>    );
>  
>  
> +//
> +// The next seven functions implement EFI_EXT_SCSI_PASS_THRU_PROTOCOL
> +// for the LSI 53C895A SCSI Controller. Refer to UEFI Spec 2.3.1 + Errata C,
> +// sections
> +// - 14.1 SCSI Driver Model Overview,
> +// - 14.7 Extended SCSI Pass Thru Protocol.
> +//
> +
> +EFI_STATUS
> +EFIAPI
> +LsiScsiPassThru (
> +  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL                *This,
> +  IN UINT8                                          *Target,
> +  IN UINT64                                         Lun,
> +  IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,
> +  IN EFI_EVENT                                      Event     OPTIONAL
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +LsiScsiGetNextTargetLun (
> +  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
> +  IN OUT UINT8                       **TargetPointer,
> +  IN OUT UINT64                      *Lun
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +LsiScsiBuildDevicePath (
> +  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
> +  IN UINT8                           *Target,
> +  IN UINT64                          Lun,
> +  IN OUT EFI_DEVICE_PATH_PROTOCOL    **DevicePath
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +LsiScsiGetTargetLun (
> +  IN  EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
> +  IN  EFI_DEVICE_PATH_PROTOCOL        *DevicePath,
> +  OUT UINT8                           **TargetPointer,
> +  OUT UINT64                          *Lun
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +LsiScsiResetChannel (
> +  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +LsiScsiResetTargetLun (
> +  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
> +  IN UINT8                           *Target,
> +  IN UINT64                          Lun
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +LsiScsiGetNextTarget (
> +  IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
> +  IN OUT UINT8                       **TargetPointer
> +  );
> +
> +
>  //
>  // The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and
>  // EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name
> diff --git a/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf b/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> index e86c626a61aa..8660513e2ffd 100644
> --- a/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> +++ b/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> @@ -26,9 +26,12 @@ [Packages]
>  
>  [LibraryClasses]
>    BaseLib
> +  BaseMemoryLib
> +  MemoryAllocationLib
>    UefiBootServicesTableLib
>    UefiDriverEntryPoint
>    UefiLib
>  
>  [Protocols]
> +  gEfiExtScsiPassThruProtocolGuid        ## BY_START
>    gEfiPciIoProtocolGuid                  ## TO_START
> 


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 02/11] OvmfPkg/LsiScsiDxe: Install the skeleton of driver binding
  2020-07-07  8:06   ` Laszlo Ersek
@ 2020-07-07  8:34     ` Gary Lin
  0 siblings, 0 replies; 35+ messages in thread
From: Gary Lin @ 2020-07-07  8:34 UTC (permalink / raw)
  To: Laszlo Ersek; +Cc: devel, Jordan Justen, Ard Biesheuvel

On Tue, Jul 07, 2020 at 10:06:59AM +0200, Laszlo Ersek wrote:
> On 07/01/20 06:04, Gary Lin wrote:
> > Implement the dummy functions for EFI Driver Binding protocol.
> > 
> > Cc: Jordan Justen <jordan.l.justen@intel.com>
> > Cc: Laszlo Ersek <lersek@redhat.com>
> > Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
> > Signed-off-by: Gary Lin <glin@suse.com>
> > ---
> >  OvmfPkg/LsiScsiDxe/LsiScsi.c      | 72 ++++++++++++++++++++++++++++++-
> >  OvmfPkg/LsiScsiDxe/LsiScsi.h      | 50 +++++++++++++++++++++
> >  OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf |  2 +
> >  3 files changed, 123 insertions(+), 1 deletion(-)
> >  create mode 100644 OvmfPkg/LsiScsiDxe/LsiScsi.h
> > 
> > diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.c b/OvmfPkg/LsiScsiDxe/LsiScsi.c
> > index 9c90941688ed..79a2af4fee73 100644
> > --- a/OvmfPkg/LsiScsiDxe/LsiScsi.c
> > +++ b/OvmfPkg/LsiScsiDxe/LsiScsi.c
> > @@ -9,8 +9,71 @@
> >  
> >  **/
> >  
> > +#include <Library/UefiLib.h>
> >  #include <Uefi/UefiSpec.h>
> >  
> > +#include "LsiScsi.h"
> > +
> > +//
> > +// Probe, start and stop functions of this driver, called by the DXE core for
> > +// specific devices.
> > +//
> > +// The following specifications document these interfaces:
> > +// - Driver Writer's Guide for UEFI 2.3.1 v1.01, 9 Driver Binding Protocol
> > +// - UEFI Spec 2.3.1 + Errata C, 10.1 EFI Driver Binding Protocol
> > +//
> > +
> > +EFI_STATUS
> > +EFIAPI
> > +LsiScsiControllerSupported (
> > +  IN EFI_DRIVER_BINDING_PROTOCOL *This,
> > +  IN EFI_HANDLE                  ControllerHandle,
> > +  IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath OPTIONAL
> > +  )
> > +{
> > +  return EFI_UNSUPPORTED;
> > +}
> > +
> > +EFI_STATUS
> > +EFIAPI
> > +LsiScsiControllerStart (
> > +  IN EFI_DRIVER_BINDING_PROTOCOL *This,
> > +  IN EFI_HANDLE                  ControllerHandle,
> > +  IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath OPTIONAL
> > +  )
> > +{
> > +  return EFI_SUCCESS;
> > +}
> > +
> > +EFI_STATUS
> > +EFIAPI
> > +LsiScsiControllerStop (
> > +  IN EFI_DRIVER_BINDING_PROTOCOL *This,
> > +  IN EFI_HANDLE                  ControllerHandle,
> > +  IN UINTN                       NumberOfChildren,
> > +  IN EFI_HANDLE                  *ChildHandleBuffer
> > +  )
> > +{
> > +  return EFI_SUCCESS;
> > +}
> > +
> > +//
> > +// The static object that groups the Supported() (ie. probe), Start() and
> > +// Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata
> > +// C, 10.1 EFI Driver Binding Protocol.
> > +//
> > +STATIC
> > +EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {
> > +  &LsiScsiControllerSupported,
> > +  &LsiScsiControllerStart,
> > +  &LsiScsiControllerStop,
> > +  0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers
> > +  NULL, // ImageHandle, to be overwritten by
> > +        // EfiLibInstallDriverBindingComponentName2() in LsiScsiEntryPoint()
> > +  NULL  // DriverBindingHandle, ditto
> > +};
> > +
> > +
> >  //
> >  // Entry point of this driver
> >  //
> > @@ -21,5 +84,12 @@ LsiScsiEntryPoint (
> >    IN EFI_SYSTEM_TABLE *SystemTable
> >    )
> >  {
> > -  return EFI_UNSUPPORTED;
> > +  return EfiLibInstallDriverBindingComponentName2 (
> > +           ImageHandle,
> > +           SystemTable,
> > +           &gDriverBinding,
> > +           ImageHandle, // The handle to install onto
> > +           NULL, // TODO Component name
> > +           NULL  // TODO Component name
> > +           );
> >  }
> > diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.h b/OvmfPkg/LsiScsiDxe/LsiScsi.h
> > new file mode 100644
> > index 000000000000..17738442fd5f
> > --- /dev/null
> > +++ b/OvmfPkg/LsiScsiDxe/LsiScsi.h
> > @@ -0,0 +1,50 @@
> > +/** @file
> > +
> > +  Internal definitions for the LSI 53C895A SCSI driver, which produces
> > +  Extended SCSI Pass Thru Protocol instances for LSI 53C895A SCSI devices.
> > +
> > +  Copyright (C) 2020, SUSE LLC.
> > +
> > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#ifndef _LSI_SCSI_DXE_H_
> > +#define _LSI_SCSI_DXE_H_
> > +
> > +//
> > +// Probe, start and stop functions of this driver, called by the DXE core for
> > +// specific devices.
> > +//
> > +// The following specifications document these interfaces:
> > +// - Driver Writer's Guide for UEFI 2.3.1 v1.01, 9 Driver Binding Protocol
> > +// - UEFI Spec 2.3.1 + Errata C, 10.1 EFI Driver Binding Protocol
> > +//
> > +
> > +STATIC
> > +EFI_STATUS
> > +EFIAPI
> > +LsiScsiControllerSupported (
> > +  IN EFI_DRIVER_BINDING_PROTOCOL *This,
> > +  IN EFI_HANDLE                  ControllerHandle,
> > +  IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath OPTIONAL
> > +  );
> 
> (1) Please drop "STATIC", to be consistent with the definition of
> LsiScsiControllerSupported(), in the .c file.
> 
> (I think the patch is not invalid C as-is, but it's confusing for the
> reader.)
Urh, some copy-paste error when refactoring the code. Thanks for
catching it. Will fix it in v2.

Gary Lin

> 
> With that fixed
> 
> Reviewed-by: Laszlo Ersek <lersek@redhat.com>
> 
> Thanks
> Laszlo
> 
> > +
> > +EFI_STATUS
> > +EFIAPI
> > +LsiScsiControllerStart (
> > +  IN EFI_DRIVER_BINDING_PROTOCOL *This,
> > +  IN EFI_HANDLE                  ControllerHandle,
> > +  IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath OPTIONAL
> > +  );
> > +
> > +EFI_STATUS
> > +EFIAPI
> > +LsiScsiControllerStop (
> > +  IN EFI_DRIVER_BINDING_PROTOCOL *This,
> > +  IN EFI_HANDLE                  ControllerHandle,
> > +  IN UINTN                       NumberOfChildren,
> > +  IN EFI_HANDLE                  *ChildHandleBuffer
> > +  );
> > +
> > +#endif // _LSI_SCSI_DXE_H_
> > diff --git a/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf b/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> > index 55b483c2fa20..444ceb78e9ca 100644
> > --- a/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> > +++ b/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> > @@ -18,9 +18,11 @@ [Defines]
> >  
> >  [Sources]
> >    LsiScsi.c
> > +  LsiScsi.h
> >  
> >  [Packages]
> >    MdePkg/MdePkg.dec
> >  
> >  [LibraryClasses]
> >    UefiDriverEntryPoint
> > +  UefiLib
> > 
> 


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 06/11] OvmfPkg/LsiScsiDxe: Report Targets and LUNs
  2020-07-01  4:04 ` [PATCH 06/11] OvmfPkg/LsiScsiDxe: Report Targets and LUNs Gary Lin
@ 2020-07-07  9:04   ` Laszlo Ersek
  2020-07-08  2:34     ` Gary Lin
  0 siblings, 1 reply; 35+ messages in thread
From: Laszlo Ersek @ 2020-07-07  9:04 UTC (permalink / raw)
  To: Gary Lin, devel; +Cc: Jordan Justen, Ard Biesheuvel

On 07/01/20 06:04, Gary Lin wrote:
> Implement LsiScsiGetNextTargetLun(), LsiScsiBuildDevicePath(),
> LsiScsiGetTargetLun(), and LsiScsiGetNextTarget() to report Targets and
> LUNs and build the device path.
> 
> This commit also introduces two PCD value: PcdLsiScsiMaxTargetLimit and
> PcdLsiScsiMaxLunLimit as the limits for Targets and LUNs.
> 
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
> Signed-off-by: Gary Lin <glin@suse.com>
> ---
>  OvmfPkg/LsiScsiDxe/LsiScsi.c      | 143 +++++++++++++++++++++++++++++-
>  OvmfPkg/LsiScsiDxe/LsiScsi.h      |   3 +
>  OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf |   6 ++
>  OvmfPkg/OvmfPkg.dec               |   5 ++
>  4 files changed, 155 insertions(+), 2 deletions(-)
> 
> diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.c b/OvmfPkg/LsiScsiDxe/LsiScsi.c
> index f633c6793298..e10a81a5f9f7 100644
> --- a/OvmfPkg/LsiScsiDxe/LsiScsi.c
> +++ b/OvmfPkg/LsiScsiDxe/LsiScsi.c
> @@ -15,6 +15,7 @@
>  #include <Library/BaseMemoryLib.h>
>  #include <Library/DebugLib.h>
>  #include <Library/MemoryAllocationLib.h>
> +#include <Library/PcdLib.h>
>  #include <Library/UefiBootServicesTableLib.h>
>  #include <Library/UefiLib.h>
>  #include <Protocol/PciIo.h>
> @@ -53,6 +54,49 @@ LsiScsiGetNextTargetLun (
>    IN OUT UINT64                      *Lun
>    )
>  {
> +  LSI_SCSI_DEV *Dev;
> +  UINTN        Idx;
> +  UINT8        *Target;
> +  UINT16       LastTarget;
> +
> +  //
> +  // the TargetPointer input parameter is unnecessarily a pointer-to-pointer
> +  //
> +  Target = *TargetPointer;
> +
> +  //
> +  // Search for first non-0xFF byte. If not found, return first target & LUN.
> +  //
> +  for (Idx = 0; Idx < TARGET_MAX_BYTES && Target[Idx] == 0xFF; ++Idx)
> +    ;
> +  if (Idx == TARGET_MAX_BYTES) {
> +    SetMem (Target, TARGET_MAX_BYTES, 0x00);
> +    *Lun = 0;
> +    return EFI_SUCCESS;
> +  }
> +
> +  CopyMem (&LastTarget, Target, sizeof LastTarget);
> +
> +  //
> +  // increment (target, LUN) pair if valid on input
> +  //
> +  Dev = LSI_SCSI_FROM_PASS_THRU (This);
> +  if (LastTarget > Dev->MaxTarget || *Lun > Dev->MaxLun) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (*Lun < Dev->MaxLun) {
> +    ++*Lun;
> +    return EFI_SUCCESS;
> +  }
> +
> +  if (LastTarget < Dev->MaxTarget) {
> +    *Lun = 0;
> +    ++LastTarget;
> +    CopyMem (Target, &LastTarget, sizeof LastTarget);
> +    return EFI_SUCCESS;
> +  }
> +
>    return EFI_NOT_FOUND;
>  }
>  
> @@ -65,7 +109,34 @@ LsiScsiBuildDevicePath (
>    IN OUT EFI_DEVICE_PATH_PROTOCOL    **DevicePath
>    )
>  {
> -  return EFI_NOT_FOUND;
> +  UINT16           TargetValue;
> +  LSI_SCSI_DEV     *Dev;
> +  SCSI_DEVICE_PATH *ScsiDevicePath;
> +
> +  if (DevicePath == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  CopyMem (&TargetValue, Target, sizeof TargetValue);
> +  Dev = LSI_SCSI_FROM_PASS_THRU (This);
> +  if (TargetValue > Dev->MaxTarget || Lun > Dev->MaxLun || Lun > 0xFFFF) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  ScsiDevicePath = AllocatePool (sizeof *ScsiDevicePath);
> +  if (ScsiDevicePath == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  ScsiDevicePath->Header.Type      = MESSAGING_DEVICE_PATH;
> +  ScsiDevicePath->Header.SubType   = MSG_SCSI_DP;
> +  ScsiDevicePath->Header.Length[0] = (UINT8)  sizeof *ScsiDevicePath;
> +  ScsiDevicePath->Header.Length[1] = (UINT8) (sizeof *ScsiDevicePath >> 8);
> +  ScsiDevicePath->Pun              = TargetValue;
> +  ScsiDevicePath->Lun              = (UINT16) Lun;
> +
> +  *DevicePath = &ScsiDevicePath->Header;
> +  return EFI_SUCCESS;
>  }
>  
>  EFI_STATUS
> @@ -77,7 +148,36 @@ LsiScsiGetTargetLun (
>    OUT UINT64                          *Lun
>    )
>  {
> -  return EFI_UNSUPPORTED;
> +  SCSI_DEVICE_PATH *ScsiDevicePath;
> +  LSI_SCSI_DEV     *Dev;
> +  UINT8            *Target;
> +
> +  if (DevicePath == NULL || TargetPointer == NULL || *TargetPointer == NULL ||
> +      Lun == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (DevicePath->Type    != MESSAGING_DEVICE_PATH ||
> +      DevicePath->SubType != MSG_SCSI_DP) {
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  ScsiDevicePath = (SCSI_DEVICE_PATH *) DevicePath;
> +  Dev = LSI_SCSI_FROM_PASS_THRU (This);
> +  if (ScsiDevicePath->Pun > Dev->MaxTarget ||
> +      ScsiDevicePath->Lun > Dev->MaxLun) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // This device support 8 targets only, so it's enough to set the LSB
> +  // of Target.
> +  //
> +  Target = *TargetPointer;
> +  *Target = (UINT8)ScsiDevicePath->Pun;

I don't like this shortcut.

The first reason is that the shortcut is not consistent with the rest of
the functions implemented in this patch. The other functions handle
target numbers that extend up to two bytes; there are no single-byte
shortcuts in them.

(1) So please either rewrite all of those functions to use a similar
shortcut like here, or please remove this shortcut, and stick with a
2-byte sized CopyMem() here too. I prefer the latter.

(2) Whether you use the single-byte shortcut or not, please zero out the
bytes in (*Target) that you do not set otherwise (from Pun).

(3) If the device supports only 8 targets, then please add an according
STATIC_ASSERT() on PcdLsiScsiMaxTargetLimit somewhere. For example:

  STATIC_ASSERT (
    FixedPcdGet8 (PcdLsiScsiMaxTargetLimit) < 8,
    "LSI 53C895A supports targets [0..7]"
    );

It's probably best to add the assert in LsiScsiControllerStart() below,
where you fetch the PCD anyway.

> +  *Lun = ScsiDevicePath->Lun;
> +
> +  return EFI_SUCCESS;
>  }
>  
>  EFI_STATUS
> @@ -107,6 +207,42 @@ LsiScsiGetNextTarget (
>    IN OUT UINT8                       **TargetPointer
>    )
>  {
> +  LSI_SCSI_DEV *Dev;
> +  UINTN        Idx;
> +  UINT8        *Target;
> +  UINT16       LastTarget;
> +
> +  //
> +  // the TargetPointer input parameter is unnecessarily a pointer-to-pointer
> +  //
> +  Target = *TargetPointer;
> +
> +  //
> +  // Search for first non-0xFF byte. If not found, return first target.
> +  //
> +  for (Idx = 0; Idx < TARGET_MAX_BYTES && Target[Idx] == 0xFF; ++Idx)
> +    ;
> +  if (Idx == TARGET_MAX_BYTES) {
> +    SetMem (Target, TARGET_MAX_BYTES, 0x00);
> +    return EFI_SUCCESS;
> +  }
> +
> +  CopyMem (&LastTarget, Target, sizeof LastTarget);
> +
> +  //
> +  // increment target if valid on input
> +  //
> +  Dev = LSI_SCSI_FROM_PASS_THRU (This);
> +  if (LastTarget > Dev->MaxTarget) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (LastTarget < Dev->MaxTarget) {
> +    ++LastTarget;
> +    CopyMem (Target, &LastTarget, sizeof LastTarget);
> +    return EFI_SUCCESS;
> +  }
> +
>    return EFI_NOT_FOUND;
>  }
>  
> @@ -189,6 +325,9 @@ LsiScsiControllerStart (
>  
>    Dev->Signature = LSI_SCSI_DEV_SIGNATURE;
>  
> +  Dev->MaxTarget = PcdGet8 (PcdLsiScsiMaxTargetLimit);
> +  Dev->MaxLun = PcdGet8 (PcdLsiScsiMaxLunLimit);
> +
>    //
>    // Host adapter channel, doesn't exist
>    //
> diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.h b/OvmfPkg/LsiScsiDxe/LsiScsi.h
> index fca1007f9b98..a3d51d8f2386 100644
> --- a/OvmfPkg/LsiScsiDxe/LsiScsi.h
> +++ b/OvmfPkg/LsiScsiDxe/LsiScsi.h
> @@ -14,6 +14,8 @@
>  
>  typedef struct {
>    UINT32                          Signature;
> +  UINT8                           MaxTarget;
> +  UINT8                           MaxLun;
>    EFI_EXT_SCSI_PASS_THRU_MODE     PassThruMode;
>    EFI_EXT_SCSI_PASS_THRU_PROTOCOL PassThru;
>  } LSI_SCSI_DEV;
> @@ -23,6 +25,7 @@ typedef struct {
>  #define LSI_SCSI_FROM_PASS_THRU(PassThruPtr) \
>    CR (PassThruPtr, LSI_SCSI_DEV, PassThru, LSI_SCSI_DEV_SIGNATURE)
>  
> +
>  //
>  // Probe, start and stop functions of this driver, called by the DXE core for
>  // specific devices.

(4) Spurious newline, please drop it. (Or squash it in the previous
patch -- for example --, where you define the LSI_SCSI_FROM_PASS_THRU
macro.)

> diff --git a/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf b/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> index 8660513e2ffd..68844c6772e3 100644
> --- a/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> +++ b/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> @@ -27,7 +27,9 @@ [Packages]
>  [LibraryClasses]
>    BaseLib
>    BaseMemoryLib
> +  DebugLib
>    MemoryAllocationLib
> +  PcdLib
>    UefiBootServicesTableLib
>    UefiDriverEntryPoint
>    UefiLib
> @@ -35,3 +37,7 @@ [LibraryClasses]
>  [Protocols]
>    gEfiExtScsiPassThruProtocolGuid        ## BY_START
>    gEfiPciIoProtocolGuid                  ## TO_START
> +
> +[FixedPcd]
> +  gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiMaxTargetLimit   ## CONSUMES
> +  gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiMaxLunLimit      ## CONSUMES
> diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
> index 65bb2bb0eb4c..ae7d1d648d22 100644
> --- a/OvmfPkg/OvmfPkg.dec
> +++ b/OvmfPkg/OvmfPkg.dec
> @@ -174,6 +174,11 @@ [PcdsFixedAtBuild]
>    ## Microseconds to stall between polling for MptScsi request result
>    gUefiOvmfPkgTokenSpaceGuid.PcdMptScsiStallPerPollUsec|5|UINT32|0x40
>  
> +  ## Set the *inclusive* number of targets and LUNs that LsiScsi exposes for
> +  #  scan by ScsiBusDxe.
> +  gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiMaxTargetLimit|7|UINT8|0x3b
> +  gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiMaxLunLimit|0|UINT8|0x3c
> +
>    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogBase|0x0|UINT32|0x8
>    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogSize|0x0|UINT32|0x9
>    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareFdSize|0x0|UINT32|0xa
> 

Commit 093cceaf79b5 ("OvmfPkg/MptScsiDxe: Report targets and one LUN",
2020-05-05) introduced PcdMptScsiMaxTargetLimit with token value 0x39.
That was OK.

Commit 505812ae1d2d ("OvmfPkg/MptScsiDxe: Implement the PassThru
method", 2020-05-05) then introduced PcdMptScsiStallPerPollUsec with
token value 0x40. That was not OK -- but I missed it. (The token value
should have been 0x3a; as 0x39 is not succeeded by 0x40 but by 0x3a.)

Token value 0x3a remains unused at this point.

(5) So please introduce the new PCDs with token values 0x3a and 0x3b, to
keep the token space dense.

Thanks
Laszlo


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 07/11] OvmfPkg/LsiScsiDxe: Open PciIo protocol and initialize the device
  2020-07-01  4:04 ` [PATCH 07/11] OvmfPkg/LsiScsiDxe: Open PciIo protocol and initialize the device Gary Lin
@ 2020-07-07  9:46   ` Laszlo Ersek
  2020-07-08  2:37     ` Gary Lin
  0 siblings, 1 reply; 35+ messages in thread
From: Laszlo Ersek @ 2020-07-07  9:46 UTC (permalink / raw)
  To: Gary Lin, devel; +Cc: Jordan Justen, Ard Biesheuvel

On 07/01/20 06:04, Gary Lin wrote:
> Open PciIo protocol and use it to initialize the device. The
> initialization of LSI 53C895A is simple: just set the SRST bit in
> Interrupt Status Zero register to reset the device.
> 
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
> Signed-off-by: Gary Lin <glin@suse.com>
> ---
>  OvmfPkg/Include/IndustryStandard/LsiScsi.h |  21 ++++
>  OvmfPkg/LsiScsiDxe/LsiScsi.c               | 129 ++++++++++++++++++++-
>  OvmfPkg/LsiScsiDxe/LsiScsi.h               |   3 +
>  3 files changed, 152 insertions(+), 1 deletion(-)
> 
> diff --git a/OvmfPkg/Include/IndustryStandard/LsiScsi.h b/OvmfPkg/Include/IndustryStandard/LsiScsi.h
> index c09e864a1f39..60e527f1c6a7 100644
> --- a/OvmfPkg/Include/IndustryStandard/LsiScsi.h
> +++ b/OvmfPkg/Include/IndustryStandard/LsiScsi.h
> @@ -17,4 +17,25 @@
>  #define LSI_LOGIC_PCI_VENDOR_ID   0x1000
>  #define LSI_53C895A_PCI_DEVICE_ID 0x0012
>  
> +//
> +// LSI 53C895A Registers
> +//
> +#define LSI_REG_DSTAT             0x0C
> +#define LSI_REG_ISTAT0            0x14
> +#define LSI_REG_DSP               0x2C
> +#define LSI_REG_SIST0             0x42
> +#define LSI_REG_SIST1             0x43
> +
> +//
> +// The status bits for Interrupt Status Zero (ISTAT0)
> +//
> +#define LSI_ISTAT0_DIP            0x01
> +#define LSI_ISTAT0_SIP            0x02
> +#define LSI_ISTAT0_INTF           0x04
> +#define LSI_ISTAT0_CON            0x08
> +#define LSI_ISTAT0_SEM            0x10
> +#define LSI_ISTAT0_SIGP           0x20
> +#define LSI_ISTAT0_SRST           0x40
> +#define LSI_ISTAT0_ABRT           0x80

(1) Please use the BIT0, BIT1, ... etc macros, which are more idiomatic
in edk2 than open-coded constants like 0x01, 0x02, ...

> +
>  #endif // _LSI_SCSI_H_
> diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.c b/OvmfPkg/LsiScsiDxe/LsiScsi.c
> index e10a81a5f9f7..f03774cc4ced 100644
> --- a/OvmfPkg/LsiScsiDxe/LsiScsi.c
> +++ b/OvmfPkg/LsiScsiDxe/LsiScsi.c
> @@ -25,6 +25,33 @@
>  
>  #include "LsiScsi.h"
>  
> +STATIC
> +EFI_STATUS
> +Out8 (
> +  IN LSI_SCSI_DEV *Dev,
> +  IN UINT32       Addr,
> +  IN UINT8        Data
> +  )
> +{
> +  return Dev->PciIo->Io.Write (
> +                          Dev->PciIo,
> +                          EfiPciIoWidthUint8,
> +                          PCI_BAR_IDX0,
> +                          Addr,
> +                          1,
> +                          &Data
> +                          );
> +}
> +
> +STATIC
> +EFI_STATUS
> +LsiScsiReset (
> +  IN LSI_SCSI_DEV *Dev
> +  )
> +{
> +  return Out8 (Dev, LSI_REG_ISTAT0, LSI_ISTAT0_SRST);
> +}
> +
>  //
>  // The next seven functions implement EFI_EXT_SCSI_PASS_THRU_PROTOCOL
>  // for the LSI 53C895A SCSI Controller. Refer to UEFI Spec 2.3.1 + Errata C,
> @@ -246,6 +273,21 @@ LsiScsiGetNextTarget (
>    return EFI_NOT_FOUND;
>  }
>  
> +STATIC
> +VOID
> +EFIAPI
> +LsiScsiExitBoot (
> +  IN  EFI_EVENT Event,
> +  IN  VOID      *Context
> +  )
> +{
> +  LSI_SCSI_DEV *Dev;
> +
> +  Dev = Context;
> +  DEBUG ((DEBUG_VERBOSE, "%a: Context=0x%p\n", __FUNCTION__, Context));
> +  LsiScsiReset (Dev);
> +}
> +
>  //
>  // Probe, start and stop functions of this driver, called by the DXE core for
>  // specific devices.
> @@ -328,6 +370,58 @@ LsiScsiControllerStart (
>    Dev->MaxTarget = PcdGet8 (PcdLsiScsiMaxTargetLimit);
>    Dev->MaxLun = PcdGet8 (PcdLsiScsiMaxLunLimit);
>  
> +  Status = gBS->OpenProtocol (
> +                  ControllerHandle,
> +                  &gEfiPciIoProtocolGuid,
> +                  (VOID **)&Dev->PciIo,
> +                  This->DriverBindingHandle,
> +                  ControllerHandle,
> +                  EFI_OPEN_PROTOCOL_BY_DRIVER
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    goto FreePool;
> +  }
> +
> +  Status = Dev->PciIo->Attributes (
> +                         Dev->PciIo,
> +                         EfiPciIoAttributeOperationGet,
> +                         0,
> +                         &Dev->OrigPciAttrs
> +                         );
> +  if (EFI_ERROR (Status)) {
> +    goto CloseProtocol;
> +  }
> +
> +  //
> +  // Enable I/O Space & Bus-Mastering
> +  //
> +  Status = Dev->PciIo->Attributes (
> +                         Dev->PciIo,
> +                         EfiPciIoAttributeOperationEnable,
> +                         (EFI_PCI_IO_ATTRIBUTE_IO |
> +                          EFI_PCI_IO_ATTRIBUTE_BUS_MASTER),
> +                         NULL
> +                         );
> +  if (EFI_ERROR (Status)) {
> +    goto CloseProtocol;
> +  }
> +
> +  Status = LsiScsiReset (Dev);
> +  if (EFI_ERROR (Status)) {
> +    goto RestoreAttributes;
> +  }
> +
> +  Status = gBS->CreateEvent (
> +                  EVT_SIGNAL_EXIT_BOOT_SERVICES,
> +                  TPL_CALLBACK,
> +                  &LsiScsiExitBoot,
> +                  Dev,
> +                  &Dev->ExitBoot
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    goto UninitDev;
> +  }
> +
>    //
>    // Host adapter channel, doesn't exist
>    //
> @@ -352,11 +446,33 @@ LsiScsiControllerStart (
>                    &Dev->PassThru
>                    );
>    if (EFI_ERROR (Status)) {
> -    goto FreePool;
> +    goto CloseExitBoot;
>    }
>  
>    return EFI_SUCCESS;
>  
> +CloseExitBoot:
> +  gBS->CloseEvent (Dev->ExitBoot);
> +
> +UninitDev:
> +  LsiScsiReset (Dev);
> +
> +RestoreAttributes:
> +  Dev->PciIo->Attributes (
> +                Dev->PciIo,
> +                EfiPciIoAttributeOperationSet,
> +                Dev->OrigPciAttrs,
> +                NULL
> +                );
> +
> +CloseProtocol:
> +  gBS->CloseProtocol (
> +         ControllerHandle,
> +         &gEfiPciIoProtocolGuid,
> +         This->DriverBindingHandle,
> +         ControllerHandle
> +         );
> +
>  FreePool:
>    FreePool (Dev);
>  
> @@ -399,6 +515,17 @@ LsiScsiControllerStop (
>      return Status;
>    }
>  
> +  gBS->CloseEvent (Dev->ExitBoot);
> +
> +  LsiScsiReset (Dev);
> +
> +  Dev->PciIo->Attributes (
> +                Dev->PciIo,
> +                EfiPciIoAttributeOperationSet,
> +                Dev->OrigPciAttrs,
> +                NULL
> +                );
> +
>    gBS->CloseProtocol (
>           ControllerHandle,
>           &gEfiPciIoProtocolGuid,

(2) So as I said under "[PATCH 05/11] OvmfPkg/LsiScsiDxe: Install
stubbed EXT_SCSI_PASS_THRU", this CloseProtocol() call should not be
"context" here (from patch 05/11); it should be introduced here,
reflecting the operations in LsiScsiControllerStart() that are also
introduced in this patch.

> diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.h b/OvmfPkg/LsiScsiDxe/LsiScsi.h
> index a3d51d8f2386..ffaee6188536 100644
> --- a/OvmfPkg/LsiScsiDxe/LsiScsi.h
> +++ b/OvmfPkg/LsiScsiDxe/LsiScsi.h
> @@ -14,6 +14,9 @@
>  
>  typedef struct {
>    UINT32                          Signature;
> +  UINT64                          OrigPciAttrs;
> +  EFI_EVENT                       ExitBoot;
> +  EFI_PCI_IO_PROTOCOL             *PciIo;
>    UINT8                           MaxTarget;
>    UINT8                           MaxLun;
>    EFI_EXT_SCSI_PASS_THRU_MODE     PassThruMode;
> 

Thanks
Laszlo


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 08/11] OvmfPkg/LsiScsiDxe: Map DMA buffer
  2020-07-01  4:04 ` [PATCH 08/11] OvmfPkg/LsiScsiDxe: Map DMA buffer Gary Lin
@ 2020-07-07  9:59   ` Laszlo Ersek
  2020-07-08  2:41     ` Gary Lin
  0 siblings, 1 reply; 35+ messages in thread
From: Laszlo Ersek @ 2020-07-07  9:59 UTC (permalink / raw)
  To: Gary Lin, devel; +Cc: Jordan Justen, Ard Biesheuvel

On 07/01/20 06:04, Gary Lin wrote:
> Map DMA buffer and perpare for the implementation of LsiScsiPassThru().
> 
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
> Signed-off-by: Gary Lin <glin@suse.com>
> ---
>  OvmfPkg/LsiScsiDxe/LsiScsi.c | 85 +++++++++++++++++++++++++++++++++++-
>  OvmfPkg/LsiScsiDxe/LsiScsi.h | 10 +++++
>  2 files changed, 94 insertions(+), 1 deletion(-)
> 
> diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.c b/OvmfPkg/LsiScsiDxe/LsiScsi.c
> index f03774cc4ced..b728d18d51df 100644
> --- a/OvmfPkg/LsiScsiDxe/LsiScsi.c
> +++ b/OvmfPkg/LsiScsiDxe/LsiScsi.c
> @@ -359,6 +359,8 @@ LsiScsiControllerStart (
>  {
>    EFI_STATUS           Status;
>    LSI_SCSI_DEV         *Dev;
> +  UINTN                Pages;
> +  UINTN                BytesMapped;
>  
>    Dev = AllocateZeroPool (sizeof (*Dev));
>    if (Dev == NULL) {
> @@ -406,11 +408,68 @@ LsiScsiControllerStart (
>      goto CloseProtocol;
>    }
>  
> -  Status = LsiScsiReset (Dev);
> +  //
> +  // Signal device supports 64-bit DMA addresses
> +  //
> +  Status = Dev->PciIo->Attributes (
> +                         Dev->PciIo,
> +                         EfiPciIoAttributeOperationEnable,
> +                         EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE,
> +                         NULL
> +                         );
> +  if (EFI_ERROR (Status)) {
> +    //
> +    // Warn user that device will only be using 32-bit DMA addresses.
> +    //
> +    // Note that this does not prevent the device/driver from working
> +    // and therefore we only warn and continue as usual.
> +    //
> +    DEBUG ((
> +      DEBUG_WARN,
> +      "%a: failed to enable 64-bit DMA addresses\n",
> +      __FUNCTION__
> +      ));
> +  }
> +
> +  //
> +  // Create buffers for data transfer
> +  //
> +  Pages = EFI_SIZE_TO_PAGES (sizeof (*Dev->Dma));
> +  Status = Dev->PciIo->AllocateBuffer (
> +                         Dev->PciIo,
> +                         AllocateAnyPages,
> +                         EfiBootServicesData,
> +                         Pages,
> +                         (VOID **)&Dev->Dma,
> +                         EFI_PCI_ATTRIBUTE_MEMORY_CACHED
> +                         );
>    if (EFI_ERROR (Status)) {
>      goto RestoreAttributes;
>    }
>  
> +  BytesMapped = EFI_PAGES_TO_SIZE (Pages);
> +  Status = Dev->PciIo->Map (
> +                         Dev->PciIo,
> +                         EfiPciIoOperationBusMasterCommonBuffer,
> +                         Dev->Dma,
> +                         &BytesMapped,
> +                         &Dev->DmaPhysical,
> +                         &Dev->DmaMapping
> +                         );
> +  if (EFI_ERROR (Status)) {
> +    goto FreeBuffer;
> +  }
> +
> +  if (BytesMapped != EFI_PAGES_TO_SIZE (Pages)) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto Unmap;
> +  }
> +
> +  Status = LsiScsiReset (Dev);
> +  if (EFI_ERROR (Status)) {
> +    goto Unmap;
> +  }
> +
>    Status = gBS->CreateEvent (
>                    EVT_SIGNAL_EXIT_BOOT_SERVICES,
>                    TPL_CALLBACK,
> @@ -457,6 +516,19 @@ CloseExitBoot:
>  UninitDev:
>    LsiScsiReset (Dev);
>  
> +Unmap:
> +  Dev->PciIo->Unmap (
> +                Dev->PciIo,
> +                Dev->DmaMapping
> +                );
> +
> +FreeBuffer:
> +  Dev->PciIo->FreeBuffer (
> +                Dev->PciIo,
> +                Pages,
> +                Dev->Dma
> +                );
> +
>  RestoreAttributes:
>    Dev->PciIo->Attributes (
>                  Dev->PciIo,
> @@ -519,6 +591,17 @@ LsiScsiControllerStop (
>  
>    LsiScsiReset (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,
>                  EfiPciIoAttributeOperationSet,
> diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.h b/OvmfPkg/LsiScsiDxe/LsiScsi.h
> index ffaee6188536..1e4bbc56f933 100644
> --- a/OvmfPkg/LsiScsiDxe/LsiScsi.h
> +++ b/OvmfPkg/LsiScsiDxe/LsiScsi.h
> @@ -12,6 +12,13 @@
>  #ifndef _LSI_SCSI_DXE_H_
>  #define _LSI_SCSI_DXE_H_
>  
> +typedef struct {
> +  //
> +  // Allocate 64KB for read/write buffer.
> +  //
> +  UINT8                           Data[0x10000];

(1) Using SIZE_64KB for the size would be more idiomatic.

(2) Please add a comment that limiting the transfer size to 64KB seems
OK in practice.

With those updates:

Reviewed-by: Laszlo Ersek <lersek@redhat.com>

Thanks
Laszlo

> +} LSI_SCSI_DMA_BUFFER;
> +
>  typedef struct {
>    UINT32                          Signature;
>    UINT64                          OrigPciAttrs;
> @@ -19,6 +26,9 @@ typedef struct {
>    EFI_PCI_IO_PROTOCOL             *PciIo;
>    UINT8                           MaxTarget;
>    UINT8                           MaxLun;
> +  LSI_SCSI_DMA_BUFFER             *Dma;
> +  EFI_PHYSICAL_ADDRESS            DmaPhysical;
> +  VOID                            *DmaMapping;
>    EFI_EXT_SCSI_PASS_THRU_MODE     PassThruMode;
>    EFI_EXT_SCSI_PASS_THRU_PROTOCOL PassThru;
>  } LSI_SCSI_DEV;
> 


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 09/11] OvmfPkg/LsiScsiDxe: Examine the incoming SCSI Request Packet
  2020-07-01  4:04 ` [PATCH 09/11] OvmfPkg/LsiScsiDxe: Examine the incoming SCSI Request Packet Gary Lin
@ 2020-07-07 10:17   ` Laszlo Ersek
  2020-07-08  2:43     ` Gary Lin
  0 siblings, 1 reply; 35+ messages in thread
From: Laszlo Ersek @ 2020-07-07 10:17 UTC (permalink / raw)
  To: Gary Lin, devel; +Cc: Jordan Justen, Ard Biesheuvel

On 07/01/20 06:04, Gary Lin wrote:
> This is the first part of LsiScsiPassThru(). Before processing the SCSI
> Request packet, we have to make sure whether the packet is valid or not.
> 
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
> Signed-off-by: Gary Lin <glin@suse.com>
> ---
>  OvmfPkg/LsiScsiDxe/LsiScsi.c | 100 ++++++++++++++++++++++++++++++++++-
>  OvmfPkg/LsiScsiDxe/LsiScsi.h |   4 ++
>  2 files changed, 103 insertions(+), 1 deletion(-)
> 
> diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.c b/OvmfPkg/LsiScsiDxe/LsiScsi.c
> index b728d18d51df..1bcebd92e455 100644
> --- a/OvmfPkg/LsiScsiDxe/LsiScsi.c
> +++ b/OvmfPkg/LsiScsiDxe/LsiScsi.c
> @@ -52,6 +52,95 @@ LsiScsiReset (
>    return Out8 (Dev, LSI_REG_ISTAT0, LSI_ISTAT0_SRST);
>  }
>  
> +STATIC
> +EFI_STATUS
> +ReportHostAdapterOverrunError (
> +  OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
> +  )
> +{
> +  Packet->SenseDataLength = 0;
> +  Packet->HostAdapterStatus =
> +            EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN;
> +  Packet->TargetStatus = EFI_EXT_SCSI_STATUS_TARGET_GOOD;
> +  return EFI_BAD_BUFFER_SIZE;
> +}
> +
> +/**
> +
> +  Check the request packet from the Extended SCSI Pass Thru Protocol. The
> +  request packet is modified, to be forwarded outwards by LsiScsiPassThru(),
> +  if invalid or unsupported parameters are detected.
> +
> +  @param[in] Dev          The LSI 53C895A SCSI device the packet targets.
> +
> +  @param[in] Target       The SCSI target controlled by the LSI 53C895A SCSI
> +                          device.
> +
> +  @param[in] Lun          The Logical Unit Number under the SCSI target.
> +
> +  @param[in out] Packet   The Extended SCSI Pass Thru Protocol packet.
> +
> +
> +  @retval EFI_SUCCESS  The Extended SCSI Pass Thru Protocol packet was valid.
> +
> +  @return              Otherwise, invalid or unsupported parameters were
> +                       detected. Status codes are meant for direct forwarding
> +                       by the EFI_EXT_SCSI_PASS_THRU_PROTOCOL.PassThru()
> +                       implementation.
> +
> + **/
> +STATIC
> +EFI_STATUS
> +LsiScsiCheckRequest (
> +  IN LSI_SCSI_DEV                                   *Dev,
> +  IN UINT8                                          Target,
> +  IN UINT64                                         Lun,
> +  IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
> +  )
> +{
> +  if (Target > Dev->MaxTarget || Lun > Dev->MaxLun ||
> +      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->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_BIDIRECTIONAL ||
> +      (Packet->InTransferLength > 0 && Packet->OutTransferLength > 0) ||
> +      Packet->CdbLength > sizeof Dev->Dma->Cdb) {
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  if (Packet->InTransferLength > sizeof Dev->Dma->Data) {
> +    Packet->InTransferLength = sizeof Dev->Dma->Data;
> +    return ReportHostAdapterOverrunError (Packet);
> +  }
> +  if (Packet->OutTransferLength > sizeof Dev->Dma->Data) {
> +    Packet->OutTransferLength = sizeof Dev->Dma->Data;
> +    return ReportHostAdapterOverrunError (Packet);
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
>  //
>  // The next seven functions implement EFI_EXT_SCSI_PASS_THRU_PROTOCOL
>  // for the LSI 53C895A SCSI Controller. Refer to UEFI Spec 2.3.1 + Errata C,
> @@ -70,7 +159,16 @@ LsiScsiPassThru (
>    IN EFI_EVENT                                      Event     OPTIONAL
>    )
>  {
> -  return EFI_UNSUPPORTED;
> +  EFI_STATUS   Status;
> +  LSI_SCSI_DEV *Dev;
> +
> +  Dev = LSI_SCSI_FROM_PASS_THRU (This);
> +  Status = LsiScsiCheckRequest (Dev, *Target, Lun, Packet);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  return EFI_SUCCESS;
>  }
>  
>  EFI_STATUS

In this patch, we do not implement LsiScsiPassThru() completely yet.
Therefore we should not return EFI_SUCCESS, just because
LsiScsiCheckRequest() succeeds.

(1) So please keep the EFI_UNSUPPORTED value for the last "return"
statement in the function, for now.

EFI_UNSUPPORTED should be replaced with EFI_SUCCESS in "[PATCH 10/11]
OvmfPkg/LsiScsiDxe: Process the SCSI Request Packet".

With that update, for this patch:

Reviewed-by: Laszlo Ersek <lersek@redhat.com>

Thanks
Laszlo

> diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.h b/OvmfPkg/LsiScsiDxe/LsiScsi.h
> index 1e4bbc56f933..9272eb7506c7 100644
> --- a/OvmfPkg/LsiScsiDxe/LsiScsi.h
> +++ b/OvmfPkg/LsiScsiDxe/LsiScsi.h
> @@ -13,6 +13,10 @@
>  #define _LSI_SCSI_DXE_H_
>  
>  typedef struct {
> +  //
> +  // The max size of CDB is 32.
> +  //
> +  UINT8                           Cdb[32];
>    //
>    // Allocate 64KB for read/write buffer.
>    //
> 


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 10/11] OvmfPkg/LsiScsiDxe: Process the SCSI Request Packet
  2020-07-01  4:04 ` [PATCH 10/11] OvmfPkg/LsiScsiDxe: Process the " Gary Lin
@ 2020-07-07 12:46   ` Laszlo Ersek
  2020-07-08  6:02     ` Gary Lin
       [not found]     ` <161FB1B03BD2D339.11266@groups.io>
  0 siblings, 2 replies; 35+ messages in thread
From: Laszlo Ersek @ 2020-07-07 12:46 UTC (permalink / raw)
  To: Gary Lin, devel; +Cc: Jordan Justen, Ard Biesheuvel

On 07/01/20 06:04, Gary Lin wrote:
> This is the second part of LsiScsiPassThru(). LsiScsiProcessRequest() is
> added to translate the SCSI Request Packet into the LSI 53C895A
> commands. This function utilizes the so-called Script buffer to transmit
> a series of commands to the chip and then polls the DMA Status (DSTAT)
> register until the Scripts Interrupt Instruction Received (SIR) bit
> sets. Once the script is done, the SCSI Request Packet will be modified
> to reflect the result of the script.
>
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
> Signed-off-by: Gary Lin <glin@suse.com>
> ---
>  OvmfPkg/Include/IndustryStandard/LsiScsi.h |  39 +++
>  OvmfPkg/LsiScsiDxe/LsiScsi.c               | 308 +++++++++++++++++++++
>  OvmfPkg/LsiScsiDxe/LsiScsi.h               |  21 ++
>  OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf          |   3 +
>  OvmfPkg/OvmfPkg.dec                        |   3 +
>  5 files changed, 374 insertions(+)
>
> diff --git a/OvmfPkg/Include/IndustryStandard/LsiScsi.h b/OvmfPkg/Include/IndustryStandard/LsiScsi.h
> index 60e527f1c6a7..cbf049c18310 100644
> --- a/OvmfPkg/Include/IndustryStandard/LsiScsi.h
> +++ b/OvmfPkg/Include/IndustryStandard/LsiScsi.h
> @@ -26,6 +26,18 @@
>  #define LSI_REG_SIST0             0x42
>  #define LSI_REG_SIST1             0x43
>
> +//
> +// The status bits for DMA Status (DSTAT)
> +//
> +#define LSI_DSTAT_IID             0x01
> +#define LSI_DSTAT_R               0x02
> +#define LSI_DSTAT_SIR             0x04
> +#define LSI_DSTAT_SSI             0x08
> +#define LSI_DSTAT_ABRT            0x10
> +#define LSI_DSTAT_BF              0x20
> +#define LSI_DSTAT_MDPE            0x40
> +#define LSI_DSTAT_DFE             0x80
> +

(1) Please use the BITx macros.


>  //
>  // The status bits for Interrupt Status Zero (ISTAT0)
>  //
> @@ -38,4 +50,31 @@
>  #define LSI_ISTAT0_SRST           0x40
>  #define LSI_ISTAT0_ABRT           0x80
>
> +//
> +// LSI 53C895A Script Instructions
> +//
> +#define LSI_INS_TYPE_BLK          0x00000000
> +#define LSI_INS_TYPE_IO           0x40000000
> +#define LSI_INS_TYPE_TC           0x80000000
> +
> +#define LSI_INS_BLK_SCSIP_DAT_OUT 0x00000000
> +#define LSI_INS_BLK_SCSIP_DAT_IN  0x01000000
> +#define LSI_INS_BLK_SCSIP_CMD     0x02000000
> +#define LSI_INS_BLK_SCSIP_STAT    0x03000000
> +#define LSI_INS_BLK_SCSIP_MSG_OUT 0x06000000
> +#define LSI_INS_BLK_SCSIP_MSG_IN  0x07000000
> +
> +#define LSI_INS_IO_OPC_SEL        0x00000000
> +#define LSI_INS_IO_OPC_WAIT_RESEL 0x10000000
> +
> +#define LSI_INS_TC_CP             0x00020000
> +#define LSI_INS_TC_JMP            0x00080000
> +#define LSI_INS_TC_RA             0x00800000
> +
> +#define LSI_INS_TC_OPC_JMP        0x00000000
> +#define LSI_INS_TC_OPC_INT        0x18000000
> +
> +#define LSI_INS_TC_SCSIP_DAT_OUT  0x00000000
> +#define LSI_INS_TC_SCSIP_MSG_IN   0x07000000
> +
>  #endif // _LSI_SCSI_H_
> diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.c b/OvmfPkg/LsiScsiDxe/LsiScsi.c
> index 1bcebd92e455..090d7df15b34 100644
> --- a/OvmfPkg/LsiScsiDxe/LsiScsi.c
> +++ b/OvmfPkg/LsiScsiDxe/LsiScsi.c
> @@ -43,6 +43,42 @@ Out8 (
>                            );
>  }
>
> +STATIC
> +EFI_STATUS
> +Out32 (
> +  IN LSI_SCSI_DEV       *Dev,
> +  IN UINT32             Addr,
> +  IN UINT32             Data
> +  )
> +{
> +  return Dev->PciIo->Io.Write (
> +                          Dev->PciIo,
> +                          EfiPciIoWidthUint32,
> +                          PCI_BAR_IDX0,
> +                          Addr,
> +                          1,
> +                          &Data
> +                          );
> +}
> +
> +STATIC
> +EFI_STATUS
> +In8 (
> +  IN  LSI_SCSI_DEV *Dev,
> +  IN  UINT32       Addr,
> +  OUT UINT8        *Data
> +  )
> +{
> +  return Dev->PciIo->Io.Read (
> +                          Dev->PciIo,
> +                          EfiPciIoWidthUint8,
> +                          PCI_BAR_IDX0,
> +                          Addr,
> +                          1,
> +                          Data
> +                          );
> +}
> +
>  STATIC
>  EFI_STATUS
>  LsiScsiReset (
> @@ -141,6 +177,272 @@ LsiScsiCheckRequest (
>    return EFI_SUCCESS;
>  }
>
> +/**
> +
> +  Interpret the request packet from the Extended SCSI Pass Thru Protocol and
> +  compose the script to submit the command and data to the contorller.

(2) s/contorller/controller/


> +
> +  @param[in] Dev          The LSI 53C895A SCSI device the packet targets.
> +
> +  @param[in] Target       The SCSI target controlled by the LSI 53C895A SCSI
> +                          device.
> +
> +  @param[in] Lun          The Logical Unit Number under the SCSI target.
> +
> +  @param[in out] Packet   The Extended SCSI Pass Thru Protocol packet.
> +
> +
> +  @retval EFI_SUCCESS  The Extended SCSI Pass Thru Protocol packet was valid.
> +
> +  @return              Otherwise, invalid or unsupported parameters were
> +                       detected. Status codes are meant for direct forwarding
> +                       by the EFI_EXT_SCSI_PASS_THRU_PROTOCOL.PassThru()
> +                       implementation.
> +
> + **/
> +STATIC
> +EFI_STATUS
> +LsiScsiProcessRequest (
> +  IN LSI_SCSI_DEV                                   *Dev,
> +  IN UINT8                                          Target,
> +  IN UINT64                                         Lun,
> +  IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
> +  )
> +{
> +  EFI_STATUS Status;
> +  UINT32     *Script;
> +  UINT8      *Cdb;
> +  UINT8      *MsgOut;
> +  UINT8      *MsgIn;
> +  UINT8      *ScsiStatus;
> +  UINT8      *Data;
> +  UINT8      DStat;
> +  UINT8      SIst0;
> +  UINT8      SIst1;
> +
> +  Script      = Dev->Dma->Script;
> +  Cdb         = Dev->Dma->Cdb;
> +  Data        = Dev->Dma->Data;
> +  MsgIn       = Dev->Dma->MsgIn;
> +  MsgOut      = &Dev->Dma->MsgOut;
> +  ScsiStatus  = &Dev->Dma->Status;
> +
> +  *ScsiStatus = 0xFF;
> +
> +  SetMem (Cdb, sizeof Dev->Dma->Cdb, 0x00);
> +  CopyMem (Cdb, Packet->Cdb, Packet->CdbLength);
> +
> +  //
> +  // Clean up the DMA buffer for the script.
> +  //
> +  SetMem (Script, sizeof Dev->Dma->Script, 0x00);
> +
> +  //
> +  // Compose the script to transfer data between the host and the device.
> +  //
> +  // Reference:
> +  //   LSI53C895A PCI to Ultra2 SCSI Controller Version 2.2
> +  //   - Chapter 5 SCSI SCRIPT Instruction Set
> +  //
> +  // All instructions used here consist of 2 32bit words. The first word
> +  // contains the command to execute. The second word is loaded into the
> +  // DMA SCRIPTS Pointer Save (DSPS) register as either the DMA address
> +  // for data transmission or the address/offset for the jump command.
> +  // Some commands, such as the selection of the target, don't need to
> +  // transfer data through DMA or jump to another instruction, then DSPS
> +  // has to be zero.
> +  //
> +  // There are 3 major parts in this script. The first part (1~3) contains
> +  // the instructions to select target and LUN and send the SCSI command
> +  // from the request packet. The second part (4~7) is to handle the
> +  // potential disconnection and prepare for the data transmission. The
> +  // instructions in the third part (8~10) transmit the given data and
> +  // collect the result. Instruction 11 raises the interrupt and marks the
> +  // end of the script.
> +  //
> +
> +  //
> +  // 1. Select target.
> +  //
> +  *Script++ = LSI_INS_TYPE_IO | LSI_INS_IO_OPC_SEL | (UINT32)Target << 16;
> +  *Script++ = 0x00000000;
> +
> +  //
> +  // 2. Select LUN.
> +  //
> +  *MsgOut   = 0x80 | (UINT8) Lun; // 0x80: Identify bit

This implies that the maximum (inclusive) LUN can be 127.

(3) I suggest adding a STATIC_ASSERT() to LsiScsiControllerStart(),
where you fetch "PcdLsiScsiMaxLunLimit".

(If the device has a stricter limit on LUNs than 127, then please use
that limit.)


> +  *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_MSG_OUT | \
> +              sizeof Dev->Dma->MsgOut;

(4) Please cast the result of the "sizeof" operator to UINT32
explicitly.


(5) Please drop the backslash; it is not needed.

Note that (4) and (5) apply to multiple locations in this function;
please update each location in the composition of the script.


> +  *Script++ = LSI_SCSI_DMA_ADDR_LOW (Dev, MsgOut);

This opcode seems to mean that the device is not capable of taking the
LUN selector message from outside of the 32-bit address space.

(6) If that's the case, then please remove DUAL_ADDRESS_CYCLE from
"[PATCH 08/11] OvmfPkg/LsiScsiDxe: Map DMA buffer".

Otherwise, AllocateBuffer() could theoretically allocate the buffer
structure (including the MsgOut member) such that
LSI_SCSI_DMA_ADDR_LOW() would truncate the address.


(7) Once you remove DUAL_ADDRESS_CYCLE (i.e. once we guarantee that the
allocation will be satisfied from the 32-bit address space), you can
drop the _LOW suffix as well, from the macro name.

Now, if the device is actually 64-bit capable, only it would take a more
complex script, and you don't want that, that's fine -- the above steps
remain the same. (IOW it doesn't matter whether the device is 64-bit
uncapable, or you don't want to write a 64-bit aware command script --
you should remove DUAL_ADDRESS_CYCLE just the same.)


> +
> +  //
> +  // 3. Send the SCSI Command.
> +  //
> +  *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_CMD | \
> +              sizeof Dev->Dma->Cdb;
> +  *Script++ = LSI_SCSI_DMA_ADDR_LOW (Dev, Cdb);
> +
> +  //
> +  // 4. Check whether the current SCSI phase is "Message In" or not
> +  //    and jump to 8 if it is.
> +  //
> +  *Script++ = LSI_INS_TYPE_TC | LSI_INS_TC_OPC_JMP | \
> +              LSI_INS_TC_SCSIP_MSG_IN | LSI_INS_TC_RA | \
> +              LSI_INS_TC_CP;
> +  *Script++ = 0x00000018;

(8) The constant 0x18 is obscure. Can you extend the comment? How is
"step 8" connected to value 0x18?

(Step 8 starts at command offset 7 in the script, meaning UINT32 offset
14, or byte offset 56. But 0x18 is 24, not matching any of those
constants.)


> +
> +  //
> +  // 5. Read "Message" from the initiator to trigger reselect.
> +  //
> +  *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_MSG_IN | \
> +              sizeof Dev->Dma->MsgIn;
> +  *Script++ = LSI_SCSI_DMA_ADDR_LOW (Dev, MsgIn);
> +
> +  //
> +  // 6. Wait reselect.
> +  //
> +  *Script++ = LSI_INS_TYPE_IO | LSI_INS_IO_OPC_WAIT_RESEL;
> +  *Script++ = 0x00000000;
> +
> +  //
> +  // 7. Read "Message" from the initiator again
> +  //
> +  *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_MSG_IN | \
> +              sizeof Dev->Dma->MsgIn;
> +  *Script++ = LSI_SCSI_DMA_ADDR_LOW (Dev, MsgIn);
> +
> +  //
> +  // 8. Set the DMA command for the read/write operations.
> +  //
> +  if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ &&
> +      Packet->InTransferLength > 0) {
> +    *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_DAT_IN | \
> +                Packet->InTransferLength;
> +    *Script++ = LSI_SCSI_DMA_ADDR_LOW (Dev, Data);
> +  } else if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_WRITE &&
> +             Packet->OutTransferLength > 0) {
> +    // LsiScsiCheckRequest() guarantees that OutTransferLength is no
> +    // larger than sizeof Dev->Dma->Data, so we can safely copy the
> +    // the data to Dev->Dma->Data.
> +    CopyMem (Data, Packet->OutDataBuffer, Packet->OutTransferLength);
> +    *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_DAT_OUT | \
> +                Packet->OutTransferLength;
> +    *Script++ = LSI_SCSI_DMA_ADDR_LOW (Dev, Data);
> +  }

The comment is not bad, but it could be improved.

First, the comment style is not 100% correct (empty "//" lines are
missing before and after.)

Second, instead of a long comment, I'd suggest a short comment, plus an
ASSERT.

Third, the transfer length in the packet ("in" and "out" alike) isn't
*only* relevant due to buffer overflow concerns, but also because the
command opcode has some bits set (in particular,
LSI_INS_BLK_SCSIP_DAT_IN) that effectively limit the transfer length to
a bitmask that's narrower than a UINT32.


Another observation is that control can flow through this snippet
without taking *either* branch.

(For example if the data direction is WRITE, but OutTransferLength is
zero. That's a condition that LsiScsiCheckRequest() does not catch. My
point is not that LsiScsiCheckRequest() should catch it -- I think it's
not an invalid request --, but that LsiScsiProcessRequest() should deal
with it.)

If we take neither branch, then (minimally) the jump address under step
4. will be wrong -- there's not going to be a DAT_IN / DAT_OUT command
to jump to.


(9) So, for addressing all of the above, I suggest:

  //
  // 8. Set the DMA command for the read/write operations.
  //
  // LsiScsiCheckRequest() prevents both integer overflows in the command
  // opcodes, and buffer overflows.
  //
  if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
    ASSERT (Packet->InTransferLength <= sizeof Dev->Dma->Data);
    *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_DAT_IN |
                Packet->InTransferLength;
  } else {
    ASSERT (Packet->OutTransferLength <= sizeof Dev->Dma->Data);
    CopyMem (Data, Packet->OutDataBuffer, Packet->OutTransferLength);
    *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_DAT_OUT |
                Packet->OutTransferLength;
  }
  *Script++ = LSI_SCSI_DMA_ADDR (Dev, Data);


> +
> +  //
> +  // 9. Get the SCSI status.
> +  //
> +  *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_STAT | \
> +              sizeof Dev->Dma->Status;
> +  *Script++ = LSI_SCSI_DMA_ADDR_LOW (Dev, Status);
> +
> +  //
> +  // 10. Get the SCSI message.
> +  //
> +  *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_MSG_IN | \
> +              sizeof Dev->Dma->MsgIn;
> +  *Script++ = LSI_SCSI_DMA_ADDR_LOW (Dev, MsgIn);
> +
> +  //
> +  // 11. Raise the interrupt to end the script.
> +  //
> +  *Script++ = LSI_INS_TYPE_TC | LSI_INS_TC_OPC_INT | \
> +              LSI_INS_TC_SCSIP_DAT_OUT | LSI_INS_TC_JMP;
> +  *Script++ = 0x00000000;
> +
> +  //
> +  // Make sure the size of the script doesn't exceed the buffer.
> +  //
> +  ASSERT (Script < Dev->Dma->Script + sizeof Dev->Dma->Script);

(10) Please replace "<" with "<=".

(11) Please replace "sizeof" with ARRAY_SIZE().


> +
> +  //
> +  // The controller starts to execute the script once the DMA Script
> +  // Pointer (DSP) register is set.
> +  //
> +  Status = Out32 (Dev, LSI_REG_DSP, LSI_SCSI_DMA_ADDR_LOW(Dev, Script));

(12) Missing space after "LSI_SCSI_DMA_ADDR".


> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }

This return statement doesn't seem right. We do not translate the error
code to one of the error codes specified for
EFI_EXT_SCSI_PASS_THRU_PROTOCOL.PassThru(). We also do not set any
output field in Packet.

(13) I think we should jump to the "Error" label from here.


> +
> +  //
> +  // Poll the device registers (DSTAT, SIST0, and SIST1) until the SIR
> +  // bit sets.
> +  //
> +  for(;;) {
> +    Status = In8 (Dev, LSI_REG_DSTAT, &DStat);
> +    if (EFI_ERROR (Status)) {
> +      goto Error;
> +    }
> +    Status = In8 (Dev, LSI_REG_SIST0, &SIst0);
> +    if (EFI_ERROR (Status)) {
> +      goto Error;
> +    }
> +    Status = In8 (Dev, LSI_REG_SIST1, &SIst1);
> +    if (EFI_ERROR (Status)) {
> +      goto Error;
> +    }
> +
> +    if (SIst0 != 0 || SIst1 != 0) {
> +      goto Error;
> +    }
> +
> +    //
> +    // Check the SIR (SCRIPTS Interrupt Instruction Received) bit.
> +    //
> +    if (DStat & LSI_DSTAT_SIR) {
> +      break;
> +    }
> +
> +    gBS->Stall (Dev->StallPerPollUsec);
> +  }
> +
> +  //
> +  // Check if everything is good.
> +  //   SCSI Message Code 0x00: COMMAND COMPLETE
> +  //   SCSI Status  Code 0x00: Good
> +  //
> +  if (MsgIn[0] == 0 && *ScsiStatus == 0) {

(14) Please negate this condition, and unnest the success branch:

  if (MsgIn[0] != 0 || *ScsiStatus != 0) {
    goto Error;
  }

  /* ... */

  return EFI_SUCCESS;


> +    //
> +    // Copy Data to InDataBuffer if necessary.
> +    //
> +    if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
> +      CopyMem (Packet->InDataBuffer, Data, Packet->InTransferLength);
> +    }
> +
> +    //
> +    // The controller doesn't return sense data when replying "TEST UNIT READY",
> +    // so we have to set SenseDataLength to 0 to notify ScsiIo to issue
> +    // "REQUEST SENSE" for the sense data.
> +    //
> +    if (Cdb[0] == 0x00) {
> +      Packet->SenseDataLength = 0;
> +    }
> +    Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK;
> +    Packet->TargetStatus      = EFI_EXT_SCSI_STATUS_TARGET_GOOD;
> +
> +    return EFI_SUCCESS;
> +  }

The mapping on success does not deal with short transfers (in or out) --
we're supposed to update InTransferLength / OutTransferLength on output.

(15) Does the device report short transfers somehow?


The spec says about SenseDataLength, "On input, the length in bytes of
the SenseData buffer. On output, the number of bytes written to the
SenseData buffer".

But we only set SenseDataLength conditionally. In case we do *not* set
it, the caller may attempt to parse garbage from the "SenseData" buffer.

(16) We should either get real sense data back to the caller, or always
zero out "SenseDataLength".


> +
> +Error:
> +  DEBUG((DEBUG_VERBOSE, "%a: dstat: %02X, sist0: %02X, sist1: %02X\n",
> +         __FUNCTION__, DStat, SIst0, SIst1));

(17) missing space after "DEBUG".

(18) The line starting with __FUNCTION__ is not correctly indented.


> +  //
> +  // Update the request packet to reflect the status.
> +  //
> +  if (*ScsiStatus != 0xFF) {
> +    Packet->TargetStatus    = *ScsiStatus;
> +  } else {
> +    Packet->TargetStatus    = EFI_EXT_SCSI_STATUS_TARGET_TASK_ABORTED;
> +  }
> +  Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;
> +  Packet->InTransferLength  = 0;
> +  Packet->OutTransferLength = 0;
> +  Packet->SenseDataLength   = 0;
> +
> +  return EFI_DEVICE_ERROR;
> +}
> +
>  //
>  // The next seven functions implement EFI_EXT_SCSI_PASS_THRU_PROTOCOL
>  // for the LSI 53C895A SCSI Controller. Refer to UEFI Spec 2.3.1 + Errata C,
> @@ -168,6 +470,11 @@ LsiScsiPassThru (
>      return Status;
>    }
>
> +  Status = LsiScsiProcessRequest (Dev, *Target, Lun, Packet);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
>    return EFI_SUCCESS;
>  }
>

(19) I think this can be simplified -- just return Status after calling
LsiScsiProcessRequest().


> @@ -469,6 +776,7 @@ LsiScsiControllerStart (
>
>    Dev->MaxTarget = PcdGet8 (PcdLsiScsiMaxTargetLimit);
>    Dev->MaxLun = PcdGet8 (PcdLsiScsiMaxLunLimit);
> +  Dev->StallPerPollUsec = PcdGet32 (PcdLsiScsiStallPerPollUsec);
>
>    Status = gBS->OpenProtocol (
>                    ControllerHandle,
> diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.h b/OvmfPkg/LsiScsiDxe/LsiScsi.h
> index 9272eb7506c7..1a16ef9f7795 100644
> --- a/OvmfPkg/LsiScsiDxe/LsiScsi.h
> +++ b/OvmfPkg/LsiScsiDxe/LsiScsi.h
> @@ -13,6 +13,11 @@
>  #define _LSI_SCSI_DXE_H_
>
>  typedef struct {
> +  //
> +  // Allocate 32 UINT32 entries for the script and it's sufficient for
> +  // 16 instructions.
> +  //
> +  UINT32                          Script[32];
>    //
>    // The max size of CDB is 32.
>    //
> @@ -21,6 +26,18 @@ typedef struct {
>    // Allocate 64KB for read/write buffer.
>    //
>    UINT8                           Data[0x10000];
> +  //
> +  // For SCSI Message In phase
> +  //
> +  UINT8                           MsgIn[2];
> +  //
> +  // For SCSI Message Out phase
> +  //
> +  UINT8                           MsgOut;
> +  //
> +  // For SCSI Status phase
> +  //
> +  UINT8                           Status;
>  } LSI_SCSI_DMA_BUFFER;
>
>  typedef struct {
> @@ -30,6 +47,7 @@ typedef struct {
>    EFI_PCI_IO_PROTOCOL             *PciIo;
>    UINT8                           MaxTarget;
>    UINT8                           MaxLun;
> +  UINT32                          StallPerPollUsec;
>    LSI_SCSI_DMA_BUFFER             *Dma;
>    EFI_PHYSICAL_ADDRESS            DmaPhysical;
>    VOID                            *DmaMapping;
> @@ -42,6 +60,9 @@ typedef struct {
>  #define LSI_SCSI_FROM_PASS_THRU(PassThruPtr) \
>    CR (PassThruPtr, LSI_SCSI_DEV, PassThru, LSI_SCSI_DEV_SIGNATURE)
>
> +#define LSI_SCSI_DMA_ADDR_LOW(Dev, MemberName) \
> +  ((UINT32)(Dev->DmaPhysical + OFFSET_OF (LSI_SCSI_DMA_BUFFER, MemberName)))
> +
>
>  //
>  // Probe, start and stop functions of this driver, called by the DXE core for
> diff --git a/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf b/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> index 68844c6772e3..cbd7294573ac 100644
> --- a/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> +++ b/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> @@ -41,3 +41,6 @@ [Protocols]
>  [FixedPcd]
>    gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiMaxTargetLimit   ## CONSUMES
>    gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiMaxLunLimit      ## CONSUMES
> +
> +[Pcd]
> +  gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiStallPerPollUsec ## CONSUMES
> diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
> index ae7d1d648d22..57e418d4b8a9 100644
> --- a/OvmfPkg/OvmfPkg.dec
> +++ b/OvmfPkg/OvmfPkg.dec
> @@ -179,6 +179,9 @@ [PcdsFixedAtBuild]
>    gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiMaxTargetLimit|7|UINT8|0x3b
>    gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiMaxLunLimit|0|UINT8|0x3c
>
> +  ## Microseconds to stall between polling for LsiScsi request result
> +  gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiStallPerPollUsec|5|UINT32|0x3d
> +

(20) The token value should be 0x3c here, according to my request (5)
under "[PATCH 06/11] OvmfPkg/LsiScsiDxe: Report Targets and LUNs".


>    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogBase|0x0|UINT32|0x8
>    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogSize|0x0|UINT32|0x9
>    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareFdSize|0x0|UINT32|0xa
>

Thanks
Laszlo


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 11/11] Maintainers.txt: Add myself as the reviewer for LsiScsi driver
  2020-07-01  4:04 ` [PATCH 11/11] Maintainers.txt: Add myself as the reviewer for LsiScsi driver Gary Lin
@ 2020-07-07 12:49   ` Laszlo Ersek
  2020-07-08  6:03     ` Gary Lin
  0 siblings, 1 reply; 35+ messages in thread
From: Laszlo Ersek @ 2020-07-07 12:49 UTC (permalink / raw)
  To: Gary Lin, devel; +Cc: Jordan Justen, Ard Biesheuvel

On 07/01/20 06:04, Gary Lin wrote:
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
> Signed-off-by: Gary Lin <glin@suse.com>
> ---
>  Maintainers.txt | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/Maintainers.txt b/Maintainers.txt
> index 32c9003a6209..666d3af4d76a 100644
> --- a/Maintainers.txt
> +++ b/Maintainers.txt
> @@ -400,6 +400,10 @@ OvmfPkg: CSM modules
>  F: OvmfPkg/Csm/
>  R: David Woodhouse <dwmw2@infradead.org>
>  
> +OvmfPkg: LsiScsi Driver
> +F: OvmfPkg/LsiScsiDxe/
> +R: Gary Lin <glin@suse.com>
> +
>  OvmfPkg: MptScsi and PVSCSI driver
>  F: OvmfPkg/MptScsiDxe/
>  F: OvmfPkg/PvScsiDxe/
> 

(1) Please use your name rather than "myself" in the subject -- consider
"git log --oneline".

(2) Please write "driver" rather than "Driver" in the new entry, for
consistency with the "MptScsi and PVSCSI" entry (and other entries in
the file too).

With those updates:

Reviewed-by: Laszlo Ersek <lersek@redhat.com>

Thanks
Laszlo


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 06/11] OvmfPkg/LsiScsiDxe: Report Targets and LUNs
  2020-07-07  9:04   ` Laszlo Ersek
@ 2020-07-08  2:34     ` Gary Lin
  2020-07-08 15:26       ` Laszlo Ersek
  0 siblings, 1 reply; 35+ messages in thread
From: Gary Lin @ 2020-07-08  2:34 UTC (permalink / raw)
  To: Laszlo Ersek; +Cc: devel, Jordan Justen, Ard Biesheuvel

On Tue, Jul 07, 2020 at 11:04:21AM +0200, Laszlo Ersek wrote:
> On 07/01/20 06:04, Gary Lin wrote:
> > Implement LsiScsiGetNextTargetLun(), LsiScsiBuildDevicePath(),
> > LsiScsiGetTargetLun(), and LsiScsiGetNextTarget() to report Targets and
> > LUNs and build the device path.
> > 
> > This commit also introduces two PCD value: PcdLsiScsiMaxTargetLimit and
> > PcdLsiScsiMaxLunLimit as the limits for Targets and LUNs.
> > 
> > Cc: Jordan Justen <jordan.l.justen@intel.com>
> > Cc: Laszlo Ersek <lersek@redhat.com>
> > Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
> > Signed-off-by: Gary Lin <glin@suse.com>
> > ---
> >  OvmfPkg/LsiScsiDxe/LsiScsi.c      | 143 +++++++++++++++++++++++++++++-
> >  OvmfPkg/LsiScsiDxe/LsiScsi.h      |   3 +
> >  OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf |   6 ++
> >  OvmfPkg/OvmfPkg.dec               |   5 ++
> >  4 files changed, 155 insertions(+), 2 deletions(-)
> > 
> > diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.c b/OvmfPkg/LsiScsiDxe/LsiScsi.c
> > index f633c6793298..e10a81a5f9f7 100644
> > --- a/OvmfPkg/LsiScsiDxe/LsiScsi.c
> > +++ b/OvmfPkg/LsiScsiDxe/LsiScsi.c
> > @@ -15,6 +15,7 @@
> >  #include <Library/BaseMemoryLib.h>
> >  #include <Library/DebugLib.h>
> >  #include <Library/MemoryAllocationLib.h>
> > +#include <Library/PcdLib.h>
> >  #include <Library/UefiBootServicesTableLib.h>
> >  #include <Library/UefiLib.h>
> >  #include <Protocol/PciIo.h>
> > @@ -53,6 +54,49 @@ LsiScsiGetNextTargetLun (
> >    IN OUT UINT64                      *Lun
> >    )
> >  {
> > +  LSI_SCSI_DEV *Dev;
> > +  UINTN        Idx;
> > +  UINT8        *Target;
> > +  UINT16       LastTarget;
> > +
> > +  //
> > +  // the TargetPointer input parameter is unnecessarily a pointer-to-pointer
> > +  //
> > +  Target = *TargetPointer;
> > +
> > +  //
> > +  // Search for first non-0xFF byte. If not found, return first target & LUN.
> > +  //
> > +  for (Idx = 0; Idx < TARGET_MAX_BYTES && Target[Idx] == 0xFF; ++Idx)
> > +    ;
> > +  if (Idx == TARGET_MAX_BYTES) {
> > +    SetMem (Target, TARGET_MAX_BYTES, 0x00);
> > +    *Lun = 0;
> > +    return EFI_SUCCESS;
> > +  }
> > +
> > +  CopyMem (&LastTarget, Target, sizeof LastTarget);
> > +
> > +  //
> > +  // increment (target, LUN) pair if valid on input
> > +  //
> > +  Dev = LSI_SCSI_FROM_PASS_THRU (This);
> > +  if (LastTarget > Dev->MaxTarget || *Lun > Dev->MaxLun) {
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  if (*Lun < Dev->MaxLun) {
> > +    ++*Lun;
> > +    return EFI_SUCCESS;
> > +  }
> > +
> > +  if (LastTarget < Dev->MaxTarget) {
> > +    *Lun = 0;
> > +    ++LastTarget;
> > +    CopyMem (Target, &LastTarget, sizeof LastTarget);
> > +    return EFI_SUCCESS;
> > +  }
> > +
> >    return EFI_NOT_FOUND;
> >  }
> >  
> > @@ -65,7 +109,34 @@ LsiScsiBuildDevicePath (
> >    IN OUT EFI_DEVICE_PATH_PROTOCOL    **DevicePath
> >    )
> >  {
> > -  return EFI_NOT_FOUND;
> > +  UINT16           TargetValue;
> > +  LSI_SCSI_DEV     *Dev;
> > +  SCSI_DEVICE_PATH *ScsiDevicePath;
> > +
> > +  if (DevicePath == NULL) {
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  CopyMem (&TargetValue, Target, sizeof TargetValue);
> > +  Dev = LSI_SCSI_FROM_PASS_THRU (This);
> > +  if (TargetValue > Dev->MaxTarget || Lun > Dev->MaxLun || Lun > 0xFFFF) {
> > +    return EFI_NOT_FOUND;
> > +  }
> > +
> > +  ScsiDevicePath = AllocatePool (sizeof *ScsiDevicePath);
> > +  if (ScsiDevicePath == NULL) {
> > +    return EFI_OUT_OF_RESOURCES;
> > +  }
> > +
> > +  ScsiDevicePath->Header.Type      = MESSAGING_DEVICE_PATH;
> > +  ScsiDevicePath->Header.SubType   = MSG_SCSI_DP;
> > +  ScsiDevicePath->Header.Length[0] = (UINT8)  sizeof *ScsiDevicePath;
> > +  ScsiDevicePath->Header.Length[1] = (UINT8) (sizeof *ScsiDevicePath >> 8);
> > +  ScsiDevicePath->Pun              = TargetValue;
> > +  ScsiDevicePath->Lun              = (UINT16) Lun;
> > +
> > +  *DevicePath = &ScsiDevicePath->Header;
> > +  return EFI_SUCCESS;
> >  }
> >  
> >  EFI_STATUS
> > @@ -77,7 +148,36 @@ LsiScsiGetTargetLun (
> >    OUT UINT64                          *Lun
> >    )
> >  {
> > -  return EFI_UNSUPPORTED;
> > +  SCSI_DEVICE_PATH *ScsiDevicePath;
> > +  LSI_SCSI_DEV     *Dev;
> > +  UINT8            *Target;
> > +
> > +  if (DevicePath == NULL || TargetPointer == NULL || *TargetPointer == NULL ||
> > +      Lun == NULL) {
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  if (DevicePath->Type    != MESSAGING_DEVICE_PATH ||
> > +      DevicePath->SubType != MSG_SCSI_DP) {
> > +    return EFI_UNSUPPORTED;
> > +  }
> > +
> > +  ScsiDevicePath = (SCSI_DEVICE_PATH *) DevicePath;
> > +  Dev = LSI_SCSI_FROM_PASS_THRU (This);
> > +  if (ScsiDevicePath->Pun > Dev->MaxTarget ||
> > +      ScsiDevicePath->Lun > Dev->MaxLun) {
> > +    return EFI_NOT_FOUND;
> > +  }
> > +
> > +  //
> > +  // This device support 8 targets only, so it's enough to set the LSB
> > +  // of Target.
> > +  //
> > +  Target = *TargetPointer;
> > +  *Target = (UINT8)ScsiDevicePath->Pun;
> 
> I don't like this shortcut.
> 
> The first reason is that the shortcut is not consistent with the rest of
> the functions implemented in this patch. The other functions handle
> target numbers that extend up to two bytes; there are no single-byte
> shortcuts in them.
> 
> (1) So please either rewrite all of those functions to use a similar
> shortcut like here, or please remove this shortcut, and stick with a
> 2-byte sized CopyMem() here too. I prefer the latter.
> 
> (2) Whether you use the single-byte shortcut or not, please zero out the
> bytes in (*Target) that you do not set otherwise (from Pun).
> 
> (3) If the device supports only 8 targets, then please add an according
> STATIC_ASSERT() on PcdLsiScsiMaxTargetLimit somewhere. For example:
> 
>   STATIC_ASSERT (
>     FixedPcdGet8 (PcdLsiScsiMaxTargetLimit) < 8,
>     "LSI 53C895A supports targets [0..7]"
>     );
> 
> It's probably best to add the assert in LsiScsiControllerStart() below,
> where you fetch the PCD anyway.
> 
Will change it to CopyMem() and add an assert to make sure MaxTarget is
always below 8.

> > +  *Lun = ScsiDevicePath->Lun;
> > +
> > +  return EFI_SUCCESS;
> >  }
> >  
> >  EFI_STATUS
> > @@ -107,6 +207,42 @@ LsiScsiGetNextTarget (
> >    IN OUT UINT8                       **TargetPointer
> >    )
> >  {
> > +  LSI_SCSI_DEV *Dev;
> > +  UINTN        Idx;
> > +  UINT8        *Target;
> > +  UINT16       LastTarget;
> > +
> > +  //
> > +  // the TargetPointer input parameter is unnecessarily a pointer-to-pointer
> > +  //
> > +  Target = *TargetPointer;
> > +
> > +  //
> > +  // Search for first non-0xFF byte. If not found, return first target.
> > +  //
> > +  for (Idx = 0; Idx < TARGET_MAX_BYTES && Target[Idx] == 0xFF; ++Idx)
> > +    ;
> > +  if (Idx == TARGET_MAX_BYTES) {
> > +    SetMem (Target, TARGET_MAX_BYTES, 0x00);
> > +    return EFI_SUCCESS;
> > +  }
> > +
> > +  CopyMem (&LastTarget, Target, sizeof LastTarget);
> > +
> > +  //
> > +  // increment target if valid on input
> > +  //
> > +  Dev = LSI_SCSI_FROM_PASS_THRU (This);
> > +  if (LastTarget > Dev->MaxTarget) {
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  if (LastTarget < Dev->MaxTarget) {
> > +    ++LastTarget;
> > +    CopyMem (Target, &LastTarget, sizeof LastTarget);
> > +    return EFI_SUCCESS;
> > +  }
> > +
> >    return EFI_NOT_FOUND;
> >  }
> >  
> > @@ -189,6 +325,9 @@ LsiScsiControllerStart (
> >  
> >    Dev->Signature = LSI_SCSI_DEV_SIGNATURE;
> >  
> > +  Dev->MaxTarget = PcdGet8 (PcdLsiScsiMaxTargetLimit);
> > +  Dev->MaxLun = PcdGet8 (PcdLsiScsiMaxLunLimit);
> > +
> >    //
> >    // Host adapter channel, doesn't exist
> >    //
> > diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.h b/OvmfPkg/LsiScsiDxe/LsiScsi.h
> > index fca1007f9b98..a3d51d8f2386 100644
> > --- a/OvmfPkg/LsiScsiDxe/LsiScsi.h
> > +++ b/OvmfPkg/LsiScsiDxe/LsiScsi.h
> > @@ -14,6 +14,8 @@
> >  
> >  typedef struct {
> >    UINT32                          Signature;
> > +  UINT8                           MaxTarget;
> > +  UINT8                           MaxLun;
> >    EFI_EXT_SCSI_PASS_THRU_MODE     PassThruMode;
> >    EFI_EXT_SCSI_PASS_THRU_PROTOCOL PassThru;
> >  } LSI_SCSI_DEV;
> > @@ -23,6 +25,7 @@ typedef struct {
> >  #define LSI_SCSI_FROM_PASS_THRU(PassThruPtr) \
> >    CR (PassThruPtr, LSI_SCSI_DEV, PassThru, LSI_SCSI_DEV_SIGNATURE)
> >  
> > +
> >  //
> >  // Probe, start and stop functions of this driver, called by the DXE core for
> >  // specific devices.
> 
> (4) Spurious newline, please drop it. (Or squash it in the previous
> patch -- for example --, where you define the LSI_SCSI_FROM_PASS_THRU
> macro.)
> 
Will remove the newline.

> > diff --git a/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf b/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> > index 8660513e2ffd..68844c6772e3 100644
> > --- a/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> > +++ b/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> > @@ -27,7 +27,9 @@ [Packages]
> >  [LibraryClasses]
> >    BaseLib
> >    BaseMemoryLib
> > +  DebugLib
> >    MemoryAllocationLib
> > +  PcdLib
> >    UefiBootServicesTableLib
> >    UefiDriverEntryPoint
> >    UefiLib
> > @@ -35,3 +37,7 @@ [LibraryClasses]
> >  [Protocols]
> >    gEfiExtScsiPassThruProtocolGuid        ## BY_START
> >    gEfiPciIoProtocolGuid                  ## TO_START
> > +
> > +[FixedPcd]
> > +  gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiMaxTargetLimit   ## CONSUMES
> > +  gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiMaxLunLimit      ## CONSUMES
> > diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
> > index 65bb2bb0eb4c..ae7d1d648d22 100644
> > --- a/OvmfPkg/OvmfPkg.dec
> > +++ b/OvmfPkg/OvmfPkg.dec
> > @@ -174,6 +174,11 @@ [PcdsFixedAtBuild]
> >    ## Microseconds to stall between polling for MptScsi request result
> >    gUefiOvmfPkgTokenSpaceGuid.PcdMptScsiStallPerPollUsec|5|UINT32|0x40
> >  
> > +  ## Set the *inclusive* number of targets and LUNs that LsiScsi exposes for
> > +  #  scan by ScsiBusDxe.
> > +  gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiMaxTargetLimit|7|UINT8|0x3b
> > +  gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiMaxLunLimit|0|UINT8|0x3c
> > +
> >    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogBase|0x0|UINT32|0x8
> >    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogSize|0x0|UINT32|0x9
> >    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareFdSize|0x0|UINT32|0xa
> > 
> 
> Commit 093cceaf79b5 ("OvmfPkg/MptScsiDxe: Report targets and one LUN",
> 2020-05-05) introduced PcdMptScsiMaxTargetLimit with token value 0x39.
> That was OK.
> 
> Commit 505812ae1d2d ("OvmfPkg/MptScsiDxe: Implement the PassThru
> method", 2020-05-05) then introduced PcdMptScsiStallPerPollUsec with
> token value 0x40. That was not OK -- but I missed it. (The token value
> should have been 0x3a; as 0x39 is not succeeded by 0x40 but by 0x3a.)
> 
> Token value 0x3a remains unused at this point.
> 
> (5) So please introduce the new PCDs with token values 0x3a and 0x3b, to
> keep the token space dense.
> 
I actually was thinking about making PcdMptScsiStallPerPollUsec 0x3a in
another patch. Since it's not related to LsiScsi, I didn't do it in this
series. Sounds like you prefer to keeping 0x40 for
PcdMptScsiStallPerPollUsec?

Gary Lin


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 07/11] OvmfPkg/LsiScsiDxe: Open PciIo protocol and initialize the device
  2020-07-07  9:46   ` Laszlo Ersek
@ 2020-07-08  2:37     ` Gary Lin
  0 siblings, 0 replies; 35+ messages in thread
From: Gary Lin @ 2020-07-08  2:37 UTC (permalink / raw)
  To: Laszlo Ersek; +Cc: devel, Jordan Justen, Ard Biesheuvel

On Tue, Jul 07, 2020 at 11:46:28AM +0200, Laszlo Ersek wrote:
> On 07/01/20 06:04, Gary Lin wrote:
> > Open PciIo protocol and use it to initialize the device. The
> > initialization of LSI 53C895A is simple: just set the SRST bit in
> > Interrupt Status Zero register to reset the device.
> > 
> > Cc: Jordan Justen <jordan.l.justen@intel.com>
> > Cc: Laszlo Ersek <lersek@redhat.com>
> > Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
> > Signed-off-by: Gary Lin <glin@suse.com>
> > ---
> >  OvmfPkg/Include/IndustryStandard/LsiScsi.h |  21 ++++
> >  OvmfPkg/LsiScsiDxe/LsiScsi.c               | 129 ++++++++++++++++++++-
> >  OvmfPkg/LsiScsiDxe/LsiScsi.h               |   3 +
> >  3 files changed, 152 insertions(+), 1 deletion(-)
> > 
> > diff --git a/OvmfPkg/Include/IndustryStandard/LsiScsi.h b/OvmfPkg/Include/IndustryStandard/LsiScsi.h
> > index c09e864a1f39..60e527f1c6a7 100644
> > --- a/OvmfPkg/Include/IndustryStandard/LsiScsi.h
> > +++ b/OvmfPkg/Include/IndustryStandard/LsiScsi.h
> > @@ -17,4 +17,25 @@
> >  #define LSI_LOGIC_PCI_VENDOR_ID   0x1000
> >  #define LSI_53C895A_PCI_DEVICE_ID 0x0012
> >  
> > +//
> > +// LSI 53C895A Registers
> > +//
> > +#define LSI_REG_DSTAT             0x0C
> > +#define LSI_REG_ISTAT0            0x14
> > +#define LSI_REG_DSP               0x2C
> > +#define LSI_REG_SIST0             0x42
> > +#define LSI_REG_SIST1             0x43
> > +
> > +//
> > +// The status bits for Interrupt Status Zero (ISTAT0)
> > +//
> > +#define LSI_ISTAT0_DIP            0x01
> > +#define LSI_ISTAT0_SIP            0x02
> > +#define LSI_ISTAT0_INTF           0x04
> > +#define LSI_ISTAT0_CON            0x08
> > +#define LSI_ISTAT0_SEM            0x10
> > +#define LSI_ISTAT0_SIGP           0x20
> > +#define LSI_ISTAT0_SRST           0x40
> > +#define LSI_ISTAT0_ABRT           0x80
> 
> (1) Please use the BIT0, BIT1, ... etc macros, which are more idiomatic
> in edk2 than open-coded constants like 0x01, 0x02, ...
> 
Got it. Will do it to improve the readability.

> > +
> >  #endif // _LSI_SCSI_H_
> > diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.c b/OvmfPkg/LsiScsiDxe/LsiScsi.c
> > index e10a81a5f9f7..f03774cc4ced 100644
> > --- a/OvmfPkg/LsiScsiDxe/LsiScsi.c
> > +++ b/OvmfPkg/LsiScsiDxe/LsiScsi.c
> > @@ -25,6 +25,33 @@
> >  
> >  #include "LsiScsi.h"
> >  
> > +STATIC
> > +EFI_STATUS
> > +Out8 (
> > +  IN LSI_SCSI_DEV *Dev,
> > +  IN UINT32       Addr,
> > +  IN UINT8        Data
> > +  )
> > +{
> > +  return Dev->PciIo->Io.Write (
> > +                          Dev->PciIo,
> > +                          EfiPciIoWidthUint8,
> > +                          PCI_BAR_IDX0,
> > +                          Addr,
> > +                          1,
> > +                          &Data
> > +                          );
> > +}
> > +
> > +STATIC
> > +EFI_STATUS
> > +LsiScsiReset (
> > +  IN LSI_SCSI_DEV *Dev
> > +  )
> > +{
> > +  return Out8 (Dev, LSI_REG_ISTAT0, LSI_ISTAT0_SRST);
> > +}
> > +
> >  //
> >  // The next seven functions implement EFI_EXT_SCSI_PASS_THRU_PROTOCOL
> >  // for the LSI 53C895A SCSI Controller. Refer to UEFI Spec 2.3.1 + Errata C,
> > @@ -246,6 +273,21 @@ LsiScsiGetNextTarget (
> >    return EFI_NOT_FOUND;
> >  }
> >  
> > +STATIC
> > +VOID
> > +EFIAPI
> > +LsiScsiExitBoot (
> > +  IN  EFI_EVENT Event,
> > +  IN  VOID      *Context
> > +  )
> > +{
> > +  LSI_SCSI_DEV *Dev;
> > +
> > +  Dev = Context;
> > +  DEBUG ((DEBUG_VERBOSE, "%a: Context=0x%p\n", __FUNCTION__, Context));
> > +  LsiScsiReset (Dev);
> > +}
> > +
> >  //
> >  // Probe, start and stop functions of this driver, called by the DXE core for
> >  // specific devices.
> > @@ -328,6 +370,58 @@ LsiScsiControllerStart (
> >    Dev->MaxTarget = PcdGet8 (PcdLsiScsiMaxTargetLimit);
> >    Dev->MaxLun = PcdGet8 (PcdLsiScsiMaxLunLimit);
> >  
> > +  Status = gBS->OpenProtocol (
> > +                  ControllerHandle,
> > +                  &gEfiPciIoProtocolGuid,
> > +                  (VOID **)&Dev->PciIo,
> > +                  This->DriverBindingHandle,
> > +                  ControllerHandle,
> > +                  EFI_OPEN_PROTOCOL_BY_DRIVER
> > +                  );
> > +  if (EFI_ERROR (Status)) {
> > +    goto FreePool;
> > +  }
> > +
> > +  Status = Dev->PciIo->Attributes (
> > +                         Dev->PciIo,
> > +                         EfiPciIoAttributeOperationGet,
> > +                         0,
> > +                         &Dev->OrigPciAttrs
> > +                         );
> > +  if (EFI_ERROR (Status)) {
> > +    goto CloseProtocol;
> > +  }
> > +
> > +  //
> > +  // Enable I/O Space & Bus-Mastering
> > +  //
> > +  Status = Dev->PciIo->Attributes (
> > +                         Dev->PciIo,
> > +                         EfiPciIoAttributeOperationEnable,
> > +                         (EFI_PCI_IO_ATTRIBUTE_IO |
> > +                          EFI_PCI_IO_ATTRIBUTE_BUS_MASTER),
> > +                         NULL
> > +                         );
> > +  if (EFI_ERROR (Status)) {
> > +    goto CloseProtocol;
> > +  }
> > +
> > +  Status = LsiScsiReset (Dev);
> > +  if (EFI_ERROR (Status)) {
> > +    goto RestoreAttributes;
> > +  }
> > +
> > +  Status = gBS->CreateEvent (
> > +                  EVT_SIGNAL_EXIT_BOOT_SERVICES,
> > +                  TPL_CALLBACK,
> > +                  &LsiScsiExitBoot,
> > +                  Dev,
> > +                  &Dev->ExitBoot
> > +                  );
> > +  if (EFI_ERROR (Status)) {
> > +    goto UninitDev;
> > +  }
> > +
> >    //
> >    // Host adapter channel, doesn't exist
> >    //
> > @@ -352,11 +446,33 @@ LsiScsiControllerStart (
> >                    &Dev->PassThru
> >                    );
> >    if (EFI_ERROR (Status)) {
> > -    goto FreePool;
> > +    goto CloseExitBoot;
> >    }
> >  
> >    return EFI_SUCCESS;
> >  
> > +CloseExitBoot:
> > +  gBS->CloseEvent (Dev->ExitBoot);
> > +
> > +UninitDev:
> > +  LsiScsiReset (Dev);
> > +
> > +RestoreAttributes:
> > +  Dev->PciIo->Attributes (
> > +                Dev->PciIo,
> > +                EfiPciIoAttributeOperationSet,
> > +                Dev->OrigPciAttrs,
> > +                NULL
> > +                );
> > +
> > +CloseProtocol:
> > +  gBS->CloseProtocol (
> > +         ControllerHandle,
> > +         &gEfiPciIoProtocolGuid,
> > +         This->DriverBindingHandle,
> > +         ControllerHandle
> > +         );
> > +
> >  FreePool:
> >    FreePool (Dev);
> >  
> > @@ -399,6 +515,17 @@ LsiScsiControllerStop (
> >      return Status;
> >    }
> >  
> > +  gBS->CloseEvent (Dev->ExitBoot);
> > +
> > +  LsiScsiReset (Dev);
> > +
> > +  Dev->PciIo->Attributes (
> > +                Dev->PciIo,
> > +                EfiPciIoAttributeOperationSet,
> > +                Dev->OrigPciAttrs,
> > +                NULL
> > +                );
> > +
> >    gBS->CloseProtocol (
> >           ControllerHandle,
> >           &gEfiPciIoProtocolGuid,
> 
> (2) So as I said under "[PATCH 05/11] OvmfPkg/LsiScsiDxe: Install
> stubbed EXT_SCSI_PASS_THRU", this CloseProtocol() call should not be
> "context" here (from patch 05/11); it should be introduced here,
> reflecting the operations in LsiScsiControllerStart() that are also
> introduced in this patch.
> 
Will move the code snippet here.

Thanks,

Gary Lin

> > diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.h b/OvmfPkg/LsiScsiDxe/LsiScsi.h
> > index a3d51d8f2386..ffaee6188536 100644
> > --- a/OvmfPkg/LsiScsiDxe/LsiScsi.h
> > +++ b/OvmfPkg/LsiScsiDxe/LsiScsi.h
> > @@ -14,6 +14,9 @@
> >  
> >  typedef struct {
> >    UINT32                          Signature;
> > +  UINT64                          OrigPciAttrs;
> > +  EFI_EVENT                       ExitBoot;
> > +  EFI_PCI_IO_PROTOCOL             *PciIo;
> >    UINT8                           MaxTarget;
> >    UINT8                           MaxLun;
> >    EFI_EXT_SCSI_PASS_THRU_MODE     PassThruMode;
> > 
> 
> Thanks
> Laszlo
> 


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 08/11] OvmfPkg/LsiScsiDxe: Map DMA buffer
  2020-07-07  9:59   ` Laszlo Ersek
@ 2020-07-08  2:41     ` Gary Lin
  0 siblings, 0 replies; 35+ messages in thread
From: Gary Lin @ 2020-07-08  2:41 UTC (permalink / raw)
  To: Laszlo Ersek; +Cc: devel, Jordan Justen, Ard Biesheuvel

On Tue, Jul 07, 2020 at 11:59:57AM +0200, Laszlo Ersek wrote:
> On 07/01/20 06:04, Gary Lin wrote:
> > Map DMA buffer and perpare for the implementation of LsiScsiPassThru().
> > 
> > Cc: Jordan Justen <jordan.l.justen@intel.com>
> > Cc: Laszlo Ersek <lersek@redhat.com>
> > Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
> > Signed-off-by: Gary Lin <glin@suse.com>
> > ---
> >  OvmfPkg/LsiScsiDxe/LsiScsi.c | 85 +++++++++++++++++++++++++++++++++++-
> >  OvmfPkg/LsiScsiDxe/LsiScsi.h | 10 +++++
> >  2 files changed, 94 insertions(+), 1 deletion(-)
> > 
> > diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.c b/OvmfPkg/LsiScsiDxe/LsiScsi.c
> > index f03774cc4ced..b728d18d51df 100644
> > --- a/OvmfPkg/LsiScsiDxe/LsiScsi.c
> > +++ b/OvmfPkg/LsiScsiDxe/LsiScsi.c
> > @@ -359,6 +359,8 @@ LsiScsiControllerStart (
> >  {
> >    EFI_STATUS           Status;
> >    LSI_SCSI_DEV         *Dev;
> > +  UINTN                Pages;
> > +  UINTN                BytesMapped;
> >  
> >    Dev = AllocateZeroPool (sizeof (*Dev));
> >    if (Dev == NULL) {
> > @@ -406,11 +408,68 @@ LsiScsiControllerStart (
> >      goto CloseProtocol;
> >    }
> >  
> > -  Status = LsiScsiReset (Dev);
> > +  //
> > +  // Signal device supports 64-bit DMA addresses
> > +  //
> > +  Status = Dev->PciIo->Attributes (
> > +                         Dev->PciIo,
> > +                         EfiPciIoAttributeOperationEnable,
> > +                         EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE,
> > +                         NULL
> > +                         );
> > +  if (EFI_ERROR (Status)) {
> > +    //
> > +    // Warn user that device will only be using 32-bit DMA addresses.
> > +    //
> > +    // Note that this does not prevent the device/driver from working
> > +    // and therefore we only warn and continue as usual.
> > +    //
> > +    DEBUG ((
> > +      DEBUG_WARN,
> > +      "%a: failed to enable 64-bit DMA addresses\n",
> > +      __FUNCTION__
> > +      ));
> > +  }
> > +
> > +  //
> > +  // Create buffers for data transfer
> > +  //
> > +  Pages = EFI_SIZE_TO_PAGES (sizeof (*Dev->Dma));
> > +  Status = Dev->PciIo->AllocateBuffer (
> > +                         Dev->PciIo,
> > +                         AllocateAnyPages,
> > +                         EfiBootServicesData,
> > +                         Pages,
> > +                         (VOID **)&Dev->Dma,
> > +                         EFI_PCI_ATTRIBUTE_MEMORY_CACHED
> > +                         );
> >    if (EFI_ERROR (Status)) {
> >      goto RestoreAttributes;
> >    }
> >  
> > +  BytesMapped = EFI_PAGES_TO_SIZE (Pages);
> > +  Status = Dev->PciIo->Map (
> > +                         Dev->PciIo,
> > +                         EfiPciIoOperationBusMasterCommonBuffer,
> > +                         Dev->Dma,
> > +                         &BytesMapped,
> > +                         &Dev->DmaPhysical,
> > +                         &Dev->DmaMapping
> > +                         );
> > +  if (EFI_ERROR (Status)) {
> > +    goto FreeBuffer;
> > +  }
> > +
> > +  if (BytesMapped != EFI_PAGES_TO_SIZE (Pages)) {
> > +    Status = EFI_OUT_OF_RESOURCES;
> > +    goto Unmap;
> > +  }
> > +
> > +  Status = LsiScsiReset (Dev);
> > +  if (EFI_ERROR (Status)) {
> > +    goto Unmap;
> > +  }
> > +
> >    Status = gBS->CreateEvent (
> >                    EVT_SIGNAL_EXIT_BOOT_SERVICES,
> >                    TPL_CALLBACK,
> > @@ -457,6 +516,19 @@ CloseExitBoot:
> >  UninitDev:
> >    LsiScsiReset (Dev);
> >  
> > +Unmap:
> > +  Dev->PciIo->Unmap (
> > +                Dev->PciIo,
> > +                Dev->DmaMapping
> > +                );
> > +
> > +FreeBuffer:
> > +  Dev->PciIo->FreeBuffer (
> > +                Dev->PciIo,
> > +                Pages,
> > +                Dev->Dma
> > +                );
> > +
> >  RestoreAttributes:
> >    Dev->PciIo->Attributes (
> >                  Dev->PciIo,
> > @@ -519,6 +591,17 @@ LsiScsiControllerStop (
> >  
> >    LsiScsiReset (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,
> >                  EfiPciIoAttributeOperationSet,
> > diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.h b/OvmfPkg/LsiScsiDxe/LsiScsi.h
> > index ffaee6188536..1e4bbc56f933 100644
> > --- a/OvmfPkg/LsiScsiDxe/LsiScsi.h
> > +++ b/OvmfPkg/LsiScsiDxe/LsiScsi.h
> > @@ -12,6 +12,13 @@
> >  #ifndef _LSI_SCSI_DXE_H_
> >  #define _LSI_SCSI_DXE_H_
> >  
> > +typedef struct {
> > +  //
> > +  // Allocate 64KB for read/write buffer.
> > +  //
> > +  UINT8                           Data[0x10000];
> 
> (1) Using SIZE_64KB for the size would be more idiomatic.
> 
> (2) Please add a comment that limiting the transfer size to 64KB seems
> OK in practice.
> 
> With those updates:
> 
> Reviewed-by: Laszlo Ersek <lersek@redhat.com>
> 
Will update the commit in v2.

Thanks,

Gary Lin

> Thanks
> Laszlo
> 
> > +} LSI_SCSI_DMA_BUFFER;
> > +
> >  typedef struct {
> >    UINT32                          Signature;
> >    UINT64                          OrigPciAttrs;
> > @@ -19,6 +26,9 @@ typedef struct {
> >    EFI_PCI_IO_PROTOCOL             *PciIo;
> >    UINT8                           MaxTarget;
> >    UINT8                           MaxLun;
> > +  LSI_SCSI_DMA_BUFFER             *Dma;
> > +  EFI_PHYSICAL_ADDRESS            DmaPhysical;
> > +  VOID                            *DmaMapping;
> >    EFI_EXT_SCSI_PASS_THRU_MODE     PassThruMode;
> >    EFI_EXT_SCSI_PASS_THRU_PROTOCOL PassThru;
> >  } LSI_SCSI_DEV;
> > 
> 


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 09/11] OvmfPkg/LsiScsiDxe: Examine the incoming SCSI Request Packet
  2020-07-07 10:17   ` Laszlo Ersek
@ 2020-07-08  2:43     ` Gary Lin
  0 siblings, 0 replies; 35+ messages in thread
From: Gary Lin @ 2020-07-08  2:43 UTC (permalink / raw)
  To: Laszlo Ersek; +Cc: devel, Jordan Justen, Ard Biesheuvel

On Tue, Jul 07, 2020 at 12:17:21PM +0200, Laszlo Ersek wrote:
> On 07/01/20 06:04, Gary Lin wrote:
> > This is the first part of LsiScsiPassThru(). Before processing the SCSI
> > Request packet, we have to make sure whether the packet is valid or not.
> > 
> > Cc: Jordan Justen <jordan.l.justen@intel.com>
> > Cc: Laszlo Ersek <lersek@redhat.com>
> > Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
> > Signed-off-by: Gary Lin <glin@suse.com>
> > ---
> >  OvmfPkg/LsiScsiDxe/LsiScsi.c | 100 ++++++++++++++++++++++++++++++++++-
> >  OvmfPkg/LsiScsiDxe/LsiScsi.h |   4 ++
> >  2 files changed, 103 insertions(+), 1 deletion(-)
> > 
> > diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.c b/OvmfPkg/LsiScsiDxe/LsiScsi.c
> > index b728d18d51df..1bcebd92e455 100644
> > --- a/OvmfPkg/LsiScsiDxe/LsiScsi.c
> > +++ b/OvmfPkg/LsiScsiDxe/LsiScsi.c
> > @@ -52,6 +52,95 @@ LsiScsiReset (
> >    return Out8 (Dev, LSI_REG_ISTAT0, LSI_ISTAT0_SRST);
> >  }
> >  
> > +STATIC
> > +EFI_STATUS
> > +ReportHostAdapterOverrunError (
> > +  OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
> > +  )
> > +{
> > +  Packet->SenseDataLength = 0;
> > +  Packet->HostAdapterStatus =
> > +            EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN;
> > +  Packet->TargetStatus = EFI_EXT_SCSI_STATUS_TARGET_GOOD;
> > +  return EFI_BAD_BUFFER_SIZE;
> > +}
> > +
> > +/**
> > +
> > +  Check the request packet from the Extended SCSI Pass Thru Protocol. The
> > +  request packet is modified, to be forwarded outwards by LsiScsiPassThru(),
> > +  if invalid or unsupported parameters are detected.
> > +
> > +  @param[in] Dev          The LSI 53C895A SCSI device the packet targets.
> > +
> > +  @param[in] Target       The SCSI target controlled by the LSI 53C895A SCSI
> > +                          device.
> > +
> > +  @param[in] Lun          The Logical Unit Number under the SCSI target.
> > +
> > +  @param[in out] Packet   The Extended SCSI Pass Thru Protocol packet.
> > +
> > +
> > +  @retval EFI_SUCCESS  The Extended SCSI Pass Thru Protocol packet was valid.
> > +
> > +  @return              Otherwise, invalid or unsupported parameters were
> > +                       detected. Status codes are meant for direct forwarding
> > +                       by the EFI_EXT_SCSI_PASS_THRU_PROTOCOL.PassThru()
> > +                       implementation.
> > +
> > + **/
> > +STATIC
> > +EFI_STATUS
> > +LsiScsiCheckRequest (
> > +  IN LSI_SCSI_DEV                                   *Dev,
> > +  IN UINT8                                          Target,
> > +  IN UINT64                                         Lun,
> > +  IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
> > +  )
> > +{
> > +  if (Target > Dev->MaxTarget || Lun > Dev->MaxLun ||
> > +      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->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_BIDIRECTIONAL ||
> > +      (Packet->InTransferLength > 0 && Packet->OutTransferLength > 0) ||
> > +      Packet->CdbLength > sizeof Dev->Dma->Cdb) {
> > +    return EFI_UNSUPPORTED;
> > +  }
> > +
> > +  if (Packet->InTransferLength > sizeof Dev->Dma->Data) {
> > +    Packet->InTransferLength = sizeof Dev->Dma->Data;
> > +    return ReportHostAdapterOverrunError (Packet);
> > +  }
> > +  if (Packet->OutTransferLength > sizeof Dev->Dma->Data) {
> > +    Packet->OutTransferLength = sizeof Dev->Dma->Data;
> > +    return ReportHostAdapterOverrunError (Packet);
> > +  }
> > +
> > +  return EFI_SUCCESS;
> > +}
> > +
> >  //
> >  // The next seven functions implement EFI_EXT_SCSI_PASS_THRU_PROTOCOL
> >  // for the LSI 53C895A SCSI Controller. Refer to UEFI Spec 2.3.1 + Errata C,
> > @@ -70,7 +159,16 @@ LsiScsiPassThru (
> >    IN EFI_EVENT                                      Event     OPTIONAL
> >    )
> >  {
> > -  return EFI_UNSUPPORTED;
> > +  EFI_STATUS   Status;
> > +  LSI_SCSI_DEV *Dev;
> > +
> > +  Dev = LSI_SCSI_FROM_PASS_THRU (This);
> > +  Status = LsiScsiCheckRequest (Dev, *Target, Lun, Packet);
> > +  if (EFI_ERROR (Status)) {
> > +    return Status;
> > +  }
> > +
> > +  return EFI_SUCCESS;
> >  }
> >  
> >  EFI_STATUS
> 
> In this patch, we do not implement LsiScsiPassThru() completely yet.
> Therefore we should not return EFI_SUCCESS, just because
> LsiScsiCheckRequest() succeeds.
> 
> (1) So please keep the EFI_UNSUPPORTED value for the last "return"
> statement in the function, for now.
> 
> EFI_UNSUPPORTED should be replaced with EFI_SUCCESS in "[PATCH 10/11]
> OvmfPkg/LsiScsiDxe: Process the SCSI Request Packet".
> 
Agree. EFI_UNSUPPORTED is more reasonable status for this
half-implemented function.

> With that update, for this patch:
> 
> Reviewed-by: Laszlo Ersek <lersek@redhat.com>
> 
Will update this commit in v2.

Thanks,

Gary Lin

> Thanks
> Laszlo
> 
> > diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.h b/OvmfPkg/LsiScsiDxe/LsiScsi.h
> > index 1e4bbc56f933..9272eb7506c7 100644
> > --- a/OvmfPkg/LsiScsiDxe/LsiScsi.h
> > +++ b/OvmfPkg/LsiScsiDxe/LsiScsi.h
> > @@ -13,6 +13,10 @@
> >  #define _LSI_SCSI_DXE_H_
> >  
> >  typedef struct {
> > +  //
> > +  // The max size of CDB is 32.
> > +  //
> > +  UINT8                           Cdb[32];
> >    //
> >    // Allocate 64KB for read/write buffer.
> >    //
> > 
> 


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 10/11] OvmfPkg/LsiScsiDxe: Process the SCSI Request Packet
  2020-07-07 12:46   ` Laszlo Ersek
@ 2020-07-08  6:02     ` Gary Lin
       [not found]     ` <161FB1B03BD2D339.11266@groups.io>
  1 sibling, 0 replies; 35+ messages in thread
From: Gary Lin @ 2020-07-08  6:02 UTC (permalink / raw)
  To: Laszlo Ersek; +Cc: devel, Jordan Justen, Ard Biesheuvel

On Tue, Jul 07, 2020 at 02:46:14PM +0200, Laszlo Ersek wrote:
> On 07/01/20 06:04, Gary Lin wrote:
> > This is the second part of LsiScsiPassThru(). LsiScsiProcessRequest() is
> > added to translate the SCSI Request Packet into the LSI 53C895A
> > commands. This function utilizes the so-called Script buffer to transmit
> > a series of commands to the chip and then polls the DMA Status (DSTAT)
> > register until the Scripts Interrupt Instruction Received (SIR) bit
> > sets. Once the script is done, the SCSI Request Packet will be modified
> > to reflect the result of the script.
> >
> > Cc: Jordan Justen <jordan.l.justen@intel.com>
> > Cc: Laszlo Ersek <lersek@redhat.com>
> > Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
> > Signed-off-by: Gary Lin <glin@suse.com>
> > ---
> >  OvmfPkg/Include/IndustryStandard/LsiScsi.h |  39 +++
> >  OvmfPkg/LsiScsiDxe/LsiScsi.c               | 308 +++++++++++++++++++++
> >  OvmfPkg/LsiScsiDxe/LsiScsi.h               |  21 ++
> >  OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf          |   3 +
> >  OvmfPkg/OvmfPkg.dec                        |   3 +
> >  5 files changed, 374 insertions(+)
> >
> > diff --git a/OvmfPkg/Include/IndustryStandard/LsiScsi.h b/OvmfPkg/Include/IndustryStandard/LsiScsi.h
> > index 60e527f1c6a7..cbf049c18310 100644
> > --- a/OvmfPkg/Include/IndustryStandard/LsiScsi.h
> > +++ b/OvmfPkg/Include/IndustryStandard/LsiScsi.h
> > @@ -26,6 +26,18 @@
> >  #define LSI_REG_SIST0             0x42
> >  #define LSI_REG_SIST1             0x43
> >
> > +//
> > +// The status bits for DMA Status (DSTAT)
> > +//
> > +#define LSI_DSTAT_IID             0x01
> > +#define LSI_DSTAT_R               0x02
> > +#define LSI_DSTAT_SIR             0x04
> > +#define LSI_DSTAT_SSI             0x08
> > +#define LSI_DSTAT_ABRT            0x10
> > +#define LSI_DSTAT_BF              0x20
> > +#define LSI_DSTAT_MDPE            0x40
> > +#define LSI_DSTAT_DFE             0x80
> > +
> 
> (1) Please use the BITx macros.
> 
Will fix it.

> 
> >  //
> >  // The status bits for Interrupt Status Zero (ISTAT0)
> >  //
> > @@ -38,4 +50,31 @@
> >  #define LSI_ISTAT0_SRST           0x40
> >  #define LSI_ISTAT0_ABRT           0x80
> >
> > +//
> > +// LSI 53C895A Script Instructions
> > +//
> > +#define LSI_INS_TYPE_BLK          0x00000000
> > +#define LSI_INS_TYPE_IO           0x40000000
> > +#define LSI_INS_TYPE_TC           0x80000000
> > +
> > +#define LSI_INS_BLK_SCSIP_DAT_OUT 0x00000000
> > +#define LSI_INS_BLK_SCSIP_DAT_IN  0x01000000
> > +#define LSI_INS_BLK_SCSIP_CMD     0x02000000
> > +#define LSI_INS_BLK_SCSIP_STAT    0x03000000
> > +#define LSI_INS_BLK_SCSIP_MSG_OUT 0x06000000
> > +#define LSI_INS_BLK_SCSIP_MSG_IN  0x07000000
> > +
> > +#define LSI_INS_IO_OPC_SEL        0x00000000
> > +#define LSI_INS_IO_OPC_WAIT_RESEL 0x10000000
> > +
> > +#define LSI_INS_TC_CP             0x00020000
> > +#define LSI_INS_TC_JMP            0x00080000
> > +#define LSI_INS_TC_RA             0x00800000
> > +
> > +#define LSI_INS_TC_OPC_JMP        0x00000000
> > +#define LSI_INS_TC_OPC_INT        0x18000000
> > +
> > +#define LSI_INS_TC_SCSIP_DAT_OUT  0x00000000
> > +#define LSI_INS_TC_SCSIP_MSG_IN   0x07000000
> > +
> >  #endif // _LSI_SCSI_H_
> > diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.c b/OvmfPkg/LsiScsiDxe/LsiScsi.c
> > index 1bcebd92e455..090d7df15b34 100644
> > --- a/OvmfPkg/LsiScsiDxe/LsiScsi.c
> > +++ b/OvmfPkg/LsiScsiDxe/LsiScsi.c
> > @@ -43,6 +43,42 @@ Out8 (
> >                            );
> >  }
> >
> > +STATIC
> > +EFI_STATUS
> > +Out32 (
> > +  IN LSI_SCSI_DEV       *Dev,
> > +  IN UINT32             Addr,
> > +  IN UINT32             Data
> > +  )
> > +{
> > +  return Dev->PciIo->Io.Write (
> > +                          Dev->PciIo,
> > +                          EfiPciIoWidthUint32,
> > +                          PCI_BAR_IDX0,
> > +                          Addr,
> > +                          1,
> > +                          &Data
> > +                          );
> > +}
> > +
> > +STATIC
> > +EFI_STATUS
> > +In8 (
> > +  IN  LSI_SCSI_DEV *Dev,
> > +  IN  UINT32       Addr,
> > +  OUT UINT8        *Data
> > +  )
> > +{
> > +  return Dev->PciIo->Io.Read (
> > +                          Dev->PciIo,
> > +                          EfiPciIoWidthUint8,
> > +                          PCI_BAR_IDX0,
> > +                          Addr,
> > +                          1,
> > +                          Data
> > +                          );
> > +}
> > +
> >  STATIC
> >  EFI_STATUS
> >  LsiScsiReset (
> > @@ -141,6 +177,272 @@ LsiScsiCheckRequest (
> >    return EFI_SUCCESS;
> >  }
> >
> > +/**
> > +
> > +  Interpret the request packet from the Extended SCSI Pass Thru Protocol and
> > +  compose the script to submit the command and data to the contorller.
> 
> (2) s/contorller/controller/
> 
Oops. Will fix it.

> 
> > +
> > +  @param[in] Dev          The LSI 53C895A SCSI device the packet targets.
> > +
> > +  @param[in] Target       The SCSI target controlled by the LSI 53C895A SCSI
> > +                          device.
> > +
> > +  @param[in] Lun          The Logical Unit Number under the SCSI target.
> > +
> > +  @param[in out] Packet   The Extended SCSI Pass Thru Protocol packet.
> > +
> > +
> > +  @retval EFI_SUCCESS  The Extended SCSI Pass Thru Protocol packet was valid.
> > +
> > +  @return              Otherwise, invalid or unsupported parameters were
> > +                       detected. Status codes are meant for direct forwarding
> > +                       by the EFI_EXT_SCSI_PASS_THRU_PROTOCOL.PassThru()
> > +                       implementation.
> > +
> > + **/
> > +STATIC
> > +EFI_STATUS
> > +LsiScsiProcessRequest (
> > +  IN LSI_SCSI_DEV                                   *Dev,
> > +  IN UINT8                                          Target,
> > +  IN UINT64                                         Lun,
> > +  IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
> > +  )
> > +{
> > +  EFI_STATUS Status;
> > +  UINT32     *Script;
> > +  UINT8      *Cdb;
> > +  UINT8      *MsgOut;
> > +  UINT8      *MsgIn;
> > +  UINT8      *ScsiStatus;
> > +  UINT8      *Data;
> > +  UINT8      DStat;
> > +  UINT8      SIst0;
> > +  UINT8      SIst1;
> > +
> > +  Script      = Dev->Dma->Script;
> > +  Cdb         = Dev->Dma->Cdb;
> > +  Data        = Dev->Dma->Data;
> > +  MsgIn       = Dev->Dma->MsgIn;
> > +  MsgOut      = &Dev->Dma->MsgOut;
> > +  ScsiStatus  = &Dev->Dma->Status;
> > +
> > +  *ScsiStatus = 0xFF;
> > +
> > +  SetMem (Cdb, sizeof Dev->Dma->Cdb, 0x00);
> > +  CopyMem (Cdb, Packet->Cdb, Packet->CdbLength);
> > +
> > +  //
> > +  // Clean up the DMA buffer for the script.
> > +  //
> > +  SetMem (Script, sizeof Dev->Dma->Script, 0x00);
> > +
> > +  //
> > +  // Compose the script to transfer data between the host and the device.
> > +  //
> > +  // Reference:
> > +  //   LSI53C895A PCI to Ultra2 SCSI Controller Version 2.2
> > +  //   - Chapter 5 SCSI SCRIPT Instruction Set
> > +  //
> > +  // All instructions used here consist of 2 32bit words. The first word
> > +  // contains the command to execute. The second word is loaded into the
> > +  // DMA SCRIPTS Pointer Save (DSPS) register as either the DMA address
> > +  // for data transmission or the address/offset for the jump command.
> > +  // Some commands, such as the selection of the target, don't need to
> > +  // transfer data through DMA or jump to another instruction, then DSPS
> > +  // has to be zero.
> > +  //
> > +  // There are 3 major parts in this script. The first part (1~3) contains
> > +  // the instructions to select target and LUN and send the SCSI command
> > +  // from the request packet. The second part (4~7) is to handle the
> > +  // potential disconnection and prepare for the data transmission. The
> > +  // instructions in the third part (8~10) transmit the given data and
> > +  // collect the result. Instruction 11 raises the interrupt and marks the
> > +  // end of the script.
> > +  //
> > +
> > +  //
> > +  // 1. Select target.
> > +  //
> > +  *Script++ = LSI_INS_TYPE_IO | LSI_INS_IO_OPC_SEL | (UINT32)Target << 16;
> > +  *Script++ = 0x00000000;
> > +
> > +  //
> > +  // 2. Select LUN.
> > +  //
> > +  *MsgOut   = 0x80 | (UINT8) Lun; // 0x80: Identify bit
> 
> This implies that the maximum (inclusive) LUN can be 127.
> 
> (3) I suggest adding a STATIC_ASSERT() to LsiScsiControllerStart(),
> where you fetch "PcdLsiScsiMaxLunLimit".
> 
> (If the device has a stricter limit on LUNs than 127, then please use
> that limit.)
> 
Ok, will add an assert for MaxLun.

> 
> > +  *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_MSG_OUT | \
> > +              sizeof Dev->Dma->MsgOut;
> 
> (4) Please cast the result of the "sizeof" operator to UINT32
> explicitly.
> 
> 
> (5) Please drop the backslash; it is not needed.
> 
> Note that (4) and (5) apply to multiple locations in this function;
> please update each location in the composition of the script.
> 
Will fix them in v2.

> 
> > +  *Script++ = LSI_SCSI_DMA_ADDR_LOW (Dev, MsgOut);
> 
> This opcode seems to mean that the device is not capable of taking the
> LUN selector message from outside of the 32-bit address space.
> 
> (6) If that's the case, then please remove DUAL_ADDRESS_CYCLE from
> "[PATCH 08/11] OvmfPkg/LsiScsiDxe: Map DMA buffer".
> 
> Otherwise, AllocateBuffer() could theoretically allocate the buffer
> structure (including the MsgOut member) such that
> LSI_SCSI_DMA_ADDR_LOW() would truncate the address.
> 
> 
> (7) Once you remove DUAL_ADDRESS_CYCLE (i.e. once we guarantee that the
> allocation will be satisfied from the 32-bit address space), you can
> drop the _LOW suffix as well, from the macro name.
> 
> Now, if the device is actually 64-bit capable, only it would take a more
> complex script, and you don't want that, that's fine -- the above steps
> remain the same. (IOW it doesn't matter whether the device is 64-bit
> uncapable, or you don't want to write a 64-bit aware command script --
> you should remove DUAL_ADDRESS_CYCLE just the same.)
> 
Ok. Will remove DUAL_ADDRESS_CYCLE.

> 
> > +
> > +  //
> > +  // 3. Send the SCSI Command.
> > +  //
> > +  *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_CMD | \
> > +              sizeof Dev->Dma->Cdb;
> > +  *Script++ = LSI_SCSI_DMA_ADDR_LOW (Dev, Cdb);
> > +
> > +  //
> > +  // 4. Check whether the current SCSI phase is "Message In" or not
> > +  //    and jump to 8 if it is.
> > +  //
> > +  *Script++ = LSI_INS_TYPE_TC | LSI_INS_TC_OPC_JMP | \
> > +              LSI_INS_TC_SCSIP_MSG_IN | LSI_INS_TC_RA | \
> > +              LSI_INS_TC_CP;
> > +  *Script++ = 0x00000018;
> 
> (8) The constant 0x18 is obscure. Can you extend the comment? How is
> "step 8" connected to value 0x18?
> 
> (Step 8 starts at command offset 7 in the script, meaning UINT32 offset
> 14, or byte offset 56. But 0x18 is 24, not matching any of those
> constants.)
> 
Urghhh, it should be "jump to 7". LSI_INS_TC_RA stands for "Relative
Addressing Mode", so it's 4 + 24/8 = 7. Will fix the comment.

> 
> > +
> > +  //
> > +  // 5. Read "Message" from the initiator to trigger reselect.
> > +  //
> > +  *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_MSG_IN | \
> > +              sizeof Dev->Dma->MsgIn;
> > +  *Script++ = LSI_SCSI_DMA_ADDR_LOW (Dev, MsgIn);
> > +
> > +  //
> > +  // 6. Wait reselect.
> > +  //
> > +  *Script++ = LSI_INS_TYPE_IO | LSI_INS_IO_OPC_WAIT_RESEL;
> > +  *Script++ = 0x00000000;
> > +
> > +  //
> > +  // 7. Read "Message" from the initiator again
> > +  //
> > +  *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_MSG_IN | \
> > +              sizeof Dev->Dma->MsgIn;
> > +  *Script++ = LSI_SCSI_DMA_ADDR_LOW (Dev, MsgIn);
> > +
> > +  //
> > +  // 8. Set the DMA command for the read/write operations.
> > +  //
> > +  if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ &&
> > +      Packet->InTransferLength > 0) {
> > +    *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_DAT_IN | \
> > +                Packet->InTransferLength;
> > +    *Script++ = LSI_SCSI_DMA_ADDR_LOW (Dev, Data);
> > +  } else if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_WRITE &&
> > +             Packet->OutTransferLength > 0) {
> > +    // LsiScsiCheckRequest() guarantees that OutTransferLength is no
> > +    // larger than sizeof Dev->Dma->Data, so we can safely copy the
> > +    // the data to Dev->Dma->Data.
> > +    CopyMem (Data, Packet->OutDataBuffer, Packet->OutTransferLength);
> > +    *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_DAT_OUT | \
> > +                Packet->OutTransferLength;
> > +    *Script++ = LSI_SCSI_DMA_ADDR_LOW (Dev, Data);
> > +  }
> 
> The comment is not bad, but it could be improved.
> 
> First, the comment style is not 100% correct (empty "//" lines are
> missing before and after.)
> 
> Second, instead of a long comment, I'd suggest a short comment, plus an
> ASSERT.
> 
Will amend the comment and add an assert.

> Third, the transfer length in the packet ("in" and "out" alike) isn't
> *only* relevant due to buffer overflow concerns, but also because the
> command opcode has some bits set (in particular,
> LSI_INS_BLK_SCSIP_DAT_IN) that effectively limit the transfer length to
> a bitmask that's narrower than a UINT32.
> 
Yeah, the controller only takes 24 bits for the transfer length.

> 
> Another observation is that control can flow through this snippet
> without taking *either* branch.
> 
> (For example if the data direction is WRITE, but OutTransferLength is
> zero. That's a condition that LsiScsiCheckRequest() does not catch. My
> point is not that LsiScsiCheckRequest() should catch it -- I think it's
> not an invalid request --, but that LsiScsiProcessRequest() should deal
> with it.)
> 
Hmmm, this is possible when ScsiIo requests sense data throught
Packet->SenseData, and it's a read request with 0 InTransferLength.
I encountered that during the development of this driver. It's gone after
I set SenseDataLength to 0 later to make ScsiIo request sense data through
Transfer buffer. Maybe I should filter this kind of requests in
LsiScsiCheckRequest().

> If we take neither branch, then (minimally) the jump address under step
> 4. will be wrong -- there's not going to be a DAT_IN / DAT_OUT command
> to jump to.
>
> 
> (9) So, for addressing all of the above, I suggest:
> 
>   //
>   // 8. Set the DMA command for the read/write operations.
>   //
>   // LsiScsiCheckRequest() prevents both integer overflows in the command
>   // opcodes, and buffer overflows.
>   //
>   if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
>     ASSERT (Packet->InTransferLength <= sizeof Dev->Dma->Data);
>     *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_DAT_IN |
>                 Packet->InTransferLength;
>   } else {
>     ASSERT (Packet->OutTransferLength <= sizeof Dev->Dma->Data);
>     CopyMem (Data, Packet->OutDataBuffer, Packet->OutTransferLength);
>     *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_DAT_OUT |
>                 Packet->OutTransferLength;
>   }
>   *Script++ = LSI_SCSI_DMA_ADDR (Dev, Data);
>
Thanks. Will modify the code here.

> 
> > +
> > +  //
> > +  // 9. Get the SCSI status.
> > +  //
> > +  *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_STAT | \
> > +              sizeof Dev->Dma->Status;
> > +  *Script++ = LSI_SCSI_DMA_ADDR_LOW (Dev, Status);
> > +
> > +  //
> > +  // 10. Get the SCSI message.
> > +  //
> > +  *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_MSG_IN | \
> > +              sizeof Dev->Dma->MsgIn;
> > +  *Script++ = LSI_SCSI_DMA_ADDR_LOW (Dev, MsgIn);
> > +
> > +  //
> > +  // 11. Raise the interrupt to end the script.
> > +  //
> > +  *Script++ = LSI_INS_TYPE_TC | LSI_INS_TC_OPC_INT | \
> > +              LSI_INS_TC_SCSIP_DAT_OUT | LSI_INS_TC_JMP;
> > +  *Script++ = 0x00000000;
> > +
> > +  //
> > +  // Make sure the size of the script doesn't exceed the buffer.
> > +  //
> > +  ASSERT (Script < Dev->Dma->Script + sizeof Dev->Dma->Script);
> 
> (10) Please replace "<" with "<=".
> 
> (11) Please replace "sizeof" with ARRAY_SIZE().
>
Will fix it.

> 
> > +
> > +  //
> > +  // The controller starts to execute the script once the DMA Script
> > +  // Pointer (DSP) register is set.
> > +  //
> > +  Status = Out32 (Dev, LSI_REG_DSP, LSI_SCSI_DMA_ADDR_LOW(Dev, Script));
> 
> (12) Missing space after "LSI_SCSI_DMA_ADDR".
> 
Ditto.

> 
> > +  if (EFI_ERROR (Status)) {
> > +    return Status;
> > +  }
> 
> This return statement doesn't seem right. We do not translate the error
> code to one of the error codes specified for
> EFI_EXT_SCSI_PASS_THRU_PROTOCOL.PassThru(). We also do not set any
> output field in Packet.
> 
> (13) I think we should jump to the "Error" label from here.
> 
Right. It should jump to "Error".

> 
> > +
> > +  //
> > +  // Poll the device registers (DSTAT, SIST0, and SIST1) until the SIR
> > +  // bit sets.
> > +  //
> > +  for(;;) {
> > +    Status = In8 (Dev, LSI_REG_DSTAT, &DStat);
> > +    if (EFI_ERROR (Status)) {
> > +      goto Error;
> > +    }
> > +    Status = In8 (Dev, LSI_REG_SIST0, &SIst0);
> > +    if (EFI_ERROR (Status)) {
> > +      goto Error;
> > +    }
> > +    Status = In8 (Dev, LSI_REG_SIST1, &SIst1);
> > +    if (EFI_ERROR (Status)) {
> > +      goto Error;
> > +    }
> > +
> > +    if (SIst0 != 0 || SIst1 != 0) {
> > +      goto Error;
> > +    }
> > +
> > +    //
> > +    // Check the SIR (SCRIPTS Interrupt Instruction Received) bit.
> > +    //
> > +    if (DStat & LSI_DSTAT_SIR) {
> > +      break;
> > +    }
> > +
> > +    gBS->Stall (Dev->StallPerPollUsec);
> > +  }
> > +
> > +  //
> > +  // Check if everything is good.
> > +  //   SCSI Message Code 0x00: COMMAND COMPLETE
> > +  //   SCSI Status  Code 0x00: Good
> > +  //
> > +  if (MsgIn[0] == 0 && *ScsiStatus == 0) {
> 
> (14) Please negate this condition, and unnest the success branch:
> 
>   if (MsgIn[0] != 0 || *ScsiStatus != 0) {
>     goto Error;
>   }
> 
>   /* ... */
> 
>   return EFI_SUCCESS;
> 
> 
Ok. Will do that.

> > +    //
> > +    // Copy Data to InDataBuffer if necessary.
> > +    //
> > +    if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
> > +      CopyMem (Packet->InDataBuffer, Data, Packet->InTransferLength);
> > +    }
> > +
> > +    //
> > +    // The controller doesn't return sense data when replying "TEST UNIT READY",
> > +    // so we have to set SenseDataLength to 0 to notify ScsiIo to issue
> > +    // "REQUEST SENSE" for the sense data.
> > +    //
> > +    if (Cdb[0] == 0x00) {
> > +      Packet->SenseDataLength = 0;
> > +    }
> > +    Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK;
> > +    Packet->TargetStatus      = EFI_EXT_SCSI_STATUS_TARGET_GOOD;
> > +
> > +    return EFI_SUCCESS;
> > +  }
> 
> The mapping on success does not deal with short transfers (in or out) --
> we're supposed to update InTransferLength / OutTransferLength on output.
> 
> (15) Does the device report short transfers somehow?
> 
I'm not sure. Have to check the spec of controller to see if there is
any instruction to fetch the real transfer length.

> 
> The spec says about SenseDataLength, "On input, the length in bytes of
> the SenseData buffer. On output, the number of bytes written to the
> SenseData buffer".
> 
> But we only set SenseDataLength conditionally. In case we do *not* set
> it, the caller may attempt to parse garbage from the "SenseData" buffer.
> 
> (16) We should either get real sense data back to the caller, or always
> zero out "SenseDataLength".
> 
> 
For simplicity, I would choose zeroing out "SenseDataLength" since
ScsiDiskDxe can handle it.

> > +
> > +Error:
> > +  DEBUG((DEBUG_VERBOSE, "%a: dstat: %02X, sist0: %02X, sist1: %02X\n",
> > +         __FUNCTION__, DStat, SIst0, SIst1));
> 
> (17) missing space after "DEBUG".
> 
> (18) The line starting with __FUNCTION__ is not correctly indented.
>
Will fix them.

> 
> > +  //
> > +  // Update the request packet to reflect the status.
> > +  //
> > +  if (*ScsiStatus != 0xFF) {
> > +    Packet->TargetStatus    = *ScsiStatus;
> > +  } else {
> > +    Packet->TargetStatus    = EFI_EXT_SCSI_STATUS_TARGET_TASK_ABORTED;
> > +  }
> > +  Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;
> > +  Packet->InTransferLength  = 0;
> > +  Packet->OutTransferLength = 0;
> > +  Packet->SenseDataLength   = 0;
> > +
> > +  return EFI_DEVICE_ERROR;
> > +}
> > +
> >  //
> >  // The next seven functions implement EFI_EXT_SCSI_PASS_THRU_PROTOCOL
> >  // for the LSI 53C895A SCSI Controller. Refer to UEFI Spec 2.3.1 + Errata C,
> > @@ -168,6 +470,11 @@ LsiScsiPassThru (
> >      return Status;
> >    }
> >
> > +  Status = LsiScsiProcessRequest (Dev, *Target, Lun, Packet);
> > +  if (EFI_ERROR (Status)) {
> > +    return Status;
> > +  }
> > +
> >    return EFI_SUCCESS;
> >  }
> >
> 
> (19) I think this can be simplified -- just return Status after calling
> LsiScsiProcessRequest().
>
Agree.

> 
> > @@ -469,6 +776,7 @@ LsiScsiControllerStart (
> >
> >    Dev->MaxTarget = PcdGet8 (PcdLsiScsiMaxTargetLimit);
> >    Dev->MaxLun = PcdGet8 (PcdLsiScsiMaxLunLimit);
> > +  Dev->StallPerPollUsec = PcdGet32 (PcdLsiScsiStallPerPollUsec);
> >
> >    Status = gBS->OpenProtocol (
> >                    ControllerHandle,
> > diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.h b/OvmfPkg/LsiScsiDxe/LsiScsi.h
> > index 9272eb7506c7..1a16ef9f7795 100644
> > --- a/OvmfPkg/LsiScsiDxe/LsiScsi.h
> > +++ b/OvmfPkg/LsiScsiDxe/LsiScsi.h
> > @@ -13,6 +13,11 @@
> >  #define _LSI_SCSI_DXE_H_
> >
> >  typedef struct {
> > +  //
> > +  // Allocate 32 UINT32 entries for the script and it's sufficient for
> > +  // 16 instructions.
> > +  //
> > +  UINT32                          Script[32];
> >    //
> >    // The max size of CDB is 32.
> >    //
> > @@ -21,6 +26,18 @@ typedef struct {
> >    // Allocate 64KB for read/write buffer.
> >    //
> >    UINT8                           Data[0x10000];
> > +  //
> > +  // For SCSI Message In phase
> > +  //
> > +  UINT8                           MsgIn[2];
> > +  //
> > +  // For SCSI Message Out phase
> > +  //
> > +  UINT8                           MsgOut;
> > +  //
> > +  // For SCSI Status phase
> > +  //
> > +  UINT8                           Status;
> >  } LSI_SCSI_DMA_BUFFER;
> >
> >  typedef struct {
> > @@ -30,6 +47,7 @@ typedef struct {
> >    EFI_PCI_IO_PROTOCOL             *PciIo;
> >    UINT8                           MaxTarget;
> >    UINT8                           MaxLun;
> > +  UINT32                          StallPerPollUsec;
> >    LSI_SCSI_DMA_BUFFER             *Dma;
> >    EFI_PHYSICAL_ADDRESS            DmaPhysical;
> >    VOID                            *DmaMapping;
> > @@ -42,6 +60,9 @@ typedef struct {
> >  #define LSI_SCSI_FROM_PASS_THRU(PassThruPtr) \
> >    CR (PassThruPtr, LSI_SCSI_DEV, PassThru, LSI_SCSI_DEV_SIGNATURE)
> >
> > +#define LSI_SCSI_DMA_ADDR_LOW(Dev, MemberName) \
> > +  ((UINT32)(Dev->DmaPhysical + OFFSET_OF (LSI_SCSI_DMA_BUFFER, MemberName)))
> > +
> >
> >  //
> >  // Probe, start and stop functions of this driver, called by the DXE core for
> > diff --git a/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf b/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> > index 68844c6772e3..cbd7294573ac 100644
> > --- a/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> > +++ b/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> > @@ -41,3 +41,6 @@ [Protocols]
> >  [FixedPcd]
> >    gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiMaxTargetLimit   ## CONSUMES
> >    gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiMaxLunLimit      ## CONSUMES
> > +
> > +[Pcd]
> > +  gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiStallPerPollUsec ## CONSUMES
> > diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
> > index ae7d1d648d22..57e418d4b8a9 100644
> > --- a/OvmfPkg/OvmfPkg.dec
> > +++ b/OvmfPkg/OvmfPkg.dec
> > @@ -179,6 +179,9 @@ [PcdsFixedAtBuild]
> >    gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiMaxTargetLimit|7|UINT8|0x3b
> >    gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiMaxLunLimit|0|UINT8|0x3c
> >
> > +  ## Microseconds to stall between polling for LsiScsi request result
> > +  gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiStallPerPollUsec|5|UINT32|0x3d
> > +
> 
> (20) The token value should be 0x3c here, according to my request (5)
> under "[PATCH 06/11] OvmfPkg/LsiScsiDxe: Report Targets and LUNs".
>
Ok, will do that if we won't change the toke value of PcdMptScsiStallPerPollUsec.

Thanks,

Gary Lin

> 
> >    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogBase|0x0|UINT32|0x8
> >    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogSize|0x0|UINT32|0x9
> >    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareFdSize|0x0|UINT32|0xa
> >
> 
> Thanks
> Laszlo
> 


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 11/11] Maintainers.txt: Add myself as the reviewer for LsiScsi driver
  2020-07-07 12:49   ` Laszlo Ersek
@ 2020-07-08  6:03     ` Gary Lin
  0 siblings, 0 replies; 35+ messages in thread
From: Gary Lin @ 2020-07-08  6:03 UTC (permalink / raw)
  To: Laszlo Ersek; +Cc: devel, Jordan Justen, Ard Biesheuvel

On Tue, Jul 07, 2020 at 02:49:48PM +0200, Laszlo Ersek wrote:
> On 07/01/20 06:04, Gary Lin wrote:
> > Cc: Jordan Justen <jordan.l.justen@intel.com>
> > Cc: Laszlo Ersek <lersek@redhat.com>
> > Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
> > Signed-off-by: Gary Lin <glin@suse.com>
> > ---
> >  Maintainers.txt | 4 ++++
> >  1 file changed, 4 insertions(+)
> > 
> > diff --git a/Maintainers.txt b/Maintainers.txt
> > index 32c9003a6209..666d3af4d76a 100644
> > --- a/Maintainers.txt
> > +++ b/Maintainers.txt
> > @@ -400,6 +400,10 @@ OvmfPkg: CSM modules
> >  F: OvmfPkg/Csm/
> >  R: David Woodhouse <dwmw2@infradead.org>
> >  
> > +OvmfPkg: LsiScsi Driver
> > +F: OvmfPkg/LsiScsiDxe/
> > +R: Gary Lin <glin@suse.com>
> > +
> >  OvmfPkg: MptScsi and PVSCSI driver
> >  F: OvmfPkg/MptScsiDxe/
> >  F: OvmfPkg/PvScsiDxe/
> > 
> 
> (1) Please use your name rather than "myself" in the subject -- consider
> "git log --oneline".
> 
> (2) Please write "driver" rather than "Driver" in the new entry, for
> consistency with the "MptScsi and PVSCSI" entry (and other entries in
> the file too).
> 
Will fix this commit in v2.

Thanks,

Gary Lin

> With those updates:
> 
> Reviewed-by: Laszlo Ersek <lersek@redhat.com>
> 
> Thanks
> Laszlo
> 


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 06/11] OvmfPkg/LsiScsiDxe: Report Targets and LUNs
  2020-07-08  2:34     ` Gary Lin
@ 2020-07-08 15:26       ` Laszlo Ersek
  0 siblings, 0 replies; 35+ messages in thread
From: Laszlo Ersek @ 2020-07-08 15:26 UTC (permalink / raw)
  To: Gary Lin; +Cc: devel, Jordan Justen, Ard Biesheuvel

On 07/08/20 04:34, Gary Lin wrote:
> On Tue, Jul 07, 2020 at 11:04:21AM +0200, Laszlo Ersek wrote:
>> On 07/01/20 06:04, Gary Lin wrote:

>>> diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
>>> index 65bb2bb0eb4c..ae7d1d648d22 100644
>>> --- a/OvmfPkg/OvmfPkg.dec
>>> +++ b/OvmfPkg/OvmfPkg.dec
>>> @@ -174,6 +174,11 @@ [PcdsFixedAtBuild]
>>>    ## Microseconds to stall between polling for MptScsi request result
>>>    gUefiOvmfPkgTokenSpaceGuid.PcdMptScsiStallPerPollUsec|5|UINT32|0x40
>>>  
>>> +  ## Set the *inclusive* number of targets and LUNs that LsiScsi exposes for
>>> +  #  scan by ScsiBusDxe.
>>> +  gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiMaxTargetLimit|7|UINT8|0x3b
>>> +  gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiMaxLunLimit|0|UINT8|0x3c
>>> +
>>>    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogBase|0x0|UINT32|0x8
>>>    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogSize|0x0|UINT32|0x9
>>>    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareFdSize|0x0|UINT32|0xa
>>>
>>
>> Commit 093cceaf79b5 ("OvmfPkg/MptScsiDxe: Report targets and one LUN",
>> 2020-05-05) introduced PcdMptScsiMaxTargetLimit with token value 0x39.
>> That was OK.
>>
>> Commit 505812ae1d2d ("OvmfPkg/MptScsiDxe: Implement the PassThru
>> method", 2020-05-05) then introduced PcdMptScsiStallPerPollUsec with
>> token value 0x40. That was not OK -- but I missed it. (The token value
>> should have been 0x3a; as 0x39 is not succeeded by 0x40 but by 0x3a.)
>>
>> Token value 0x3a remains unused at this point.
>>
>> (5) So please introduce the new PCDs with token values 0x3a and 0x3b, to
>> keep the token space dense.
>>
> I actually was thinking about making PcdMptScsiStallPerPollUsec 0x3a in
> another patch. Since it's not related to LsiScsi, I didn't do it in this
> series. Sounds like you prefer to keeping 0x40 for
> PcdMptScsiStallPerPollUsec?

If you can post a separate patch for changing the
PcdMptScsiStallPerPollUsec token value to 0x3a, that's best!

Thanks
Laszlo


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [edk2-devel] [PATCH 10/11] OvmfPkg/LsiScsiDxe: Process the SCSI Request Packet
       [not found]     ` <161FB1B03BD2D339.11266@groups.io>
@ 2020-07-14  8:19       ` Gary Lin
  0 siblings, 0 replies; 35+ messages in thread
From: Gary Lin @ 2020-07-14  8:19 UTC (permalink / raw)
  To: devel; +Cc: Laszlo Ersek, Jordan Justen, Ard Biesheuvel

On Wed, Jul 08, 2020 at 02:02:27PM +0800, Gary Lin via groups.io wrote:
> On Tue, Jul 07, 2020 at 02:46:14PM +0200, Laszlo Ersek wrote:
> > On 07/01/20 06:04, Gary Lin wrote:
> > > This is the second part of LsiScsiPassThru(). LsiScsiProcessRequest() is
> > > added to translate the SCSI Request Packet into the LSI 53C895A
> > > commands. This function utilizes the so-called Script buffer to transmit
> > > a series of commands to the chip and then polls the DMA Status (DSTAT)
> > > register until the Scripts Interrupt Instruction Received (SIR) bit
> > > sets. Once the script is done, the SCSI Request Packet will be modified
> > > to reflect the result of the script.
> > >
> > > Cc: Jordan Justen <jordan.l.justen@intel.com>
> > > Cc: Laszlo Ersek <lersek@redhat.com>
> > > Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
> > > Signed-off-by: Gary Lin <glin@suse.com>
> > > ---
> > >  OvmfPkg/Include/IndustryStandard/LsiScsi.h |  39 +++
> > >  OvmfPkg/LsiScsiDxe/LsiScsi.c               | 308 +++++++++++++++++++++
> > >  OvmfPkg/LsiScsiDxe/LsiScsi.h               |  21 ++
> > >  OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf          |   3 +
> > >  OvmfPkg/OvmfPkg.dec                        |   3 +
> > >  5 files changed, 374 insertions(+)
> > >
> > > diff --git a/OvmfPkg/Include/IndustryStandard/LsiScsi.h b/OvmfPkg/Include/IndustryStandard/LsiScsi.h
> > > index 60e527f1c6a7..cbf049c18310 100644
> > > --- a/OvmfPkg/Include/IndustryStandard/LsiScsi.h
> > > +++ b/OvmfPkg/Include/IndustryStandard/LsiScsi.h
> > > @@ -26,6 +26,18 @@
> > >  #define LSI_REG_SIST0             0x42
> > >  #define LSI_REG_SIST1             0x43
> > >
> > > +//
> > > +// The status bits for DMA Status (DSTAT)
> > > +//
> > > +#define LSI_DSTAT_IID             0x01
> > > +#define LSI_DSTAT_R               0x02
> > > +#define LSI_DSTAT_SIR             0x04
> > > +#define LSI_DSTAT_SSI             0x08
> > > +#define LSI_DSTAT_ABRT            0x10
> > > +#define LSI_DSTAT_BF              0x20
> > > +#define LSI_DSTAT_MDPE            0x40
> > > +#define LSI_DSTAT_DFE             0x80
> > > +
> > 
> > (1) Please use the BITx macros.
> > 
> Will fix it.
> 
> > 
> > >  //
> > >  // The status bits for Interrupt Status Zero (ISTAT0)
> > >  //
> > > @@ -38,4 +50,31 @@
> > >  #define LSI_ISTAT0_SRST           0x40
> > >  #define LSI_ISTAT0_ABRT           0x80
> > >
> > > +//
> > > +// LSI 53C895A Script Instructions
> > > +//
> > > +#define LSI_INS_TYPE_BLK          0x00000000
> > > +#define LSI_INS_TYPE_IO           0x40000000
> > > +#define LSI_INS_TYPE_TC           0x80000000
> > > +
> > > +#define LSI_INS_BLK_SCSIP_DAT_OUT 0x00000000
> > > +#define LSI_INS_BLK_SCSIP_DAT_IN  0x01000000
> > > +#define LSI_INS_BLK_SCSIP_CMD     0x02000000
> > > +#define LSI_INS_BLK_SCSIP_STAT    0x03000000
> > > +#define LSI_INS_BLK_SCSIP_MSG_OUT 0x06000000
> > > +#define LSI_INS_BLK_SCSIP_MSG_IN  0x07000000
> > > +
> > > +#define LSI_INS_IO_OPC_SEL        0x00000000
> > > +#define LSI_INS_IO_OPC_WAIT_RESEL 0x10000000
> > > +
> > > +#define LSI_INS_TC_CP             0x00020000
> > > +#define LSI_INS_TC_JMP            0x00080000
> > > +#define LSI_INS_TC_RA             0x00800000
> > > +
> > > +#define LSI_INS_TC_OPC_JMP        0x00000000
> > > +#define LSI_INS_TC_OPC_INT        0x18000000
> > > +
> > > +#define LSI_INS_TC_SCSIP_DAT_OUT  0x00000000
> > > +#define LSI_INS_TC_SCSIP_MSG_IN   0x07000000
> > > +
> > >  #endif // _LSI_SCSI_H_
> > > diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.c b/OvmfPkg/LsiScsiDxe/LsiScsi.c
> > > index 1bcebd92e455..090d7df15b34 100644
> > > --- a/OvmfPkg/LsiScsiDxe/LsiScsi.c
> > > +++ b/OvmfPkg/LsiScsiDxe/LsiScsi.c
> > > @@ -43,6 +43,42 @@ Out8 (
> > >                            );
> > >  }
> > >
> > > +STATIC
> > > +EFI_STATUS
> > > +Out32 (
> > > +  IN LSI_SCSI_DEV       *Dev,
> > > +  IN UINT32             Addr,
> > > +  IN UINT32             Data
> > > +  )
> > > +{
> > > +  return Dev->PciIo->Io.Write (
> > > +                          Dev->PciIo,
> > > +                          EfiPciIoWidthUint32,
> > > +                          PCI_BAR_IDX0,
> > > +                          Addr,
> > > +                          1,
> > > +                          &Data
> > > +                          );
> > > +}
> > > +
> > > +STATIC
> > > +EFI_STATUS
> > > +In8 (
> > > +  IN  LSI_SCSI_DEV *Dev,
> > > +  IN  UINT32       Addr,
> > > +  OUT UINT8        *Data
> > > +  )
> > > +{
> > > +  return Dev->PciIo->Io.Read (
> > > +                          Dev->PciIo,
> > > +                          EfiPciIoWidthUint8,
> > > +                          PCI_BAR_IDX0,
> > > +                          Addr,
> > > +                          1,
> > > +                          Data
> > > +                          );
> > > +}
> > > +
> > >  STATIC
> > >  EFI_STATUS
> > >  LsiScsiReset (
> > > @@ -141,6 +177,272 @@ LsiScsiCheckRequest (
> > >    return EFI_SUCCESS;
> > >  }
> > >
> > > +/**
> > > +
> > > +  Interpret the request packet from the Extended SCSI Pass Thru Protocol and
> > > +  compose the script to submit the command and data to the contorller.
> > 
> > (2) s/contorller/controller/
> > 
> Oops. Will fix it.
> 
> > 
> > > +
> > > +  @param[in] Dev          The LSI 53C895A SCSI device the packet targets.
> > > +
> > > +  @param[in] Target       The SCSI target controlled by the LSI 53C895A SCSI
> > > +                          device.
> > > +
> > > +  @param[in] Lun          The Logical Unit Number under the SCSI target.
> > > +
> > > +  @param[in out] Packet   The Extended SCSI Pass Thru Protocol packet.
> > > +
> > > +
> > > +  @retval EFI_SUCCESS  The Extended SCSI Pass Thru Protocol packet was valid.
> > > +
> > > +  @return              Otherwise, invalid or unsupported parameters were
> > > +                       detected. Status codes are meant for direct forwarding
> > > +                       by the EFI_EXT_SCSI_PASS_THRU_PROTOCOL.PassThru()
> > > +                       implementation.
> > > +
> > > + **/
> > > +STATIC
> > > +EFI_STATUS
> > > +LsiScsiProcessRequest (
> > > +  IN LSI_SCSI_DEV                                   *Dev,
> > > +  IN UINT8                                          Target,
> > > +  IN UINT64                                         Lun,
> > > +  IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
> > > +  )
> > > +{
> > > +  EFI_STATUS Status;
> > > +  UINT32     *Script;
> > > +  UINT8      *Cdb;
> > > +  UINT8      *MsgOut;
> > > +  UINT8      *MsgIn;
> > > +  UINT8      *ScsiStatus;
> > > +  UINT8      *Data;
> > > +  UINT8      DStat;
> > > +  UINT8      SIst0;
> > > +  UINT8      SIst1;
> > > +
> > > +  Script      = Dev->Dma->Script;
> > > +  Cdb         = Dev->Dma->Cdb;
> > > +  Data        = Dev->Dma->Data;
> > > +  MsgIn       = Dev->Dma->MsgIn;
> > > +  MsgOut      = &Dev->Dma->MsgOut;
> > > +  ScsiStatus  = &Dev->Dma->Status;
> > > +
> > > +  *ScsiStatus = 0xFF;
> > > +
> > > +  SetMem (Cdb, sizeof Dev->Dma->Cdb, 0x00);
> > > +  CopyMem (Cdb, Packet->Cdb, Packet->CdbLength);
> > > +
> > > +  //
> > > +  // Clean up the DMA buffer for the script.
> > > +  //
> > > +  SetMem (Script, sizeof Dev->Dma->Script, 0x00);
> > > +
> > > +  //
> > > +  // Compose the script to transfer data between the host and the device.
> > > +  //
> > > +  // Reference:
> > > +  //   LSI53C895A PCI to Ultra2 SCSI Controller Version 2.2
> > > +  //   - Chapter 5 SCSI SCRIPT Instruction Set
> > > +  //
> > > +  // All instructions used here consist of 2 32bit words. The first word
> > > +  // contains the command to execute. The second word is loaded into the
> > > +  // DMA SCRIPTS Pointer Save (DSPS) register as either the DMA address
> > > +  // for data transmission or the address/offset for the jump command.
> > > +  // Some commands, such as the selection of the target, don't need to
> > > +  // transfer data through DMA or jump to another instruction, then DSPS
> > > +  // has to be zero.
> > > +  //
> > > +  // There are 3 major parts in this script. The first part (1~3) contains
> > > +  // the instructions to select target and LUN and send the SCSI command
> > > +  // from the request packet. The second part (4~7) is to handle the
> > > +  // potential disconnection and prepare for the data transmission. The
> > > +  // instructions in the third part (8~10) transmit the given data and
> > > +  // collect the result. Instruction 11 raises the interrupt and marks the
> > > +  // end of the script.
> > > +  //
> > > +
> > > +  //
> > > +  // 1. Select target.
> > > +  //
> > > +  *Script++ = LSI_INS_TYPE_IO | LSI_INS_IO_OPC_SEL | (UINT32)Target << 16;
> > > +  *Script++ = 0x00000000;
> > > +
> > > +  //
> > > +  // 2. Select LUN.
> > > +  //
> > > +  *MsgOut   = 0x80 | (UINT8) Lun; // 0x80: Identify bit
> > 
> > This implies that the maximum (inclusive) LUN can be 127.
> > 
> > (3) I suggest adding a STATIC_ASSERT() to LsiScsiControllerStart(),
> > where you fetch "PcdLsiScsiMaxLunLimit".
> > 
> > (If the device has a stricter limit on LUNs than 127, then please use
> > that limit.)
> > 
> Ok, will add an assert for MaxLun.
> 
> > 
> > > +  *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_MSG_OUT | \
> > > +              sizeof Dev->Dma->MsgOut;
> > 
> > (4) Please cast the result of the "sizeof" operator to UINT32
> > explicitly.
> > 
> > 
> > (5) Please drop the backslash; it is not needed.
> > 
> > Note that (4) and (5) apply to multiple locations in this function;
> > please update each location in the composition of the script.
> > 
> Will fix them in v2.
> 
> > 
> > > +  *Script++ = LSI_SCSI_DMA_ADDR_LOW (Dev, MsgOut);
> > 
> > This opcode seems to mean that the device is not capable of taking the
> > LUN selector message from outside of the 32-bit address space.
> > 
> > (6) If that's the case, then please remove DUAL_ADDRESS_CYCLE from
> > "[PATCH 08/11] OvmfPkg/LsiScsiDxe: Map DMA buffer".
> > 
> > Otherwise, AllocateBuffer() could theoretically allocate the buffer
> > structure (including the MsgOut member) such that
> > LSI_SCSI_DMA_ADDR_LOW() would truncate the address.
> > 
> > 
> > (7) Once you remove DUAL_ADDRESS_CYCLE (i.e. once we guarantee that the
> > allocation will be satisfied from the 32-bit address space), you can
> > drop the _LOW suffix as well, from the macro name.
> > 
> > Now, if the device is actually 64-bit capable, only it would take a more
> > complex script, and you don't want that, that's fine -- the above steps
> > remain the same. (IOW it doesn't matter whether the device is 64-bit
> > uncapable, or you don't want to write a 64-bit aware command script --
> > you should remove DUAL_ADDRESS_CYCLE just the same.)
> > 
> Ok. Will remove DUAL_ADDRESS_CYCLE.
> 
> > 
> > > +
> > > +  //
> > > +  // 3. Send the SCSI Command.
> > > +  //
> > > +  *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_CMD | \
> > > +              sizeof Dev->Dma->Cdb;
> > > +  *Script++ = LSI_SCSI_DMA_ADDR_LOW (Dev, Cdb);
> > > +
> > > +  //
> > > +  // 4. Check whether the current SCSI phase is "Message In" or not
> > > +  //    and jump to 8 if it is.
> > > +  //
> > > +  *Script++ = LSI_INS_TYPE_TC | LSI_INS_TC_OPC_JMP | \
> > > +              LSI_INS_TC_SCSIP_MSG_IN | LSI_INS_TC_RA | \
> > > +              LSI_INS_TC_CP;
> > > +  *Script++ = 0x00000018;
> > 
> > (8) The constant 0x18 is obscure. Can you extend the comment? How is
> > "step 8" connected to value 0x18?
> > 
> > (Step 8 starts at command offset 7 in the script, meaning UINT32 offset
> > 14, or byte offset 56. But 0x18 is 24, not matching any of those
> > constants.)
> > 
> Urghhh, it should be "jump to 7". LSI_INS_TC_RA stands for "Relative
> Addressing Mode", so it's 4 + 24/8 = 7. Will fix the comment.
> 
> > 
> > > +
> > > +  //
> > > +  // 5. Read "Message" from the initiator to trigger reselect.
> > > +  //
> > > +  *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_MSG_IN | \
> > > +              sizeof Dev->Dma->MsgIn;
> > > +  *Script++ = LSI_SCSI_DMA_ADDR_LOW (Dev, MsgIn);
> > > +
> > > +  //
> > > +  // 6. Wait reselect.
> > > +  //
> > > +  *Script++ = LSI_INS_TYPE_IO | LSI_INS_IO_OPC_WAIT_RESEL;
> > > +  *Script++ = 0x00000000;
> > > +
> > > +  //
> > > +  // 7. Read "Message" from the initiator again
> > > +  //
> > > +  *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_MSG_IN | \
> > > +              sizeof Dev->Dma->MsgIn;
> > > +  *Script++ = LSI_SCSI_DMA_ADDR_LOW (Dev, MsgIn);
> > > +
> > > +  //
> > > +  // 8. Set the DMA command for the read/write operations.
> > > +  //
> > > +  if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ &&
> > > +      Packet->InTransferLength > 0) {
> > > +    *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_DAT_IN | \
> > > +                Packet->InTransferLength;
> > > +    *Script++ = LSI_SCSI_DMA_ADDR_LOW (Dev, Data);
> > > +  } else if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_WRITE &&
> > > +             Packet->OutTransferLength > 0) {
> > > +    // LsiScsiCheckRequest() guarantees that OutTransferLength is no
> > > +    // larger than sizeof Dev->Dma->Data, so we can safely copy the
> > > +    // the data to Dev->Dma->Data.
> > > +    CopyMem (Data, Packet->OutDataBuffer, Packet->OutTransferLength);
> > > +    *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_DAT_OUT | \
> > > +                Packet->OutTransferLength;
> > > +    *Script++ = LSI_SCSI_DMA_ADDR_LOW (Dev, Data);
> > > +  }
> > 
> > The comment is not bad, but it could be improved.
> > 
> > First, the comment style is not 100% correct (empty "//" lines are
> > missing before and after.)
> > 
> > Second, instead of a long comment, I'd suggest a short comment, plus an
> > ASSERT.
> > 
> Will amend the comment and add an assert.
> 
> > Third, the transfer length in the packet ("in" and "out" alike) isn't
> > *only* relevant due to buffer overflow concerns, but also because the
> > command opcode has some bits set (in particular,
> > LSI_INS_BLK_SCSIP_DAT_IN) that effectively limit the transfer length to
> > a bitmask that's narrower than a UINT32.
> > 
> Yeah, the controller only takes 24 bits for the transfer length.
> 
> > 
> > Another observation is that control can flow through this snippet
> > without taking *either* branch.
> > 
> > (For example if the data direction is WRITE, but OutTransferLength is
> > zero. That's a condition that LsiScsiCheckRequest() does not catch. My
> > point is not that LsiScsiCheckRequest() should catch it -- I think it's
> > not an invalid request --, but that LsiScsiProcessRequest() should deal
> > with it.)
> > 
> Hmmm, this is possible when ScsiIo requests sense data throught
> Packet->SenseData, and it's a read request with 0 InTransferLength.
> I encountered that during the development of this driver. It's gone after
> I set SenseDataLength to 0 later to make ScsiIo request sense data through
> Transfer buffer. Maybe I should filter this kind of requests in
> LsiScsiCheckRequest().
> 
> > If we take neither branch, then (minimally) the jump address under step
> > 4. will be wrong -- there's not going to be a DAT_IN / DAT_OUT command
> > to jump to.
> >
> > 
> > (9) So, for addressing all of the above, I suggest:
> > 
> >   //
> >   // 8. Set the DMA command for the read/write operations.
> >   //
> >   // LsiScsiCheckRequest() prevents both integer overflows in the command
> >   // opcodes, and buffer overflows.
> >   //
> >   if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
> >     ASSERT (Packet->InTransferLength <= sizeof Dev->Dma->Data);
> >     *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_DAT_IN |
> >                 Packet->InTransferLength;
> >   } else {
> >     ASSERT (Packet->OutTransferLength <= sizeof Dev->Dma->Data);
> >     CopyMem (Data, Packet->OutDataBuffer, Packet->OutTransferLength);
> >     *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_DAT_OUT |
> >                 Packet->OutTransferLength;
> >   }
> >   *Script++ = LSI_SCSI_DMA_ADDR (Dev, Data);
> >
> Thanks. Will modify the code here.
> 

The above code actually doesn't work because "TEST UNIT READY", the scsi
command, generates a request packet with 0 InTransferLength, and the
controller returns an error for data underflow.

The original code skips the DMA command for the 0 InTransferLength
requests and avoids the error. I'll keep the original code and add some
comments about that error.

Gary Lin

> > 
> > > +
> > > +  //
> > > +  // 9. Get the SCSI status.
> > > +  //
> > > +  *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_STAT | \
> > > +              sizeof Dev->Dma->Status;
> > > +  *Script++ = LSI_SCSI_DMA_ADDR_LOW (Dev, Status);
> > > +
> > > +  //
> > > +  // 10. Get the SCSI message.
> > > +  //
> > > +  *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_MSG_IN | \
> > > +              sizeof Dev->Dma->MsgIn;
> > > +  *Script++ = LSI_SCSI_DMA_ADDR_LOW (Dev, MsgIn);
> > > +
> > > +  //
> > > +  // 11. Raise the interrupt to end the script.
> > > +  //
> > > +  *Script++ = LSI_INS_TYPE_TC | LSI_INS_TC_OPC_INT | \
> > > +              LSI_INS_TC_SCSIP_DAT_OUT | LSI_INS_TC_JMP;
> > > +  *Script++ = 0x00000000;
> > > +
> > > +  //
> > > +  // Make sure the size of the script doesn't exceed the buffer.
> > > +  //
> > > +  ASSERT (Script < Dev->Dma->Script + sizeof Dev->Dma->Script);
> > 
> > (10) Please replace "<" with "<=".
> > 
> > (11) Please replace "sizeof" with ARRAY_SIZE().
> >
> Will fix it.
> 
> > 
> > > +
> > > +  //
> > > +  // The controller starts to execute the script once the DMA Script
> > > +  // Pointer (DSP) register is set.
> > > +  //
> > > +  Status = Out32 (Dev, LSI_REG_DSP, LSI_SCSI_DMA_ADDR_LOW(Dev, Script));
> > 
> > (12) Missing space after "LSI_SCSI_DMA_ADDR".
> > 
> Ditto.
> 
> > 
> > > +  if (EFI_ERROR (Status)) {
> > > +    return Status;
> > > +  }
> > 
> > This return statement doesn't seem right. We do not translate the error
> > code to one of the error codes specified for
> > EFI_EXT_SCSI_PASS_THRU_PROTOCOL.PassThru(). We also do not set any
> > output field in Packet.
> > 
> > (13) I think we should jump to the "Error" label from here.
> > 
> Right. It should jump to "Error".
> 
> > 
> > > +
> > > +  //
> > > +  // Poll the device registers (DSTAT, SIST0, and SIST1) until the SIR
> > > +  // bit sets.
> > > +  //
> > > +  for(;;) {
> > > +    Status = In8 (Dev, LSI_REG_DSTAT, &DStat);
> > > +    if (EFI_ERROR (Status)) {
> > > +      goto Error;
> > > +    }
> > > +    Status = In8 (Dev, LSI_REG_SIST0, &SIst0);
> > > +    if (EFI_ERROR (Status)) {
> > > +      goto Error;
> > > +    }
> > > +    Status = In8 (Dev, LSI_REG_SIST1, &SIst1);
> > > +    if (EFI_ERROR (Status)) {
> > > +      goto Error;
> > > +    }
> > > +
> > > +    if (SIst0 != 0 || SIst1 != 0) {
> > > +      goto Error;
> > > +    }
> > > +
> > > +    //
> > > +    // Check the SIR (SCRIPTS Interrupt Instruction Received) bit.
> > > +    //
> > > +    if (DStat & LSI_DSTAT_SIR) {
> > > +      break;
> > > +    }
> > > +
> > > +    gBS->Stall (Dev->StallPerPollUsec);
> > > +  }
> > > +
> > > +  //
> > > +  // Check if everything is good.
> > > +  //   SCSI Message Code 0x00: COMMAND COMPLETE
> > > +  //   SCSI Status  Code 0x00: Good
> > > +  //
> > > +  if (MsgIn[0] == 0 && *ScsiStatus == 0) {
> > 
> > (14) Please negate this condition, and unnest the success branch:
> > 
> >   if (MsgIn[0] != 0 || *ScsiStatus != 0) {
> >     goto Error;
> >   }
> > 
> >   /* ... */
> > 
> >   return EFI_SUCCESS;
> > 
> > 
> Ok. Will do that.
> 
> > > +    //
> > > +    // Copy Data to InDataBuffer if necessary.
> > > +    //
> > > +    if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
> > > +      CopyMem (Packet->InDataBuffer, Data, Packet->InTransferLength);
> > > +    }
> > > +
> > > +    //
> > > +    // The controller doesn't return sense data when replying "TEST UNIT READY",
> > > +    // so we have to set SenseDataLength to 0 to notify ScsiIo to issue
> > > +    // "REQUEST SENSE" for the sense data.
> > > +    //
> > > +    if (Cdb[0] == 0x00) {
> > > +      Packet->SenseDataLength = 0;
> > > +    }
> > > +    Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK;
> > > +    Packet->TargetStatus      = EFI_EXT_SCSI_STATUS_TARGET_GOOD;
> > > +
> > > +    return EFI_SUCCESS;
> > > +  }
> > 
> > The mapping on success does not deal with short transfers (in or out) --
> > we're supposed to update InTransferLength / OutTransferLength on output.
> > 
> > (15) Does the device report short transfers somehow?
> > 
> I'm not sure. Have to check the spec of controller to see if there is
> any instruction to fetch the real transfer length.
> 
> > 
> > The spec says about SenseDataLength, "On input, the length in bytes of
> > the SenseData buffer. On output, the number of bytes written to the
> > SenseData buffer".
> > 
> > But we only set SenseDataLength conditionally. In case we do *not* set
> > it, the caller may attempt to parse garbage from the "SenseData" buffer.
> > 
> > (16) We should either get real sense data back to the caller, or always
> > zero out "SenseDataLength".
> > 
> > 
> For simplicity, I would choose zeroing out "SenseDataLength" since
> ScsiDiskDxe can handle it.
> 
> > > +
> > > +Error:
> > > +  DEBUG((DEBUG_VERBOSE, "%a: dstat: %02X, sist0: %02X, sist1: %02X\n",
> > > +         __FUNCTION__, DStat, SIst0, SIst1));
> > 
> > (17) missing space after "DEBUG".
> > 
> > (18) The line starting with __FUNCTION__ is not correctly indented.
> >
> Will fix them.
> 
> > 
> > > +  //
> > > +  // Update the request packet to reflect the status.
> > > +  //
> > > +  if (*ScsiStatus != 0xFF) {
> > > +    Packet->TargetStatus    = *ScsiStatus;
> > > +  } else {
> > > +    Packet->TargetStatus    = EFI_EXT_SCSI_STATUS_TARGET_TASK_ABORTED;
> > > +  }
> > > +  Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;
> > > +  Packet->InTransferLength  = 0;
> > > +  Packet->OutTransferLength = 0;
> > > +  Packet->SenseDataLength   = 0;
> > > +
> > > +  return EFI_DEVICE_ERROR;
> > > +}
> > > +
> > >  //
> > >  // The next seven functions implement EFI_EXT_SCSI_PASS_THRU_PROTOCOL
> > >  // for the LSI 53C895A SCSI Controller. Refer to UEFI Spec 2.3.1 + Errata C,
> > > @@ -168,6 +470,11 @@ LsiScsiPassThru (
> > >      return Status;
> > >    }
> > >
> > > +  Status = LsiScsiProcessRequest (Dev, *Target, Lun, Packet);
> > > +  if (EFI_ERROR (Status)) {
> > > +    return Status;
> > > +  }
> > > +
> > >    return EFI_SUCCESS;
> > >  }
> > >
> > 
> > (19) I think this can be simplified -- just return Status after calling
> > LsiScsiProcessRequest().
> >
> Agree.
> 
> > 
> > > @@ -469,6 +776,7 @@ LsiScsiControllerStart (
> > >
> > >    Dev->MaxTarget = PcdGet8 (PcdLsiScsiMaxTargetLimit);
> > >    Dev->MaxLun = PcdGet8 (PcdLsiScsiMaxLunLimit);
> > > +  Dev->StallPerPollUsec = PcdGet32 (PcdLsiScsiStallPerPollUsec);
> > >
> > >    Status = gBS->OpenProtocol (
> > >                    ControllerHandle,
> > > diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.h b/OvmfPkg/LsiScsiDxe/LsiScsi.h
> > > index 9272eb7506c7..1a16ef9f7795 100644
> > > --- a/OvmfPkg/LsiScsiDxe/LsiScsi.h
> > > +++ b/OvmfPkg/LsiScsiDxe/LsiScsi.h
> > > @@ -13,6 +13,11 @@
> > >  #define _LSI_SCSI_DXE_H_
> > >
> > >  typedef struct {
> > > +  //
> > > +  // Allocate 32 UINT32 entries for the script and it's sufficient for
> > > +  // 16 instructions.
> > > +  //
> > > +  UINT32                          Script[32];
> > >    //
> > >    // The max size of CDB is 32.
> > >    //
> > > @@ -21,6 +26,18 @@ typedef struct {
> > >    // Allocate 64KB for read/write buffer.
> > >    //
> > >    UINT8                           Data[0x10000];
> > > +  //
> > > +  // For SCSI Message In phase
> > > +  //
> > > +  UINT8                           MsgIn[2];
> > > +  //
> > > +  // For SCSI Message Out phase
> > > +  //
> > > +  UINT8                           MsgOut;
> > > +  //
> > > +  // For SCSI Status phase
> > > +  //
> > > +  UINT8                           Status;
> > >  } LSI_SCSI_DMA_BUFFER;
> > >
> > >  typedef struct {
> > > @@ -30,6 +47,7 @@ typedef struct {
> > >    EFI_PCI_IO_PROTOCOL             *PciIo;
> > >    UINT8                           MaxTarget;
> > >    UINT8                           MaxLun;
> > > +  UINT32                          StallPerPollUsec;
> > >    LSI_SCSI_DMA_BUFFER             *Dma;
> > >    EFI_PHYSICAL_ADDRESS            DmaPhysical;
> > >    VOID                            *DmaMapping;
> > > @@ -42,6 +60,9 @@ typedef struct {
> > >  #define LSI_SCSI_FROM_PASS_THRU(PassThruPtr) \
> > >    CR (PassThruPtr, LSI_SCSI_DEV, PassThru, LSI_SCSI_DEV_SIGNATURE)
> > >
> > > +#define LSI_SCSI_DMA_ADDR_LOW(Dev, MemberName) \
> > > +  ((UINT32)(Dev->DmaPhysical + OFFSET_OF (LSI_SCSI_DMA_BUFFER, MemberName)))
> > > +
> > >
> > >  //
> > >  // Probe, start and stop functions of this driver, called by the DXE core for
> > > diff --git a/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf b/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> > > index 68844c6772e3..cbd7294573ac 100644
> > > --- a/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> > > +++ b/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
> > > @@ -41,3 +41,6 @@ [Protocols]
> > >  [FixedPcd]
> > >    gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiMaxTargetLimit   ## CONSUMES
> > >    gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiMaxLunLimit      ## CONSUMES
> > > +
> > > +[Pcd]
> > > +  gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiStallPerPollUsec ## CONSUMES
> > > diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
> > > index ae7d1d648d22..57e418d4b8a9 100644
> > > --- a/OvmfPkg/OvmfPkg.dec
> > > +++ b/OvmfPkg/OvmfPkg.dec
> > > @@ -179,6 +179,9 @@ [PcdsFixedAtBuild]
> > >    gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiMaxTargetLimit|7|UINT8|0x3b
> > >    gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiMaxLunLimit|0|UINT8|0x3c
> > >
> > > +  ## Microseconds to stall between polling for LsiScsi request result
> > > +  gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiStallPerPollUsec|5|UINT32|0x3d
> > > +
> > 
> > (20) The token value should be 0x3c here, according to my request (5)
> > under "[PATCH 06/11] OvmfPkg/LsiScsiDxe: Report Targets and LUNs".
> >
> Ok, will do that if we won't change the toke value of PcdMptScsiStallPerPollUsec.
> 
> Thanks,
> 
> Gary Lin
> 
> > 
> > >    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogBase|0x0|UINT32|0x8
> > >    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogSize|0x0|UINT32|0x9
> > >    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareFdSize|0x0|UINT32|0xa
> > >
> > 
> > Thanks
> > Laszlo
> > 
> 
> 
> 
> 


^ permalink raw reply	[flat|nested] 35+ messages in thread

end of thread, other threads:[~2020-07-14  8:19 UTC | newest]

Thread overview: 35+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-07-01  4:04 [PATCH 00/11] Introduce LsiScsi driver to OvmfPkg Gary Lin
2020-07-01  4:04 ` [PATCH 01/11] OvmfPkg/LsiScsiDxe: Create the empty driver Gary Lin
2020-07-07  7:59   ` Laszlo Ersek
2020-07-07  8:24     ` Gary Lin
2020-07-01  4:04 ` [PATCH 02/11] OvmfPkg/LsiScsiDxe: Install the skeleton of driver binding Gary Lin
2020-07-07  8:06   ` Laszlo Ersek
2020-07-07  8:34     ` Gary Lin
2020-07-01  4:04 ` [PATCH 03/11] OvmfPkg/LsiScsiDxe: Report the name of the driver Gary Lin
2020-07-07  8:09   ` Laszlo Ersek
2020-07-01  4:04 ` [PATCH 04/11] OvmfPkg/LsiScsiDxe: Probe PCI devices and look for LsiScsi Gary Lin
2020-07-07  8:15   ` Laszlo Ersek
2020-07-07  8:16     ` Laszlo Ersek
2020-07-01  4:04 ` [PATCH 05/11] OvmfPkg/LsiScsiDxe: Install stubbed EXT_SCSI_PASS_THRU Gary Lin
2020-07-07  8:28   ` Laszlo Ersek
2020-07-01  4:04 ` [PATCH 06/11] OvmfPkg/LsiScsiDxe: Report Targets and LUNs Gary Lin
2020-07-07  9:04   ` Laszlo Ersek
2020-07-08  2:34     ` Gary Lin
2020-07-08 15:26       ` Laszlo Ersek
2020-07-01  4:04 ` [PATCH 07/11] OvmfPkg/LsiScsiDxe: Open PciIo protocol and initialize the device Gary Lin
2020-07-07  9:46   ` Laszlo Ersek
2020-07-08  2:37     ` Gary Lin
2020-07-01  4:04 ` [PATCH 08/11] OvmfPkg/LsiScsiDxe: Map DMA buffer Gary Lin
2020-07-07  9:59   ` Laszlo Ersek
2020-07-08  2:41     ` Gary Lin
2020-07-01  4:04 ` [PATCH 09/11] OvmfPkg/LsiScsiDxe: Examine the incoming SCSI Request Packet Gary Lin
2020-07-07 10:17   ` Laszlo Ersek
2020-07-08  2:43     ` Gary Lin
2020-07-01  4:04 ` [PATCH 10/11] OvmfPkg/LsiScsiDxe: Process the " Gary Lin
2020-07-07 12:46   ` Laszlo Ersek
2020-07-08  6:02     ` Gary Lin
     [not found]     ` <161FB1B03BD2D339.11266@groups.io>
2020-07-14  8:19       ` [edk2-devel] " Gary Lin
2020-07-01  4:04 ` [PATCH 11/11] Maintainers.txt: Add myself as the reviewer for LsiScsi driver Gary Lin
2020-07-07 12:49   ` Laszlo Ersek
2020-07-08  6:03     ` Gary Lin
2020-07-03 14:08 ` [edk2-devel] [PATCH 00/11] Introduce LsiScsi driver to OvmfPkg Laszlo Ersek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox