]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdePkg UefiScsiLib: Add non-blocking support for SCSI Read/Write command
authorHao Wu <hao.a.wu@intel.com>
Fri, 11 Dec 2015 01:57:41 +0000 (01:57 +0000)
committerhwu1225 <hwu1225@Edk2>
Fri, 11 Dec 2015 01:57:41 +0000 (01:57 +0000)
Four new functions are added to UefiScsiLib:
ScsiRead10CommandEx
ScsiWrite10CommandEx
ScsiRead16CommandEx
ScsiWrite16CommandEx

They support both blocking and non-blocking SCSI Read/Write operation
depending on the optional parameter 'Event' passed to those APIs.

When 'Event' is NULL, these four functions will call the non-EX version
couterparts to execute blocking SCSI I/O. When 'Event' is not NULL,
non-blocking I/O operation is executed.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Hao Wu <hao.a.wu@intel.com>
Reviewed-by: Feng Tian <feng.tian@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@19214 6f19259b-4bc3-4df7-8a09-765794883524

MdePkg/Include/Library/UefiScsiLib.h
MdePkg/Library/UefiScsiLib/UefiScsiLib.c
MdePkg/Library/UefiScsiLib/UefiScsiLib.inf

index 26e4aa4e0f02b158aacb585b9cbd65dcb59da097..067acfdb43478898dbd1c6c833093157c2c7dc7e 100644 (file)
@@ -818,4 +818,364 @@ ScsiWrite16Command (
   IN     UINT32                SectorSize\r
   );\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
+  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(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
+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
+\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
+\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
+\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
 #endif\r
index 89f261777bb62627a592860a08d5aca40cdab7df..d8babcee406a6232a3ee6e10c3119c51d047591d 100644 (file)
@@ -18,6 +18,8 @@
 #include <Library/DebugLib.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
 #define EFI_SCSI_OP_LENGTH_TEN      0xa\r
 #define EFI_SCSI_OP_LENGTH_SIXTEEN  0x10\r
 \r
+//\r
+// The context structure used when non-blocking SCSI read/write operation\r
+// completes.\r
+//\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
 \r
 /**\r
@@ -1249,3 +1284,744 @@ ScsiWrite16Command (
 \r
   return Status;\r
 }\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
+  FreePool (Context);\r
+\r
+  gBS->CloseEvent (Event);\r
+  gBS->SignalEvent (CallerEvent);\r
+}\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
+  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(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
+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_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
+  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_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_CALLBACK,\r
+                  ScsiLibNotify,\r
+                  Context,\r
+                  &SelfEvent\r
+                  );\r
+  if (EFI_ERROR(Status)) {\r
+    goto ErrorExit;\r
+  }\r
+\r
+  return ScsiIo->ExecuteScsiCommand (ScsiIo, CommandPacket, SelfEvent);\r
+\r
+ErrorExit:\r
+  if (Context != NULL) {\r
+    FreePool (Context);\r
+  }\r
+\r
+  return Status;\r
+}\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
+  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
+  Cdb[0]                           = EFI_SCSI_OP_WRITE10;\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
+  //\r
+  // Create Event\r
+  //\r
+  Status = gBS->CreateEvent (\r
+                  EVT_NOTIFY_SIGNAL,\r
+                  TPL_CALLBACK,\r
+                  ScsiLibNotify,\r
+                  Context,\r
+                  &SelfEvent\r
+                  );\r
+  if (EFI_ERROR(Status)) {\r
+    goto ErrorExit;\r
+  }\r
+\r
+  return ScsiIo->ExecuteScsiCommand (ScsiIo, CommandPacket, Event);\r
+\r
+ErrorExit:\r
+  if (Context != NULL) {\r
+    FreePool (Context);\r
+  }\r
+\r
+  return Status;\r
+}\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_CALLBACK,\r
+                  ScsiLibNotify,\r
+                  Context,\r
+                  &SelfEvent\r
+                  );\r
+  if (EFI_ERROR(Status)) {\r
+    goto ErrorExit;\r
+  }\r
+\r
+  return ScsiIo->ExecuteScsiCommand (ScsiIo, CommandPacket, Event);\r
+\r
+ErrorExit:\r
+  if (Context != NULL) {\r
+    FreePool (Context);\r
+  }\r
+\r
+  return Status;\r
+}\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_CALLBACK,\r
+                  ScsiLibNotify,\r
+                  Context,\r
+                  &SelfEvent\r
+                  );\r
+  if (EFI_ERROR(Status)) {\r
+    goto ErrorExit;\r
+  }\r
+\r
+  return ScsiIo->ExecuteScsiCommand (ScsiIo, CommandPacket, Event);\r
+\r
+ErrorExit:\r
+  if (Context != NULL) {\r
+    FreePool (Context);\r
+  }\r
+\r
+  return Status;\r
+}\r
index 1eb90765af42f3f445508e6f2f36f10bd05860ff..cd0c5c1ec80333c3ee5cbb5f730421d91a58be08 100644 (file)
@@ -4,7 +4,7 @@
 # This libarary provides the functions to submit Scsi commands defined\r
 # in SCSI-2 specification for scsi device.\r
 #\r
-# Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>\r
 #\r
 #  This program and the accompanying materials\r
 #  are licensed and made available under the terms and conditions of the BSD License\r
@@ -42,4 +42,6 @@
   BaseMemoryLib\r
   DebugLib\r
   BaseLib\r
+  MemoryAllocationLib\r
+  UefiBootServicesTableLib\r
 \r