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.jus...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Cc: Ard Biesheuvel <ard.biesheu...@arm.com> Signed-off-by: Gary Lin <g...@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 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#61210): https://edk2.groups.io/g/devel/message/61210 Mute This Topic: https://groups.io/mt/74836137/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-