X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=MdePkg%2FLibrary%2FUefiScsiLib%2FUefiScsiLib.c;h=62a73e27731cafe466804ed789f134d045590d6d;hb=d7634dc0c5a83360b3b6c155df29c078ad9c77ce;hp=ef6a4ebd8872cbc66ff51a29eeaaf4fbeb90768f;hpb=a02e796b5edcdd538c6052b8b65798eb77436504;p=mirror_edk2.git
diff --git a/MdePkg/Library/UefiScsiLib/UefiScsiLib.c b/MdePkg/Library/UefiScsiLib/UefiScsiLib.c
index ef6a4ebd88..62a73e2773 100644
--- a/MdePkg/Library/UefiScsiLib/UefiScsiLib.c
+++ b/MdePkg/Library/UefiScsiLib/UefiScsiLib.c
@@ -1,94 +1,160 @@
-/*++
+/** @file
+ UEFI SCSI Library implementation
-Copyright (c) 2006, Intel Corporation
-All rights reserved. This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
-Module Name:
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
- ScsiLib.c
-
-Abstract:
-
+**/
-Revision History
---*/
-//
-// The package level header files this module uses
-//
-#include
-
-//
-// The protocols, PPI and GUID defintions for this module
-//
-//
-// The Library classes this module consumes
-//
-#include
+#include
+#include
+#include
+#include
#include
+#include
+#include
-#include
+#include
+
+ //
+ // Scsi Command Length
+ //
+#define EFI_SCSI_OP_LENGTH_SIX 0x6
+#define EFI_SCSI_OP_LENGTH_TEN 0xa
+#define EFI_SCSI_OP_LENGTH_SIXTEEN 0x10
+
+//
+// The context structure used when non-blocking SCSI read/write operation
+// completes.
+//
+typedef struct {
+ ///
+ /// The SCSI request packet to send to the SCSI controller specified by
+ /// the device handle.
+ ///
+ EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
+ ///
+ /// The length of the output sense data.
+ ///
+ UINT8 *SenseDataLength;
+ ///
+ /// The status of the SCSI host adapter.
+ ///
+ UINT8 *HostAdapterStatus;
+ ///
+ /// The status of the target SCSI device.
+ ///
+ UINT8 *TargetStatus;
+ ///
+ /// The length of the data buffer for the SCSI read/write command.
+ ///
+ UINT32 *DataLength;
+ ///
+ /// The caller event to be signaled when the SCSI read/write command
+ /// completes.
+ ///
+ EFI_EVENT CallerEvent;
+} EFI_SCSI_LIB_ASYNC_CONTEXT;
+
+
+
+/**
+ Execute Test Unit Ready SCSI command on a specific SCSI target.
+
+ Executes the Test Unit Ready command on the SCSI target specified by ScsiIo.
+ If Timeout is zero, then this function waits indefinitely for the command to complete.
+ If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.
+ If ScsiIo is NULL, then ASSERT().
+ If SenseDataLength is NULL, then ASSERT().
+ If HostAdapterStatus is NULL, then ASSERT().
+ If TargetStatus is NULL, then ASSERT().
+
+ If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
+ gets returned.
+
+ @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance
+ for the specific SCSI target.
+ @param[in] Timeout The timeout in 100 ns units to use for the execution
+ of this SCSI Request Packet. A Timeout value of
+ zero means that this function will wait indefinitely
+ for the SCSI Request Packet to execute. If Timeout
+ is greater than zero, then this function will return
+ EFI_TIMEOUT if the time required to execute the SCSI
+ Request Packet is greater than Timeout.
+ @param[in, out] SenseData A pointer to sense data that was generated by
+ the execution of the SCSI Request Packet. This
+ buffer must be allocated by the caller.
+ If SenseDataLength is 0, then this parameter is
+ optional and may be NULL.
+ @param[in, out] SenseDataLength On input, a pointer to the length in bytes of
+ the SenseData buffer. On output, a pointer to
+ the number of bytes written to the SenseData buffer.
+ @param[out] HostAdapterStatus The status of the SCSI Host Controller that produces
+ the SCSI bus containing the SCSI target specified by
+ ScsiIo when the SCSI Request Packet was executed.
+ See the EFI SCSI I/O Protocol in the UEFI Specification
+ for details on the possible return values.
+ @param[out] TargetStatus The status returned by the SCSI target specified
+ by ScsiIo when the SCSI Request Packet was executed
+ on the SCSI Host Controller. See the EFI SCSI I/O
+ Protocol in the UEFI Specification for details on
+ the possible return values.
+
+ @retval EFI_SUCCESS The command was executed successfully.
+ See HostAdapterStatus, TargetStatus, SenseDataLength,
+ and SenseData in that order for additional status
+ information.
+ @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
+ there are too many SCSI Command Packets already
+ queued. The SCSI Request Packet was not sent, so
+ no additional status information is available.
+ The caller may retry again later.
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
+ SCSI Request Packet. See HostAdapterStatus,
+ TargetStatus, SenseDataLength, and SenseData in that
+ order for additional status information.
+ @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
+ is not supported by the SCSI initiator(i.e., SCSI
+ Host Controller). The SCSI Request Packet was not
+ sent, so no additional status information is available.
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request
+ Packet to execute. See HostAdapterStatus, TargetStatus,
+ SenseDataLength, and SenseData in that order for
+ additional status information.
+ @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.
+
+**/
EFI_STATUS
-SubmitTestUnitReadyCommand (
- IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
- IN UINT64 Timeout,
- OUT VOID *SenseData,
- OUT UINT8 *SenseDataLength,
- OUT UINT8 *HostAdapterStatus,
- OUT UINT8 *TargetStatus
+EFIAPI
+ScsiTestUnitReadyCommand (
+ IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
+ IN UINT64 Timeout,
+ IN OUT VOID *SenseData, OPTIONAL
+ IN OUT UINT8 *SenseDataLength,
+ OUT UINT8 *HostAdapterStatus,
+ OUT UINT8 *TargetStatus
)
-/*++
-
-Routine Description:
- Function tests the ready status of SCSI unit.
-
-Arguments:
- ScsiIo - A pointer to SCSI IO protocol.
- Timeout - The length of timeout period.
- SenseData - A pointer to output sense data.
- SenseDataLength - The length of output sense data.
- HostAdapterStatus - The status of Host Adapter.
- TargetStatus - The status of the target.
-
-Returns:
-
- Returns:
- EFI_SUCCESS - The status of the unit is tested successfully.
- EFI_BAD_BUFFER_SIZE - The SCSI Request Packet was executed,
- but the entire DataBuffer could not be transferred.
- The actual number of bytes transferred is returned
- in InTransferLength.
- EFI_NOT_READY - The SCSI Request Packet could not be sent because
- there are too many SCSI Command Packets already
- queued.
- EFI_DEVICE_ERROR - A device error occurred while attempting to send
- the SCSI Request Packet.
- EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid.
- EFI_UNSUPPORTED - The command described by the SCSI Request Packet
- is not supported by the SCSI initiator(i.e., SCSI
- Host Controller).
- EFI_TIMEOUT - A timeout occurred while waiting for the SCSI
- Request Packet to execute.
-
---*/
{
EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
- UINT64 Lun;
- UINT8 *Target;
- UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];
EFI_STATUS Status;
- UINT8 Cdb[6];
+ UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];
+ ASSERT (SenseDataLength != NULL);
+ ASSERT (HostAdapterStatus != NULL);
+ ASSERT (TargetStatus != NULL);
+ ASSERT (ScsiIo != NULL);
ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
- ZeroMem (Cdb, 6);
+ ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX);
CommandPacket.Timeout = Timeout;
CommandPacket.InDataBuffer = NULL;
@@ -100,12 +166,8 @@ Returns:
//
// Fill Cdb for Test Unit Ready Command
//
- Target = &TargetArray[0];
- ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);
-
Cdb[0] = EFI_SCSI_OP_TEST_UNIT_READY;
- Cdb[1] = (UINT8) (Lun & 0xe0);
- CommandPacket.CdbLength = (UINT8) 6;
+ CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX;
CommandPacket.SenseDataLength = *SenseDataLength;
Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
@@ -117,65 +179,123 @@ Returns:
return Status;
}
+
+/**
+ Execute Inquiry SCSI command on a specific SCSI target.
+
+ Executes the Inquiry command on the SCSI target specified by ScsiIo.
+ If Timeout is zero, then this function waits indefinitely for the command to complete.
+ If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.
+ If ScsiIo is NULL, then ASSERT().
+ If SenseDataLength is NULL, then ASSERT().
+ If HostAdapterStatus is NULL, then ASSERT().
+ If TargetStatus is NULL, then ASSERT().
+ If InquiryDataLength is NULL, then ASSERT().
+
+ If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
+ gets returned.
+
+ If InquiryDataLength is non-zero and InquiryDataBuffer is not NULL, InquiryDataBuffer
+ must meet buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
+ EFI_INVALID_PARAMETER gets returned.
+
+ @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance
+ for the specific SCSI target.
+ @param[in] Timeout The timeout in 100 ns units to use for the
+ execution of this SCSI Request Packet. A Timeout
+ value of zero means that this function will wait
+ indefinitely for the SCSI Request Packet to execute.
+ If Timeout is greater than zero, then this function
+ will return EFI_TIMEOUT if the time required to
+ execute the SCSI Request Packet is greater than Timeout.
+ @param[in, out] SenseData A pointer to sense data that was generated
+ by the execution of the SCSI Request Packet.
+ This buffer must be allocated by the caller.
+ If SenseDataLength is 0, then this parameter
+ is optional and may be NULL.
+ @param[in, out] SenseDataLength On input, the length in bytes of the SenseData buffer.
+ On output, the number of bytes written to the SenseData buffer.
+ @param[out] HostAdapterStatus The status of the SCSI Host Controller that
+ produces the SCSI bus containing the SCSI
+ target specified by ScsiIo when the SCSI
+ Request Packet was executed. See the EFI
+ SCSI I/O Protocol in the UEFI Specification
+ for details on the possible return values.
+ @param[out] TargetStatus The status returned by the SCSI target specified
+ by ScsiIo when the SCSI Request Packet was
+ executed on the SCSI Host Controller.
+ See the EFI SCSI I/O Protocol in the UEFI
+ Specification for details on the possible
+ return values.
+ @param[in, out] InquiryDataBuffer A pointer to inquiry data that was generated
+ by the execution of the SCSI Request Packet.
+ This buffer must be allocated by the caller.
+ If InquiryDataLength is 0, then this parameter
+ is optional and may be NULL.
+ @param[in, out] InquiryDataLength On input, a pointer to the length in bytes
+ of the InquiryDataBuffer buffer.
+ On output, a pointer to the number of bytes
+ written to the InquiryDataBuffer buffer.
+ @param[in] EnableVitalProductData If TRUE, then the supported vital product
+ data for the PageCode is returned in InquiryDataBuffer.
+ If FALSE, then the standard inquiry data is
+ returned in InquiryDataBuffer and PageCode is ignored.
+ @param[in] PageCode The page code of the vital product data.
+ It's ignored if EnableVitalProductData is FALSE.
+
+ @retval EFI_SUCCESS The command executed successfully. See HostAdapterStatus,
+ TargetStatus, SenseDataLength, and SenseData in that order
+ for additional status information.
+ @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire
+ InquiryDataBuffer could not be transferred. The actual
+ number of bytes transferred is returned in InquiryDataLength.
+ @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there
+ are too many SCSI Command Packets already queued.
+ The SCSI Request Packet was not sent, so no additional
+ status information is available. The caller may retry again later.
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI
+ Request Packet. See HostAdapterStatus, TargetStatus,
+ SenseDataLength, and SenseData in that order for additional
+ status information.
+ @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not
+ supported by the SCSI initiator(i.e., SCSI Host Controller).
+ The SCSI Request Packet was not sent, so no additional
+ status information is available.
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request
+ Packet to execute. See HostAdapterStatus, TargetStatus,
+ SenseDataLength, and SenseData in that order for
+ additional status information.
+ @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.
+
+**/
EFI_STATUS
-SubmitInquiryCommand (
- IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
- IN UINT64 Timeout,
- IN VOID *SenseData,
- IN OUT UINT8 *SenseDataLength,
- OUT UINT8 *HostAdapterStatus,
- OUT UINT8 *TargetStatus,
- IN OUT VOID *InquiryDataBuffer,
- IN OUT UINT32 *InquiryDataLength,
- IN BOOLEAN EnableVitalProductData
+EFIAPI
+ScsiInquiryCommandEx (
+ IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
+ IN UINT64 Timeout,
+ IN OUT VOID *SenseData, OPTIONAL
+ IN OUT UINT8 *SenseDataLength,
+ OUT UINT8 *HostAdapterStatus,
+ OUT UINT8 *TargetStatus,
+ IN OUT VOID *InquiryDataBuffer, OPTIONAL
+ IN OUT UINT32 *InquiryDataLength,
+ IN BOOLEAN EnableVitalProductData,
+ IN UINT8 PageCode
)
-/*++
-
-Routine Description:
- Function to submit SCSI inquiry command.
-
-Arguments:
- ScsiIo - A pointer to SCSI IO protocol.
- Timeout - The length of timeout period.
- SenseData - A pointer to output sense data.
- SenseDataLength - The length of output sense data.
- HostAdapterStatus - The status of Host Adapter.
- TargetStatus - The status of the target.
- InquiryDataBuffer - A pointer to inquiry data buffer.
- InquiryDataLength - The length of inquiry data buffer.
- EnableVitalProductData - Boolean to enable Vital Product Data.
-
-Returns:
-
- Returns:
- EFI_SUCCESS - The status of the unit is tested successfully.
- EFI_BAD_BUFFER_SIZE - The SCSI Request Packet was executed,
- but the entire DataBuffer could not be transferred.
- The actual number of bytes transferred is returned
- in TransferLength.
- EFI_NOT_READY - The SCSI Request Packet could not be sent because
- there are too many SCSI Command Packets already
- queued.
- EFI_DEVICE_ERROR - A device error occurred while attempting to send
- the SCSI Request Packet.
- EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid.
- EFI_UNSUPPORTED - The command described by the SCSI Request Packet
- is not supported by the SCSI initiator(i.e., SCSI
- Host Controller).
- EFI_TIMEOUT - A timeout occurred while waiting for the SCSI
- Request Packet to execute.
-
---*/
{
EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
- UINT64 Lun;
- UINT8 *Target;
- UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];
EFI_STATUS Status;
- UINT8 Cdb[6];
+ UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];
+
+ ASSERT (SenseDataLength != NULL);
+ ASSERT (HostAdapterStatus != NULL);
+ ASSERT (TargetStatus != NULL);
+ ASSERT (InquiryDataLength != NULL);
+ ASSERT (ScsiIo != NULL);
ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
- ZeroMem (Cdb, 6);
+ ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX);
CommandPacket.Timeout = Timeout;
CommandPacket.InDataBuffer = InquiryDataBuffer;
@@ -184,13 +304,10 @@ Returns:
CommandPacket.SenseDataLength = *SenseDataLength;
CommandPacket.Cdb = Cdb;
- Target = &TargetArray[0];
- ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);
-
Cdb[0] = EFI_SCSI_OP_INQUIRY;
- Cdb[1] = (UINT8) (Lun & 0xe0);
if (EnableVitalProductData) {
Cdb[1] |= 0x01;
+ Cdb[2] = PageCode;
}
if (*InquiryDataLength > 0xff) {
@@ -198,7 +315,7 @@ Returns:
}
Cdb[4] = (UINT8) (*InquiryDataLength);
- CommandPacket.CdbLength = (UINT8) 6;
+ CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX;
CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
@@ -211,69 +328,239 @@ Returns:
return Status;
}
+
+/**
+ Execute Inquiry SCSI command on a specific SCSI target.
+
+ Executes the Inquiry command on the SCSI target specified by ScsiIo.
+ If Timeout is zero, then this function waits indefinitely for the command to complete.
+ If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.
+ If ScsiIo is NULL, then ASSERT().
+ If SenseDataLength is NULL, then ASSERT().
+ If HostAdapterStatus is NULL, then ASSERT().
+ If TargetStatus is NULL, then ASSERT().
+ If InquiryDataLength is NULL, then ASSERT().
+
+ If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
+ gets returned.
+
+ If InquiryDataLength is non-zero and InquiryDataBuffer is not NULL, InquiryDataBuffer
+ must meet buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
+ EFI_INVALID_PARAMETER gets returned.
+
+ @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance
+ for the specific SCSI target.
+ @param[in] Timeout The timeout in 100 ns units to use for the
+ execution of this SCSI Request Packet. A Timeout
+ value of zero means that this function will wait
+ indefinitely for the SCSI Request Packet to execute.
+ If Timeout is greater than zero, then this function
+ will return EFI_TIMEOUT if the time required to
+ execute the SCSI Request Packet is greater than Timeout.
+ @param[in, out] SenseData A pointer to sense data that was generated
+ by the execution of the SCSI Request Packet.
+ This buffer must be allocated by the caller.
+ If SenseDataLength is 0, then this parameter
+ is optional and may be NULL.
+ @param[in, out] SenseDataLength On input, the length in bytes of the SenseData buffer.
+ On output, the number of bytes written to the SenseData buffer.
+ @param[out] HostAdapterStatus The status of the SCSI Host Controller that
+ produces the SCSI bus containing the SCSI
+ target specified by ScsiIo when the SCSI
+ Request Packet was executed. See the EFI
+ SCSI I/O Protocol in the UEFI Specification
+ for details on the possible return values.
+ @param[out] TargetStatus The status returned by the SCSI target specified
+ by ScsiIo when the SCSI Request Packet was
+ executed on the SCSI Host Controller.
+ See the EFI SCSI I/O Protocol in the UEFI
+ Specification for details on the possible
+ return values.
+ @param[in, out] InquiryDataBuffer A pointer to inquiry data that was generated
+ by the execution of the SCSI Request Packet.
+ This buffer must be allocated by the caller.
+ If InquiryDataLength is 0, then this parameter
+ is optional and may be NULL.
+ @param[in, out] InquiryDataLength On input, a pointer to the length in bytes
+ of the InquiryDataBuffer buffer.
+ On output, a pointer to the number of bytes
+ written to the InquiryDataBuffer buffer.
+ @param[in] EnableVitalProductData If TRUE, then the supported vital product
+ data is returned in InquiryDataBuffer.
+ If FALSE, then the standard inquiry data is
+ returned in InquiryDataBuffer.
+
+ @retval EFI_SUCCESS The command was executed successfully. See HostAdapterStatus,
+ TargetStatus, SenseDataLength, and SenseData in that order
+ for additional status information.
+ @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire
+ InquiryDataBuffer could not be transferred. The actual
+ number of bytes transferred is returned in InquiryDataLength.
+ @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there
+ are too many SCSI Command Packets already queued.
+ The SCSI Request Packet was not sent, so no additional
+ status information is available. The caller may retry again later.
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI
+ Request Packet. See HostAdapterStatus, TargetStatus,
+ SenseDataLength, and SenseData in that order for additional
+ status information.
+ @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not
+ supported by the SCSI initiator(i.e., SCSI Host Controller).
+ The SCSI Request Packet was not sent, so no additional
+ status information is available.
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request
+ Packet to execute. See HostAdapterStatus, TargetStatus,
+ SenseDataLength, and SenseData in that order for
+ additional status information.
+ @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.
+
+**/
EFI_STATUS
-SubmitModeSense10Command (
- IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
- IN UINT64 Timeout,
- IN VOID *SenseData,
- IN OUT UINT8 *SenseDataLength,
- OUT UINT8 *HostAdapterStatus,
- OUT UINT8 *TargetStatus,
- IN VOID *DataBuffer,
- IN OUT UINT32 *DataLength,
- IN UINT8 DBDField, OPTIONAL
- IN UINT8 PageControl,
- IN UINT8 PageCode
+EFIAPI
+ScsiInquiryCommand (
+ IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
+ IN UINT64 Timeout,
+ IN OUT VOID *SenseData, OPTIONAL
+ IN OUT UINT8 *SenseDataLength,
+ OUT UINT8 *HostAdapterStatus,
+ OUT UINT8 *TargetStatus,
+ IN OUT VOID *InquiryDataBuffer, OPTIONAL
+ IN OUT UINT32 *InquiryDataLength,
+ IN BOOLEAN EnableVitalProductData
+ )
+{
+ return ScsiInquiryCommandEx (
+ ScsiIo,
+ Timeout,
+ SenseData,
+ SenseDataLength,
+ HostAdapterStatus,
+ TargetStatus,
+ InquiryDataBuffer,
+ InquiryDataLength,
+ EnableVitalProductData,
+ 0
+ );
+}
+
+/**
+ Execute Mode Sense(10) SCSI command on a specific SCSI target.
+
+ Executes the SCSI Mode Sense(10) command on the SCSI target specified by ScsiIo.
+ If Timeout is zero, then this function waits indefinitely for the command to complete.
+ If Timeout is greater than zero, then the command is executed and will timeout
+ after Timeout 100 ns units. The DBDField, PageControl, and PageCode parameters
+ are used to construct the CDB for this SCSI command.
+ If ScsiIo is NULL, then ASSERT().
+ If SenseDataLength is NULL, then ASSERT().
+ If HostAdapterStatus is NULL, then ASSERT().
+ If TargetStatus is NULL, then ASSERT().
+ If DataLength is NULL, then ASSERT().
+
+ If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
+ gets returned.
+
+ If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
+ gets returned.
+
+ @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance
+ for the specific SCSI target.
+ @param[in] Timeout The timeout in 100 ns units to use for the
+ execution of this SCSI Request Packet. A Timeout
+ value of zero means that this function will wait
+ indefinitely for the SCSI Request Packet to execute.
+ If Timeout is greater than zero, then this function
+ will return EFI_TIMEOUT if the time required to
+ execute the SCSI Request Packet is greater than Timeout.
+ @param[in, out] SenseData A pointer to sense data that was generated
+ by the execution of the SCSI Request Packet.
+ This buffer must be allocated by the caller.
+ If SenseDataLength is 0, then this parameter
+ is optional and may be NULL.
+ @param[in, out] SenseDataLength On input, the length in bytes of the SenseData buffer.
+ On output, the number of bytes written to the SenseData buffer.
+ @param[out] HostAdapterStatus The status of the SCSI Host Controller that
+ produces the SCSI bus containing the SCSI target
+ specified by ScsiIo when the SCSI Request Packet
+ was executed. See the EFI SCSI I/O Protocol in the
+ UEFI Specification for details on the possible
+ return values.
+ @param[out] TargetStatus The status returned by the SCSI target specified
+ by ScsiIo when the SCSI Request Packet was executed
+ on the SCSI Host Controller. See the EFI SCSI
+ I/O Protocol in the UEFI Specification for details
+ on the possible return values.
+ @param[in, out] DataBuffer A pointer to data that was generated by the
+ execution of the SCSI Request Packet. This
+ buffer must be allocated by the caller. If
+ DataLength is 0, then this parameter is optional
+ and may be NULL.
+ @param[in, out] DataLength On input, a pointer to the length in bytes of
+ the DataBuffer buffer. On output, a pointer
+ to the number of bytes written to the DataBuffer
+ buffer.
+ @param[in] DBDField Specifies the DBD field of the CDB for this SCSI Command.
+ @param[in] PageControl Specifies the PC field of the CDB for this SCSI Command.
+ @param[in] PageCode Specifies the Page Control field of the CDB for this SCSI Command.
+
+ @retval EFI_SUCCESS The command was executed successfully.
+ See HostAdapterStatus, TargetStatus, SenseDataLength,
+ and SenseData in that order for additional status information.
+ @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the
+ entire DataBuffer could not be transferred.
+ The actual number of bytes transferred is returned
+ in DataLength.
+ @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
+ there are too many SCSI Command Packets already queued.
+ The SCSI Request Packet was not sent, so no additional
+ status information is available. The caller may retry
+ again later.
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
+ SCSI Request Packet. See HostAdapterStatus, TargetStatus,
+ SenseDataLength, and SenseData in that order for
+ additional status information.
+ @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
+ is not supported by the SCSI initiator(i.e., SCSI
+ Host Controller). The SCSI Request Packet was not
+ sent, so no additional status information is available.
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
+ Request Packet to execute. See HostAdapterStatus,
+ TargetStatus, SenseDataLength, and SenseData in that
+ order for additional status information.
+ @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+ScsiModeSense10Command (
+ IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
+ IN UINT64 Timeout,
+ IN OUT VOID *SenseData, OPTIONAL
+ IN OUT UINT8 *SenseDataLength,
+ OUT UINT8 *HostAdapterStatus,
+ OUT UINT8 *TargetStatus,
+ IN OUT VOID *DataBuffer, OPTIONAL
+ IN OUT UINT32 *DataLength,
+ IN UINT8 DBDField, OPTIONAL
+ IN UINT8 PageControl,
+ IN UINT8 PageCode
)
-/*++
-
-Routine Description:
- Function to submit SCSI mode sense 10 command.
-
-Arguments:
- ScsiIo - A pointer to SCSI IO protocol.
- Timeout - The length of timeout period.
- SenseData - A pointer to output sense data.
- SenseDataLength - The length of output sense data.
- HostAdapterStatus - The status of Host Adapter.
- TargetStatus - The status of the target.
- DataBuffer - A pointer to input data buffer.
- DataLength - The length of input data buffer.
- DBDField - The DBD Field (Optional).
- PageControl - Page Control.
- PageCode - Page code.
-
-Returns:
-
- Returns:
- EFI_SUCCESS - The status of the unit is tested successfully.
- EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed,
- but the entire DataBuffer could not be transferred.
- The actual number of bytes transferred is returned
- in TransferLength.
- EFI_NOT_READY - The SCSI Request Packet could not be sent because
- there are too many SCSI Command Packets already
- queued.
- EFI_DEVICE_ERROR - A device error occurred while attempting to send
- the SCSI Request Packet.
- EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid.
- EFI_UNSUPPORTED - The command described by the SCSI Request Packet
- is not supported by the SCSI initiator(i.e., SCSI
- Host Controller).
- EFI_TIMEOUT - A timeout occurred while waiting for the SCSI
- Request Packet to execute.
-
---*/
{
EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
- UINT64 Lun;
- UINT8 *Target;
- UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];
EFI_STATUS Status;
- UINT8 Cdb[10];
+ UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];
+
+ ASSERT (SenseDataLength != NULL);
+ ASSERT (HostAdapterStatus != NULL);
+ ASSERT (TargetStatus != NULL);
+ ASSERT (DataLength != NULL);
+ ASSERT (ScsiIo != NULL);
ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
- ZeroMem (Cdb, 10);
+ ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);
CommandPacket.Timeout = Timeout;
CommandPacket.InDataBuffer = DataBuffer;
@@ -283,16 +570,19 @@ Returns:
//
// Fill Cdb for Mode Sense (10) Command
//
- Target = &TargetArray[0];
- ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);
-
Cdb[0] = EFI_SCSI_OP_MODE_SEN10;
- Cdb[1] = (UINT8) (Lun & 0xe0 + (DBDField << 3) & 0x08);
- Cdb[2] = (UINT8) ((PageControl & 0xc0) | (PageCode & 0x3f));
+ //
+ // DBDField is in Cdb[1] bit3 of (bit7..0)
+ //
+ Cdb[1] = (UINT8) ((DBDField << 3) & 0x08);
+ //
+ // PageControl is in Cdb[2] bit7..6, PageCode is in Cdb[2] bit5..0
+ //
+ Cdb[2] = (UINT8) (((PageControl << 6) & 0xc0) | (PageCode & 0x3f));
Cdb[7] = (UINT8) (*DataLength >> 8);
Cdb[8] = (UINT8) (*DataLength);
- CommandPacket.CdbLength = 10;
+ CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;
CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
CommandPacket.SenseDataLength = *SenseDataLength;
@@ -306,59 +596,61 @@ Returns:
return Status;
}
+
+/**
+ Execute Request Sense SCSI command on a specific SCSI target.
+
+ Executes the Request Sense command on the SCSI target specified by ScsiIo.
+ If Timeout is zero, then this function waits indefinitely for the command to complete.
+ If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.
+ If ScsiIo is NULL, then ASSERT().
+ If SenseDataLength is NULL, then ASSERT().
+ If HostAdapterStatus is NULL, then ASSERT().
+ If TargetStatus is NULL, then ASSERT().
+
+ If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
+ gets returned.
+
+ @param[in] ScsiIo A pointer to SCSI IO protocol.
+ @param[in] Timeout The length of timeout period.
+ @param[in, out] SenseData A pointer to output sense data.
+ @param[in, out] SenseDataLength The length of output sense data.
+ @param[out] HostAdapterStatus The status of Host Adapter.
+ @param[out] TargetStatus The status of the target.
+
+ @retval EFI_SUCCESS Command is executed successfully.
+ @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are
+ too many SCSI Command Packets already queued.
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
+ @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by
+ the SCSI initiator(i.e., SCSI Host Controller)
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
+ @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.
+
+**/
EFI_STATUS
-SubmitRequestSenseCommand (
- IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
- IN UINT64 Timeout,
- IN VOID *SenseData,
- IN OUT UINT8 *SenseDataLength,
- OUT UINT8 *HostAdapterStatus,
- OUT UINT8 *TargetStatus
+EFIAPI
+ScsiRequestSenseCommand (
+ IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
+ IN UINT64 Timeout,
+ IN OUT VOID *SenseData, OPTIONAL
+ IN OUT UINT8 *SenseDataLength,
+ OUT UINT8 *HostAdapterStatus,
+ OUT UINT8 *TargetStatus
)
-/*++
-
-Routine Description:
- Function to submit SCSI request sense command.
-
-Arguments:
- ScsiIo - A pointer to SCSI IO protocol.
- Timeout - The length of timeout period.
- SenseData - A pointer to output sense data.
- SenseDataLength - The length of output sense data.
- HostAdapterStatus - The status of Host Adapter.
- TargetStatus - The status of the target.
-
-Returns:
-
- Returns:
- EFI_SUCCESS - The status of the unit is tested successfully.
- EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed,
- but the entire DataBuffer could not be transferred.
- The actual number of bytes transferred is returned
- in TransferLength.
- EFI_NOT_READY - The SCSI Request Packet could not be sent because
- there are too many SCSI Command Packets already
- queued.
- EFI_DEVICE_ERROR - A device error occurred while attempting to send
- the SCSI Request Packet.
- EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid.
- EFI_UNSUPPORTED - The command described by the SCSI Request Packet
- is not supported by the SCSI initiator(i.e., SCSI
- Host Controller).
- EFI_TIMEOUT - A timeout occurred while waiting for the SCSI
- Request Packet to execute.
-
---*/
{
EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
- UINT64 Lun;
- UINT8 *Target;
- UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];
EFI_STATUS Status;
- UINT8 Cdb[6];
+ UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];
+
+ ASSERT (SenseDataLength != NULL);
+ ASSERT (HostAdapterStatus != NULL);
+ ASSERT (TargetStatus != NULL);
+ ASSERT (ScsiIo != NULL);
ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
- ZeroMem (Cdb, 6);
+ ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX);
CommandPacket.Timeout = Timeout;
CommandPacket.InDataBuffer = SenseData;
@@ -368,14 +660,10 @@ Returns:
//
// Fill Cdb for Request Sense Command
//
- Target = &TargetArray[0];
- ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);
-
Cdb[0] = EFI_SCSI_OP_REQUEST_SENSE;
- Cdb[1] = (UINT8) (Lun & 0xe0);
Cdb[4] = (UINT8) (*SenseDataLength);
- CommandPacket.CdbLength = (UINT8) 6;
+ CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX;
CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
CommandPacket.SenseDataLength = 0;
@@ -388,65 +676,77 @@ Returns:
return Status;
}
+
+/**
+ Execute Read Capacity SCSI command on a specific SCSI target.
+
+ Executes the SCSI Read Capacity command on the SCSI target specified by ScsiIo.
+ If Timeout is zero, then this function waits indefinitely for the command to complete.
+ If Timeout is greater than zero, then the command is executed and will timeout after
+ Timeout 100 ns units. The Pmi parameter is used to construct the CDB for this SCSI command.
+ If ScsiIo is NULL, then ASSERT().
+ If SenseDataLength is NULL, then ASSERT().
+ If HostAdapterStatus is NULL, then ASSERT().
+ If TargetStatus is NULL, then ASSERT().
+ If DataLength is NULL, then ASSERT().
+
+ If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
+ gets returned.
+
+ If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
+ gets returned.
+
+ @param[in] ScsiIo A pointer to SCSI IO protocol.
+ @param[in] Timeout The length of timeout period.
+ @param[in, out] SenseData A pointer to output sense data.
+ @param[in, out] SenseDataLength The length of output sense data.
+ @param[out] HostAdapterStatus The status of Host Adapter.
+ @param[out] TargetStatus The status of the target.
+ @param[in, out] DataBuffer A pointer to a data buffer.
+ @param[in, out] DataLength The length of data buffer.
+ @param[in] Pmi Partial medium indicator.
+
+ @retval EFI_SUCCESS Command is executed successfully.
+ @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire
+ DataBuffer could not be transferred. The actual
+ number of bytes transferred is returned in DataLength.
+ @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
+ there are too many SCSI Command Packets already queued.
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
+ @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
+ is not supported by the SCSI initiator(i.e., SCSI Host Controller)
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
+ @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.
+
+**/
EFI_STATUS
-SubmitReadCapacityCommand (
- IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
- IN UINT64 Timeout,
- IN VOID *SenseData,
- IN OUT UINT8 *SenseDataLength,
- OUT UINT8 *HostAdapterStatus,
- OUT UINT8 *TargetStatus,
- OUT VOID *DataBuffer,
- IN OUT UINT32 *DataLength,
- IN BOOLEAN PMI
+EFIAPI
+ScsiReadCapacityCommand (
+ IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
+ IN UINT64 Timeout,
+ IN OUT VOID *SenseData, OPTIONAL
+ IN OUT UINT8 *SenseDataLength,
+ OUT UINT8 *HostAdapterStatus,
+ OUT UINT8 *TargetStatus,
+ IN OUT VOID *DataBuffer, OPTIONAL
+ IN OUT UINT32 *DataLength,
+ IN BOOLEAN Pmi
)
-/*++
-
-Routine Description:
- Function to submit read capacity command.
-
-Arguments:
- ScsiIo - A pointer to SCSI IO protocol.
- Timeout - The length of timeout period.
- SenseData - A pointer to output sense data.
- SenseDataLength - The length of output sense data.
- HostAdapterStatus - The status of Host Adapter.
- TargetStatus - The status of the target.
- DataBuffer - A pointer to a data buffer.
- DataLength - The length of data buffer.
- PMI - Partial medium indicator.
-
-Returns:
-
- Returns:
- EFI_SUCCESS - The status of the unit is tested successfully.
- EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed,
- but the entire DataBuffer could not be transferred.
- The actual number of bytes transferred is returned
- in TransferLength.
- EFI_NOT_READY - The SCSI Request Packet could not be sent because
- there are too many SCSI Command Packets already
- queued.
- EFI_DEVICE_ERROR - A device error occurred while attempting to send
- the SCSI Request Packet.
- EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid.
- EFI_UNSUPPORTED - The command described by the SCSI Request Packet
- is not supported by the SCSI initiator(i.e., SCSI
- Host Controller).
- EFI_TIMEOUT - A timeout occurred while waiting for the SCSI
- Request Packet to execute.
-
---*/
{
EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
- UINT64 Lun;
- UINT8 *Target;
- UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];
EFI_STATUS Status;
- UINT8 Cdb[10];
+ UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];
+
+ ASSERT (SenseDataLength != NULL);
+ ASSERT (HostAdapterStatus != NULL);
+ ASSERT (TargetStatus != NULL);
+ ASSERT (DataLength != NULL);
+ ASSERT (ScsiIo != NULL);
ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
- ZeroMem (Cdb, 10);
+ ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);
CommandPacket.Timeout = Timeout;
CommandPacket.InDataBuffer = DataBuffer;
@@ -456,21 +756,17 @@ Returns:
//
// Fill Cdb for Read Capacity Command
//
- Target = &TargetArray[0];
- ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);
-
Cdb[0] = EFI_SCSI_OP_READ_CAPACITY;
- Cdb[1] = (UINT8) (Lun & 0xe0);
- if (!PMI) {
+ if (!Pmi) {
//
- // Partial medium indicator,if PMI is FALSE, the Cdb.2 ~ Cdb.5 MUST BE ZERO.
+ // Partial medium indicator,if Pmi is FALSE, the Cdb.2 ~ Cdb.5 MUST BE ZERO.
//
ZeroMem ((Cdb + 2), 4);
} else {
Cdb[8] |= 0x01;
}
- CommandPacket.CdbLength = 10;
+ CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;
CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
CommandPacket.SenseDataLength = *SenseDataLength;
@@ -484,67 +780,77 @@ Returns:
return Status;
}
+
+/**
+ Execute Read Capacity SCSI 16 command on a specific SCSI target.
+
+ Executes the SCSI Read Capacity 16 command on the SCSI target specified by ScsiIo.
+ If Timeout is zero, then this function waits indefinitely for the command to complete.
+ If Timeout is greater than zero, then the command is executed and will timeout after
+ Timeout 100 ns units. The Pmi parameter is used to construct the CDB for this SCSI command.
+ If ScsiIo is NULL, then ASSERT().
+ If SenseDataLength is NULL, then ASSERT().
+ If HostAdapterStatus is NULL, then ASSERT().
+ If TargetStatus is NULL, then ASSERT().
+ If DataLength is NULL, then ASSERT().
+
+ If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
+ gets returned.
+
+ If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
+ gets returned.
+
+ @param[in] ScsiIo A pointer to SCSI IO protocol.
+ @param[in] Timeout The length of timeout period.
+ @param[in, out] SenseData A pointer to output sense data.
+ @param[in, out] SenseDataLength The length of output sense data.
+ @param[out] HostAdapterStatus The status of Host Adapter.
+ @param[out] TargetStatus The status of the target.
+ @param[in, out] DataBuffer A pointer to a data buffer.
+ @param[in, out] DataLength The length of data buffer.
+ @param[in] Pmi Partial medium indicator.
+
+ @retval EFI_SUCCESS Command is executed successfully.
+ @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire
+ DataBuffer could not be transferred. The actual
+ number of bytes transferred is returned in DataLength.
+ @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
+ there are too many SCSI Command Packets already queued.
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
+ @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
+ is not supported by the SCSI initiator(i.e., SCSI Host Controller)
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
+ @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.
+
+**/
EFI_STATUS
-SubmitRead10Command (
- IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
- IN UINT64 Timeout,
- IN VOID *SenseData,
- IN OUT UINT8 *SenseDataLength,
- OUT UINT8 *HostAdapterStatus,
- OUT UINT8 *TargetStatus,
- OUT VOID *DataBuffer,
- IN OUT UINT32 *DataLength,
- IN UINT32 StartLba,
- IN UINT32 SectorSize
+EFIAPI
+ScsiReadCapacity16Command (
+ IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
+ IN UINT64 Timeout,
+ IN OUT VOID *SenseData, OPTIONAL
+ IN OUT UINT8 *SenseDataLength,
+ OUT UINT8 *HostAdapterStatus,
+ OUT UINT8 *TargetStatus,
+ IN OUT VOID *DataBuffer, OPTIONAL
+ IN OUT UINT32 *DataLength,
+ IN BOOLEAN Pmi
)
-/*++
-
-Routine Description:
- Function to submit read 10 command.
-
-Arguments:
- ScsiIo - A pointer to SCSI IO protocol.
- Timeout - The length of timeout period.
- SenseData - A pointer to output sense data.
- SenseDataLength - The length of output sense data.
- HostAdapterStatus - The status of Host Adapter.
- TargetStatus - The status of the target.
- DataBuffer - A pointer to a data buffer.
- DataLength - The length of data buffer.
- StartLba - The start address of LBA.
- SectorSize - The sector size.
-
-Returns:
-
- Returns:
- EFI_SUCCESS - The status of the unit is tested successfully.
- EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed,
- but the entire DataBuffer could not be transferred.
- The actual number of bytes transferred is returned
- in TransferLength.
- EFI_NOT_READY - The SCSI Request Packet could not be sent because
- there are too many SCSI Command Packets already
- queued.
- EFI_DEVICE_ERROR - A device error occurred while attempting to send
- the SCSI Request Packet.
- EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid.
- EFI_UNSUPPORTED - The command described by the SCSI Request Packet
- is not supported by the SCSI initiator(i.e., SCSI
- Host Controller).
- EFI_TIMEOUT - A timeout occurred while waiting for the SCSI
- Request Packet to execute.
-
---*/
{
EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
- UINT64 Lun;
- UINT8 *Target;
- UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];
EFI_STATUS Status;
- UINT8 Cdb[10];
+ UINT8 Cdb[16];
+
+ ASSERT (SenseDataLength != NULL);
+ ASSERT (HostAdapterStatus != NULL);
+ ASSERT (TargetStatus != NULL);
+ ASSERT (DataLength != NULL);
+ ASSERT (ScsiIo != NULL);
ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
- ZeroMem (Cdb, 10);
+ ZeroMem (Cdb, 16);
CommandPacket.Timeout = Timeout;
CommandPacket.InDataBuffer = DataBuffer;
@@ -552,21 +858,121 @@ Returns:
CommandPacket.InTransferLength= *DataLength;
CommandPacket.Cdb = Cdb;
//
- // Fill Cdb for Read (10) Command
+ // Fill Cdb for Read Capacity Command
//
- Target = &TargetArray[0];
- ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);
+ Cdb[0] = EFI_SCSI_OP_READ_CAPACITY16;
+ Cdb[1] = 0x10;
+ if (!Pmi) {
+ //
+ // Partial medium indicator,if Pmi is FALSE, the Cdb.2 ~ Cdb.9 MUST BE ZERO.
+ //
+ ZeroMem ((Cdb + 2), 8);
+ } else {
+ Cdb[14] |= 0x01;
+ }
+ Cdb[13] = 0x20;
+ CommandPacket.CdbLength = 16;
+ CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
+ CommandPacket.SenseDataLength = *SenseDataLength;
+
+ Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
+
+ *HostAdapterStatus = CommandPacket.HostAdapterStatus;
+ *TargetStatus = CommandPacket.TargetStatus;
+ *SenseDataLength = CommandPacket.SenseDataLength;
+ *DataLength = CommandPacket.InTransferLength;
+
+ return Status;
+}
+
+
+/**
+ Execute Read(10) SCSI command on a specific SCSI target.
+
+ Executes the SCSI Read(10) command on the SCSI target specified by ScsiIo.
+ If Timeout is zero, then this function waits indefinitely for the command to complete.
+ If Timeout is greater than zero, then the command is executed and will timeout
+ after Timeout 100 ns units. The StartLba and SectorSize parameters are used to
+ construct the CDB for this SCSI command.
+ If ScsiIo is NULL, then ASSERT().
+ If SenseDataLength is NULL, then ASSERT().
+ If HostAdapterStatus is NULL, then ASSERT().
+ If TargetStatus is NULL, then ASSERT().
+ If DataLength is NULL, then ASSERT().
+
+ If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
+ gets returned.
+
+ If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
+ gets returned.
+
+ @param[in] ScsiIo A pointer to SCSI IO protocol.
+ @param[in] Timeout The length of timeout period.
+ @param[in, out] SenseData A pointer to output sense data.
+ @param[in, out] SenseDataLength The length of output sense data.
+ @param[out] HostAdapterStatus The status of Host Adapter.
+ @param[out] TargetStatus The status of the target.
+ @param[in, out] DataBuffer Read 10 command data.
+ @param[in, out] DataLength The length of data buffer.
+ @param[in] StartLba The start address of LBA.
+ @param[in] SectorSize The number of contiguous logical blocks of data that shall be transferred.
+
+ @retval EFI_SUCCESS Command is executed successfully.
+ @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could
+ not be transferred. The actual number of bytes transferred is returned in DataLength.
+ @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many
+ SCSI Command Packets already queued.
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
+ @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by
+ the SCSI initiator(i.e., SCSI Host Controller)
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
+ @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+ScsiRead10Command (
+ IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
+ IN UINT64 Timeout,
+ IN OUT VOID *SenseData, OPTIONAL
+ IN OUT UINT8 *SenseDataLength,
+ OUT UINT8 *HostAdapterStatus,
+ OUT UINT8 *TargetStatus,
+ IN OUT VOID *DataBuffer, OPTIONAL
+ IN OUT UINT32 *DataLength,
+ IN UINT32 StartLba,
+ IN UINT32 SectorSize
+ )
+{
+ EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
+ EFI_STATUS Status;
+ UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];
+
+ ASSERT (SenseDataLength != NULL);
+ ASSERT (HostAdapterStatus != NULL);
+ ASSERT (TargetStatus != NULL);
+ ASSERT (DataLength != NULL);
+ ASSERT (ScsiIo != NULL);
+
+ ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
+ ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);
+
+ CommandPacket.Timeout = Timeout;
+ CommandPacket.InDataBuffer = DataBuffer;
+ CommandPacket.SenseData = SenseData;
+ CommandPacket.InTransferLength= *DataLength;
+ CommandPacket.Cdb = Cdb;
+ //
+ // Fill Cdb for Read (10) Command
+ //
Cdb[0] = EFI_SCSI_OP_READ10;
- Cdb[1] = (UINT8) (Lun & 0xe0);
- Cdb[2] = (UINT8) (StartLba >> 24);
- Cdb[3] = (UINT8) (StartLba >> 16);
- Cdb[4] = (UINT8) (StartLba >> 8);
- Cdb[5] = (UINT8) (StartLba & 0xff);
- Cdb[7] = (UINT8) (SectorSize >> 8);
- Cdb[8] = (UINT8) (SectorSize & 0xff);
-
- CommandPacket.CdbLength = 10;
+ WriteUnaligned32 ((UINT32 *)&Cdb[2], SwapBytes32 (StartLba));
+ WriteUnaligned16 ((UINT16 *)&Cdb[7], SwapBytes16 ((UINT16) SectorSize));
+
+ CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;
CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
CommandPacket.SenseDataLength = *SenseDataLength;
@@ -580,67 +986,79 @@ Returns:
return Status;
}
+
+/**
+ Execute Write(10) SCSI command on a specific SCSI target.
+
+ Executes the SCSI Write(10) command on the SCSI target specified by ScsiIo.
+ If Timeout is zero, then this function waits indefinitely for the command to complete.
+ If Timeout is greater than zero, then the command is executed and will timeout after
+ Timeout 100 ns units. The StartLba and SectorSize parameters are used to construct
+ the CDB for this SCSI command.
+ If ScsiIo is NULL, then ASSERT().
+ If SenseDataLength is NULL, then ASSERT().
+ If HostAdapterStatus is NULL, then ASSERT().
+ If TargetStatus is NULL, then ASSERT().
+ If DataLength is NULL, then ASSERT().
+
+ If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
+ gets returned.
+
+ If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
+ gets returned.
+
+ @param[in] ScsiIo SCSI IO Protocol to use
+ @param[in] Timeout The length of timeout period.
+ @param[in, out] SenseData A pointer to output sense data.
+ @param[in, out] SenseDataLength The length of output sense data.
+ @param[out] HostAdapterStatus The status of Host Adapter.
+ @param[out] TargetStatus The status of the target.
+ @param[in, out] DataBuffer A pointer to a data buffer.
+ @param[in, out] DataLength The length of data buffer.
+ @param[in] StartLba The start address of LBA.
+ @param[in] SectorSize The number of contiguous logical blocks of data that shall be transferred.
+
+ @retval EFI_SUCCESS Command is executed successfully.
+ @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could
+ not be transferred. The actual number of bytes transferred is returned in DataLength.
+ @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many
+ SCSI Command Packets already queued.
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
+ @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by
+ the SCSI initiator(i.e., SCSI Host Controller)
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
+ @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.
+
+**/
EFI_STATUS
-SubmitWrite10Command (
- IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
- IN UINT64 Timeout,
- IN VOID *SenseData,
- IN OUT UINT8 *SenseDataLength,
- OUT UINT8 *HostAdapterStatus,
- OUT UINT8 *TargetStatus,
- OUT VOID *DataBuffer,
- IN OUT UINT32 *DataLength,
- IN UINT32 StartLba,
- IN UINT32 SectorSize
+EFIAPI
+ScsiWrite10Command (
+ IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
+ IN UINT64 Timeout,
+ IN OUT VOID *SenseData, OPTIONAL
+ IN OUT UINT8 *SenseDataLength,
+ OUT UINT8 *HostAdapterStatus,
+ OUT UINT8 *TargetStatus,
+ IN OUT VOID *DataBuffer, OPTIONAL
+ IN OUT UINT32 *DataLength,
+ IN UINT32 StartLba,
+ IN UINT32 SectorSize
)
-/*++
-
-Routine Description:
- Function to submit SCSI write 10 command.
-
-Arguments:
- ScsiIo - A pointer to SCSI IO protocol.
- Timeout - The length of timeout period.
- SenseData - A pointer to output sense data.
- SenseDataLength - The length of output sense data.
- HostAdapterStatus - The status of Host Adapter.
- TargetStatus - The status of the target.
- DataBuffer - A pointer to a data buffer.
- DataLength - The length of data buffer.
- StartLba - The start address of LBA.
- SectorSize - The sector size.
-
-Returns:
-
- Returns:
- EFI_SUCCESS - The status of the unit is tested successfully.
- EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed,
- but the entire DataBuffer could not be transferred.
- The actual number of bytes transferred is returned
- in InTransferLength.
- EFI_NOT_READY - The SCSI Request Packet could not be sent because
- there are too many SCSI Command Packets already
- queued.
- EFI_DEVICE_ERROR - A device error occurred while attempting to send
- the SCSI Request Packet.
- EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid.
- EFI_UNSUPPORTED - The command described by the SCSI Request Packet
- is not supported by the SCSI initiator(i.e., SCSI
- Host Controller).
- EFI_TIMEOUT - A timeout occurred while waiting for the SCSI
- Request Packet to execute.
-
---*/
{
EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
- UINT64 Lun;
- UINT8 *Target;
- UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];
EFI_STATUS Status;
- UINT8 Cdb[10];
+ UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];
+
+ ASSERT (SenseDataLength != NULL);
+ ASSERT (HostAdapterStatus != NULL);
+ ASSERT (TargetStatus != NULL);
+ ASSERT (DataLength != NULL);
+ ASSERT (ScsiIo != NULL);
ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
- ZeroMem (Cdb, 10);
+ ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);
CommandPacket.Timeout = Timeout;
CommandPacket.OutDataBuffer = DataBuffer;
@@ -650,24 +1068,115 @@ Returns:
//
// Fill Cdb for Write (10) Command
//
- Target = &TargetArray[0];
- ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);
-
Cdb[0] = EFI_SCSI_OP_WRITE10;
- Cdb[1] = (UINT8) (Lun & 0xe0);
- Cdb[2] = (UINT8) (StartLba >> 24);
- Cdb[3] = (UINT8) (StartLba >> 16);
- Cdb[4] = (UINT8) (StartLba >> 8);
- Cdb[5] = (UINT8) StartLba;
- Cdb[7] = (UINT8) (SectorSize >> 8);
- Cdb[8] = (UINT8) SectorSize;
-
- CommandPacket.CdbLength = 10;
+ WriteUnaligned32 ((UINT32 *)&Cdb[2], SwapBytes32 (StartLba));
+ WriteUnaligned16 ((UINT16 *)&Cdb[7], SwapBytes16 ((UINT16) SectorSize));
+
+ CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;
CommandPacket.DataDirection = EFI_SCSI_DATA_OUT;
CommandPacket.SenseDataLength = *SenseDataLength;
Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
+ *HostAdapterStatus = CommandPacket.HostAdapterStatus;
+ *TargetStatus = CommandPacket.TargetStatus;
+ *SenseDataLength = CommandPacket.SenseDataLength;
+ *DataLength = CommandPacket.OutTransferLength;
+
+ return Status;
+}
+
+/**
+ Execute Read(16) SCSI command on a specific SCSI target.
+
+ Executes the SCSI Read(16) command on the SCSI target specified by ScsiIo.
+ If Timeout is zero, then this function waits indefinitely for the command to complete.
+ If Timeout is greater than zero, then the command is executed and will timeout
+ after Timeout 100 ns units. The StartLba and SectorSize parameters are used to
+ construct the CDB for this SCSI command.
+ If ScsiIo is NULL, then ASSERT().
+ If SenseDataLength is NULL, then ASSERT().
+ If HostAdapterStatus is NULL, then ASSERT().
+ If TargetStatus is NULL, then ASSERT().
+ If DataLength is NULL, then ASSERT().
+
+ If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
+ gets returned.
+
+ If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
+ gets returned.
+
+ @param[in] ScsiIo A pointer to SCSI IO protocol.
+ @param[in] Timeout The length of timeout period.
+ @param[in, out] SenseData A pointer to output sense data.
+ @param[in, out] SenseDataLength The length of output sense data.
+ @param[out] HostAdapterStatus The status of Host Adapter.
+ @param[out] TargetStatus The status of the target.
+ @param[in, out] DataBuffer Read 16 command data.
+ @param[in, out] DataLength The length of data buffer.
+ @param[in] StartLba The start address of LBA.
+ @param[in] SectorSize The number of contiguous logical blocks of data that shall be transferred.
+
+ @retval EFI_SUCCESS Command is executed successfully.
+ @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could
+ not be transferred. The actual number of bytes transferred is returned in DataLength.
+ @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many
+ SCSI Command Packets already queued.
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
+ @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by
+ the SCSI initiator(i.e., SCSI Host Controller)
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
+ @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+ScsiRead16Command (
+ IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
+ IN UINT64 Timeout,
+ IN OUT VOID *SenseData, OPTIONAL
+ IN OUT UINT8 *SenseDataLength,
+ OUT UINT8 *HostAdapterStatus,
+ OUT UINT8 *TargetStatus,
+ IN OUT VOID *DataBuffer, OPTIONAL
+ IN OUT UINT32 *DataLength,
+ IN UINT64 StartLba,
+ IN UINT32 SectorSize
+ )
+{
+ EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
+ EFI_STATUS Status;
+ UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIXTEEN];
+
+ ASSERT (SenseDataLength != NULL);
+ ASSERT (HostAdapterStatus != NULL);
+ ASSERT (TargetStatus != NULL);
+ ASSERT (DataLength != NULL);
+ ASSERT (ScsiIo != NULL);
+
+ ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
+ ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIXTEEN);
+
+ CommandPacket.Timeout = Timeout;
+ CommandPacket.InDataBuffer = DataBuffer;
+ CommandPacket.SenseData = SenseData;
+ CommandPacket.InTransferLength = *DataLength;
+ CommandPacket.Cdb = Cdb;
+ //
+ // Fill Cdb for Read (16) Command
+ //
+ Cdb[0] = EFI_SCSI_OP_READ16;
+ WriteUnaligned64 ((UINT64 *)&Cdb[2], SwapBytes64 (StartLba));
+ WriteUnaligned32 ((UINT32 *)&Cdb[10], SwapBytes32 (SectorSize));
+
+ CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_SIXTEEN;
+ CommandPacket.DataDirection = EFI_SCSI_DATA_IN;
+ CommandPacket.SenseDataLength = *SenseDataLength;
+
+ Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
+
*HostAdapterStatus = CommandPacket.HostAdapterStatus;
*TargetStatus = CommandPacket.TargetStatus;
*SenseDataLength = CommandPacket.SenseDataLength;
@@ -675,3 +1184,884 @@ Returns:
return Status;
}
+
+
+/**
+ Execute Write(16) SCSI command on a specific SCSI target.
+
+ Executes the SCSI Write(16) command on the SCSI target specified by ScsiIo.
+ If Timeout is zero, then this function waits indefinitely for the command to complete.
+ If Timeout is greater than zero, then the command is executed and will timeout after
+ Timeout 100 ns units. The StartLba and SectorSize parameters are used to construct
+ the CDB for this SCSI command.
+ If ScsiIo is NULL, then ASSERT().
+ If SenseDataLength is NULL, then ASSERT().
+ If HostAdapterStatus is NULL, then ASSERT().
+ If TargetStatus is NULL, then ASSERT().
+ If DataLength is NULL, then ASSERT().
+
+ If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
+ gets returned.
+
+ If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER
+ gets returned.
+
+ @param[in] ScsiIo SCSI IO Protocol to use
+ @param[in] Timeout The length of timeout period.
+ @param[in, out] SenseData A pointer to output sense data.
+ @param[in, out] SenseDataLength The length of output sense data.
+ @param[out] HostAdapterStatus The status of Host Adapter.
+ @param[out] TargetStatus The status of the target.
+ @param[in, out] DataBuffer A pointer to a data buffer.
+ @param[in, out] DataLength The length of data buffer.
+ @param[in] StartLba The start address of LBA.
+ @param[in] SectorSize The number of contiguous logical blocks of data that shall be transferred.
+
+ @retval EFI_SUCCESS Command is executed successfully.
+ @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could
+ not be transferred. The actual number of bytes transferred is returned in DataLength.
+ @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many
+ SCSI Command Packets already queued.
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
+ @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by
+ the SCSI initiator(i.e., SCSI Host Controller)
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
+ @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+ScsiWrite16Command (
+ IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
+ IN UINT64 Timeout,
+ IN OUT VOID *SenseData, OPTIONAL
+ IN OUT UINT8 *SenseDataLength,
+ OUT UINT8 *HostAdapterStatus,
+ OUT UINT8 *TargetStatus,
+ IN OUT VOID *DataBuffer, OPTIONAL
+ IN OUT UINT32 *DataLength,
+ IN UINT64 StartLba,
+ IN UINT32 SectorSize
+ )
+{
+ EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
+ EFI_STATUS Status;
+ UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIXTEEN];
+
+ ASSERT (SenseDataLength != NULL);
+ ASSERT (HostAdapterStatus != NULL);
+ ASSERT (TargetStatus != NULL);
+ ASSERT (DataLength != NULL);
+ ASSERT (ScsiIo != NULL);
+
+ ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));
+ ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIXTEEN);
+
+ CommandPacket.Timeout = Timeout;
+ CommandPacket.OutDataBuffer = DataBuffer;
+ CommandPacket.SenseData = SenseData;
+ CommandPacket.OutTransferLength = *DataLength;
+ CommandPacket.Cdb = Cdb;
+ //
+ // Fill Cdb for Write (16) Command
+ //
+ Cdb[0] = EFI_SCSI_OP_WRITE16;
+ WriteUnaligned64 ((UINT64 *)&Cdb[2], SwapBytes64 (StartLba));
+ WriteUnaligned32 ((UINT32 *)&Cdb[10], SwapBytes32 (SectorSize));
+
+ CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_SIXTEEN;
+ CommandPacket.DataDirection = EFI_SCSI_DATA_OUT;
+ CommandPacket.SenseDataLength = *SenseDataLength;
+
+ Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);
+
+ *HostAdapterStatus = CommandPacket.HostAdapterStatus;
+ *TargetStatus = CommandPacket.TargetStatus;
+ *SenseDataLength = CommandPacket.SenseDataLength;
+ *DataLength = CommandPacket.OutTransferLength;
+
+ return Status;
+}
+
+
+/**
+ Internal helper notify function in which update the result of the
+ non-blocking SCSI Read/Write commands and signal caller event.
+
+ @param Event The instance of EFI_EVENT.
+ @param Context The parameter passed in.
+
+**/
+VOID
+EFIAPI
+ScsiLibNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_SCSI_LIB_ASYNC_CONTEXT *LibContext;
+ EFI_SCSI_IO_SCSI_REQUEST_PACKET *CommandPacket;
+ EFI_EVENT CallerEvent;
+
+ LibContext = (EFI_SCSI_LIB_ASYNC_CONTEXT *) Context;
+ CommandPacket = &LibContext->CommandPacket;
+ CallerEvent = LibContext->CallerEvent;
+
+ //
+ // Update SCSI Read/Write operation results
+ //
+ *LibContext->SenseDataLength = CommandPacket->SenseDataLength;
+ *LibContext->HostAdapterStatus = CommandPacket->HostAdapterStatus;
+ *LibContext->TargetStatus = CommandPacket->TargetStatus;
+ if (CommandPacket->InDataBuffer != NULL) {
+ *LibContext->DataLength = CommandPacket->InTransferLength;
+ } else {
+ *LibContext->DataLength = CommandPacket->OutTransferLength;
+ }
+
+ if (CommandPacket->Cdb != NULL) {
+ FreePool (CommandPacket->Cdb);
+ }
+ FreePool (Context);
+
+ gBS->CloseEvent (Event);
+ gBS->SignalEvent (CallerEvent);
+}
+
+
+/**
+ Execute blocking/non-blocking Read(10) SCSI command on a specific SCSI
+ target.
+
+ Executes the SCSI Read(10) command on the SCSI target specified by ScsiIo.
+ When Event is NULL, blocking command will be executed. Otherwise non-blocking
+ command will be executed.
+ For blocking I/O, if Timeout is zero, this function will wait indefinitely
+ for the command to complete. If Timeout is greater than zero, then the
+ command is executed and will timeout after Timeout 100 ns units.
+ For non-blocking I/O, if Timeout is zero, Event will be signaled only after
+ the command to completes. If Timeout is greater than zero, Event will also be
+ signaled after Timeout 100 ns units.
+ The StartLba and SectorSize parameters are used to construct the CDB for this
+ SCSI command.
+
+ If ScsiIo is NULL, then ASSERT().
+ If SenseDataLength is NULL, then ASSERT().
+ If HostAdapterStatus is NULL, then ASSERT().
+ If TargetStatus is NULL, then ASSERT().
+ If DataLength is NULL, then ASSERT().
+
+ If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet
+ buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
+ EFI_INVALID_PARAMETER gets returned.
+
+ If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet
+ buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
+ EFI_INVALID_PARAMETER gets returned.
+
+ @param[in] ScsiIo A pointer to SCSI IO protocol.
+ @param[in] Timeout The length of timeout period.
+ @param[in, out] SenseData A pointer to output sense data.
+ @param[in, out] SenseDataLength The length of output sense data.
+ @param[out] HostAdapterStatus The status of Host Adapter.
+ @param[out] TargetStatus The status of the target.
+ @param[in, out] DataBuffer Read 16 command data.
+ @param[in, out] DataLength The length of data buffer.
+ @param[in] StartLba The start address of LBA.
+ @param[in] SectorSize The number of contiguous logical blocks
+ of data that shall be transferred.
+ @param[in] Event If the SCSI target does not support
+ non-blocking I/O, then Event is ignored,
+ and blocking I/O is performed. If Event
+ is NULL, then blocking I/O is performed.
+ If Event is not NULL and non-blocking
+ I/O is supported, then non-blocking I/O
+ is performed, and Event will be signaled
+ when the SCSI Read(10) command
+ completes.
+
+ @retval EFI_SUCCESS Command is executed successfully.
+ @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
+ but the entire DataBuffer could not be
+ transferred. The actual number of bytes
+ transferred is returned in DataLength.
+ @retval EFI_NOT_READY The SCSI Request Packet could not be
+ sent because there are too many SCSI
+ Command Packets already queued.
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting
+ to send SCSI Request Packet.
+ @retval EFI_UNSUPPORTED The command described by the SCSI
+ Request Packet is not supported by the
+ SCSI initiator(i.e., SCSI Host
+ Controller)
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the
+ SCSI Request Packet to execute.
+ @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet
+ are invalid.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due
+ to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+ScsiRead10CommandEx (
+ IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
+ IN UINT64 Timeout,
+ IN OUT VOID *SenseData, OPTIONAL
+ IN OUT UINT8 *SenseDataLength,
+ OUT UINT8 *HostAdapterStatus,
+ OUT UINT8 *TargetStatus,
+ IN OUT VOID *DataBuffer, OPTIONAL
+ IN OUT UINT32 *DataLength,
+ IN UINT32 StartLba,
+ IN UINT32 SectorSize,
+ IN EFI_EVENT Event OPTIONAL
+ )
+{
+ EFI_SCSI_LIB_ASYNC_CONTEXT *Context;
+ EFI_SCSI_IO_SCSI_REQUEST_PACKET *CommandPacket;
+ EFI_STATUS Status;
+ UINT8 *Cdb;
+ EFI_EVENT SelfEvent;
+
+ if (Event == NULL) {
+ return ScsiRead10Command (
+ ScsiIo,
+ Timeout,
+ SenseData,
+ SenseDataLength,
+ HostAdapterStatus,
+ TargetStatus,
+ DataBuffer,
+ DataLength,
+ StartLba,
+ SectorSize
+ );
+ }
+
+ ASSERT (SenseDataLength != NULL);
+ ASSERT (HostAdapterStatus != NULL);
+ ASSERT (TargetStatus != NULL);
+ ASSERT (DataLength != NULL);
+ ASSERT (ScsiIo != NULL);
+
+ Context = AllocateZeroPool (sizeof (EFI_SCSI_LIB_ASYNC_CONTEXT));
+ if (Context == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Cdb = AllocateZeroPool (EFI_SCSI_OP_LENGTH_TEN);
+ if (Cdb == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ErrorExit;
+ }
+
+ Context->SenseDataLength = SenseDataLength;
+ Context->HostAdapterStatus = HostAdapterStatus;
+ Context->TargetStatus = TargetStatus;
+ Context->CallerEvent = Event;
+
+ CommandPacket = &Context->CommandPacket;
+ CommandPacket->Timeout = Timeout;
+ CommandPacket->InDataBuffer = DataBuffer;
+ CommandPacket->SenseData = SenseData;
+ CommandPacket->InTransferLength = *DataLength;
+ CommandPacket->Cdb = Cdb;
+ //
+ // Fill Cdb for Read (10) Command
+ //
+ Cdb[0] = EFI_SCSI_OP_READ10;
+ WriteUnaligned32 ((UINT32 *)&Cdb[2], SwapBytes32 (StartLba));
+ WriteUnaligned16 ((UINT16 *)&Cdb[7], SwapBytes16 ((UINT16) SectorSize));
+
+ CommandPacket->CdbLength = EFI_SCSI_OP_LENGTH_TEN;
+ CommandPacket->DataDirection = EFI_SCSI_DATA_IN;
+ CommandPacket->SenseDataLength = *SenseDataLength;
+
+ //
+ // Create Event
+ //
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ ScsiLibNotify,
+ Context,
+ &SelfEvent
+ );
+ if (EFI_ERROR(Status)) {
+ goto ErrorExit;
+ }
+
+ Status = ScsiIo->ExecuteScsiCommand (ScsiIo, CommandPacket, SelfEvent);
+ if (EFI_ERROR(Status)) {
+ //
+ // Since ScsiLibNotify() will not be signaled if ExecuteScsiCommand()
+ // returns with error, close the event here.
+ //
+ gBS->CloseEvent (SelfEvent);
+ goto ErrorExit;
+ } else {
+ return EFI_SUCCESS;
+ }
+
+ErrorExit:
+ if (Context != NULL) {
+ FreePool (Context);
+ }
+
+ return Status;
+}
+
+
+/**
+ Execute blocking/non-blocking Write(10) SCSI command on a specific SCSI
+ target.
+
+ Executes the SCSI Write(10) command on the SCSI target specified by ScsiIo.
+ When Event is NULL, blocking command will be executed. Otherwise non-blocking
+ command will be executed.
+ For blocking I/O, if Timeout is zero, this function will wait indefinitely
+ for the command to complete. If Timeout is greater than zero, then the
+ command is executed and will timeout after Timeout 100 ns units.
+ For non-blocking I/O, if Timeout is zero, Event will be signaled only after
+ the command to completes. If Timeout is greater than zero, Event will also be
+ signaled after Timeout 100 ns units.
+ The StartLba and SectorSize parameters are used to construct the CDB for this
+ SCSI command.
+
+ If ScsiIo is NULL, then ASSERT().
+ If SenseDataLength is NULL, then ASSERT().
+ If HostAdapterStatus is NULL, then ASSERT().
+ If TargetStatus is NULL, then ASSERT().
+ If DataLength is NULL, then ASSERT().
+
+ If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet
+ buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
+ EFI_INVALID_PARAMETER gets returned.
+
+ If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet
+ buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
+ EFI_INVALID_PARAMETER gets returned.
+
+ @param[in] ScsiIo SCSI IO Protocol to use
+ @param[in] Timeout The length of timeout period.
+ @param[in, out] SenseData A pointer to output sense data.
+ @param[in, out] SenseDataLength The length of output sense data.
+ @param[out] HostAdapterStatus The status of Host Adapter.
+ @param[out] TargetStatus The status of the target.
+ @param[in, out] DataBuffer A pointer to a data buffer.
+ @param[in, out] DataLength The length of data buffer.
+ @param[in] StartLba The start address of LBA.
+ @param[in] SectorSize The number of contiguous logical blocks
+ of data that shall be transferred.
+ @param[in] Event If the SCSI target does not support
+ non-blocking I/O, then Event is ignored,
+ and blocking I/O is performed. If Event
+ is NULL, then blocking I/O is performed.
+ If Event is not NULL and non-blocking
+ I/O is supported, then non-blocking I/O
+ is performed, and Event will be signaled
+ when the SCSI Write(10) command
+ completes.
+
+ @retval EFI_SUCCESS Command is executed successfully.
+ @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
+ but the entire DataBuffer could not be
+ transferred. The actual number of bytes
+ transferred is returned in DataLength.
+ @retval EFI_NOT_READY The SCSI Request Packet could not be
+ sent because there are too many SCSI
+ Command Packets already queued.
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting
+ to send SCSI Request Packet.
+ @retval EFI_UNSUPPORTED The command described by the SCSI
+ Request Packet is not supported by the
+ SCSI initiator(i.e., SCSI Host
+ Controller)
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the
+ SCSI Request Packet to execute.
+ @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet
+ are invalid.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due
+ to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+ScsiWrite10CommandEx (
+ IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
+ IN UINT64 Timeout,
+ IN OUT VOID *SenseData, OPTIONAL
+ IN OUT UINT8 *SenseDataLength,
+ OUT UINT8 *HostAdapterStatus,
+ OUT UINT8 *TargetStatus,
+ IN OUT VOID *DataBuffer, OPTIONAL
+ IN OUT UINT32 *DataLength,
+ IN UINT32 StartLba,
+ IN UINT32 SectorSize,
+ IN EFI_EVENT Event OPTIONAL
+ )
+{
+ EFI_SCSI_LIB_ASYNC_CONTEXT *Context;
+ EFI_SCSI_IO_SCSI_REQUEST_PACKET *CommandPacket;
+ EFI_STATUS Status;
+ UINT8 *Cdb;
+ EFI_EVENT SelfEvent;
+
+ if (Event == NULL) {
+ return ScsiWrite10Command (
+ ScsiIo,
+ Timeout,
+ SenseData,
+ SenseDataLength,
+ HostAdapterStatus,
+ TargetStatus,
+ DataBuffer,
+ DataLength,
+ StartLba,
+ SectorSize
+ );
+ }
+
+ ASSERT (SenseDataLength != NULL);
+ ASSERT (HostAdapterStatus != NULL);
+ ASSERT (TargetStatus != NULL);
+ ASSERT (DataLength != NULL);
+ ASSERT (ScsiIo != NULL);
+
+ Context = AllocateZeroPool (sizeof (EFI_SCSI_LIB_ASYNC_CONTEXT));
+ if (Context == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Cdb = AllocateZeroPool (EFI_SCSI_OP_LENGTH_TEN);
+ if (Cdb == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ErrorExit;
+ }
+
+ Context->SenseDataLength = SenseDataLength;
+ Context->HostAdapterStatus = HostAdapterStatus;
+ Context->TargetStatus = TargetStatus;
+ Context->CallerEvent = Event;
+
+ CommandPacket = &Context->CommandPacket;
+ CommandPacket->Timeout = Timeout;
+ CommandPacket->OutDataBuffer = DataBuffer;
+ CommandPacket->SenseData = SenseData;
+ CommandPacket->OutTransferLength = *DataLength;
+ CommandPacket->Cdb = Cdb;
+ //
+ // Fill Cdb for Write (10) Command
+ //
+ Cdb[0] = EFI_SCSI_OP_WRITE10;
+ WriteUnaligned32 ((UINT32 *)&Cdb[2], SwapBytes32 (StartLba));
+ WriteUnaligned16 ((UINT16 *)&Cdb[7], SwapBytes16 ((UINT16) SectorSize));
+
+ CommandPacket->CdbLength = EFI_SCSI_OP_LENGTH_TEN;
+ CommandPacket->DataDirection = EFI_SCSI_DATA_OUT;
+ CommandPacket->SenseDataLength = *SenseDataLength;
+
+ //
+ // Create Event
+ //
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ ScsiLibNotify,
+ Context,
+ &SelfEvent
+ );
+ if (EFI_ERROR(Status)) {
+ goto ErrorExit;
+ }
+
+ Status = ScsiIo->ExecuteScsiCommand (ScsiIo, CommandPacket, SelfEvent);
+ if (EFI_ERROR(Status)) {
+ //
+ // Since ScsiLibNotify() will not be signaled if ExecuteScsiCommand()
+ // returns with error, close the event here.
+ //
+ gBS->CloseEvent (SelfEvent);
+ goto ErrorExit;
+ } else {
+ return EFI_SUCCESS;
+ }
+
+ErrorExit:
+ if (Context != NULL) {
+ FreePool (Context);
+ }
+
+ return Status;
+}
+
+
+/**
+ Execute blocking/non-blocking Read(16) SCSI command on a specific SCSI
+ target.
+
+ Executes the SCSI Read(16) command on the SCSI target specified by ScsiIo.
+ When Event is NULL, blocking command will be executed. Otherwise non-blocking
+ command will be executed.
+ For blocking I/O, if Timeout is zero, this function will wait indefinitely
+ for the command to complete. If Timeout is greater than zero, then the
+ command is executed and will timeout after Timeout 100 ns units.
+ For non-blocking I/O, if Timeout is zero, Event will be signaled only after
+ the command to completes. If Timeout is greater than zero, Event will also be
+ signaled after Timeout 100 ns units.
+ The StartLba and SectorSize parameters are used to construct the CDB for this
+ SCSI command.
+
+ If ScsiIo is NULL, then ASSERT().
+ If SenseDataLength is NULL, then ASSERT().
+ If HostAdapterStatus is NULL, then ASSERT().
+ If TargetStatus is NULL, then ASSERT().
+ If DataLength is NULL, then ASSERT().
+
+ If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet
+ buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
+ EFI_INVALID_PARAMETER gets returned.
+
+ If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet
+ buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
+ EFI_INVALID_PARAMETER gets returned.
+
+ @param[in] ScsiIo A pointer to SCSI IO protocol.
+ @param[in] Timeout The length of timeout period.
+ @param[in, out] SenseData A pointer to output sense data.
+ @param[in, out] SenseDataLength The length of output sense data.
+ @param[out] HostAdapterStatus The status of Host Adapter.
+ @param[out] TargetStatus The status of the target.
+ @param[in, out] DataBuffer Read 16 command data.
+ @param[in, out] DataLength The length of data buffer.
+ @param[in] StartLba The start address of LBA.
+ @param[in] SectorSize The number of contiguous logical blocks
+ of data that shall be transferred.
+ @param[in] Event If the SCSI target does not support
+ non-blocking I/O, then Event is ignored,
+ and blocking I/O is performed. If Event
+ is NULL, then blocking I/O is performed.
+ If Event is not NULL and non-blocking
+ I/O is supported, then non-blocking I/O
+ is performed, and Event will be signaled
+ when the SCSI Read(16) command
+ completes.
+
+ @retval EFI_SUCCESS Command is executed successfully.
+ @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
+ but the entire DataBuffer could not be
+ transferred. The actual number of bytes
+ transferred is returned in DataLength.
+ @retval EFI_NOT_READY The SCSI Request Packet could not be
+ sent because there are too many SCSI
+ Command Packets already queued.
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting
+ to send SCSI Request Packet.
+ @retval EFI_UNSUPPORTED The command described by the SCSI
+ Request Packet is not supported by the
+ SCSI initiator(i.e., SCSI Host
+ Controller)
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the
+ SCSI Request Packet to execute.
+ @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet
+ are invalid.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due
+ to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+ScsiRead16CommandEx (
+ IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
+ IN UINT64 Timeout,
+ IN OUT VOID *SenseData, OPTIONAL
+ IN OUT UINT8 *SenseDataLength,
+ OUT UINT8 *HostAdapterStatus,
+ OUT UINT8 *TargetStatus,
+ IN OUT VOID *DataBuffer, OPTIONAL
+ IN OUT UINT32 *DataLength,
+ IN UINT64 StartLba,
+ IN UINT32 SectorSize,
+ IN EFI_EVENT Event OPTIONAL
+ )
+{
+ EFI_SCSI_LIB_ASYNC_CONTEXT *Context;
+ EFI_SCSI_IO_SCSI_REQUEST_PACKET *CommandPacket;
+ EFI_STATUS Status;
+ UINT8 *Cdb;
+ EFI_EVENT SelfEvent;
+
+ if (Event == NULL) {
+ return ScsiRead16Command (
+ ScsiIo,
+ Timeout,
+ SenseData,
+ SenseDataLength,
+ HostAdapterStatus,
+ TargetStatus,
+ DataBuffer,
+ DataLength,
+ StartLba,
+ SectorSize
+ );
+ }
+
+ ASSERT (SenseDataLength != NULL);
+ ASSERT (HostAdapterStatus != NULL);
+ ASSERT (TargetStatus != NULL);
+ ASSERT (DataLength != NULL);
+ ASSERT (ScsiIo != NULL);
+
+ Context = AllocateZeroPool (sizeof (EFI_SCSI_LIB_ASYNC_CONTEXT));
+ if (Context == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Cdb = AllocateZeroPool (EFI_SCSI_OP_LENGTH_SIXTEEN);
+ if (Cdb == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ErrorExit;
+ }
+
+ Context->SenseDataLength = SenseDataLength;
+ Context->HostAdapterStatus = HostAdapterStatus;
+ Context->TargetStatus = TargetStatus;
+ Context->CallerEvent = Event;
+
+ CommandPacket = &Context->CommandPacket;
+ CommandPacket->Timeout = Timeout;
+ CommandPacket->InDataBuffer = DataBuffer;
+ CommandPacket->SenseData = SenseData;
+ CommandPacket->InTransferLength = *DataLength;
+ CommandPacket->Cdb = Cdb;
+ //
+ // Fill Cdb for Read (16) Command
+ //
+ Cdb[0] = EFI_SCSI_OP_READ16;
+ WriteUnaligned64 ((UINT64 *)&Cdb[2], SwapBytes64 (StartLba));
+ WriteUnaligned32 ((UINT32 *)&Cdb[10], SwapBytes32 (SectorSize));
+
+ CommandPacket->CdbLength = EFI_SCSI_OP_LENGTH_SIXTEEN;
+ CommandPacket->DataDirection = EFI_SCSI_DATA_IN;
+ CommandPacket->SenseDataLength = *SenseDataLength;
+
+ //
+ // Create Event
+ //
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ ScsiLibNotify,
+ Context,
+ &SelfEvent
+ );
+ if (EFI_ERROR(Status)) {
+ goto ErrorExit;
+ }
+
+ Status = ScsiIo->ExecuteScsiCommand (ScsiIo, CommandPacket, SelfEvent);
+ if (EFI_ERROR(Status)) {
+ //
+ // Since ScsiLibNotify() will not be signaled if ExecuteScsiCommand()
+ // returns with error, close the event here.
+ //
+ gBS->CloseEvent (SelfEvent);
+ goto ErrorExit;
+ } else {
+ return EFI_SUCCESS;
+ }
+
+ErrorExit:
+ if (Context != NULL) {
+ FreePool (Context);
+ }
+
+ return Status;
+}
+
+
+/**
+ Execute blocking/non-blocking Write(16) SCSI command on a specific SCSI
+ target.
+
+ Executes the SCSI Write(16) command on the SCSI target specified by ScsiIo.
+ When Event is NULL, blocking command will be executed. Otherwise non-blocking
+ command will be executed.
+ For blocking I/O, if Timeout is zero, this function will wait indefinitely
+ for the command to complete. If Timeout is greater than zero, then the
+ command is executed and will timeout after Timeout 100 ns units.
+ For non-blocking I/O, if Timeout is zero, Event will be signaled only after
+ the command to completes. If Timeout is greater than zero, Event will also be
+ signaled after Timeout 100 ns units.
+ The StartLba and SectorSize parameters are used to construct the CDB for this
+ SCSI command.
+
+ If ScsiIo is NULL, then ASSERT().
+ If SenseDataLength is NULL, then ASSERT().
+ If HostAdapterStatus is NULL, then ASSERT().
+ If TargetStatus is NULL, then ASSERT().
+ If DataLength is NULL, then ASSERT().
+
+ If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet
+ buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
+ EFI_INVALID_PARAMETER gets returned.
+
+ If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet
+ buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
+ EFI_INVALID_PARAMETER gets returned.
+
+ @param[in] ScsiIo SCSI IO Protocol to use
+ @param[in] Timeout The length of timeout period.
+ @param[in, out] SenseData A pointer to output sense data.
+ @param[in, out] SenseDataLength The length of output sense data.
+ @param[out] HostAdapterStatus The status of Host Adapter.
+ @param[out] TargetStatus The status of the target.
+ @param[in, out] DataBuffer A pointer to a data buffer.
+ @param[in, out] DataLength The length of data buffer.
+ @param[in] StartLba The start address of LBA.
+ @param[in] SectorSize The number of contiguous logical blocks
+ of data that shall be transferred.
+ @param[in] Event If the SCSI target does not support
+ non-blocking I/O, then Event is ignored,
+ and blocking I/O is performed. If Event
+ is NULL, then blocking I/O is performed.
+ If Event is not NULL and non-blocking
+ I/O is supported, then non-blocking I/O
+ is performed, and Event will be signaled
+ when the SCSI Write(16) command
+ completes.
+
+ @retval EFI_SUCCESS Command is executed successfully.
+ @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
+ but the entire DataBuffer could not be
+ transferred. The actual number of bytes
+ transferred is returned in DataLength.
+ @retval EFI_NOT_READY The SCSI Request Packet could not be
+ sent because there are too many SCSI
+ Command Packets already queued.
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting
+ to send SCSI Request Packet.
+ @retval EFI_UNSUPPORTED The command described by the SCSI
+ Request Packet is not supported by the
+ SCSI initiator(i.e., SCSI Host
+ Controller)
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the
+ SCSI Request Packet to execute.
+ @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet
+ are invalid.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due
+ to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+ScsiWrite16CommandEx (
+ IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
+ IN UINT64 Timeout,
+ IN OUT VOID *SenseData, OPTIONAL
+ IN OUT UINT8 *SenseDataLength,
+ OUT UINT8 *HostAdapterStatus,
+ OUT UINT8 *TargetStatus,
+ IN OUT VOID *DataBuffer, OPTIONAL
+ IN OUT UINT32 *DataLength,
+ IN UINT64 StartLba,
+ IN UINT32 SectorSize,
+ IN EFI_EVENT Event OPTIONAL
+ )
+{
+ EFI_SCSI_LIB_ASYNC_CONTEXT *Context;
+ EFI_SCSI_IO_SCSI_REQUEST_PACKET *CommandPacket;
+ EFI_STATUS Status;
+ UINT8 *Cdb;
+ EFI_EVENT SelfEvent;
+
+ if (Event == NULL) {
+ return ScsiWrite16Command (
+ ScsiIo,
+ Timeout,
+ SenseData,
+ SenseDataLength,
+ HostAdapterStatus,
+ TargetStatus,
+ DataBuffer,
+ DataLength,
+ StartLba,
+ SectorSize
+ );
+ }
+
+ ASSERT (SenseDataLength != NULL);
+ ASSERT (HostAdapterStatus != NULL);
+ ASSERT (TargetStatus != NULL);
+ ASSERT (DataLength != NULL);
+ ASSERT (ScsiIo != NULL);
+
+ Context = AllocateZeroPool (sizeof (EFI_SCSI_LIB_ASYNC_CONTEXT));
+ if (Context == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Cdb = AllocateZeroPool (EFI_SCSI_OP_LENGTH_SIXTEEN);
+ if (Cdb == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ErrorExit;
+ }
+
+ Context->SenseDataLength = SenseDataLength;
+ Context->HostAdapterStatus = HostAdapterStatus;
+ Context->TargetStatus = TargetStatus;
+ Context->CallerEvent = Event;
+
+ CommandPacket = &Context->CommandPacket;
+ CommandPacket->Timeout = Timeout;
+ CommandPacket->OutDataBuffer = DataBuffer;
+ CommandPacket->SenseData = SenseData;
+ CommandPacket->OutTransferLength = *DataLength;
+ CommandPacket->Cdb = Cdb;
+ //
+ // Fill Cdb for Write (16) Command
+ //
+ Cdb[0] = EFI_SCSI_OP_WRITE16;
+ WriteUnaligned64 ((UINT64 *)&Cdb[2], SwapBytes64 (StartLba));
+ WriteUnaligned32 ((UINT32 *)&Cdb[10], SwapBytes32 (SectorSize));
+
+ CommandPacket->CdbLength = EFI_SCSI_OP_LENGTH_SIXTEEN;
+ CommandPacket->DataDirection = EFI_SCSI_DATA_OUT;
+ CommandPacket->SenseDataLength = *SenseDataLength;
+
+ //
+ // Create Event
+ //
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ ScsiLibNotify,
+ Context,
+ &SelfEvent
+ );
+ if (EFI_ERROR(Status)) {
+ goto ErrorExit;
+ }
+
+ Status = ScsiIo->ExecuteScsiCommand (ScsiIo, CommandPacket, SelfEvent);
+ if (EFI_ERROR(Status)) {
+ //
+ // Since ScsiLibNotify() will not be signaled if ExecuteScsiCommand()
+ // returns with error, close the event here.
+ //
+ gBS->CloseEvent (SelfEvent);
+ goto ErrorExit;
+ } else {
+ return EFI_SUCCESS;
+ }
+
+ErrorExit:
+ if (Context != NULL) {
+ FreePool (Context);
+ }
+
+ return Status;
+}