/** @file\r
UEFI SCSI Library implementation\r
\r
- Copyright (c) 2006 - 2008, Intel Corporation.<BR>\r
- All rights reserved. This program and the accompanying materials \r
- are licensed and made available under the terms and conditions of the BSD License \r
- which accompanies this distribution. The full text of the license may be found at \r
- http://opensource.org/licenses/bsd-license.php \r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+ Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
-\r
#include <Uefi.h>\r
+#include <Library/BaseLib.h>\r
#include <Library/DebugLib.h>\r
-#include <Library/ScsiLib.h>\r
+#include <Library/UefiScsiLib.h>\r
#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
\r
#include <IndustryStandard/Scsi.h>\r
\r
//\r
-// Max bytes needed to represent ID of a SCSI device\r
-//\r
-#define EFI_SCSI_TARGET_MAX_BYTES (0x10)\r
-\r
-//\r
-// bit5..7 are for Logical unit number\r
-// 11100000b (0xe0)\r
+// Scsi Command Length\r
//\r
-#define EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK 0xe0\r
+#define EFI_SCSI_OP_LENGTH_SIX 0x6\r
+#define EFI_SCSI_OP_LENGTH_TEN 0xa\r
+#define EFI_SCSI_OP_LENGTH_TWELVE 0xc\r
+#define EFI_SCSI_OP_LENGTH_SIXTEEN 0x10\r
\r
//\r
-// Scsi Command Length six or ten\r
+// The context structure used when non-blocking SCSI read/write operation\r
+// completes.\r
//\r
-#define EFI_SCSI_OP_LENGTH_SIX 0x6\r
-#define EFI_SCSI_OP_LENGTH_TEN 0xa\r
+typedef struct {\r
+ ///\r
+ /// The SCSI request packet to send to the SCSI controller specified by\r
+ /// the device handle.\r
+ ///\r
+ EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
+ ///\r
+ /// The length of the output sense data.\r
+ ///\r
+ UINT8 *SenseDataLength;\r
+ ///\r
+ /// The status of the SCSI host adapter.\r
+ ///\r
+ UINT8 *HostAdapterStatus;\r
+ ///\r
+ /// The status of the target SCSI device.\r
+ ///\r
+ UINT8 *TargetStatus;\r
+ ///\r
+ /// The length of the data buffer for the SCSI read/write command.\r
+ ///\r
+ UINT32 *DataLength;\r
+ ///\r
+ /// The caller event to be signaled when the SCSI read/write command\r
+ /// completes.\r
+ ///\r
+ EFI_EVENT CallerEvent;\r
+} EFI_SCSI_LIB_ASYNC_CONTEXT;\r
\r
/**\r
- Function test the ready status of the SCSI unit.\r
-\r
- Submit SCSI test unit ready command with SCSI request packet specified by this scsi command, TimeOut\r
- and SenseData, then get the status of the target Scsi unit.\r
+ Execute Test Unit Ready SCSI command on a specific SCSI target.\r
\r
+ Executes the Test Unit Ready command on the SCSI target specified by ScsiIo.\r
+ If Timeout is zero, then this function waits indefinitely for the command to complete.\r
+ If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.\r
+ If ScsiIo is NULL, then ASSERT().\r
If SenseDataLength is NULL, then ASSERT().\r
-\r
If HostAdapterStatus is NULL, then ASSERT().\r
-\r
If TargetStatus is NULL, then ASSERT().\r
\r
- @param[in] ScsiIo A pointer to SCSI IO protocol.\r
- @param[in] Timeout The length of timeout period.\r
- @param[in] SenseData A pointer to output sense data.\r
- @param[out] SenseDataLength The length of output sense data.\r
- @param[out] HostAdapterStatus The status of Host Adapter.\r
- @param[out] TargetStatus The status of the target.\r
-\r
- @retval EFI_SUCCESS The status of the unit is tested successfully.\r
- @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, \r
- but the entire DataBuffer could not be transferred.\r
- The actual number of bytes transferred is returned\r
- in InTransferLength.\r
- @retval EFI_NOT_READY The SCSI Request Packet could not be sent because \r
- there are too many SCSI Command Packets already \r
- queued.\r
- @retval EFI_DEVICE_ERROR A device error occurred while attempting to send \r
- the SCSI Request Packet.\r
- @retval EFI_INVALID_PARAMETER ScsiIo is NULL.\r
- @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet\r
- is not supported by the SCSI initiator(i.e., SCSI \r
- Host Controller).\r
- @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI \r
- Request Packet to execute.\r
+ If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer\r
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
+ gets returned.\r
+\r
+ @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance\r
+ for the specific SCSI target.\r
+ @param[in] Timeout The timeout in 100 ns units to use for the execution\r
+ of this SCSI Request Packet. A Timeout value of\r
+ zero means that this function will wait indefinitely\r
+ for the SCSI Request Packet to execute. If Timeout\r
+ is greater than zero, then this function will return\r
+ EFI_TIMEOUT if the time required to execute the SCSI\r
+ Request Packet is greater than Timeout.\r
+ @param[in, out] SenseData A pointer to sense data that was generated by\r
+ the execution of the SCSI Request Packet. This\r
+ buffer must be allocated by the caller.\r
+ If SenseDataLength is 0, then this parameter is\r
+ optional and may be NULL.\r
+ @param[in, out] SenseDataLength On input, a pointer to the length in bytes of\r
+ the SenseData buffer. On output, a pointer to\r
+ the number of bytes written to the SenseData buffer.\r
+ @param[out] HostAdapterStatus The status of the SCSI Host Controller that produces\r
+ the SCSI bus containing the SCSI target specified by\r
+ ScsiIo when the SCSI Request Packet was executed.\r
+ See the EFI SCSI I/O Protocol in the UEFI Specification\r
+ for details on the possible return values.\r
+ @param[out] TargetStatus The status returned by the SCSI target specified\r
+ by ScsiIo when the SCSI Request Packet was executed\r
+ on the SCSI Host Controller. See the EFI SCSI I/O\r
+ Protocol in the UEFI Specification for details on\r
+ the possible return values.\r
+\r
+ @retval EFI_SUCCESS The command was executed successfully.\r
+ See HostAdapterStatus, TargetStatus, SenseDataLength,\r
+ and SenseData in that order for additional status\r
+ information.\r
+ @retval EFI_NOT_READY The SCSI Request Packet could not be sent because\r
+ there are too many SCSI Command Packets already\r
+ queued. The SCSI Request Packet was not sent, so\r
+ no additional status information is available.\r
+ The caller may retry again later.\r
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to send\r
+ SCSI Request Packet. See HostAdapterStatus,\r
+ TargetStatus, SenseDataLength, and SenseData in that\r
+ order for additional status information.\r
+ @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet\r
+ is not supported by the SCSI initiator(i.e., SCSI\r
+ Host Controller). The SCSI Request Packet was not\r
+ sent, so no additional status information is available.\r
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request\r
+ Packet to execute. See HostAdapterStatus, TargetStatus,\r
+ SenseDataLength, and SenseData in that order for\r
+ additional status information.\r
+ @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.\r
\r
**/\r
EFI_STATUS\r
EFIAPI\r
ScsiTestUnitReadyCommand (\r
- IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
- IN UINT64 Timeout,\r
- IN VOID *SenseData,\r
- OUT UINT8 *SenseDataLength,\r
- OUT UINT8 *HostAdapterStatus,\r
- OUT UINT8 *TargetStatus\r
+ IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
+ IN UINT64 Timeout,\r
+ IN OUT VOID *SenseData OPTIONAL,\r
+ IN OUT UINT8 *SenseDataLength,\r
+ OUT UINT8 *HostAdapterStatus,\r
+ OUT UINT8 *TargetStatus\r
)\r
{\r
- EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
- UINT64 Lun;\r
- UINT8 *Target;\r
- UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];\r
- EFI_STATUS Status;\r
- UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];\r
+ EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
+ EFI_STATUS Status;\r
+ UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];\r
\r
ASSERT (SenseDataLength != NULL);\r
ASSERT (HostAdapterStatus != NULL);\r
ASSERT (TargetStatus != NULL);\r
- \r
- if (ScsiIo == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
+ ASSERT (ScsiIo != NULL);\r
\r
ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX);\r
\r
- CommandPacket.Timeout = Timeout;\r
- CommandPacket.InDataBuffer = NULL;\r
- CommandPacket.InTransferLength= 0;\r
- CommandPacket.OutDataBuffer = NULL;\r
- CommandPacket.OutTransferLength= 0;\r
- CommandPacket.SenseData = SenseData;\r
- CommandPacket.Cdb = Cdb;\r
+ CommandPacket.Timeout = Timeout;\r
+ CommandPacket.InDataBuffer = NULL;\r
+ CommandPacket.InTransferLength = 0;\r
+ CommandPacket.OutDataBuffer = NULL;\r
+ CommandPacket.OutTransferLength = 0;\r
+ CommandPacket.SenseData = SenseData;\r
+ CommandPacket.Cdb = Cdb;\r
//\r
// Fill Cdb for Test Unit Ready Command\r
//\r
- Target = &TargetArray[0];\r
- ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);\r
-\r
Cdb[0] = EFI_SCSI_OP_TEST_UNIT_READY;\r
- Cdb[1] = (UINT8) (Lun & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);\r
- CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX;\r
+ CommandPacket.CdbLength = (UINT8)EFI_SCSI_OP_LENGTH_SIX;\r
CommandPacket.SenseDataLength = *SenseDataLength;\r
\r
- Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
+ Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
\r
- *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
- *TargetStatus = CommandPacket.TargetStatus;\r
- *SenseDataLength = CommandPacket.SenseDataLength;\r
+ *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
+ *TargetStatus = CommandPacket.TargetStatus;\r
+ *SenseDataLength = CommandPacket.SenseDataLength;\r
\r
return Status;\r
}\r
\r
-\r
/**\r
- Function to submit SCSI inquiry command.\r
-\r
- Submit SCSI inquiry command with the SCSI request packet specified by this SCSI command and input\r
- parameters, then return the status of Scsi unit execution.\r
+ Execute Inquiry SCSI command on a specific SCSI target.\r
\r
+ Executes the Inquiry command on the SCSI target specified by ScsiIo.\r
+ If Timeout is zero, then this function waits indefinitely for the command to complete.\r
+ If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.\r
+ If ScsiIo is NULL, then ASSERT().\r
If SenseDataLength is NULL, then ASSERT().\r
-\r
If HostAdapterStatus is NULL, then ASSERT().\r
-\r
If TargetStatus is NULL, then ASSERT().\r
-\r
If InquiryDataLength is NULL, then ASSERT().\r
\r
- @param[in] ScsiIo SCSI IO Protocol to use\r
- @param[in] Timeout The length of timeout period.\r
- @param[in] SenseData A pointer to output sense data.\r
- @param[in, out] SenseDataLength The length of output sense data.\r
- @param[out] HostAdapterStatus The status of Host Adapter.\r
- @param[out] TargetStatus The status of the target.\r
- @param[in, out] InquirydataBuffer A pointer to inquiry data buffer.\r
- @param[in, out] InquiryDataLength The length of inquiry data buffer.\r
- @param[in] EnableVitalProductData Boolean to enable Vital Product Data.\r
-\r
- @retval EFI_SUCCESS Command is executed successfully.\r
- @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, \r
- but the entire DataBuffer could not be transferred.\r
- The actual number of bytes transferred is returned\r
- in TransferLength.\r
- @retval EFI_NOT_READY The SCSI Request Packet could not be sent because \r
- there are too many SCSI Command Packets already \r
- queued.\r
- @retval EFI_DEVICE_ERROR A device error occurred while attempting to send \r
- the SCSI Request Packet.\r
- @retval EFI_INVALID_PARAMETER ScsiIo is NULL.\r
- @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet\r
- is not supported by the SCSI initiator(i.e., SCSI \r
- Host Controller).\r
- @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI \r
- Request Packet to execute.\r
+ If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer\r
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
+ gets returned.\r
+\r
+ If InquiryDataLength is non-zero and InquiryDataBuffer is not NULL, InquiryDataBuffer\r
+ must meet buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise\r
+ EFI_INVALID_PARAMETER gets returned.\r
+\r
+ @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance\r
+ for the specific SCSI target.\r
+ @param[in] Timeout The timeout in 100 ns units to use for the\r
+ execution of this SCSI Request Packet. A Timeout\r
+ value of zero means that this function will wait\r
+ indefinitely for the SCSI Request Packet to execute.\r
+ If Timeout is greater than zero, then this function\r
+ will return EFI_TIMEOUT if the time required to\r
+ execute the SCSI Request Packet is greater than Timeout.\r
+ @param[in, out] SenseData A pointer to sense data that was generated\r
+ by the execution of the SCSI Request Packet.\r
+ This buffer must be allocated by the caller.\r
+ If SenseDataLength is 0, then this parameter\r
+ is optional and may be NULL.\r
+ @param[in, out] SenseDataLength On input, the length in bytes of the SenseData buffer.\r
+ On output, the number of bytes written to the SenseData buffer.\r
+ @param[out] HostAdapterStatus The status of the SCSI Host Controller that\r
+ produces the SCSI bus containing the SCSI\r
+ target specified by ScsiIo when the SCSI\r
+ Request Packet was executed. See the EFI\r
+ SCSI I/O Protocol in the UEFI Specification\r
+ for details on the possible return values.\r
+ @param[out] TargetStatus The status returned by the SCSI target specified\r
+ by ScsiIo when the SCSI Request Packet was\r
+ executed on the SCSI Host Controller.\r
+ See the EFI SCSI I/O Protocol in the UEFI\r
+ Specification for details on the possible\r
+ return values.\r
+ @param[in, out] InquiryDataBuffer A pointer to inquiry data that was generated\r
+ by the execution of the SCSI Request Packet.\r
+ This buffer must be allocated by the caller.\r
+ If InquiryDataLength is 0, then this parameter\r
+ is optional and may be NULL.\r
+ @param[in, out] InquiryDataLength On input, a pointer to the length in bytes\r
+ of the InquiryDataBuffer buffer.\r
+ On output, a pointer to the number of bytes\r
+ written to the InquiryDataBuffer buffer.\r
+ @param[in] EnableVitalProductData If TRUE, then the supported vital product\r
+ data for the PageCode is returned in InquiryDataBuffer.\r
+ If FALSE, then the standard inquiry data is\r
+ returned in InquiryDataBuffer and PageCode is ignored.\r
+ @param[in] PageCode The page code of the vital product data.\r
+ It's ignored if EnableVitalProductData is FALSE.\r
+\r
+ @retval EFI_SUCCESS The command executed successfully. See HostAdapterStatus,\r
+ TargetStatus, SenseDataLength, and SenseData in that order\r
+ for additional status information.\r
+ @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire\r
+ InquiryDataBuffer could not be transferred. The actual\r
+ number of bytes transferred is returned in InquiryDataLength.\r
+ @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there\r
+ are too many SCSI Command Packets already queued.\r
+ The SCSI Request Packet was not sent, so no additional\r
+ status information is available. The caller may retry again later.\r
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI\r
+ Request Packet. See HostAdapterStatus, TargetStatus,\r
+ SenseDataLength, and SenseData in that order for additional\r
+ status information.\r
+ @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not\r
+ supported by the SCSI initiator(i.e., SCSI Host Controller).\r
+ The SCSI Request Packet was not sent, so no additional\r
+ status information is available.\r
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request\r
+ Packet to execute. See HostAdapterStatus, TargetStatus,\r
+ SenseDataLength, and SenseData in that order for\r
+ additional status information.\r
+ @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.\r
\r
**/\r
EFI_STATUS\r
EFIAPI\r
-ScsiInquiryCommand (\r
- IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
- IN UINT64 Timeout,\r
- IN VOID *SenseData,\r
- IN OUT UINT8 *SenseDataLength,\r
- OUT UINT8 *HostAdapterStatus,\r
- OUT UINT8 *TargetStatus,\r
- IN OUT VOID *InquiryDataBuffer,\r
- IN OUT UINT32 *InquiryDataLength,\r
- IN BOOLEAN EnableVitalProductData\r
+ScsiInquiryCommandEx (\r
+ IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
+ IN UINT64 Timeout,\r
+ IN OUT VOID *SenseData OPTIONAL,\r
+ IN OUT UINT8 *SenseDataLength,\r
+ OUT UINT8 *HostAdapterStatus,\r
+ OUT UINT8 *TargetStatus,\r
+ IN OUT VOID *InquiryDataBuffer OPTIONAL,\r
+ IN OUT UINT32 *InquiryDataLength,\r
+ IN BOOLEAN EnableVitalProductData,\r
+ IN UINT8 PageCode\r
)\r
{\r
- EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
- UINT64 Lun;\r
- UINT8 *Target;\r
- UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];\r
- EFI_STATUS Status;\r
- UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];\r
+ EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
+ EFI_STATUS Status;\r
+ UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];\r
\r
ASSERT (SenseDataLength != NULL);\r
ASSERT (HostAdapterStatus != NULL);\r
ASSERT (TargetStatus != NULL);\r
ASSERT (InquiryDataLength != NULL);\r
- \r
- if (ScsiIo == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
+ ASSERT (ScsiIo != NULL);\r
\r
ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX);\r
\r
- CommandPacket.Timeout = Timeout;\r
- CommandPacket.InDataBuffer = InquiryDataBuffer;\r
- CommandPacket.InTransferLength= *InquiryDataLength;\r
- CommandPacket.SenseData = SenseData;\r
- CommandPacket.SenseDataLength = *SenseDataLength;\r
- CommandPacket.Cdb = Cdb;\r
-\r
- Target = &TargetArray[0];\r
- ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);\r
+ CommandPacket.Timeout = Timeout;\r
+ CommandPacket.InDataBuffer = InquiryDataBuffer;\r
+ CommandPacket.InTransferLength = *InquiryDataLength;\r
+ CommandPacket.SenseData = SenseData;\r
+ CommandPacket.SenseDataLength = *SenseDataLength;\r
+ CommandPacket.Cdb = Cdb;\r
\r
- Cdb[0] = EFI_SCSI_OP_INQUIRY;\r
- Cdb[1] = (UINT8) (Lun & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);\r
+ Cdb[0] = EFI_SCSI_OP_INQUIRY;\r
if (EnableVitalProductData) {\r
Cdb[1] |= 0x01;\r
+ Cdb[2] = PageCode;\r
}\r
\r
if (*InquiryDataLength > 0xff) {\r
*InquiryDataLength = 0xff;\r
}\r
\r
- Cdb[4] = (UINT8) (*InquiryDataLength);\r
- CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX;\r
+ Cdb[4] = (UINT8)(*InquiryDataLength);\r
+ CommandPacket.CdbLength = (UINT8)EFI_SCSI_OP_LENGTH_SIX;\r
CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
\r
- Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
+ Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
\r
- *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
- *TargetStatus = CommandPacket.TargetStatus;\r
- *SenseDataLength = CommandPacket.SenseDataLength;\r
- *InquiryDataLength = CommandPacket.InTransferLength;\r
+ *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
+ *TargetStatus = CommandPacket.TargetStatus;\r
+ *SenseDataLength = CommandPacket.SenseDataLength;\r
+ *InquiryDataLength = CommandPacket.InTransferLength;\r
\r
return Status;\r
}\r
\r
-\r
/**\r
- Function to submit SCSI mode sense 10 command.\r
-\r
- Submit SCSI Mode Sense (10) command with the SCSI request packet specified by this SCSI command and\r
- the input parameters, then return the status of Scsi unit execution.\r
+ Execute Inquiry SCSI command on a specific SCSI target.\r
\r
+ Executes the Inquiry command on the SCSI target specified by ScsiIo.\r
+ If Timeout is zero, then this function waits indefinitely for the command to complete.\r
+ If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.\r
+ If ScsiIo is NULL, then ASSERT().\r
If SenseDataLength is NULL, then ASSERT().\r
-\r
If HostAdapterStatus is NULL, then ASSERT().\r
-\r
If TargetStatus is NULL, then ASSERT().\r
+ If InquiryDataLength is NULL, then ASSERT().\r
+\r
+ If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer\r
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
+ gets returned.\r
+\r
+ If InquiryDataLength is non-zero and InquiryDataBuffer is not NULL, InquiryDataBuffer\r
+ must meet buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise\r
+ EFI_INVALID_PARAMETER gets returned.\r
+\r
+ @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance\r
+ for the specific SCSI target.\r
+ @param[in] Timeout The timeout in 100 ns units to use for the\r
+ execution of this SCSI Request Packet. A Timeout\r
+ value of zero means that this function will wait\r
+ indefinitely for the SCSI Request Packet to execute.\r
+ If Timeout is greater than zero, then this function\r
+ will return EFI_TIMEOUT if the time required to\r
+ execute the SCSI Request Packet is greater than Timeout.\r
+ @param[in, out] SenseData A pointer to sense data that was generated\r
+ by the execution of the SCSI Request Packet.\r
+ This buffer must be allocated by the caller.\r
+ If SenseDataLength is 0, then this parameter\r
+ is optional and may be NULL.\r
+ @param[in, out] SenseDataLength On input, the length in bytes of the SenseData buffer.\r
+ On output, the number of bytes written to the SenseData buffer.\r
+ @param[out] HostAdapterStatus The status of the SCSI Host Controller that\r
+ produces the SCSI bus containing the SCSI\r
+ target specified by ScsiIo when the SCSI\r
+ Request Packet was executed. See the EFI\r
+ SCSI I/O Protocol in the UEFI Specification\r
+ for details on the possible return values.\r
+ @param[out] TargetStatus The status returned by the SCSI target specified\r
+ by ScsiIo when the SCSI Request Packet was\r
+ executed on the SCSI Host Controller.\r
+ See the EFI SCSI I/O Protocol in the UEFI\r
+ Specification for details on the possible\r
+ return values.\r
+ @param[in, out] InquiryDataBuffer A pointer to inquiry data that was generated\r
+ by the execution of the SCSI Request Packet.\r
+ This buffer must be allocated by the caller.\r
+ If InquiryDataLength is 0, then this parameter\r
+ is optional and may be NULL.\r
+ @param[in, out] InquiryDataLength On input, a pointer to the length in bytes\r
+ of the InquiryDataBuffer buffer.\r
+ On output, a pointer to the number of bytes\r
+ written to the InquiryDataBuffer buffer.\r
+ @param[in] EnableVitalProductData If TRUE, then the supported vital product\r
+ data is returned in InquiryDataBuffer.\r
+ If FALSE, then the standard inquiry data is\r
+ returned in InquiryDataBuffer.\r
+\r
+ @retval EFI_SUCCESS The command was executed successfully. See HostAdapterStatus,\r
+ TargetStatus, SenseDataLength, and SenseData in that order\r
+ for additional status information.\r
+ @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire\r
+ InquiryDataBuffer could not be transferred. The actual\r
+ number of bytes transferred is returned in InquiryDataLength.\r
+ @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there\r
+ are too many SCSI Command Packets already queued.\r
+ The SCSI Request Packet was not sent, so no additional\r
+ status information is available. The caller may retry again later.\r
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI\r
+ Request Packet. See HostAdapterStatus, TargetStatus,\r
+ SenseDataLength, and SenseData in that order for additional\r
+ status information.\r
+ @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not\r
+ supported by the SCSI initiator(i.e., SCSI Host Controller).\r
+ The SCSI Request Packet was not sent, so no additional\r
+ status information is available.\r
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request\r
+ Packet to execute. See HostAdapterStatus, TargetStatus,\r
+ SenseDataLength, and SenseData in that order for\r
+ additional status information.\r
+ @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.\r
\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ScsiInquiryCommand (\r
+ IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
+ IN UINT64 Timeout,\r
+ IN OUT VOID *SenseData OPTIONAL,\r
+ IN OUT UINT8 *SenseDataLength,\r
+ OUT UINT8 *HostAdapterStatus,\r
+ OUT UINT8 *TargetStatus,\r
+ IN OUT VOID *InquiryDataBuffer OPTIONAL,\r
+ IN OUT UINT32 *InquiryDataLength,\r
+ IN BOOLEAN EnableVitalProductData\r
+ )\r
+{\r
+ return ScsiInquiryCommandEx (\r
+ ScsiIo,\r
+ Timeout,\r
+ SenseData,\r
+ SenseDataLength,\r
+ HostAdapterStatus,\r
+ TargetStatus,\r
+ InquiryDataBuffer,\r
+ InquiryDataLength,\r
+ EnableVitalProductData,\r
+ 0\r
+ );\r
+}\r
+\r
+/**\r
+ Execute Mode Sense(10) SCSI command on a specific SCSI target.\r
+\r
+ Executes the SCSI Mode Sense(10) command on the SCSI target specified by ScsiIo.\r
+ If Timeout is zero, then this function waits indefinitely for the command to complete.\r
+ If Timeout is greater than zero, then the command is executed and will timeout\r
+ after Timeout 100 ns units. The DBDField, PageControl, and PageCode parameters\r
+ are used to construct the CDB for this SCSI command.\r
+ If ScsiIo is NULL, then ASSERT().\r
+ If SenseDataLength is NULL, then ASSERT().\r
+ If HostAdapterStatus is NULL, then ASSERT().\r
+ If TargetStatus is NULL, then ASSERT().\r
If DataLength is NULL, then ASSERT().\r
\r
- @param[in] ScsiIo A pointer to SCSI IO protocol.\r
- @param[in] Timeout The length of timeout period.\r
- @param[in] SenseData A pointer to output sense data.\r
- @param[in, out] SenseDataLength The length of output sense data.\r
- @param[out] HostAdapterStatus The status of Host Adapter.\r
- @param[out] TargetStatus The status of the target.\r
- @param[in] DataBuffer A pointer to input data buffer.\r
- @param[in, out] DataLength The length of input data buffer.\r
- @param[in] DBDField The DBD Field (Optional).\r
- @param[in] PageControl Page Control.\r
- @param[in] PageCode Page code.\r
-\r
- @retval EFI_SUCCESS The status of the unit is tested successfully.\r
- @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, \r
- but the entire DataBuffer could not be transferred.\r
- The actual number of bytes transferred is returned\r
- in TransferLength.\r
- @retval EFI_NOT_READY The SCSI Request Packet could not be sent because \r
- there are too many SCSI Command Packets already \r
- queued.\r
- @retval EFI_DEVICE_ERROR A device error occurred while attempting to send \r
- the SCSI Request Packet.\r
- @retval EFI_INVALID_PARAMETER ScsiIo is NULL. \r
- @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet\r
- is not supported by the SCSI initiator(i.e., SCSI \r
- Host Controller).\r
- @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI \r
- Request Packet to execute.\r
+ If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer\r
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
+ gets returned.\r
+\r
+ If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer\r
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
+ gets returned.\r
+\r
+ @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance\r
+ for the specific SCSI target.\r
+ @param[in] Timeout The timeout in 100 ns units to use for the\r
+ execution of this SCSI Request Packet. A Timeout\r
+ value of zero means that this function will wait\r
+ indefinitely for the SCSI Request Packet to execute.\r
+ If Timeout is greater than zero, then this function\r
+ will return EFI_TIMEOUT if the time required to\r
+ execute the SCSI Request Packet is greater than Timeout.\r
+ @param[in, out] SenseData A pointer to sense data that was generated\r
+ by the execution of the SCSI Request Packet.\r
+ This buffer must be allocated by the caller.\r
+ If SenseDataLength is 0, then this parameter\r
+ is optional and may be NULL.\r
+ @param[in, out] SenseDataLength On input, the length in bytes of the SenseData buffer.\r
+ On output, the number of bytes written to the SenseData buffer.\r
+ @param[out] HostAdapterStatus The status of the SCSI Host Controller that\r
+ produces the SCSI bus containing the SCSI target\r
+ specified by ScsiIo when the SCSI Request Packet\r
+ was executed. See the EFI SCSI I/O Protocol in the\r
+ UEFI Specification for details on the possible\r
+ return values.\r
+ @param[out] TargetStatus The status returned by the SCSI target specified\r
+ by ScsiIo when the SCSI Request Packet was executed\r
+ on the SCSI Host Controller. See the EFI SCSI\r
+ I/O Protocol in the UEFI Specification for details\r
+ on the possible return values.\r
+ @param[in, out] DataBuffer A pointer to data that was generated by the\r
+ execution of the SCSI Request Packet. This\r
+ buffer must be allocated by the caller. If\r
+ DataLength is 0, then this parameter is optional\r
+ and may be NULL.\r
+ @param[in, out] DataLength On input, a pointer to the length in bytes of\r
+ the DataBuffer buffer. On output, a pointer\r
+ to the number of bytes written to the DataBuffer\r
+ buffer.\r
+ @param[in] DBDField Specifies the DBD field of the CDB for this SCSI Command.\r
+ @param[in] PageControl Specifies the PC field of the CDB for this SCSI Command.\r
+ @param[in] PageCode Specifies the Page Control field of the CDB for this SCSI Command.\r
+\r
+ @retval EFI_SUCCESS The command was executed successfully.\r
+ See HostAdapterStatus, TargetStatus, SenseDataLength,\r
+ and SenseData in that order for additional status information.\r
+ @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the\r
+ entire DataBuffer could not be transferred.\r
+ The actual number of bytes transferred is returned\r
+ in DataLength.\r
+ @retval EFI_NOT_READY The SCSI Request Packet could not be sent because\r
+ there are too many SCSI Command Packets already queued.\r
+ The SCSI Request Packet was not sent, so no additional\r
+ status information is available. The caller may retry\r
+ again later.\r
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to send\r
+ SCSI Request Packet. See HostAdapterStatus, TargetStatus,\r
+ SenseDataLength, and SenseData in that order for\r
+ additional status information.\r
+ @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet\r
+ is not supported by the SCSI initiator(i.e., SCSI\r
+ Host Controller). The SCSI Request Packet was not\r
+ sent, so no additional status information is available.\r
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI\r
+ Request Packet to execute. See HostAdapterStatus,\r
+ TargetStatus, SenseDataLength, and SenseData in that\r
+ order for additional status information.\r
+ @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.\r
\r
**/\r
EFI_STATUS\r
EFIAPI\r
ScsiModeSense10Command (\r
- IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
- IN UINT64 Timeout,\r
- IN VOID *SenseData,\r
- IN OUT UINT8 *SenseDataLength,\r
- OUT UINT8 *HostAdapterStatus,\r
- OUT UINT8 *TargetStatus,\r
- IN VOID *DataBuffer,\r
- IN OUT UINT32 *DataLength,\r
- IN UINT8 DBDField, OPTIONAL\r
- IN UINT8 PageControl,\r
- IN UINT8 PageCode\r
+ IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
+ IN UINT64 Timeout,\r
+ IN OUT VOID *SenseData OPTIONAL,\r
+ IN OUT UINT8 *SenseDataLength,\r
+ OUT UINT8 *HostAdapterStatus,\r
+ OUT UINT8 *TargetStatus,\r
+ IN OUT VOID *DataBuffer OPTIONAL,\r
+ IN OUT UINT32 *DataLength,\r
+ IN UINT8 DBDField OPTIONAL,\r
+ IN UINT8 PageControl,\r
+ IN UINT8 PageCode\r
)\r
{\r
- EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
- UINT64 Lun;\r
- UINT8 *Target;\r
- UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];\r
- EFI_STATUS Status;\r
- UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];\r
+ EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
+ EFI_STATUS Status;\r
+ UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];\r
\r
ASSERT (SenseDataLength != NULL);\r
ASSERT (HostAdapterStatus != NULL);\r
ASSERT (TargetStatus != NULL);\r
ASSERT (DataLength != NULL);\r
- \r
- if (ScsiIo == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
+ ASSERT (ScsiIo != NULL);\r
\r
ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);\r
\r
- CommandPacket.Timeout = Timeout;\r
- CommandPacket.InDataBuffer = DataBuffer;\r
- CommandPacket.SenseData = SenseData;\r
- CommandPacket.InTransferLength= *DataLength;\r
- CommandPacket.Cdb = Cdb;\r
+ CommandPacket.Timeout = Timeout;\r
+ CommandPacket.InDataBuffer = DataBuffer;\r
+ CommandPacket.SenseData = SenseData;\r
+ CommandPacket.InTransferLength = *DataLength;\r
+ CommandPacket.Cdb = Cdb;\r
//\r
// Fill Cdb for Mode Sense (10) Command\r
//\r
- Target = &TargetArray[0];\r
- ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);\r
-\r
- Cdb[0] = EFI_SCSI_OP_MODE_SEN10;\r
+ Cdb[0] = EFI_SCSI_OP_MODE_SEN10;\r
//\r
// DBDField is in Cdb[1] bit3 of (bit7..0)\r
//\r
- Cdb[1] = (UINT8) ((Lun & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK) + ((DBDField << 3) & 0x08));\r
+ Cdb[1] = (UINT8)((DBDField << 3) & 0x08);\r
//\r
// PageControl is in Cdb[2] bit7..6, PageCode is in Cdb[2] bit5..0\r
//\r
- Cdb[2] = (UINT8) ((PageControl & 0xc0) | (PageCode & 0x3f));\r
- Cdb[7] = (UINT8) (*DataLength >> 8);\r
- Cdb[8] = (UINT8) (*DataLength);\r
+ Cdb[2] = (UINT8)(((PageControl << 6) & 0xc0) | (PageCode & 0x3f));\r
+ Cdb[7] = (UINT8)(*DataLength >> 8);\r
+ Cdb[8] = (UINT8)(*DataLength);\r
\r
CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;\r
CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
CommandPacket.SenseDataLength = *SenseDataLength;\r
\r
- Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
+ Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
\r
- *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
- *TargetStatus = CommandPacket.TargetStatus;\r
- *SenseDataLength = CommandPacket.SenseDataLength;\r
- *DataLength = CommandPacket.InTransferLength;\r
+ *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
+ *TargetStatus = CommandPacket.TargetStatus;\r
+ *SenseDataLength = CommandPacket.SenseDataLength;\r
+ *DataLength = CommandPacket.InTransferLength;\r
\r
return Status;\r
}\r
\r
-\r
/**\r
- Function to submit SCSI request sense command.\r
-\r
- Submit SCSI request sense command with the SCSI requested packet specified by this\r
- SCSI command, TimeOut and SenseData, and then return the status of scsi unit execution.\r
+ Execute Request Sense SCSI command on a specific SCSI target.\r
\r
+ Executes the Request Sense command on the SCSI target specified by ScsiIo.\r
+ If Timeout is zero, then this function waits indefinitely for the command to complete.\r
+ If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.\r
+ If ScsiIo is NULL, then ASSERT().\r
If SenseDataLength is NULL, then ASSERT().\r
- \r
If HostAdapterStatus is NULL, then ASSERT().\r
- \r
If TargetStatus is NULL, then ASSERT().\r
\r
+ If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer\r
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
+ gets returned.\r
+\r
@param[in] ScsiIo A pointer to SCSI IO protocol.\r
@param[in] Timeout The length of timeout period.\r
- @param[in] SenseData A pointer to output sense data.\r
- @param[in, out] SenseDataLength The length of output sense data.\r
+ @param[in, out] SenseData A pointer to output sense data.\r
+ @param[in, out] SenseDataLength The length of output sense data.\r
@param[out] HostAdapterStatus The status of Host Adapter.\r
@param[out] TargetStatus The status of the target.\r
\r
@retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by\r
the SCSI initiator(i.e., SCSI Host Controller)\r
@retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
- @retval EFI_INVALID_PARAMETER ScsiIo is NULL.\r
+ @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.\r
\r
**/\r
EFI_STATUS\r
EFIAPI\r
ScsiRequestSenseCommand (\r
- IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
- IN UINT64 Timeout,\r
- IN VOID *SenseData,\r
- IN OUT UINT8 *SenseDataLength,\r
- OUT UINT8 *HostAdapterStatus,\r
- OUT UINT8 *TargetStatus\r
+ IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
+ IN UINT64 Timeout,\r
+ IN OUT VOID *SenseData OPTIONAL,\r
+ IN OUT UINT8 *SenseDataLength,\r
+ OUT UINT8 *HostAdapterStatus,\r
+ OUT UINT8 *TargetStatus\r
)\r
{\r
- EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
- UINT64 Lun;\r
- UINT8 *Target;\r
- UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];\r
- EFI_STATUS Status;\r
- UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];\r
+ EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
+ EFI_STATUS Status;\r
+ UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];\r
\r
ASSERT (SenseDataLength != NULL);\r
ASSERT (HostAdapterStatus != NULL);\r
ASSERT (TargetStatus != NULL);\r
- \r
- if (ScsiIo == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
+ ASSERT (ScsiIo != NULL);\r
\r
ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX);\r
\r
- CommandPacket.Timeout = Timeout;\r
- CommandPacket.InDataBuffer = SenseData;\r
- CommandPacket.SenseData = NULL;\r
- CommandPacket.InTransferLength= *SenseDataLength;\r
- CommandPacket.Cdb = Cdb;\r
+ CommandPacket.Timeout = Timeout;\r
+ CommandPacket.InDataBuffer = SenseData;\r
+ CommandPacket.SenseData = NULL;\r
+ CommandPacket.InTransferLength = *SenseDataLength;\r
+ CommandPacket.Cdb = Cdb;\r
//\r
// Fill Cdb for Request Sense Command\r
//\r
- Target = &TargetArray[0];\r
- ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);\r
-\r
- Cdb[0] = EFI_SCSI_OP_REQUEST_SENSE;\r
- Cdb[1] = (UINT8) (Lun & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);\r
- Cdb[4] = (UINT8) (*SenseDataLength);\r
+ Cdb[0] = EFI_SCSI_OP_REQUEST_SENSE;\r
+ Cdb[4] = (UINT8)(*SenseDataLength);\r
\r
- CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX;\r
+ CommandPacket.CdbLength = (UINT8)EFI_SCSI_OP_LENGTH_SIX;\r
CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
CommandPacket.SenseDataLength = 0;\r
\r
- Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
+ Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
\r
- *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
- *TargetStatus = CommandPacket.TargetStatus;\r
- *SenseDataLength = (UINT8) CommandPacket.InTransferLength;\r
+ *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
+ *TargetStatus = CommandPacket.TargetStatus;\r
+ *SenseDataLength = (UINT8)CommandPacket.InTransferLength;\r
\r
return Status;\r
}\r
\r
-\r
/**\r
- Function to submit read capacity command.\r
-\r
- Submit SCSI read capacity command with the SCSI request packet specified by this SCSI \r
- command and the input parameters, and then return the status of Scsi unit execution.\r
+ Execute Read Capacity SCSI command on a specific SCSI target.\r
\r
+ Executes the SCSI Read Capacity command on the SCSI target specified by ScsiIo.\r
+ If Timeout is zero, then this function waits indefinitely for the command to complete.\r
+ If Timeout is greater than zero, then the command is executed and will timeout after\r
+ Timeout 100 ns units. The Pmi parameter is used to construct the CDB for this SCSI command.\r
+ If ScsiIo is NULL, then ASSERT().\r
If SenseDataLength is NULL, then ASSERT().\r
-\r
If HostAdapterStatus is NULL, then ASSERT().\r
-\r
If TargetStatus is NULL, then ASSERT().\r
-\r
If DataLength is NULL, then ASSERT().\r
\r
- @param[in] ScsiIo A pointer to SCSI IO protocol.\r
- @param[in] Timeout The length of timeout period.\r
- @param[in] SenseData A pointer to output sense data.\r
+ If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer\r
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
+ gets returned.\r
+\r
+ If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer\r
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
+ gets returned.\r
+\r
+ @param[in] ScsiIo A pointer to SCSI IO protocol.\r
+ @param[in] Timeout The length of timeout period.\r
+ @param[in, out] SenseData A pointer to output sense data.\r
@param[in, out] SenseDataLength The length of output sense data.\r
- @param[out] HostAdapterStatus The status of Host Adapter.\r
- @param[out] TargetStatus The status of the target.\r
- @param[out] DataBuffer A pointer to a data buffer.\r
+ @param[out] HostAdapterStatus The status of Host Adapter.\r
+ @param[out] TargetStatus The status of the target.\r
+ @param[in, out] DataBuffer A pointer to a data buffer.\r
@param[in, out] DataLength The length of data buffer.\r
- @param[in] PMI Partial medium indicator.\r
-\r
- @retval EFI_SUCCESS Command is executed successfully.\r
- @retval EFI_WARN_BUFFER_TOO_SMALL The SCSI Request Packet was executed, but the entire DataBuffer could\r
- not be transferred. The actual number of bytes transferred is returned in DataLength.\r
- @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many \r
- SCSI Command Packets already queued.\r
- @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
- @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by \r
- the SCSI initiator(i.e., SCSI Host Controller)\r
- @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
- @retval EFI_INVALID_PARAMETER ScsiIo is NULL.\r
+ @param[in] Pmi Partial medium indicator.\r
+\r
+ @retval EFI_SUCCESS Command is executed successfully.\r
+ @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire\r
+ DataBuffer could not be transferred. The actual\r
+ number of bytes transferred is returned in DataLength.\r
+ @retval EFI_NOT_READY The SCSI Request Packet could not be sent because\r
+ there are too many SCSI Command Packets already queued.\r
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
+ @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet\r
+ is not supported by the SCSI initiator(i.e., SCSI Host Controller)\r
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
+ @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.\r
\r
**/\r
EFI_STATUS\r
EFIAPI\r
ScsiReadCapacityCommand (\r
- IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
- IN UINT64 Timeout,\r
- IN VOID *SenseData,\r
- IN OUT UINT8 *SenseDataLength,\r
- OUT UINT8 *HostAdapterStatus,\r
- OUT UINT8 *TargetStatus,\r
- OUT VOID *DataBuffer,\r
- IN OUT UINT32 *DataLength,\r
- IN BOOLEAN PMI\r
+ IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
+ IN UINT64 Timeout,\r
+ IN OUT VOID *SenseData OPTIONAL,\r
+ IN OUT UINT8 *SenseDataLength,\r
+ OUT UINT8 *HostAdapterStatus,\r
+ OUT UINT8 *TargetStatus,\r
+ IN OUT VOID *DataBuffer OPTIONAL,\r
+ IN OUT UINT32 *DataLength,\r
+ IN BOOLEAN Pmi\r
)\r
{\r
- EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
- UINT64 Lun;\r
- UINT8 *Target;\r
- UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];\r
- EFI_STATUS Status;\r
- UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];\r
+ EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
+ EFI_STATUS Status;\r
+ UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];\r
\r
ASSERT (SenseDataLength != NULL);\r
ASSERT (HostAdapterStatus != NULL);\r
ASSERT (TargetStatus != NULL);\r
ASSERT (DataLength != NULL);\r
- \r
- if (ScsiIo == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
+ ASSERT (ScsiIo != NULL);\r
\r
ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);\r
\r
- CommandPacket.Timeout = Timeout;\r
- CommandPacket.InDataBuffer = DataBuffer;\r
- CommandPacket.SenseData = SenseData;\r
- CommandPacket.InTransferLength= *DataLength;\r
- CommandPacket.Cdb = Cdb;\r
+ CommandPacket.Timeout = Timeout;\r
+ CommandPacket.InDataBuffer = DataBuffer;\r
+ CommandPacket.SenseData = SenseData;\r
+ CommandPacket.InTransferLength = *DataLength;\r
+ CommandPacket.Cdb = Cdb;\r
//\r
// Fill Cdb for Read Capacity Command\r
//\r
- Target = &TargetArray[0];\r
- ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);\r
-\r
- Cdb[0] = EFI_SCSI_OP_READ_CAPACITY;\r
- Cdb[1] = (UINT8) (Lun & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);\r
- if (!PMI) {\r
+ Cdb[0] = EFI_SCSI_OP_READ_CAPACITY;\r
+ if (!Pmi) {\r
//\r
- // Partial medium indicator,if PMI is FALSE, the Cdb.2 ~ Cdb.5 MUST BE ZERO.\r
+ // Partial medium indicator,if Pmi is FALSE, the Cdb.2 ~ Cdb.5 MUST BE ZERO.\r
//\r
ZeroMem ((Cdb + 2), 4);\r
} else {\r
CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
CommandPacket.SenseDataLength = *SenseDataLength;\r
\r
- Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
+ Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
\r
- *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
- *TargetStatus = CommandPacket.TargetStatus;\r
- *SenseDataLength = CommandPacket.SenseDataLength;\r
- *DataLength = CommandPacket.InTransferLength;\r
+ *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
+ *TargetStatus = CommandPacket.TargetStatus;\r
+ *SenseDataLength = CommandPacket.SenseDataLength;\r
+ *DataLength = CommandPacket.InTransferLength;\r
\r
return Status;\r
}\r
\r
-\r
/**\r
- Function to submit read 10 command.\r
-\r
- Submit SCSI read (10) command with the SCSI request packet specified by this SCSI command \r
- and the input parameters, and then return the status of Scsi unit execution.\r
+ Execute Read Capacity SCSI 16 command on a specific SCSI target.\r
\r
+ Executes the SCSI Read Capacity 16 command on the SCSI target specified by ScsiIo.\r
+ If Timeout is zero, then this function waits indefinitely for the command to complete.\r
+ If Timeout is greater than zero, then the command is executed and will timeout after\r
+ Timeout 100 ns units. The Pmi parameter is used to construct the CDB for this SCSI command.\r
+ If ScsiIo is NULL, then ASSERT().\r
If SenseDataLength is NULL, then ASSERT().\r
-\r
If HostAdapterStatus is NULL, then ASSERT().\r
-\r
If TargetStatus is NULL, then ASSERT().\r
+ If DataLength is NULL, then ASSERT().\r
+\r
+ If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer\r
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
+ gets returned.\r
+\r
+ If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer\r
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
+ gets returned.\r
+\r
+ @param[in] ScsiIo A pointer to SCSI IO protocol.\r
+ @param[in] Timeout The length of timeout period.\r
+ @param[in, out] SenseData A pointer to output sense data.\r
+ @param[in, out] SenseDataLength The length of output sense data.\r
+ @param[out] HostAdapterStatus The status of Host Adapter.\r
+ @param[out] TargetStatus The status of the target.\r
+ @param[in, out] DataBuffer A pointer to a data buffer.\r
+ @param[in, out] DataLength The length of data buffer.\r
+ @param[in] Pmi Partial medium indicator.\r
+\r
+ @retval EFI_SUCCESS Command is executed successfully.\r
+ @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire\r
+ DataBuffer could not be transferred. The actual\r
+ number of bytes transferred is returned in DataLength.\r
+ @retval EFI_NOT_READY The SCSI Request Packet could not be sent because\r
+ there are too many SCSI Command Packets already queued.\r
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
+ @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet\r
+ is not supported by the SCSI initiator(i.e., SCSI Host Controller)\r
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
+ @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ScsiReadCapacity16Command (\r
+ IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
+ IN UINT64 Timeout,\r
+ IN OUT VOID *SenseData OPTIONAL,\r
+ IN OUT UINT8 *SenseDataLength,\r
+ OUT UINT8 *HostAdapterStatus,\r
+ OUT UINT8 *TargetStatus,\r
+ IN OUT VOID *DataBuffer OPTIONAL,\r
+ IN OUT UINT32 *DataLength,\r
+ IN BOOLEAN Pmi\r
+ )\r
+{\r
+ EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
+ EFI_STATUS Status;\r
+ UINT8 Cdb[16];\r
+\r
+ ASSERT (SenseDataLength != NULL);\r
+ ASSERT (HostAdapterStatus != NULL);\r
+ ASSERT (TargetStatus != NULL);\r
+ ASSERT (DataLength != NULL);\r
+ ASSERT (ScsiIo != NULL);\r
+\r
+ ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
+ ZeroMem (Cdb, 16);\r
+\r
+ CommandPacket.Timeout = Timeout;\r
+ CommandPacket.InDataBuffer = DataBuffer;\r
+ CommandPacket.SenseData = SenseData;\r
+ CommandPacket.InTransferLength = *DataLength;\r
+ CommandPacket.Cdb = Cdb;\r
+ //\r
+ // Fill Cdb for Read Capacity Command\r
+ //\r
+ Cdb[0] = EFI_SCSI_OP_READ_CAPACITY16;\r
+ Cdb[1] = 0x10;\r
+ if (!Pmi) {\r
+ //\r
+ // Partial medium indicator,if Pmi is FALSE, the Cdb.2 ~ Cdb.9 MUST BE ZERO.\r
+ //\r
+ ZeroMem ((Cdb + 2), 8);\r
+ } else {\r
+ Cdb[14] |= 0x01;\r
+ }\r
+\r
+ Cdb[13] = 0x20;\r
+ CommandPacket.CdbLength = 16;\r
+ CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
+ CommandPacket.SenseDataLength = *SenseDataLength;\r
+\r
+ Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
\r
+ *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
+ *TargetStatus = CommandPacket.TargetStatus;\r
+ *SenseDataLength = CommandPacket.SenseDataLength;\r
+ *DataLength = CommandPacket.InTransferLength;\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Execute Read(10) SCSI command on a specific SCSI target.\r
+\r
+ Executes the SCSI Read(10) command on the SCSI target specified by ScsiIo.\r
+ If Timeout is zero, then this function waits indefinitely for the command to complete.\r
+ If Timeout is greater than zero, then the command is executed and will timeout\r
+ after Timeout 100 ns units. The StartLba and SectorSize parameters are used to\r
+ construct the CDB for this SCSI command.\r
+ If ScsiIo is NULL, then ASSERT().\r
+ If SenseDataLength is NULL, then ASSERT().\r
+ If HostAdapterStatus is NULL, then ASSERT().\r
+ If TargetStatus is NULL, then ASSERT().\r
If DataLength is NULL, then ASSERT().\r
\r
- @param[in] ScsiIo A pointer to SCSI IO protocol.\r
- @param[in] Timeout The length of timeout period.\r
- @param[in] SenseData A pointer to output sense data.\r
+ If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer\r
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
+ gets returned.\r
+\r
+ If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer\r
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
+ gets returned.\r
+\r
+ @param[in] ScsiIo A pointer to SCSI IO protocol.\r
+ @param[in] Timeout The length of timeout period.\r
+ @param[in, out] SenseData A pointer to output sense data.\r
@param[in, out] SenseDataLength The length of output sense data.\r
- @param[out] HostAdapterStatus The status of Host Adapter.\r
- @param[out] TargetStatus The status of the target.\r
- @param[out] DataBuffer Read 10 command data.\r
+ @param[out] HostAdapterStatus The status of Host Adapter.\r
+ @param[out] TargetStatus The status of the target.\r
+ @param[in, out] DataBuffer Read 10 command data.\r
@param[in, out] DataLength The length of data buffer.\r
- @param[in] StartLba The start address of LBA.\r
- @param[in] SectorSize The sector size.\r
-\r
- @retval EFI_SUCCESS Command is executed successfully.\r
- @retval EFI_WARN_BUFFER_TOO_SMALL The SCSI Request Packet was executed, but the entire DataBuffer could\r
- not be transferred. The actual number of bytes transferred is returned in DataLength.\r
- @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many \r
- SCSI Command Packets already queued.\r
- @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
- @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by \r
- the SCSI initiator(i.e., SCSI Host Controller)\r
- @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
- @retval EFI_INVALID_PARAMETER ScsiIo is NULL.\r
+ @param[in] StartLba The start address of LBA.\r
+ @param[in] SectorSize The number of contiguous logical blocks of data that shall be transferred.\r
+\r
+ @retval EFI_SUCCESS Command is executed successfully.\r
+ @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could\r
+ not be transferred. The actual number of bytes transferred is returned in DataLength.\r
+ @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many\r
+ SCSI Command Packets already queued.\r
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
+ @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by\r
+ the SCSI initiator(i.e., SCSI Host Controller)\r
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
+ @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.\r
\r
**/\r
EFI_STATUS\r
EFIAPI\r
ScsiRead10Command (\r
- IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
- IN UINT64 Timeout,\r
- IN VOID *SenseData,\r
- IN OUT UINT8 *SenseDataLength,\r
- OUT UINT8 *HostAdapterStatus,\r
- OUT UINT8 *TargetStatus,\r
- OUT VOID *DataBuffer,\r
- IN OUT UINT32 *DataLength,\r
- IN UINT32 StartLba,\r
- IN UINT32 SectorSize\r
+ IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
+ IN UINT64 Timeout,\r
+ IN OUT VOID *SenseData OPTIONAL,\r
+ IN OUT UINT8 *SenseDataLength,\r
+ OUT UINT8 *HostAdapterStatus,\r
+ OUT UINT8 *TargetStatus,\r
+ IN OUT VOID *DataBuffer OPTIONAL,\r
+ IN OUT UINT32 *DataLength,\r
+ IN UINT32 StartLba,\r
+ IN UINT32 SectorSize\r
)\r
{\r
- EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
- UINT64 Lun;\r
- UINT8 *Target;\r
- UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];\r
- EFI_STATUS Status;\r
- UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];\r
+ EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
+ EFI_STATUS Status;\r
+ UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];\r
\r
ASSERT (SenseDataLength != NULL);\r
ASSERT (HostAdapterStatus != NULL);\r
ASSERT (TargetStatus != NULL);\r
ASSERT (DataLength != NULL);\r
- \r
- if (ScsiIo == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
+ ASSERT (ScsiIo != NULL);\r
\r
ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);\r
\r
- CommandPacket.Timeout = Timeout;\r
- CommandPacket.InDataBuffer = DataBuffer;\r
- CommandPacket.SenseData = SenseData;\r
- CommandPacket.InTransferLength= *DataLength;\r
- CommandPacket.Cdb = Cdb;\r
+ CommandPacket.Timeout = Timeout;\r
+ CommandPacket.InDataBuffer = DataBuffer;\r
+ CommandPacket.SenseData = SenseData;\r
+ CommandPacket.InTransferLength = *DataLength;\r
+ CommandPacket.Cdb = Cdb;\r
//\r
// Fill Cdb for Read (10) Command\r
//\r
- Target = &TargetArray[0];\r
- ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);\r
-\r
- Cdb[0] = EFI_SCSI_OP_READ10;\r
- Cdb[1] = (UINT8) (Lun & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);\r
- Cdb[2] = (UINT8) (StartLba >> 24);\r
- Cdb[3] = (UINT8) (StartLba >> 16);\r
- Cdb[4] = (UINT8) (StartLba >> 8);\r
- Cdb[5] = (UINT8) (StartLba & 0xff);\r
- Cdb[7] = (UINT8) (SectorSize >> 8);\r
- Cdb[8] = (UINT8) (SectorSize & 0xff);\r
+ Cdb[0] = EFI_SCSI_OP_READ10;\r
+ WriteUnaligned32 ((UINT32 *)&Cdb[2], SwapBytes32 (StartLba));\r
+ WriteUnaligned16 ((UINT16 *)&Cdb[7], SwapBytes16 ((UINT16)SectorSize));\r
\r
CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;\r
CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
CommandPacket.SenseDataLength = *SenseDataLength;\r
\r
- Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
+ Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
\r
- *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
- *TargetStatus = CommandPacket.TargetStatus;\r
- *SenseDataLength = CommandPacket.SenseDataLength;\r
- *DataLength = CommandPacket.InTransferLength;\r
+ *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
+ *TargetStatus = CommandPacket.TargetStatus;\r
+ *SenseDataLength = CommandPacket.SenseDataLength;\r
+ *DataLength = CommandPacket.InTransferLength;\r
\r
return Status;\r
}\r
\r
+/**\r
+ Execute Write(10) SCSI command on a specific SCSI target.\r
+\r
+ Executes the SCSI Write(10) command on the SCSI target specified by ScsiIo.\r
+ If Timeout is zero, then this function waits indefinitely for the command to complete.\r
+ If Timeout is greater than zero, then the command is executed and will timeout after\r
+ Timeout 100 ns units. The StartLba and SectorSize parameters are used to construct\r
+ the CDB for this SCSI command.\r
+ If ScsiIo is NULL, then ASSERT().\r
+ If SenseDataLength is NULL, then ASSERT().\r
+ If HostAdapterStatus is NULL, then ASSERT().\r
+ If TargetStatus is NULL, then ASSERT().\r
+ If DataLength is NULL, then ASSERT().\r
+\r
+ If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer\r
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
+ gets returned.\r
+\r
+ If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer\r
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
+ gets returned.\r
+\r
+ @param[in] ScsiIo SCSI IO Protocol to use\r
+ @param[in] Timeout The length of timeout period.\r
+ @param[in, out] SenseData A pointer to output sense data.\r
+ @param[in, out] SenseDataLength The length of output sense data.\r
+ @param[out] HostAdapterStatus The status of Host Adapter.\r
+ @param[out] TargetStatus The status of the target.\r
+ @param[in, out] DataBuffer A pointer to a data buffer.\r
+ @param[in, out] DataLength The length of data buffer.\r
+ @param[in] StartLba The start address of LBA.\r
+ @param[in] SectorSize The number of contiguous logical blocks of data that shall be transferred.\r
+\r
+ @retval EFI_SUCCESS Command is executed successfully.\r
+ @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could\r
+ not be transferred. The actual number of bytes transferred is returned in DataLength.\r
+ @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many\r
+ SCSI Command Packets already queued.\r
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
+ @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by\r
+ the SCSI initiator(i.e., SCSI Host Controller)\r
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
+ @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ScsiWrite10Command (\r
+ IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
+ IN UINT64 Timeout,\r
+ IN OUT VOID *SenseData OPTIONAL,\r
+ IN OUT UINT8 *SenseDataLength,\r
+ OUT UINT8 *HostAdapterStatus,\r
+ OUT UINT8 *TargetStatus,\r
+ IN OUT VOID *DataBuffer OPTIONAL,\r
+ IN OUT UINT32 *DataLength,\r
+ IN UINT32 StartLba,\r
+ IN UINT32 SectorSize\r
+ )\r
+{\r
+ EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
+ EFI_STATUS Status;\r
+ UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];\r
+\r
+ ASSERT (SenseDataLength != NULL);\r
+ ASSERT (HostAdapterStatus != NULL);\r
+ ASSERT (TargetStatus != NULL);\r
+ ASSERT (DataLength != NULL);\r
+ ASSERT (ScsiIo != NULL);\r
+\r
+ ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
+ ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);\r
+\r
+ CommandPacket.Timeout = Timeout;\r
+ CommandPacket.OutDataBuffer = DataBuffer;\r
+ CommandPacket.SenseData = SenseData;\r
+ CommandPacket.OutTransferLength = *DataLength;\r
+ CommandPacket.Cdb = Cdb;\r
+ //\r
+ // Fill Cdb for Write (10) Command\r
+ //\r
+ Cdb[0] = EFI_SCSI_OP_WRITE10;\r
+ Cdb[1] = EFI_SCSI_BLOCK_FUA;\r
+ WriteUnaligned32 ((UINT32 *)&Cdb[2], SwapBytes32 (StartLba));\r
+ WriteUnaligned16 ((UINT16 *)&Cdb[7], SwapBytes16 ((UINT16)SectorSize));\r
+\r
+ CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;\r
+ CommandPacket.DataDirection = EFI_SCSI_DATA_OUT;\r
+ CommandPacket.SenseDataLength = *SenseDataLength;\r
+\r
+ Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
+\r
+ *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
+ *TargetStatus = CommandPacket.TargetStatus;\r
+ *SenseDataLength = CommandPacket.SenseDataLength;\r
+ *DataLength = CommandPacket.OutTransferLength;\r
+\r
+ return Status;\r
+}\r
\r
/**\r
- Function to submit SCSI write 10 command.\r
+ Execute Read(16) SCSI command on a specific SCSI target.\r
+\r
+ Executes the SCSI Read(16) command on the SCSI target specified by ScsiIo.\r
+ If Timeout is zero, then this function waits indefinitely for the command to complete.\r
+ If Timeout is greater than zero, then the command is executed and will timeout\r
+ after Timeout 100 ns units. The StartLba and SectorSize parameters are used to\r
+ construct the CDB for this SCSI command.\r
+ If ScsiIo is NULL, then ASSERT().\r
+ If SenseDataLength is NULL, then ASSERT().\r
+ If HostAdapterStatus is NULL, then ASSERT().\r
+ If TargetStatus is NULL, then ASSERT().\r
+ If DataLength is NULL, then ASSERT().\r
+\r
+ If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer\r
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
+ gets returned.\r
+\r
+ If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer\r
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
+ gets returned.\r
+\r
+ @param[in] ScsiIo A pointer to SCSI IO protocol.\r
+ @param[in] Timeout The length of timeout period.\r
+ @param[in, out] SenseData A pointer to output sense data.\r
+ @param[in, out] SenseDataLength The length of output sense data.\r
+ @param[out] HostAdapterStatus The status of Host Adapter.\r
+ @param[out] TargetStatus The status of the target.\r
+ @param[in, out] DataBuffer Read 16 command data.\r
+ @param[in, out] DataLength The length of data buffer.\r
+ @param[in] StartLba The start address of LBA.\r
+ @param[in] SectorSize The number of contiguous logical blocks of data that shall be transferred.\r
+\r
+ @retval EFI_SUCCESS Command is executed successfully.\r
+ @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could\r
+ not be transferred. The actual number of bytes transferred is returned in DataLength.\r
+ @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many\r
+ SCSI Command Packets already queued.\r
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
+ @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by\r
+ the SCSI initiator(i.e., SCSI Host Controller)\r
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
+ @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ScsiRead16Command (\r
+ IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
+ IN UINT64 Timeout,\r
+ IN OUT VOID *SenseData OPTIONAL,\r
+ IN OUT UINT8 *SenseDataLength,\r
+ OUT UINT8 *HostAdapterStatus,\r
+ OUT UINT8 *TargetStatus,\r
+ IN OUT VOID *DataBuffer OPTIONAL,\r
+ IN OUT UINT32 *DataLength,\r
+ IN UINT64 StartLba,\r
+ IN UINT32 SectorSize\r
+ )\r
+{\r
+ EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
+ EFI_STATUS Status;\r
+ UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIXTEEN];\r
+\r
+ ASSERT (SenseDataLength != NULL);\r
+ ASSERT (HostAdapterStatus != NULL);\r
+ ASSERT (TargetStatus != NULL);\r
+ ASSERT (DataLength != NULL);\r
+ ASSERT (ScsiIo != NULL);\r
+\r
+ ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
+ ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIXTEEN);\r
+\r
+ CommandPacket.Timeout = Timeout;\r
+ CommandPacket.InDataBuffer = DataBuffer;\r
+ CommandPacket.SenseData = SenseData;\r
+ CommandPacket.InTransferLength = *DataLength;\r
+ CommandPacket.Cdb = Cdb;\r
+ //\r
+ // Fill Cdb for Read (16) Command\r
+ //\r
+ Cdb[0] = EFI_SCSI_OP_READ16;\r
+ WriteUnaligned64 ((UINT64 *)&Cdb[2], SwapBytes64 (StartLba));\r
+ WriteUnaligned32 ((UINT32 *)&Cdb[10], SwapBytes32 (SectorSize));\r
\r
- Submit SCSI write (10) command with the SCSI request packet specified by this SCSI command and the\r
- input parameters, and then return the status of Scsi unit execution.\r
+ CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_SIXTEEN;\r
+ CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
+ CommandPacket.SenseDataLength = *SenseDataLength;\r
+\r
+ Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
+\r
+ *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
+ *TargetStatus = CommandPacket.TargetStatus;\r
+ *SenseDataLength = CommandPacket.SenseDataLength;\r
+ *DataLength = CommandPacket.InTransferLength;\r
+\r
+ return Status;\r
+}\r
\r
+/**\r
+ Execute Write(16) SCSI command on a specific SCSI target.\r
+\r
+ Executes the SCSI Write(16) command on the SCSI target specified by ScsiIo.\r
+ If Timeout is zero, then this function waits indefinitely for the command to complete.\r
+ If Timeout is greater than zero, then the command is executed and will timeout after\r
+ Timeout 100 ns units. The StartLba and SectorSize parameters are used to construct\r
+ the CDB for this SCSI command.\r
+ If ScsiIo is NULL, then ASSERT().\r
If SenseDataLength is NULL, then ASSERT().\r
+ If HostAdapterStatus is NULL, then ASSERT().\r
+ If TargetStatus is NULL, then ASSERT().\r
+ If DataLength is NULL, then ASSERT().\r
+\r
+ If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer\r
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
+ gets returned.\r
+\r
+ If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer\r
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
+ gets returned.\r
+\r
+ @param[in] ScsiIo SCSI IO Protocol to use\r
+ @param[in] Timeout The length of timeout period.\r
+ @param[in, out] SenseData A pointer to output sense data.\r
+ @param[in, out] SenseDataLength The length of output sense data.\r
+ @param[out] HostAdapterStatus The status of Host Adapter.\r
+ @param[out] TargetStatus The status of the target.\r
+ @param[in, out] DataBuffer A pointer to a data buffer.\r
+ @param[in, out] DataLength The length of data buffer.\r
+ @param[in] StartLba The start address of LBA.\r
+ @param[in] SectorSize The number of contiguous logical blocks of data that shall be transferred.\r
+\r
+ @retval EFI_SUCCESS Command is executed successfully.\r
+ @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could\r
+ not be transferred. The actual number of bytes transferred is returned in DataLength.\r
+ @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many\r
+ SCSI Command Packets already queued.\r
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
+ @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by\r
+ the SCSI initiator(i.e., SCSI Host Controller)\r
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
+ @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ScsiWrite16Command (\r
+ IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
+ IN UINT64 Timeout,\r
+ IN OUT VOID *SenseData OPTIONAL,\r
+ IN OUT UINT8 *SenseDataLength,\r
+ OUT UINT8 *HostAdapterStatus,\r
+ OUT UINT8 *TargetStatus,\r
+ IN OUT VOID *DataBuffer OPTIONAL,\r
+ IN OUT UINT32 *DataLength,\r
+ IN UINT64 StartLba,\r
+ IN UINT32 SectorSize\r
+ )\r
+{\r
+ EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
+ EFI_STATUS Status;\r
+ UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIXTEEN];\r
+\r
+ ASSERT (SenseDataLength != NULL);\r
+ ASSERT (HostAdapterStatus != NULL);\r
+ ASSERT (TargetStatus != NULL);\r
+ ASSERT (DataLength != NULL);\r
+ ASSERT (ScsiIo != NULL);\r
+\r
+ ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
+ ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIXTEEN);\r
+\r
+ CommandPacket.Timeout = Timeout;\r
+ CommandPacket.OutDataBuffer = DataBuffer;\r
+ CommandPacket.SenseData = SenseData;\r
+ CommandPacket.OutTransferLength = *DataLength;\r
+ CommandPacket.Cdb = Cdb;\r
+ //\r
+ // Fill Cdb for Write (16) Command\r
+ //\r
+ Cdb[0] = EFI_SCSI_OP_WRITE16;\r
+ Cdb[1] = EFI_SCSI_BLOCK_FUA;\r
+ WriteUnaligned64 ((UINT64 *)&Cdb[2], SwapBytes64 (StartLba));\r
+ WriteUnaligned32 ((UINT32 *)&Cdb[10], SwapBytes32 (SectorSize));\r
+\r
+ CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_SIXTEEN;\r
+ CommandPacket.DataDirection = EFI_SCSI_DATA_OUT;\r
+ CommandPacket.SenseDataLength = *SenseDataLength;\r
+\r
+ Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
+\r
+ *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
+ *TargetStatus = CommandPacket.TargetStatus;\r
+ *SenseDataLength = CommandPacket.SenseDataLength;\r
+ *DataLength = CommandPacket.OutTransferLength;\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Execute Security Protocol In SCSI command on a specific SCSI target.\r
\r
+ Executes the SCSI Security Protocol In command on the SCSI target specified by ScsiIo.\r
+ If Timeout is zero, then this function waits indefinitely for the command to complete.\r
+ If Timeout is greater than zero, then the command is executed and will timeout after\r
+ Timeout 100 ns units.\r
+ If ScsiIo is NULL, then ASSERT().\r
+ If SenseDataLength is NULL, then ASSERT().\r
If HostAdapterStatus is NULL, then ASSERT().\r
+ If TargetStatus is NULL, then ASSERT().\r
+ If TransferLength is NULL, then ASSERT().\r
+\r
+ If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer\r
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
+ gets returned.\r
+\r
+ If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer\r
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
+ gets returned.\r
+\r
+ @param[in] ScsiIo SCSI IO Protocol to use.\r
+ @param[in] Timeout The length of timeout period.\r
+ @param[in, out] SenseData A pointer to output sense data.\r
+ @param[in, out] SenseDataLength The length of output sense data.\r
+ @param[out] HostAdapterStatus The status of Host Adapter.\r
+ @param[out] TargetStatus The status of the target.\r
+ @param[in] SecurityProtocol The Security Protocol to use.\r
+ @param[in] SecurityProtocolSpecific The Security Protocol Specific data.\r
+ @param[in] Inc512 If TRUE, 512 increment (INC_512) bit will be set for the\r
+ SECURITY PROTOCOL IN command.\r
+ @param[in] DataLength The size in bytes of the data buffer.\r
+ @param[in, out] DataBuffer A pointer to a data buffer.\r
+ @param[out] TransferLength A pointer to a buffer to store the size in\r
+ bytes of the data written to the data buffer.\r
+\r
+ @retval EFI_SUCCESS Command is executed successfully.\r
+ @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could\r
+ not be transferred. The actual number of bytes transferred is returned in TransferLength.\r
+ @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many\r
+ SCSI Command Packets already queued.\r
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
+ @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by\r
+ the SCSI initiator(i.e., SCSI Host Controller)\r
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
+ @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ScsiSecurityProtocolInCommand (\r
+ IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
+ IN UINT64 Timeout,\r
+ IN OUT VOID *SenseData OPTIONAL,\r
+ IN OUT UINT8 *SenseDataLength,\r
+ OUT UINT8 *HostAdapterStatus,\r
+ OUT UINT8 *TargetStatus,\r
+ IN UINT8 SecurityProtocol,\r
+ IN UINT16 SecurityProtocolSpecific,\r
+ IN BOOLEAN Inc512,\r
+ IN UINTN DataLength,\r
+ IN OUT VOID *DataBuffer OPTIONAL,\r
+ OUT UINTN *TransferLength\r
+ )\r
+{\r
+ EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
+ EFI_STATUS Status;\r
+ UINT8 Cdb[EFI_SCSI_OP_LENGTH_TWELVE];\r
+\r
+ ASSERT (SenseDataLength != NULL);\r
+ ASSERT (HostAdapterStatus != NULL);\r
+ ASSERT (TargetStatus != NULL);\r
+ ASSERT (ScsiIo != NULL);\r
+ ASSERT (TransferLength != NULL);\r
+ ASSERT (DataLength <= MAX_UINT32);\r
+\r
+ ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
+ ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TWELVE);\r
\r
+ CommandPacket.Timeout = Timeout;\r
+ CommandPacket.InDataBuffer = DataBuffer;\r
+ CommandPacket.SenseData = SenseData;\r
+ CommandPacket.InTransferLength = (UINT32)DataLength;\r
+ CommandPacket.Cdb = Cdb;\r
+ //\r
+ // Fill Cdb for Security Protocol In Command\r
+ //\r
+ Cdb[0] = EFI_SCSI_OP_SECURITY_PROTOCOL_IN;\r
+ Cdb[1] = SecurityProtocol;\r
+ WriteUnaligned16 ((UINT16 *)&Cdb[2], SwapBytes16 (SecurityProtocolSpecific));\r
+\r
+ if (Inc512) {\r
+ if (DataLength % 512 != 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Cdb[4] = BIT7;\r
+ WriteUnaligned32 ((UINT32 *)&Cdb[6], SwapBytes32 ((UINT32)DataLength / 512));\r
+ } else {\r
+ WriteUnaligned32 ((UINT32 *)&Cdb[6], SwapBytes32 ((UINT32)DataLength));\r
+ }\r
+\r
+ CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TWELVE;\r
+ CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
+ CommandPacket.SenseDataLength = *SenseDataLength;\r
+\r
+ Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
+\r
+ *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
+ *TargetStatus = CommandPacket.TargetStatus;\r
+ *SenseDataLength = CommandPacket.SenseDataLength;\r
+ *TransferLength = (UINTN)CommandPacket.InTransferLength;\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Execute Security Protocol Out SCSI command on a specific SCSI target.\r
+\r
+ Executes the SCSI Security Protocol Out command on the SCSI target specified by ScsiIo.\r
+ If Timeout is zero, then this function waits indefinitely for the command to complete.\r
+ If Timeout is greater than zero, then the command is executed and will timeout after\r
+ Timeout 100 ns units.\r
+ If ScsiIo is NULL, then ASSERT().\r
+ If SenseDataLength is NULL, then ASSERT().\r
+ If HostAdapterStatus is NULL, then ASSERT().\r
If TargetStatus is NULL, then ASSERT().\r
\r
+ If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer\r
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
+ gets returned.\r
+\r
+ If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer\r
+ alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
+ gets returned.\r
+\r
+ @param[in] ScsiIo SCSI IO Protocol to use.\r
+ @param[in] Timeout The length of timeout period.\r
+ @param[in, out] SenseData A pointer to output sense data.\r
+ @param[in, out] SenseDataLength The length of output sense data.\r
+ @param[out] HostAdapterStatus The status of Host Adapter.\r
+ @param[out] TargetStatus The status of the target.\r
+ @param[in] SecurityProtocol The Security Protocol to use.\r
+ @param[in] SecurityProtocolSpecific The Security Protocol Specific data.\r
+ @param[in] Inc512 If TRUE, 512 increment (INC_512) bit will be set for the\r
+ SECURITY PROTOCOL OUT command.\r
+ @param[in] DataLength The size in bytes of the transfer data.\r
+ @param[in, out] DataBuffer A pointer to a data buffer.\r
+\r
+ @retval EFI_SUCCESS Command is executed successfully.\r
+ @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could\r
+ not be transferred. The actual number of bytes transferred is returned in DataLength.\r
+ @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many\r
+ SCSI Command Packets already queued.\r
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
+ @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by\r
+ the SCSI initiator(i.e., SCSI Host Controller)\r
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
+ @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ScsiSecurityProtocolOutCommand (\r
+ IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
+ IN UINT64 Timeout,\r
+ IN OUT VOID *SenseData OPTIONAL,\r
+ IN OUT UINT8 *SenseDataLength,\r
+ OUT UINT8 *HostAdapterStatus,\r
+ OUT UINT8 *TargetStatus,\r
+ IN UINT8 SecurityProtocol,\r
+ IN UINT16 SecurityProtocolSpecific,\r
+ IN BOOLEAN Inc512,\r
+ IN UINTN DataLength,\r
+ IN OUT VOID *DataBuffer OPTIONAL\r
+ )\r
+{\r
+ EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
+ EFI_STATUS Status;\r
+ UINT8 Cdb[EFI_SCSI_OP_LENGTH_TWELVE];\r
+\r
+ ASSERT (SenseDataLength != NULL);\r
+ ASSERT (HostAdapterStatus != NULL);\r
+ ASSERT (TargetStatus != NULL);\r
+ ASSERT (ScsiIo != NULL);\r
+ ASSERT (DataLength <= MAX_UINT32);\r
+\r
+ ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
+ ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TWELVE);\r
+\r
+ CommandPacket.Timeout = Timeout;\r
+ CommandPacket.OutDataBuffer = DataBuffer;\r
+ CommandPacket.SenseData = SenseData;\r
+ CommandPacket.OutTransferLength = (UINT32)DataLength;\r
+ CommandPacket.Cdb = Cdb;\r
+ //\r
+ // Fill Cdb for Security Protocol Out Command\r
+ //\r
+ Cdb[0] = EFI_SCSI_OP_SECURITY_PROTOCOL_OUT;\r
+ Cdb[1] = SecurityProtocol;\r
+ WriteUnaligned16 ((UINT16 *)&Cdb[2], SwapBytes16 (SecurityProtocolSpecific));\r
+\r
+ if (Inc512) {\r
+ if (DataLength % 512 != 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Cdb[4] = BIT7;\r
+ WriteUnaligned32 ((UINT32 *)&Cdb[6], SwapBytes32 ((UINT32)DataLength / 512));\r
+ } else {\r
+ WriteUnaligned32 ((UINT32 *)&Cdb[6], SwapBytes32 ((UINT32)DataLength));\r
+ }\r
+\r
+ CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TWELVE;\r
+ CommandPacket.DataDirection = EFI_SCSI_DATA_OUT;\r
+ CommandPacket.SenseDataLength = *SenseDataLength;\r
+\r
+ Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
+\r
+ *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
+ *TargetStatus = CommandPacket.TargetStatus;\r
+ *SenseDataLength = CommandPacket.SenseDataLength;\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Internal helper notify function in which update the result of the\r
+ non-blocking SCSI Read/Write commands and signal caller event.\r
+\r
+ @param Event The instance of EFI_EVENT.\r
+ @param Context The parameter passed in.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+ScsiLibNotify (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ EFI_SCSI_LIB_ASYNC_CONTEXT *LibContext;\r
+ EFI_SCSI_IO_SCSI_REQUEST_PACKET *CommandPacket;\r
+ EFI_EVENT CallerEvent;\r
+\r
+ LibContext = (EFI_SCSI_LIB_ASYNC_CONTEXT *)Context;\r
+ CommandPacket = &LibContext->CommandPacket;\r
+ CallerEvent = LibContext->CallerEvent;\r
+\r
+ //\r
+ // Update SCSI Read/Write operation results\r
+ //\r
+ *LibContext->SenseDataLength = CommandPacket->SenseDataLength;\r
+ *LibContext->HostAdapterStatus = CommandPacket->HostAdapterStatus;\r
+ *LibContext->TargetStatus = CommandPacket->TargetStatus;\r
+ if (CommandPacket->InDataBuffer != NULL) {\r
+ *LibContext->DataLength = CommandPacket->InTransferLength;\r
+ } else {\r
+ *LibContext->DataLength = CommandPacket->OutTransferLength;\r
+ }\r
+\r
+ if (CommandPacket->Cdb != NULL) {\r
+ FreePool (CommandPacket->Cdb);\r
+ }\r
+\r
+ FreePool (Context);\r
+\r
+ gBS->CloseEvent (Event);\r
+ gBS->SignalEvent (CallerEvent);\r
+}\r
+\r
+/**\r
+ Execute blocking/non-blocking Read(10) SCSI command on a specific SCSI\r
+ target.\r
+\r
+ Executes the SCSI Read(10) command on the SCSI target specified by ScsiIo.\r
+ When Event is NULL, blocking command will be executed. Otherwise non-blocking\r
+ command will be executed.\r
+ For blocking I/O, if Timeout is zero, this function will wait indefinitely\r
+ for the command to complete. If Timeout is greater than zero, then the\r
+ command is executed and will timeout after Timeout 100 ns units.\r
+ For non-blocking I/O, if Timeout is zero, Event will be signaled only after\r
+ the command to completes. If Timeout is greater than zero, Event will also be\r
+ signaled after Timeout 100 ns units.\r
+ The StartLba and SectorSize parameters are used to construct the CDB for this\r
+ SCSI command.\r
+\r
+ If ScsiIo is NULL, then ASSERT().\r
+ If SenseDataLength is NULL, then ASSERT().\r
+ If HostAdapterStatus is NULL, then ASSERT().\r
+ If TargetStatus is NULL, then ASSERT().\r
If DataLength is NULL, then ASSERT().\r
\r
- @param[in] ScsiIo SCSI IO Protocol to use\r
- @param[in] Timeout The length of timeout period.\r
- @param[in] SenseData A pointer to output sense data.\r
+ If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet\r
+ buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise\r
+ EFI_INVALID_PARAMETER gets returned.\r
+\r
+ If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet\r
+ buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise\r
+ EFI_INVALID_PARAMETER gets returned.\r
+\r
+ @param[in] ScsiIo A pointer to SCSI IO protocol.\r
+ @param[in] Timeout The length of timeout period.\r
+ @param[in, out] SenseData A pointer to output sense data.\r
@param[in, out] SenseDataLength The length of output sense data.\r
- @param[out] HostAdapterStatus The status of Host Adapter.\r
- @param[out] TargetStatus The status of the target.\r
- @param[out] DataBuffer A pointer to a data buffer.\r
+ @param[out] HostAdapterStatus The status of Host Adapter.\r
+ @param[out] TargetStatus The status of the target.\r
+ @param[in, out] DataBuffer Read 16 command data.\r
@param[in, out] DataLength The length of data buffer.\r
- @param[in] StartLba The start address of LBA.\r
- @param[in] SectorSize The sector size.\r
-\r
- @retval EFI_SUCCESS Command is executed successfully.\r
- @retval EFI_WARN_BUFFER_TOO_SMALL The SCSI Request Packet was executed, but the entire DataBuffer could\r
- not be transferred. The actual number of bytes transferred is returned in DataLength.\r
- @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many \r
- SCSI Command Packets already queued.\r
- @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
- @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by \r
- the SCSI initiator(i.e., SCSI Host Controller)\r
- @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
- @retval EFI_INVALID_PARAMETER ScsiIo is NULL.\r
+ @param[in] StartLba The start address of LBA.\r
+ @param[in] SectorSize The number of contiguous logical blocks\r
+ of data that shall be transferred.\r
+ @param[in] Event If the SCSI target does not support\r
+ non-blocking I/O, then Event is ignored,\r
+ and blocking I/O is performed. If Event\r
+ is NULL, then blocking I/O is performed.\r
+ If Event is not NULL and non-blocking\r
+ I/O is supported, then non-blocking I/O\r
+ is performed, and Event will be signaled\r
+ when the SCSI Read(10) command\r
+ completes.\r
+\r
+ @retval EFI_SUCCESS Command is executed successfully.\r
+ @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,\r
+ but the entire DataBuffer could not be\r
+ transferred. The actual number of bytes\r
+ transferred is returned in DataLength.\r
+ @retval EFI_NOT_READY The SCSI Request Packet could not be\r
+ sent because there are too many SCSI\r
+ Command Packets already queued.\r
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting\r
+ to send SCSI Request Packet.\r
+ @retval EFI_UNSUPPORTED The command described by the SCSI\r
+ Request Packet is not supported by the\r
+ SCSI initiator(i.e., SCSI Host\r
+ Controller)\r
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the\r
+ SCSI Request Packet to execute.\r
+ @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet\r
+ are invalid.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due\r
+ to a lack of resources.\r
\r
**/\r
EFI_STATUS\r
EFIAPI\r
-ScsiWrite10Command (\r
- IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
- IN UINT64 Timeout,\r
- IN VOID *SenseData,\r
- IN OUT UINT8 *SenseDataLength,\r
- OUT UINT8 *HostAdapterStatus,\r
- OUT UINT8 *TargetStatus,\r
- OUT VOID *DataBuffer,\r
- IN OUT UINT32 *DataLength,\r
- IN UINT32 StartLba,\r
- IN UINT32 SectorSize\r
+ScsiRead10CommandEx (\r
+ IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
+ IN UINT64 Timeout,\r
+ IN OUT VOID *SenseData OPTIONAL,\r
+ IN OUT UINT8 *SenseDataLength,\r
+ OUT UINT8 *HostAdapterStatus,\r
+ OUT UINT8 *TargetStatus,\r
+ IN OUT VOID *DataBuffer OPTIONAL,\r
+ IN OUT UINT32 *DataLength,\r
+ IN UINT32 StartLba,\r
+ IN UINT32 SectorSize,\r
+ IN EFI_EVENT Event OPTIONAL\r
)\r
{\r
- EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
- UINT64 Lun;\r
- UINT8 *Target;\r
- UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];\r
- EFI_STATUS Status;\r
- UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];\r
+ EFI_SCSI_LIB_ASYNC_CONTEXT *Context;\r
+ EFI_SCSI_IO_SCSI_REQUEST_PACKET *CommandPacket;\r
+ EFI_STATUS Status;\r
+ UINT8 *Cdb;\r
+ EFI_EVENT SelfEvent;\r
+\r
+ if (Event == NULL) {\r
+ return ScsiRead10Command (\r
+ ScsiIo,\r
+ Timeout,\r
+ SenseData,\r
+ SenseDataLength,\r
+ HostAdapterStatus,\r
+ TargetStatus,\r
+ DataBuffer,\r
+ DataLength,\r
+ StartLba,\r
+ SectorSize\r
+ );\r
+ }\r
\r
ASSERT (SenseDataLength != NULL);\r
ASSERT (HostAdapterStatus != NULL);\r
ASSERT (TargetStatus != NULL);\r
ASSERT (DataLength != NULL);\r
- \r
- if (ScsiIo == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
+ ASSERT (ScsiIo != NULL);\r
+\r
+ Context = AllocateZeroPool (sizeof (EFI_SCSI_LIB_ASYNC_CONTEXT));\r
+ if (Context == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
- ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);\r
+ Cdb = AllocateZeroPool (EFI_SCSI_OP_LENGTH_TEN);\r
+ if (Cdb == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ErrorExit;\r
+ }\r
+\r
+ Context->SenseDataLength = SenseDataLength;\r
+ Context->HostAdapterStatus = HostAdapterStatus;\r
+ Context->TargetStatus = TargetStatus;\r
+ Context->CallerEvent = Event;\r
+\r
+ CommandPacket = &Context->CommandPacket;\r
+ CommandPacket->Timeout = Timeout;\r
+ CommandPacket->InDataBuffer = DataBuffer;\r
+ CommandPacket->SenseData = SenseData;\r
+ CommandPacket->InTransferLength = *DataLength;\r
+ CommandPacket->Cdb = Cdb;\r
+ //\r
+ // Fill Cdb for Read (10) Command\r
+ //\r
+ Cdb[0] = EFI_SCSI_OP_READ10;\r
+ WriteUnaligned32 ((UINT32 *)&Cdb[2], SwapBytes32 (StartLba));\r
+ WriteUnaligned16 ((UINT16 *)&Cdb[7], SwapBytes16 ((UINT16)SectorSize));\r
+\r
+ CommandPacket->CdbLength = EFI_SCSI_OP_LENGTH_TEN;\r
+ CommandPacket->DataDirection = EFI_SCSI_DATA_IN;\r
+ CommandPacket->SenseDataLength = *SenseDataLength;\r
+\r
+ //\r
+ // Create Event\r
+ //\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
+ ScsiLibNotify,\r
+ Context,\r
+ &SelfEvent\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ErrorExit;\r
+ }\r
+\r
+ Status = ScsiIo->ExecuteScsiCommand (ScsiIo, CommandPacket, SelfEvent);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Since ScsiLibNotify() will not be signaled if ExecuteScsiCommand()\r
+ // returns with error, close the event here.\r
+ //\r
+ gBS->CloseEvent (SelfEvent);\r
+ goto ErrorExit;\r
+ } else {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ErrorExit:\r
+ if (Context != NULL) {\r
+ FreePool (Context);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Execute blocking/non-blocking Write(10) SCSI command on a specific SCSI\r
+ target.\r
+\r
+ Executes the SCSI Write(10) command on the SCSI target specified by ScsiIo.\r
+ When Event is NULL, blocking command will be executed. Otherwise non-blocking\r
+ command will be executed.\r
+ For blocking I/O, if Timeout is zero, this function will wait indefinitely\r
+ for the command to complete. If Timeout is greater than zero, then the\r
+ command is executed and will timeout after Timeout 100 ns units.\r
+ For non-blocking I/O, if Timeout is zero, Event will be signaled only after\r
+ the command to completes. If Timeout is greater than zero, Event will also be\r
+ signaled after Timeout 100 ns units.\r
+ The StartLba and SectorSize parameters are used to construct the CDB for this\r
+ SCSI command.\r
+\r
+ If ScsiIo is NULL, then ASSERT().\r
+ If SenseDataLength is NULL, then ASSERT().\r
+ If HostAdapterStatus is NULL, then ASSERT().\r
+ If TargetStatus is NULL, then ASSERT().\r
+ If DataLength is NULL, then ASSERT().\r
+\r
+ If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet\r
+ buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise\r
+ EFI_INVALID_PARAMETER gets returned.\r
+\r
+ If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet\r
+ buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise\r
+ EFI_INVALID_PARAMETER gets returned.\r
+\r
+ @param[in] ScsiIo SCSI IO Protocol to use\r
+ @param[in] Timeout The length of timeout period.\r
+ @param[in, out] SenseData A pointer to output sense data.\r
+ @param[in, out] SenseDataLength The length of output sense data.\r
+ @param[out] HostAdapterStatus The status of Host Adapter.\r
+ @param[out] TargetStatus The status of the target.\r
+ @param[in, out] DataBuffer A pointer to a data buffer.\r
+ @param[in, out] DataLength The length of data buffer.\r
+ @param[in] StartLba The start address of LBA.\r
+ @param[in] SectorSize The number of contiguous logical blocks\r
+ of data that shall be transferred.\r
+ @param[in] Event If the SCSI target does not support\r
+ non-blocking I/O, then Event is ignored,\r
+ and blocking I/O is performed. If Event\r
+ is NULL, then blocking I/O is performed.\r
+ If Event is not NULL and non-blocking\r
+ I/O is supported, then non-blocking I/O\r
+ is performed, and Event will be signaled\r
+ when the SCSI Write(10) command\r
+ completes.\r
+\r
+ @retval EFI_SUCCESS Command is executed successfully.\r
+ @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,\r
+ but the entire DataBuffer could not be\r
+ transferred. The actual number of bytes\r
+ transferred is returned in DataLength.\r
+ @retval EFI_NOT_READY The SCSI Request Packet could not be\r
+ sent because there are too many SCSI\r
+ Command Packets already queued.\r
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting\r
+ to send SCSI Request Packet.\r
+ @retval EFI_UNSUPPORTED The command described by the SCSI\r
+ Request Packet is not supported by the\r
+ SCSI initiator(i.e., SCSI Host\r
+ Controller)\r
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the\r
+ SCSI Request Packet to execute.\r
+ @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet\r
+ are invalid.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due\r
+ to a lack of resources.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ScsiWrite10CommandEx (\r
+ IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
+ IN UINT64 Timeout,\r
+ IN OUT VOID *SenseData OPTIONAL,\r
+ IN OUT UINT8 *SenseDataLength,\r
+ OUT UINT8 *HostAdapterStatus,\r
+ OUT UINT8 *TargetStatus,\r
+ IN OUT VOID *DataBuffer OPTIONAL,\r
+ IN OUT UINT32 *DataLength,\r
+ IN UINT32 StartLba,\r
+ IN UINT32 SectorSize,\r
+ IN EFI_EVENT Event OPTIONAL\r
+ )\r
+{\r
+ EFI_SCSI_LIB_ASYNC_CONTEXT *Context;\r
+ EFI_SCSI_IO_SCSI_REQUEST_PACKET *CommandPacket;\r
+ EFI_STATUS Status;\r
+ UINT8 *Cdb;\r
+ EFI_EVENT SelfEvent;\r
+\r
+ if (Event == NULL) {\r
+ return ScsiWrite10Command (\r
+ ScsiIo,\r
+ Timeout,\r
+ SenseData,\r
+ SenseDataLength,\r
+ HostAdapterStatus,\r
+ TargetStatus,\r
+ DataBuffer,\r
+ DataLength,\r
+ StartLba,\r
+ SectorSize\r
+ );\r
+ }\r
+\r
+ ASSERT (SenseDataLength != NULL);\r
+ ASSERT (HostAdapterStatus != NULL);\r
+ ASSERT (TargetStatus != NULL);\r
+ ASSERT (DataLength != NULL);\r
+ ASSERT (ScsiIo != NULL);\r
+\r
+ Context = AllocateZeroPool (sizeof (EFI_SCSI_LIB_ASYNC_CONTEXT));\r
+ if (Context == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
\r
- CommandPacket.Timeout = Timeout;\r
- CommandPacket.OutDataBuffer = DataBuffer;\r
- CommandPacket.SenseData = SenseData;\r
- CommandPacket.OutTransferLength= *DataLength;\r
- CommandPacket.Cdb = Cdb;\r
+ Cdb = AllocateZeroPool (EFI_SCSI_OP_LENGTH_TEN);\r
+ if (Cdb == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ErrorExit;\r
+ }\r
+\r
+ Context->SenseDataLength = SenseDataLength;\r
+ Context->HostAdapterStatus = HostAdapterStatus;\r
+ Context->TargetStatus = TargetStatus;\r
+ Context->CallerEvent = Event;\r
+\r
+ CommandPacket = &Context->CommandPacket;\r
+ CommandPacket->Timeout = Timeout;\r
+ CommandPacket->OutDataBuffer = DataBuffer;\r
+ CommandPacket->SenseData = SenseData;\r
+ CommandPacket->OutTransferLength = *DataLength;\r
+ CommandPacket->Cdb = Cdb;\r
//\r
// Fill Cdb for Write (10) Command\r
//\r
- Target = &TargetArray[0];\r
- ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);\r
+ Cdb[0] = EFI_SCSI_OP_WRITE10;\r
+ WriteUnaligned32 ((UINT32 *)&Cdb[2], SwapBytes32 (StartLba));\r
+ WriteUnaligned16 ((UINT16 *)&Cdb[7], SwapBytes16 ((UINT16)SectorSize));\r
\r
- Cdb[0] = EFI_SCSI_OP_WRITE10;\r
- Cdb[1] = (UINT8) (Lun & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);\r
- Cdb[2] = (UINT8) (StartLba >> 24);\r
- Cdb[3] = (UINT8) (StartLba >> 16);\r
- Cdb[4] = (UINT8) (StartLba >> 8);\r
- Cdb[5] = (UINT8) StartLba;\r
- Cdb[7] = (UINT8) (SectorSize >> 8);\r
- Cdb[8] = (UINT8) SectorSize;\r
+ CommandPacket->CdbLength = EFI_SCSI_OP_LENGTH_TEN;\r
+ CommandPacket->DataDirection = EFI_SCSI_DATA_OUT;\r
+ CommandPacket->SenseDataLength = *SenseDataLength;\r
\r
- CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;\r
- CommandPacket.DataDirection = EFI_SCSI_DATA_OUT;\r
- CommandPacket.SenseDataLength = *SenseDataLength;\r
+ //\r
+ // Create Event\r
+ //\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
+ ScsiLibNotify,\r
+ Context,\r
+ &SelfEvent\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ErrorExit;\r
+ }\r
+\r
+ Status = ScsiIo->ExecuteScsiCommand (ScsiIo, CommandPacket, SelfEvent);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Since ScsiLibNotify() will not be signaled if ExecuteScsiCommand()\r
+ // returns with error, close the event here.\r
+ //\r
+ gBS->CloseEvent (SelfEvent);\r
+ goto ErrorExit;\r
+ } else {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ErrorExit:\r
+ if (Context != NULL) {\r
+ FreePool (Context);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Execute blocking/non-blocking Read(16) SCSI command on a specific SCSI\r
+ target.\r
+\r
+ Executes the SCSI Read(16) command on the SCSI target specified by ScsiIo.\r
+ When Event is NULL, blocking command will be executed. Otherwise non-blocking\r
+ command will be executed.\r
+ For blocking I/O, if Timeout is zero, this function will wait indefinitely\r
+ for the command to complete. If Timeout is greater than zero, then the\r
+ command is executed and will timeout after Timeout 100 ns units.\r
+ For non-blocking I/O, if Timeout is zero, Event will be signaled only after\r
+ the command to completes. If Timeout is greater than zero, Event will also be\r
+ signaled after Timeout 100 ns units.\r
+ The StartLba and SectorSize parameters are used to construct the CDB for this\r
+ SCSI command.\r
+\r
+ If ScsiIo is NULL, then ASSERT().\r
+ If SenseDataLength is NULL, then ASSERT().\r
+ If HostAdapterStatus is NULL, then ASSERT().\r
+ If TargetStatus is NULL, then ASSERT().\r
+ If DataLength is NULL, then ASSERT().\r
+\r
+ If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet\r
+ buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise\r
+ EFI_INVALID_PARAMETER gets returned.\r
+\r
+ If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet\r
+ buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise\r
+ EFI_INVALID_PARAMETER gets returned.\r
+\r
+ @param[in] ScsiIo A pointer to SCSI IO protocol.\r
+ @param[in] Timeout The length of timeout period.\r
+ @param[in, out] SenseData A pointer to output sense data.\r
+ @param[in, out] SenseDataLength The length of output sense data.\r
+ @param[out] HostAdapterStatus The status of Host Adapter.\r
+ @param[out] TargetStatus The status of the target.\r
+ @param[in, out] DataBuffer Read 16 command data.\r
+ @param[in, out] DataLength The length of data buffer.\r
+ @param[in] StartLba The start address of LBA.\r
+ @param[in] SectorSize The number of contiguous logical blocks\r
+ of data that shall be transferred.\r
+ @param[in] Event If the SCSI target does not support\r
+ non-blocking I/O, then Event is ignored,\r
+ and blocking I/O is performed. If Event\r
+ is NULL, then blocking I/O is performed.\r
+ If Event is not NULL and non-blocking\r
+ I/O is supported, then non-blocking I/O\r
+ is performed, and Event will be signaled\r
+ when the SCSI Read(16) command\r
+ completes.\r
+\r
+ @retval EFI_SUCCESS Command is executed successfully.\r
+ @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,\r
+ but the entire DataBuffer could not be\r
+ transferred. The actual number of bytes\r
+ transferred is returned in DataLength.\r
+ @retval EFI_NOT_READY The SCSI Request Packet could not be\r
+ sent because there are too many SCSI\r
+ Command Packets already queued.\r
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting\r
+ to send SCSI Request Packet.\r
+ @retval EFI_UNSUPPORTED The command described by the SCSI\r
+ Request Packet is not supported by the\r
+ SCSI initiator(i.e., SCSI Host\r
+ Controller)\r
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the\r
+ SCSI Request Packet to execute.\r
+ @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet\r
+ are invalid.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due\r
+ to a lack of resources.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ScsiRead16CommandEx (\r
+ IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
+ IN UINT64 Timeout,\r
+ IN OUT VOID *SenseData OPTIONAL,\r
+ IN OUT UINT8 *SenseDataLength,\r
+ OUT UINT8 *HostAdapterStatus,\r
+ OUT UINT8 *TargetStatus,\r
+ IN OUT VOID *DataBuffer OPTIONAL,\r
+ IN OUT UINT32 *DataLength,\r
+ IN UINT64 StartLba,\r
+ IN UINT32 SectorSize,\r
+ IN EFI_EVENT Event OPTIONAL\r
+ )\r
+{\r
+ EFI_SCSI_LIB_ASYNC_CONTEXT *Context;\r
+ EFI_SCSI_IO_SCSI_REQUEST_PACKET *CommandPacket;\r
+ EFI_STATUS Status;\r
+ UINT8 *Cdb;\r
+ EFI_EVENT SelfEvent;\r
+\r
+ if (Event == NULL) {\r
+ return ScsiRead16Command (\r
+ ScsiIo,\r
+ Timeout,\r
+ SenseData,\r
+ SenseDataLength,\r
+ HostAdapterStatus,\r
+ TargetStatus,\r
+ DataBuffer,\r
+ DataLength,\r
+ StartLba,\r
+ SectorSize\r
+ );\r
+ }\r
+\r
+ ASSERT (SenseDataLength != NULL);\r
+ ASSERT (HostAdapterStatus != NULL);\r
+ ASSERT (TargetStatus != NULL);\r
+ ASSERT (DataLength != NULL);\r
+ ASSERT (ScsiIo != NULL);\r
+\r
+ Context = AllocateZeroPool (sizeof (EFI_SCSI_LIB_ASYNC_CONTEXT));\r
+ if (Context == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Cdb = AllocateZeroPool (EFI_SCSI_OP_LENGTH_SIXTEEN);\r
+ if (Cdb == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ErrorExit;\r
+ }\r
+\r
+ Context->SenseDataLength = SenseDataLength;\r
+ Context->HostAdapterStatus = HostAdapterStatus;\r
+ Context->TargetStatus = TargetStatus;\r
+ Context->CallerEvent = Event;\r
+\r
+ CommandPacket = &Context->CommandPacket;\r
+ CommandPacket->Timeout = Timeout;\r
+ CommandPacket->InDataBuffer = DataBuffer;\r
+ CommandPacket->SenseData = SenseData;\r
+ CommandPacket->InTransferLength = *DataLength;\r
+ CommandPacket->Cdb = Cdb;\r
+ //\r
+ // Fill Cdb for Read (16) Command\r
+ //\r
+ Cdb[0] = EFI_SCSI_OP_READ16;\r
+ WriteUnaligned64 ((UINT64 *)&Cdb[2], SwapBytes64 (StartLba));\r
+ WriteUnaligned32 ((UINT32 *)&Cdb[10], SwapBytes32 (SectorSize));\r
+\r
+ CommandPacket->CdbLength = EFI_SCSI_OP_LENGTH_SIXTEEN;\r
+ CommandPacket->DataDirection = EFI_SCSI_DATA_IN;\r
+ CommandPacket->SenseDataLength = *SenseDataLength;\r
+\r
+ //\r
+ // Create Event\r
+ //\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
+ ScsiLibNotify,\r
+ Context,\r
+ &SelfEvent\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ErrorExit;\r
+ }\r
\r
- Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
+ Status = ScsiIo->ExecuteScsiCommand (ScsiIo, CommandPacket, SelfEvent);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Since ScsiLibNotify() will not be signaled if ExecuteScsiCommand()\r
+ // returns with error, close the event here.\r
+ //\r
+ gBS->CloseEvent (SelfEvent);\r
+ goto ErrorExit;\r
+ } else {\r
+ return EFI_SUCCESS;\r
+ }\r
\r
- *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
- *TargetStatus = CommandPacket.TargetStatus;\r
- *SenseDataLength = CommandPacket.SenseDataLength;\r
- *DataLength = CommandPacket.OutTransferLength;\r
+ErrorExit:\r
+ if (Context != NULL) {\r
+ FreePool (Context);\r
+ }\r
\r
return Status;\r
}\r
\r
+/**\r
+ Execute blocking/non-blocking Write(16) SCSI command on a specific SCSI\r
+ target.\r
+\r
+ Executes the SCSI Write(16) command on the SCSI target specified by ScsiIo.\r
+ When Event is NULL, blocking command will be executed. Otherwise non-blocking\r
+ command will be executed.\r
+ For blocking I/O, if Timeout is zero, this function will wait indefinitely\r
+ for the command to complete. If Timeout is greater than zero, then the\r
+ command is executed and will timeout after Timeout 100 ns units.\r
+ For non-blocking I/O, if Timeout is zero, Event will be signaled only after\r
+ the command to completes. If Timeout is greater than zero, Event will also be\r
+ signaled after Timeout 100 ns units.\r
+ The StartLba and SectorSize parameters are used to construct the CDB for this\r
+ SCSI command.\r
+\r
+ If ScsiIo is NULL, then ASSERT().\r
+ If SenseDataLength is NULL, then ASSERT().\r
+ If HostAdapterStatus is NULL, then ASSERT().\r
+ If TargetStatus is NULL, then ASSERT().\r
+ If DataLength is NULL, then ASSERT().\r
+\r
+ If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet\r
+ buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise\r
+ EFI_INVALID_PARAMETER gets returned.\r
+\r
+ If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet\r
+ buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise\r
+ EFI_INVALID_PARAMETER gets returned.\r
+\r
+ @param[in] ScsiIo SCSI IO Protocol to use\r
+ @param[in] Timeout The length of timeout period.\r
+ @param[in, out] SenseData A pointer to output sense data.\r
+ @param[in, out] SenseDataLength The length of output sense data.\r
+ @param[out] HostAdapterStatus The status of Host Adapter.\r
+ @param[out] TargetStatus The status of the target.\r
+ @param[in, out] DataBuffer A pointer to a data buffer.\r
+ @param[in, out] DataLength The length of data buffer.\r
+ @param[in] StartLba The start address of LBA.\r
+ @param[in] SectorSize The number of contiguous logical blocks\r
+ of data that shall be transferred.\r
+ @param[in] Event If the SCSI target does not support\r
+ non-blocking I/O, then Event is ignored,\r
+ and blocking I/O is performed. If Event\r
+ is NULL, then blocking I/O is performed.\r
+ If Event is not NULL and non-blocking\r
+ I/O is supported, then non-blocking I/O\r
+ is performed, and Event will be signaled\r
+ when the SCSI Write(16) command\r
+ completes.\r
+\r
+ @retval EFI_SUCCESS Command is executed successfully.\r
+ @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,\r
+ but the entire DataBuffer could not be\r
+ transferred. The actual number of bytes\r
+ transferred is returned in DataLength.\r
+ @retval EFI_NOT_READY The SCSI Request Packet could not be\r
+ sent because there are too many SCSI\r
+ Command Packets already queued.\r
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting\r
+ to send SCSI Request Packet.\r
+ @retval EFI_UNSUPPORTED The command described by the SCSI\r
+ Request Packet is not supported by the\r
+ SCSI initiator(i.e., SCSI Host\r
+ Controller)\r
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the\r
+ SCSI Request Packet to execute.\r
+ @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet\r
+ are invalid.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due\r
+ to a lack of resources.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ScsiWrite16CommandEx (\r
+ IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
+ IN UINT64 Timeout,\r
+ IN OUT VOID *SenseData OPTIONAL,\r
+ IN OUT UINT8 *SenseDataLength,\r
+ OUT UINT8 *HostAdapterStatus,\r
+ OUT UINT8 *TargetStatus,\r
+ IN OUT VOID *DataBuffer OPTIONAL,\r
+ IN OUT UINT32 *DataLength,\r
+ IN UINT64 StartLba,\r
+ IN UINT32 SectorSize,\r
+ IN EFI_EVENT Event OPTIONAL\r
+ )\r
+{\r
+ EFI_SCSI_LIB_ASYNC_CONTEXT *Context;\r
+ EFI_SCSI_IO_SCSI_REQUEST_PACKET *CommandPacket;\r
+ EFI_STATUS Status;\r
+ UINT8 *Cdb;\r
+ EFI_EVENT SelfEvent;\r
+\r
+ if (Event == NULL) {\r
+ return ScsiWrite16Command (\r
+ ScsiIo,\r
+ Timeout,\r
+ SenseData,\r
+ SenseDataLength,\r
+ HostAdapterStatus,\r
+ TargetStatus,\r
+ DataBuffer,\r
+ DataLength,\r
+ StartLba,\r
+ SectorSize\r
+ );\r
+ }\r
+\r
+ ASSERT (SenseDataLength != NULL);\r
+ ASSERT (HostAdapterStatus != NULL);\r
+ ASSERT (TargetStatus != NULL);\r
+ ASSERT (DataLength != NULL);\r
+ ASSERT (ScsiIo != NULL);\r
+\r
+ Context = AllocateZeroPool (sizeof (EFI_SCSI_LIB_ASYNC_CONTEXT));\r
+ if (Context == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Cdb = AllocateZeroPool (EFI_SCSI_OP_LENGTH_SIXTEEN);\r
+ if (Cdb == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ErrorExit;\r
+ }\r
+\r
+ Context->SenseDataLength = SenseDataLength;\r
+ Context->HostAdapterStatus = HostAdapterStatus;\r
+ Context->TargetStatus = TargetStatus;\r
+ Context->CallerEvent = Event;\r
+\r
+ CommandPacket = &Context->CommandPacket;\r
+ CommandPacket->Timeout = Timeout;\r
+ CommandPacket->OutDataBuffer = DataBuffer;\r
+ CommandPacket->SenseData = SenseData;\r
+ CommandPacket->OutTransferLength = *DataLength;\r
+ CommandPacket->Cdb = Cdb;\r
+ //\r
+ // Fill Cdb for Write (16) Command\r
+ //\r
+ Cdb[0] = EFI_SCSI_OP_WRITE16;\r
+ WriteUnaligned64 ((UINT64 *)&Cdb[2], SwapBytes64 (StartLba));\r
+ WriteUnaligned32 ((UINT32 *)&Cdb[10], SwapBytes32 (SectorSize));\r
+\r
+ CommandPacket->CdbLength = EFI_SCSI_OP_LENGTH_SIXTEEN;\r
+ CommandPacket->DataDirection = EFI_SCSI_DATA_OUT;\r
+ CommandPacket->SenseDataLength = *SenseDataLength;\r
+\r
+ //\r
+ // Create Event\r
+ //\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
+ ScsiLibNotify,\r
+ Context,\r
+ &SelfEvent\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ErrorExit;\r
+ }\r
+\r
+ Status = ScsiIo->ExecuteScsiCommand (ScsiIo, CommandPacket, SelfEvent);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Since ScsiLibNotify() will not be signaled if ExecuteScsiCommand()\r
+ // returns with error, close the event here.\r
+ //\r
+ gBS->CloseEvent (SelfEvent);\r
+ goto ErrorExit;\r
+ } else {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ErrorExit:\r
+ if (Context != NULL) {\r
+ FreePool (Context);\r
+ }\r
+\r
+ return Status;\r
+}\r