* [RFC PATCH 1/1] OvmfPkg: Introduce LSI 53C895A SCSI Controller Driver
@ 2020-06-12 10:04 Gary Lin
2020-06-15 11:27 ` Laszlo Ersek
0 siblings, 1 reply; 4+ messages in thread
From: Gary Lin @ 2020-06-12 10:04 UTC (permalink / raw)
To: devel; +Cc: Jordan Justen, Laszlo Ersek, Ard Biesheuvel
This commit introduces the driver for LSI 53C895A SCSI Controller which,
so that OVMF can access the devices attached to the emulated "lsi" 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>
---
Although lsi is now considered obsolete in QEMU, I wrote this driver
mainly for learning the UEFI SCSI driver and ... FUN! The majority of
the code is actually borrowed from VirtioScsci and MptScsi, and I mainly
focus on LsiScsiPassThru().
If it's fine to add this driver into OvmfPkg, I'll start to split this
patch into smaller pieces to make it easier to review.
---
OvmfPkg/Include/IndustryStandard/LsiScsi.h | 80 ++
OvmfPkg/LsiScsiDxe/LsiScsi.c | 1120 ++++++++++++++++++++
OvmfPkg/LsiScsiDxe/LsiScsi.h | 199 ++++
OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf | 45 +
OvmfPkg/OvmfPkg.dec | 9 +
OvmfPkg/OvmfPkgIa32.dsc | 4 +
OvmfPkg/OvmfPkgIa32.fdf | 3 +
OvmfPkg/OvmfPkgIa32X64.dsc | 4 +
OvmfPkg/OvmfPkgIa32X64.fdf | 3 +
OvmfPkg/OvmfPkgX64.dsc | 4 +
OvmfPkg/OvmfPkgX64.fdf | 3 +
11 files changed, 1474 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
diff --git a/OvmfPkg/Include/IndustryStandard/LsiScsi.h b/OvmfPkg/Include/IndustryStandard/LsiScsi.h
new file mode 100644
index 000000000000..cbf049c18310
--- /dev/null
+++ b/OvmfPkg/Include/IndustryStandard/LsiScsi.h
@@ -0,0 +1,80 @@
+/** @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
+
+//
+// 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 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)
+//
+#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
+
+//
+// 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
new file mode 100644
index 000000000000..a226a0e789da
--- /dev/null
+++ b/OvmfPkg/LsiScsiDxe/LsiScsi.c
@@ -0,0 +1,1120 @@
+/** @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 <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/PcdLib.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"
+
+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
+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 (
+ IN LSI_SCSI_DEV *Dev
+ )
+{
+ 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;
+}
+
+/**
+
+ 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);
+
+ //
+ // 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.
+ //
+ // The controller starts to execute the script once the DMA Script
+ // Pointer (DSP) register is set.
+ //
+ SetMem (Script, sizeof Dev->Dma->Script, 0x00);
+
+ //
+ // Select target.
+ //
+ *Script++ = LSI_INS_TYPE_IO | LSI_INS_IO_OPC_SEL | (UINT32)Target << 16;
+ *Script++ = 0x00000000;
+
+ //
+ // 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);
+
+ //
+ // 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);
+
+ //
+ // Handle disconnect
+ //
+ // Check whether the current SCSI phase is "Message In" or not.
+ // If not, try to enter the "Message In" phase to reconnect to the
+ // device.
+ //
+ *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;
+ //
+ // 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);
+ //
+ // Wait reselect.
+ //
+ *Script++ = LSI_INS_TYPE_IO | LSI_INS_IO_OPC_WAIT_RESEL;
+ *Script++ = 0x00000000;
+ //
+ // 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);
+
+ //
+ // 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);
+ }
+
+ //
+ // 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);
+
+ //
+ // 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);
+
+ //
+ // 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 script doesn't exceed the size.
+ //
+ ASSERT (Script < Dev->Dma->Script + sizeof Dev->Dma->Script);
+
+ //
+ // Execute the script.
+ //
+ 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,
+// 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 Status;
+ LSI_SCSI_DEV *Dev;
+
+ Dev = LSI_SCSI_FROM_PASS_THRU (This);
+ Status = LsiScsiCheckRequest (Dev, *Target, Lun, Packet);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = LsiScsiProcessRequest (Dev, *Target, Lun, Packet);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+LsiScsiGetNextTargetLun (
+ IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
+ IN OUT UINT8 **TargetPointer,
+ 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;
+}
+
+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
+ )
+{
+ 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
+EFIAPI
+LsiScsiGetTargetLun (
+ IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ OUT UINT8 **TargetPointer,
+ OUT UINT64 *Lun
+ )
+{
+ 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
+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
+ )
+{
+ 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;
+}
+
+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.
+//
+// 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
+ )
+{
+ 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
+EFIAPI
+LsiScsiControllerStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ LSI_SCSI_DEV *Dev;
+ UINTN Pages;
+ UINTN BytesMapped;
+
+ Dev = AllocateZeroPool (sizeof (*Dev));
+ if (Dev == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Dev->Signature = LSI_SCSI_DEV_SIGNATURE;
+
+ Dev->MaxTarget = PcdGet8 (PcdLsiScsiMaxTargetLimit);
+ Dev->MaxLun = PcdGet8 (PcdLsiScsiMaxLunLimit);
+ Dev->StallPerPollUsec = PcdGet32 (PcdLsiScsiStallPerPollUsec);
+
+ 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;
+ }
+
+ //
+ // 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,
+ &LsiScsiExitBoot,
+ Dev,
+ &Dev->ExitBoot
+ );
+ if (EFI_ERROR (Status)) {
+ goto UninitDev;
+ }
+
+ //
+ // 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 CloseExitBoot;
+ }
+
+ return EFI_SUCCESS;
+
+CloseExitBoot:
+ gBS->CloseEvent (Dev->ExitBoot);
+
+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,
+ EfiPciIoAttributeOperationSet,
+ Dev->OrigPciAttrs,
+ NULL
+ );
+
+CloseProtocol:
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+
+FreePool:
+ FreePool (Dev);
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+LsiScsiControllerStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+{
+ 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->CloseEvent (Dev->ExitBoot);
+
+ 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,
+ Dev->OrigPciAttrs,
+ NULL
+ );
+
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+
+ FreePool (Dev);
+
+ return Status;
+}
+
+//
+// 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
+};
+
+
+//
+// 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
+//
+EFI_STATUS
+EFIAPI
+LsiScsiEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ return EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gDriverBinding,
+ ImageHandle, // The handle to install onto
+ &gComponentName,
+ &gComponentName2
+ );
+}
diff --git a/OvmfPkg/LsiScsiDxe/LsiScsi.h b/OvmfPkg/LsiScsiDxe/LsiScsi.h
new file mode 100644
index 000000000000..1a16ef9f7795
--- /dev/null
+++ b/OvmfPkg/LsiScsiDxe/LsiScsi.h
@@ -0,0 +1,199 @@
+/** @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_
+
+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.
+ //
+ UINT8 Cdb[32];
+ //
+ // 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 {
+ UINT32 Signature;
+ UINT64 OrigPciAttrs;
+ EFI_EVENT ExitBoot;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT8 MaxTarget;
+ UINT8 MaxLun;
+ UINT32 StallPerPollUsec;
+ 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;
+
+#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)
+
+#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
+// 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
+ );
+
+
+//
+// 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
+// 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_
diff --git a/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf b/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
new file mode 100644
index 000000000000..10f7f0eebd0e
--- /dev/null
+++ b/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
@@ -0,0 +1,45 @@
+## @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
+ OvmfPkg/OvmfPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ MemoryAllocationLib
+ PcdLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiLib
+
+[Protocols]
+ gEfiExtScsiPassThruProtocolGuid ## BY_START
+ gEfiPciIoProtocolGuid ## TO_START
+
+[FixedPcd]
+ gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiMaxTargetLimit ## CONSUMES
+ gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiMaxLunLimit ## CONSUMES
+
+[Pcd]
+ gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiStallPerPollUsec ## CONSUMES
diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index 65bb2bb0eb4c..ddf81f2bbcb8 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -174,6 +174,15 @@ [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
+
+ ## 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
diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
index d0df9cbbfb2b..ea1940fc354b 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 = TRUE
#
# Flash size selection. Setting FD_SIZE_IN_KB on the command line directly to
@@ -775,6 +776,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 b3ae62fee92b..2cc8cb8053c6 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 = TRUE
#
# Flash size selection. Setting FD_SIZE_IN_KB on the command line directly to
@@ -789,6 +790,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 f7fe75ebf531..2708ce0d2df5 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 = TRUE
#
# Flash size selection. Setting FD_SIZE_IN_KB on the command line directly to
@@ -785,6 +786,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] 4+ messages in thread
* Re: [RFC PATCH 1/1] OvmfPkg: Introduce LSI 53C895A SCSI Controller Driver
2020-06-12 10:04 [RFC PATCH 1/1] OvmfPkg: Introduce LSI 53C895A SCSI Controller Driver Gary Lin
@ 2020-06-15 11:27 ` Laszlo Ersek
2020-06-17 2:09 ` Gary Lin
0 siblings, 1 reply; 4+ messages in thread
From: Laszlo Ersek @ 2020-06-15 11:27 UTC (permalink / raw)
To: Gary Lin; +Cc: devel, Jordan Justen, Ard Biesheuvel
Hello Gary,
On 06/12/20 12:04, Gary Lin wrote:
> This commit introduces the driver for LSI 53C895A SCSI Controller
> which, so that OVMF can access the devices attached to the emulated
> "lsi" 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>
> ---
> Although lsi is now considered obsolete in QEMU, I wrote this driver
> mainly for learning the UEFI SCSI driver and ... FUN! The majority of
> the code is actually borrowed from VirtioScsci and MptScsi, and I
> mainly focus on LsiScsiPassThru().
>
> If it's fine to add this driver into OvmfPkg, I'll start to split this
> patch into smaller pieces to make it easier to review.
(1) Do we have an official deprecation notice for this SCSI controller
in QEMU?
If we do, then (AIUI) the controller will be removed in QEMU in one or
two releases, so this code would become effectively dead in the mid
term. I wouldn't like to review and/or carry code that's soon to be
dead.
(2) If there is no official deprecation notice in QEMU, then I agree it
makes sense to include this driver. In that case, I have another
question:
Do you intend this driver for production purposes? I.e., do you expect
users or "layered products" (libvirt, proxmox, openstack, ...) to use
this SCSI controller for some well-defined purpose? (The MPT SCSI and PV
SCSI drivers had a clear product-oriented modivation:
https://edk2.groups.io/g/devel/message/55620
http://mid.mail-archive.com/a96b6b74-c35d-e291-2122-9d77f1d5f89c@oracle.com
)
(2a) If this driver is not meant for a production environment, then
LSI_SCSI_ENABLE should be FALSE by default (and I'll do a lighter
review).
(2b) If the driver is meant for production, then LSI_SCSI_ENABLE should
indeed be TRUE, and I'll have to be more diligent in reviewing this.
For either (2a) or (2b), please do split up the driver into smaller
patches, and please also add yourself to Maintainers.txt as the
designated reviewer of the new driver.
Thanks
Laszlo
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [RFC PATCH 1/1] OvmfPkg: Introduce LSI 53C895A SCSI Controller Driver
2020-06-15 11:27 ` Laszlo Ersek
@ 2020-06-17 2:09 ` Gary Lin
2020-06-17 10:38 ` Laszlo Ersek
0 siblings, 1 reply; 4+ messages in thread
From: Gary Lin @ 2020-06-17 2:09 UTC (permalink / raw)
To: Laszlo Ersek; +Cc: devel, Jordan Justen, Ard Biesheuvel
On Mon, Jun 15, 2020 at 01:27:22PM +0200, Laszlo Ersek wrote:
> Hello Gary,
>
Hi Laszlo,
> On 06/12/20 12:04, Gary Lin wrote:
> > This commit introduces the driver for LSI 53C895A SCSI Controller
> > which, so that OVMF can access the devices attached to the emulated
> > "lsi" 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>
> > ---
> > Although lsi is now considered obsolete in QEMU, I wrote this driver
> > mainly for learning the UEFI SCSI driver and ... FUN! The majority of
> > the code is actually borrowed from VirtioScsci and MptScsi, and I
> > mainly focus on LsiScsiPassThru().
> >
> > If it's fine to add this driver into OvmfPkg, I'll start to split this
> > patch into smaller pieces to make it easier to review.
>
> (1) Do we have an official deprecation notice for this SCSI controller
> in QEMU?
>
> If we do, then (AIUI) the controller will be removed in QEMU in one or
> two releases, so this code would become effectively dead in the mid
> term. I wouldn't like to review and/or carry code that's soon to be
> dead.
>
I just vaguely remember that virtio-scsi is the new default over lsi and
it's not recommended to use lsi except for the old OS without virtio-scsi
driver.
> (2) If there is no official deprecation notice in QEMU, then I agree it
> makes sense to include this driver. In that case, I have another
> question:
>
> Do you intend this driver for production purposes? I.e., do you expect
> users or "layered products" (libvirt, proxmox, openstack, ...) to use
> this SCSI controller for some well-defined purpose? (The MPT SCSI and PV
> SCSI drivers had a clear product-oriented modivation:
>
> https://edk2.groups.io/g/devel/message/55620
> http://mid.mail-archive.com/a96b6b74-c35d-e291-2122-9d77f1d5f89c@oracle.com
> )
>
> (2a) If this driver is not meant for a production environment, then
> LSI_SCSI_ENABLE should be FALSE by default (and I'll do a lighter
> review).
>
> (2b) If the driver is meant for production, then LSI_SCSI_ENABLE should
> indeed be TRUE, and I'll have to be more diligent in reviewing this.
>
I kind of wonder if the any serious use for lsi+ovmf. If the OS is so
old and only supports lsi, seabios probably serves it better. Anyway,
I'll try to gather more information from my colleagues to see if they
got any feedback about lsi from our customers. If not, I'll set
LSI_SCSI_ENABLE to FALSE by default.
> For either (2a) or (2b), please do split up the driver into smaller
> patches, and please also add yourself to Maintainers.txt as the
> designated reviewer of the new driver.
>
Sure. Will do that.
Thanks,
Gary Lin
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [RFC PATCH 1/1] OvmfPkg: Introduce LSI 53C895A SCSI Controller Driver
2020-06-17 2:09 ` Gary Lin
@ 2020-06-17 10:38 ` Laszlo Ersek
0 siblings, 0 replies; 4+ messages in thread
From: Laszlo Ersek @ 2020-06-17 10:38 UTC (permalink / raw)
To: Gary Lin; +Cc: devel, Jordan Justen, Ard Biesheuvel
On 06/17/20 04:09, Gary Lin wrote:
> On Mon, Jun 15, 2020 at 01:27:22PM +0200, Laszlo Ersek wrote:
>> Hello Gary,
>>
> Hi Laszlo,
>
>> On 06/12/20 12:04, Gary Lin wrote:
>>> This commit introduces the driver for LSI 53C895A SCSI Controller
>>> which, so that OVMF can access the devices attached to the emulated
>>> "lsi" 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>
>>> ---
>>> Although lsi is now considered obsolete in QEMU, I wrote this driver
>>> mainly for learning the UEFI SCSI driver and ... FUN! The majority of
>>> the code is actually borrowed from VirtioScsci and MptScsi, and I
>>> mainly focus on LsiScsiPassThru().
>>>
>>> If it's fine to add this driver into OvmfPkg, I'll start to split this
>>> patch into smaller pieces to make it easier to review.
>>
>> (1) Do we have an official deprecation notice for this SCSI controller
>> in QEMU?
>>
>> If we do, then (AIUI) the controller will be removed in QEMU in one or
>> two releases, so this code would become effectively dead in the mid
>> term. I wouldn't like to review and/or carry code that's soon to be
>> dead.
>>
> I just vaguely remember that virtio-scsi is the new default over lsi and
> it's not recommended to use lsi except for the old OS without virtio-scsi
> driver.
So the question is then whether the old OS that supports LSI but not
virtio-scsi is capable of booting on UEFI in the first place.
>
>> (2) If there is no official deprecation notice in QEMU, then I agree it
>> makes sense to include this driver. In that case, I have another
>> question:
>>
>> Do you intend this driver for production purposes? I.e., do you expect
>> users or "layered products" (libvirt, proxmox, openstack, ...) to use
>> this SCSI controller for some well-defined purpose? (The MPT SCSI and PV
>> SCSI drivers had a clear product-oriented modivation:
>>
>> https://edk2.groups.io/g/devel/message/55620
>> http://mid.mail-archive.com/a96b6b74-c35d-e291-2122-9d77f1d5f89c@oracle.com
>> )
>>
>> (2a) If this driver is not meant for a production environment, then
>> LSI_SCSI_ENABLE should be FALSE by default (and I'll do a lighter
>> review).
>>
>> (2b) If the driver is meant for production, then LSI_SCSI_ENABLE should
>> indeed be TRUE, and I'll have to be more diligent in reviewing this.
>>
> I kind of wonder if the any serious use for lsi+ovmf. If the OS is so
> old and only supports lsi, seabios probably serves it better.
Right, my point exactly!
> Anyway,
> I'll try to gather more information from my colleagues to see if they
> got any feedback about lsi from our customers. If not, I'll set
> LSI_SCSI_ENABLE to FALSE by default.
Sounds like a good approach!
>
>> For either (2a) or (2b), please do split up the driver into smaller
>> patches, and please also add yourself to Maintainers.txt as the
>> designated reviewer of the new driver.
>>
> Sure. Will do that.
Thanks!
Laszlo
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2020-06-17 10:39 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-06-12 10:04 [RFC PATCH 1/1] OvmfPkg: Introduce LSI 53C895A SCSI Controller Driver Gary Lin
2020-06-15 11:27 ` Laszlo Ersek
2020-06-17 2:09 ` Gary Lin
2020-06-17 10:38 ` Laszlo Ersek
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox