mirror of https://github.com/acidanthera/audk.git
MdePkg UefiScsiLib: Add non-blocking support for SCSI Read/Write command
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
This commit is contained in:
parent
4960d8e004
commit
9c58193927
|
@ -818,4 +818,364 @@ ScsiWrite16Command (
|
||||||
IN UINT32 SectorSize
|
IN UINT32 SectorSize
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Execute blocking/non-blocking Read(10) SCSI command on a specific SCSI
|
||||||
|
target.
|
||||||
|
|
||||||
|
Executes the SCSI Read(10) command on the SCSI target specified by ScsiIo.
|
||||||
|
When Event is NULL, blocking command will be executed. Otherwise non-blocking
|
||||||
|
command will be executed.
|
||||||
|
For blocking I/O, if Timeout is zero, this function will wait indefinitely
|
||||||
|
for the command to complete. If Timeout is greater than zero, then the
|
||||||
|
command is executed and will timeout after Timeout 100 ns units.
|
||||||
|
For non-blocking I/O, if Timeout is zero, Event will be signaled only after
|
||||||
|
the command to completes. If Timeout is greater than zero, Event will also be
|
||||||
|
signaled after Timeout 100 ns units.
|
||||||
|
The StartLba and SectorSize parameters are used to construct the CDB for this
|
||||||
|
SCSI command.
|
||||||
|
|
||||||
|
If ScsiIo is NULL, then ASSERT().
|
||||||
|
If SenseDataLength is NULL, then ASSERT().
|
||||||
|
If HostAdapterStatus is NULL, then ASSERT().
|
||||||
|
If TargetStatus is NULL, then ASSERT().
|
||||||
|
If DataLength is NULL, then ASSERT().
|
||||||
|
|
||||||
|
If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet
|
||||||
|
buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
|
||||||
|
EFI_INVALID_PARAMETER gets returned.
|
||||||
|
|
||||||
|
If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet
|
||||||
|
buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
|
||||||
|
EFI_INVALID_PARAMETER gets returned.
|
||||||
|
|
||||||
|
@param[in] ScsiIo A pointer to SCSI IO protocol.
|
||||||
|
@param[in] Timeout The length of timeout period.
|
||||||
|
@param[in, out] SenseData A pointer to output sense data.
|
||||||
|
@param[in, out] SenseDataLength The length of output sense data.
|
||||||
|
@param[out] HostAdapterStatus The status of Host Adapter.
|
||||||
|
@param[out] TargetStatus The status of the target.
|
||||||
|
@param[in, out] DataBuffer Read 16 command data.
|
||||||
|
@param[in, out] DataLength The length of data buffer.
|
||||||
|
@param[in] StartLba The start address of LBA.
|
||||||
|
@param[in] SectorSize The number of contiguous logical blocks
|
||||||
|
of data that shall be transferred.
|
||||||
|
@param[in] Event If the SCSI target does not support
|
||||||
|
non-blocking I/O, then Event is ignored,
|
||||||
|
and blocking I/O is performed. If Event
|
||||||
|
is NULL, then blocking I/O is performed.
|
||||||
|
If Event is not NULL and non-blocking
|
||||||
|
I/O is supported, then non-blocking I/O
|
||||||
|
is performed, and Event will be signaled
|
||||||
|
when the SCSI Read(10) command
|
||||||
|
completes.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Command is executed successfully.
|
||||||
|
@retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
|
||||||
|
but the entire DataBuffer could not be
|
||||||
|
transferred. The actual number of bytes
|
||||||
|
transferred is returned in DataLength.
|
||||||
|
@retval EFI_NOT_READY The SCSI Request Packet could not be
|
||||||
|
sent because there are too many SCSI
|
||||||
|
Command Packets already queued.
|
||||||
|
@retval EFI_DEVICE_ERROR A device error occurred while attempting
|
||||||
|
to send SCSI Request Packet.
|
||||||
|
@retval EFI_UNSUPPORTED The command described by the SCSI
|
||||||
|
Request Packet is not supported by the
|
||||||
|
SCSI initiator(i.e., SCSI Host
|
||||||
|
Controller)
|
||||||
|
@retval EFI_TIMEOUT A timeout occurred while waiting for the
|
||||||
|
SCSI Request Packet to execute.
|
||||||
|
@retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet
|
||||||
|
are invalid.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES The request could not be completed due
|
||||||
|
to a lack of resources.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
ScsiRead10CommandEx (
|
||||||
|
IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
|
||||||
|
IN UINT64 Timeout,
|
||||||
|
IN OUT VOID *SenseData, OPTIONAL
|
||||||
|
IN OUT UINT8 *SenseDataLength,
|
||||||
|
OUT UINT8 *HostAdapterStatus,
|
||||||
|
OUT UINT8 *TargetStatus,
|
||||||
|
IN OUT VOID *DataBuffer, OPTIONAL
|
||||||
|
IN OUT UINT32 *DataLength,
|
||||||
|
IN UINT32 StartLba,
|
||||||
|
IN UINT32 SectorSize,
|
||||||
|
IN EFI_EVENT Event OPTIONAL
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Execute blocking/non-blocking Write(10) SCSI command on a specific SCSI
|
||||||
|
target.
|
||||||
|
|
||||||
|
Executes the SCSI Write(10) command on the SCSI target specified by ScsiIo.
|
||||||
|
When Event is NULL, blocking command will be executed. Otherwise non-blocking
|
||||||
|
command will be executed.
|
||||||
|
For blocking I/O, if Timeout is zero, this function will wait indefinitely
|
||||||
|
for the command to complete. If Timeout is greater than zero, then the
|
||||||
|
command is executed and will timeout after Timeout 100 ns units.
|
||||||
|
For non-blocking I/O, if Timeout is zero, Event will be signaled only after
|
||||||
|
the command to completes. If Timeout is greater than zero, Event will also be
|
||||||
|
signaled after Timeout 100 ns units.
|
||||||
|
The StartLba and SectorSize parameters are used to construct the CDB for this
|
||||||
|
SCSI command.
|
||||||
|
|
||||||
|
If ScsiIo is NULL, then ASSERT().
|
||||||
|
If SenseDataLength is NULL, then ASSERT().
|
||||||
|
If HostAdapterStatus is NULL, then ASSERT().
|
||||||
|
If TargetStatus is NULL, then ASSERT().
|
||||||
|
If DataLength is NULL, then ASSERT().
|
||||||
|
|
||||||
|
If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet
|
||||||
|
buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
|
||||||
|
EFI_INVALID_PARAMETER gets returned.
|
||||||
|
|
||||||
|
If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet
|
||||||
|
buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
|
||||||
|
EFI_INVALID_PARAMETER gets returned.
|
||||||
|
|
||||||
|
@param[in] ScsiIo SCSI IO Protocol to use
|
||||||
|
@param[in] Timeout The length of timeout period.
|
||||||
|
@param[in, out] SenseData A pointer to output sense data.
|
||||||
|
@param[in, out] SenseDataLength The length of output sense data.
|
||||||
|
@param[out] HostAdapterStatus The status of Host Adapter.
|
||||||
|
@param[out] TargetStatus The status of the target.
|
||||||
|
@param[in, out] DataBuffer A pointer to a data buffer.
|
||||||
|
@param[in, out] DataLength The length of data buffer.
|
||||||
|
@param[in] StartLba The start address of LBA.
|
||||||
|
@param[in] SectorSize The number of contiguous logical blocks
|
||||||
|
of data that shall be transferred.
|
||||||
|
@param[in] Event If the SCSI target does not support
|
||||||
|
non-blocking I/O, then Event is ignored,
|
||||||
|
and blocking I/O is performed. If Event
|
||||||
|
is NULL, then blocking I/O is performed.
|
||||||
|
If Event is not NULL and non-blocking
|
||||||
|
I/O is supported, then non-blocking I/O
|
||||||
|
is performed, and Event will be signaled
|
||||||
|
when the SCSI Write(10) command
|
||||||
|
completes.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Command is executed successfully.
|
||||||
|
@retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
|
||||||
|
but the entire DataBuffer could not be
|
||||||
|
transferred. The actual number of bytes
|
||||||
|
transferred is returned in DataLength.
|
||||||
|
@retval EFI_NOT_READY The SCSI Request Packet could not be
|
||||||
|
sent because there are too many SCSI
|
||||||
|
Command Packets already queued.
|
||||||
|
@retval EFI_DEVICE_ERROR A device error occurred while attempting
|
||||||
|
to send SCSI Request Packet.
|
||||||
|
@retval EFI_UNSUPPORTED The command described by the SCSI
|
||||||
|
Request Packet is not supported by the
|
||||||
|
SCSI initiator(i.e., SCSI Host
|
||||||
|
Controller)
|
||||||
|
@retval EFI_TIMEOUT A timeout occurred while waiting for the
|
||||||
|
SCSI Request Packet to execute.
|
||||||
|
@retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet
|
||||||
|
are invalid.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES The request could not be completed due
|
||||||
|
to a lack of resources.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
ScsiWrite10CommandEx (
|
||||||
|
IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
|
||||||
|
IN UINT64 Timeout,
|
||||||
|
IN OUT VOID *SenseData, OPTIONAL
|
||||||
|
IN OUT UINT8 *SenseDataLength,
|
||||||
|
OUT UINT8 *HostAdapterStatus,
|
||||||
|
OUT UINT8 *TargetStatus,
|
||||||
|
IN OUT VOID *DataBuffer, OPTIONAL
|
||||||
|
IN OUT UINT32 *DataLength,
|
||||||
|
IN UINT32 StartLba,
|
||||||
|
IN UINT32 SectorSize,
|
||||||
|
IN EFI_EVENT Event OPTIONAL
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Execute blocking/non-blocking Read(16) SCSI command on a specific SCSI
|
||||||
|
target.
|
||||||
|
|
||||||
|
Executes the SCSI Read(16) command on the SCSI target specified by ScsiIo.
|
||||||
|
When Event is NULL, blocking command will be executed. Otherwise non-blocking
|
||||||
|
command will be executed.
|
||||||
|
For blocking I/O, if Timeout is zero, this function will wait indefinitely
|
||||||
|
for the command to complete. If Timeout is greater than zero, then the
|
||||||
|
command is executed and will timeout after Timeout 100 ns units.
|
||||||
|
For non-blocking I/O, if Timeout is zero, Event will be signaled only after
|
||||||
|
the command to completes. If Timeout is greater than zero, Event will also be
|
||||||
|
signaled after Timeout 100 ns units.
|
||||||
|
The StartLba and SectorSize parameters are used to construct the CDB for this
|
||||||
|
SCSI command.
|
||||||
|
|
||||||
|
If ScsiIo is NULL, then ASSERT().
|
||||||
|
If SenseDataLength is NULL, then ASSERT().
|
||||||
|
If HostAdapterStatus is NULL, then ASSERT().
|
||||||
|
If TargetStatus is NULL, then ASSERT().
|
||||||
|
If DataLength is NULL, then ASSERT().
|
||||||
|
|
||||||
|
If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet
|
||||||
|
buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
|
||||||
|
EFI_INVALID_PARAMETER gets returned.
|
||||||
|
|
||||||
|
If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet
|
||||||
|
buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
|
||||||
|
EFI_INVALID_PARAMETER gets returned.
|
||||||
|
|
||||||
|
@param[in] ScsiIo A pointer to SCSI IO protocol.
|
||||||
|
@param[in] Timeout The length of timeout period.
|
||||||
|
@param[in, out] SenseData A pointer to output sense data.
|
||||||
|
@param[in, out] SenseDataLength The length of output sense data.
|
||||||
|
@param[out] HostAdapterStatus The status of Host Adapter.
|
||||||
|
@param[out] TargetStatus The status of the target.
|
||||||
|
@param[in, out] DataBuffer Read 16 command data.
|
||||||
|
@param[in, out] DataLength The length of data buffer.
|
||||||
|
@param[in] StartLba The start address of LBA.
|
||||||
|
@param[in] SectorSize The number of contiguous logical blocks
|
||||||
|
of data that shall be transferred.
|
||||||
|
@param[in] Event If the SCSI target does not support
|
||||||
|
non-blocking I/O, then Event is ignored,
|
||||||
|
and blocking I/O is performed. If Event
|
||||||
|
is NULL, then blocking I/O is performed.
|
||||||
|
If Event is not NULL and non-blocking
|
||||||
|
I/O is supported, then non-blocking I/O
|
||||||
|
is performed, and Event will be signaled
|
||||||
|
when the SCSI Read(16) command
|
||||||
|
completes.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Command is executed successfully.
|
||||||
|
@retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
|
||||||
|
but the entire DataBuffer could not be
|
||||||
|
transferred. The actual number of bytes
|
||||||
|
transferred is returned in DataLength.
|
||||||
|
@retval EFI_NOT_READY The SCSI Request Packet could not be
|
||||||
|
sent because there are too many SCSI
|
||||||
|
Command Packets already queued.
|
||||||
|
@retval EFI_DEVICE_ERROR A device error occurred while attempting
|
||||||
|
to send SCSI Request Packet.
|
||||||
|
@retval EFI_UNSUPPORTED The command described by the SCSI
|
||||||
|
Request Packet is not supported by the
|
||||||
|
SCSI initiator(i.e., SCSI Host
|
||||||
|
Controller)
|
||||||
|
@retval EFI_TIMEOUT A timeout occurred while waiting for the
|
||||||
|
SCSI Request Packet to execute.
|
||||||
|
@retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet
|
||||||
|
are invalid.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES The request could not be completed due
|
||||||
|
to a lack of resources.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
ScsiRead16CommandEx (
|
||||||
|
IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
|
||||||
|
IN UINT64 Timeout,
|
||||||
|
IN OUT VOID *SenseData, OPTIONAL
|
||||||
|
IN OUT UINT8 *SenseDataLength,
|
||||||
|
OUT UINT8 *HostAdapterStatus,
|
||||||
|
OUT UINT8 *TargetStatus,
|
||||||
|
IN OUT VOID *DataBuffer, OPTIONAL
|
||||||
|
IN OUT UINT32 *DataLength,
|
||||||
|
IN UINT64 StartLba,
|
||||||
|
IN UINT32 SectorSize,
|
||||||
|
IN EFI_EVENT Event OPTIONAL
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Execute blocking/non-blocking Write(16) SCSI command on a specific SCSI
|
||||||
|
target.
|
||||||
|
|
||||||
|
Executes the SCSI Write(16) command on the SCSI target specified by ScsiIo.
|
||||||
|
When Event is NULL, blocking command will be executed. Otherwise non-blocking
|
||||||
|
command will be executed.
|
||||||
|
For blocking I/O, if Timeout is zero, this function will wait indefinitely
|
||||||
|
for the command to complete. If Timeout is greater than zero, then the
|
||||||
|
command is executed and will timeout after Timeout 100 ns units.
|
||||||
|
For non-blocking I/O, if Timeout is zero, Event will be signaled only after
|
||||||
|
the command to completes. If Timeout is greater than zero, Event will also be
|
||||||
|
signaled after Timeout 100 ns units.
|
||||||
|
The StartLba and SectorSize parameters are used to construct the CDB for this
|
||||||
|
SCSI command.
|
||||||
|
|
||||||
|
If ScsiIo is NULL, then ASSERT().
|
||||||
|
If SenseDataLength is NULL, then ASSERT().
|
||||||
|
If HostAdapterStatus is NULL, then ASSERT().
|
||||||
|
If TargetStatus is NULL, then ASSERT().
|
||||||
|
If DataLength is NULL, then ASSERT().
|
||||||
|
|
||||||
|
If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet
|
||||||
|
buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
|
||||||
|
EFI_INVALID_PARAMETER gets returned.
|
||||||
|
|
||||||
|
If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet
|
||||||
|
buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
|
||||||
|
EFI_INVALID_PARAMETER gets returned.
|
||||||
|
|
||||||
|
@param[in] ScsiIo SCSI IO Protocol to use
|
||||||
|
@param[in] Timeout The length of timeout period.
|
||||||
|
@param[in, out] SenseData A pointer to output sense data.
|
||||||
|
@param[in, out] SenseDataLength The length of output sense data.
|
||||||
|
@param[out] HostAdapterStatus The status of Host Adapter.
|
||||||
|
@param[out] TargetStatus The status of the target.
|
||||||
|
@param[in, out] DataBuffer A pointer to a data buffer.
|
||||||
|
@param[in, out] DataLength The length of data buffer.
|
||||||
|
@param[in] StartLba The start address of LBA.
|
||||||
|
@param[in] SectorSize The number of contiguous logical blocks
|
||||||
|
of data that shall be transferred.
|
||||||
|
@param[in] Event If the SCSI target does not support
|
||||||
|
non-blocking I/O, then Event is ignored,
|
||||||
|
and blocking I/O is performed. If Event
|
||||||
|
is NULL, then blocking I/O is performed.
|
||||||
|
If Event is not NULL and non-blocking
|
||||||
|
I/O is supported, then non-blocking I/O
|
||||||
|
is performed, and Event will be signaled
|
||||||
|
when the SCSI Write(16) command
|
||||||
|
completes.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Command is executed successfully.
|
||||||
|
@retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
|
||||||
|
but the entire DataBuffer could not be
|
||||||
|
transferred. The actual number of bytes
|
||||||
|
transferred is returned in DataLength.
|
||||||
|
@retval EFI_NOT_READY The SCSI Request Packet could not be
|
||||||
|
sent because there are too many SCSI
|
||||||
|
Command Packets already queued.
|
||||||
|
@retval EFI_DEVICE_ERROR A device error occurred while attempting
|
||||||
|
to send SCSI Request Packet.
|
||||||
|
@retval EFI_UNSUPPORTED The command described by the SCSI
|
||||||
|
Request Packet is not supported by the
|
||||||
|
SCSI initiator(i.e., SCSI Host
|
||||||
|
Controller)
|
||||||
|
@retval EFI_TIMEOUT A timeout occurred while waiting for the
|
||||||
|
SCSI Request Packet to execute.
|
||||||
|
@retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet
|
||||||
|
are invalid.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES The request could not be completed due
|
||||||
|
to a lack of resources.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
ScsiWrite16CommandEx (
|
||||||
|
IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
|
||||||
|
IN UINT64 Timeout,
|
||||||
|
IN OUT VOID *SenseData, OPTIONAL
|
||||||
|
IN OUT UINT8 *SenseDataLength,
|
||||||
|
OUT UINT8 *HostAdapterStatus,
|
||||||
|
OUT UINT8 *TargetStatus,
|
||||||
|
IN OUT VOID *DataBuffer, OPTIONAL
|
||||||
|
IN OUT UINT32 *DataLength,
|
||||||
|
IN UINT64 StartLba,
|
||||||
|
IN UINT32 SectorSize,
|
||||||
|
IN EFI_EVENT Event OPTIONAL
|
||||||
|
);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
#include <Library/DebugLib.h>
|
#include <Library/DebugLib.h>
|
||||||
#include <Library/UefiScsiLib.h>
|
#include <Library/UefiScsiLib.h>
|
||||||
#include <Library/BaseMemoryLib.h>
|
#include <Library/BaseMemoryLib.h>
|
||||||
|
#include <Library/MemoryAllocationLib.h>
|
||||||
|
#include <Library/UefiBootServicesTableLib.h>
|
||||||
|
|
||||||
#include <IndustryStandard/Scsi.h>
|
#include <IndustryStandard/Scsi.h>
|
||||||
|
|
||||||
|
@ -29,6 +31,39 @@
|
||||||
#define EFI_SCSI_OP_LENGTH_TEN 0xa
|
#define EFI_SCSI_OP_LENGTH_TEN 0xa
|
||||||
#define EFI_SCSI_OP_LENGTH_SIXTEEN 0x10
|
#define EFI_SCSI_OP_LENGTH_SIXTEEN 0x10
|
||||||
|
|
||||||
|
//
|
||||||
|
// The context structure used when non-blocking SCSI read/write operation
|
||||||
|
// completes.
|
||||||
|
//
|
||||||
|
typedef struct {
|
||||||
|
///
|
||||||
|
/// The SCSI request packet to send to the SCSI controller specified by
|
||||||
|
/// the device handle.
|
||||||
|
///
|
||||||
|
EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;
|
||||||
|
///
|
||||||
|
/// The length of the output sense data.
|
||||||
|
///
|
||||||
|
UINT8 *SenseDataLength;
|
||||||
|
///
|
||||||
|
/// The status of the SCSI host adapter.
|
||||||
|
///
|
||||||
|
UINT8 *HostAdapterStatus;
|
||||||
|
///
|
||||||
|
/// The status of the target SCSI device.
|
||||||
|
///
|
||||||
|
UINT8 *TargetStatus;
|
||||||
|
///
|
||||||
|
/// The length of the data buffer for the SCSI read/write command.
|
||||||
|
///
|
||||||
|
UINT32 *DataLength;
|
||||||
|
///
|
||||||
|
/// The caller event to be signaled when the SCSI read/write command
|
||||||
|
/// completes.
|
||||||
|
///
|
||||||
|
EFI_EVENT CallerEvent;
|
||||||
|
} EFI_SCSI_LIB_ASYNC_CONTEXT;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1249,3 +1284,744 @@ ScsiWrite16Command (
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Internal helper notify function in which update the result of the
|
||||||
|
non-blocking SCSI Read/Write commands and signal caller event.
|
||||||
|
|
||||||
|
@param Event The instance of EFI_EVENT.
|
||||||
|
@param Context The parameter passed in.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
ScsiLibNotify (
|
||||||
|
IN EFI_EVENT Event,
|
||||||
|
IN VOID *Context
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_SCSI_LIB_ASYNC_CONTEXT *LibContext;
|
||||||
|
EFI_SCSI_IO_SCSI_REQUEST_PACKET *CommandPacket;
|
||||||
|
EFI_EVENT CallerEvent;
|
||||||
|
|
||||||
|
LibContext = (EFI_SCSI_LIB_ASYNC_CONTEXT *) Context;
|
||||||
|
CommandPacket = &LibContext->CommandPacket;
|
||||||
|
CallerEvent = LibContext->CallerEvent;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Update SCSI Read/Write operation results
|
||||||
|
//
|
||||||
|
*LibContext->SenseDataLength = CommandPacket->SenseDataLength;
|
||||||
|
*LibContext->HostAdapterStatus = CommandPacket->HostAdapterStatus;
|
||||||
|
*LibContext->TargetStatus = CommandPacket->TargetStatus;
|
||||||
|
if (CommandPacket->InDataBuffer != NULL) {
|
||||||
|
*LibContext->DataLength = CommandPacket->InTransferLength;
|
||||||
|
} else {
|
||||||
|
*LibContext->DataLength = CommandPacket->OutTransferLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CommandPacket->Cdb != NULL) {
|
||||||
|
FreePool (CommandPacket->Cdb);
|
||||||
|
}
|
||||||
|
FreePool (Context);
|
||||||
|
|
||||||
|
gBS->CloseEvent (Event);
|
||||||
|
gBS->SignalEvent (CallerEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Execute blocking/non-blocking Read(10) SCSI command on a specific SCSI
|
||||||
|
target.
|
||||||
|
|
||||||
|
Executes the SCSI Read(10) command on the SCSI target specified by ScsiIo.
|
||||||
|
When Event is NULL, blocking command will be executed. Otherwise non-blocking
|
||||||
|
command will be executed.
|
||||||
|
For blocking I/O, if Timeout is zero, this function will wait indefinitely
|
||||||
|
for the command to complete. If Timeout is greater than zero, then the
|
||||||
|
command is executed and will timeout after Timeout 100 ns units.
|
||||||
|
For non-blocking I/O, if Timeout is zero, Event will be signaled only after
|
||||||
|
the command to completes. If Timeout is greater than zero, Event will also be
|
||||||
|
signaled after Timeout 100 ns units.
|
||||||
|
The StartLba and SectorSize parameters are used to construct the CDB for this
|
||||||
|
SCSI command.
|
||||||
|
|
||||||
|
If ScsiIo is NULL, then ASSERT().
|
||||||
|
If SenseDataLength is NULL, then ASSERT().
|
||||||
|
If HostAdapterStatus is NULL, then ASSERT().
|
||||||
|
If TargetStatus is NULL, then ASSERT().
|
||||||
|
If DataLength is NULL, then ASSERT().
|
||||||
|
|
||||||
|
If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet
|
||||||
|
buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
|
||||||
|
EFI_INVALID_PARAMETER gets returned.
|
||||||
|
|
||||||
|
If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet
|
||||||
|
buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
|
||||||
|
EFI_INVALID_PARAMETER gets returned.
|
||||||
|
|
||||||
|
@param[in] ScsiIo A pointer to SCSI IO protocol.
|
||||||
|
@param[in] Timeout The length of timeout period.
|
||||||
|
@param[in, out] SenseData A pointer to output sense data.
|
||||||
|
@param[in, out] SenseDataLength The length of output sense data.
|
||||||
|
@param[out] HostAdapterStatus The status of Host Adapter.
|
||||||
|
@param[out] TargetStatus The status of the target.
|
||||||
|
@param[in, out] DataBuffer Read 16 command data.
|
||||||
|
@param[in, out] DataLength The length of data buffer.
|
||||||
|
@param[in] StartLba The start address of LBA.
|
||||||
|
@param[in] SectorSize The number of contiguous logical blocks
|
||||||
|
of data that shall be transferred.
|
||||||
|
@param[in] Event If the SCSI target does not support
|
||||||
|
non-blocking I/O, then Event is ignored,
|
||||||
|
and blocking I/O is performed. If Event
|
||||||
|
is NULL, then blocking I/O is performed.
|
||||||
|
If Event is not NULL and non-blocking
|
||||||
|
I/O is supported, then non-blocking I/O
|
||||||
|
is performed, and Event will be signaled
|
||||||
|
when the SCSI Read(10) command
|
||||||
|
completes.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Command is executed successfully.
|
||||||
|
@retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
|
||||||
|
but the entire DataBuffer could not be
|
||||||
|
transferred. The actual number of bytes
|
||||||
|
transferred is returned in DataLength.
|
||||||
|
@retval EFI_NOT_READY The SCSI Request Packet could not be
|
||||||
|
sent because there are too many SCSI
|
||||||
|
Command Packets already queued.
|
||||||
|
@retval EFI_DEVICE_ERROR A device error occurred while attempting
|
||||||
|
to send SCSI Request Packet.
|
||||||
|
@retval EFI_UNSUPPORTED The command described by the SCSI
|
||||||
|
Request Packet is not supported by the
|
||||||
|
SCSI initiator(i.e., SCSI Host
|
||||||
|
Controller)
|
||||||
|
@retval EFI_TIMEOUT A timeout occurred while waiting for the
|
||||||
|
SCSI Request Packet to execute.
|
||||||
|
@retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet
|
||||||
|
are invalid.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES The request could not be completed due
|
||||||
|
to a lack of resources.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
ScsiRead10CommandEx (
|
||||||
|
IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
|
||||||
|
IN UINT64 Timeout,
|
||||||
|
IN OUT VOID *SenseData, OPTIONAL
|
||||||
|
IN OUT UINT8 *SenseDataLength,
|
||||||
|
OUT UINT8 *HostAdapterStatus,
|
||||||
|
OUT UINT8 *TargetStatus,
|
||||||
|
IN OUT VOID *DataBuffer, OPTIONAL
|
||||||
|
IN OUT UINT32 *DataLength,
|
||||||
|
IN UINT32 StartLba,
|
||||||
|
IN UINT32 SectorSize,
|
||||||
|
IN EFI_EVENT Event OPTIONAL
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_SCSI_LIB_ASYNC_CONTEXT *Context;
|
||||||
|
EFI_SCSI_IO_SCSI_REQUEST_PACKET *CommandPacket;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINT8 *Cdb;
|
||||||
|
EFI_EVENT SelfEvent;
|
||||||
|
|
||||||
|
if (Event == NULL) {
|
||||||
|
return ScsiRead10Command (
|
||||||
|
ScsiIo,
|
||||||
|
Timeout,
|
||||||
|
SenseData,
|
||||||
|
SenseDataLength,
|
||||||
|
HostAdapterStatus,
|
||||||
|
TargetStatus,
|
||||||
|
DataBuffer,
|
||||||
|
DataLength,
|
||||||
|
StartLba,
|
||||||
|
SectorSize
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT (SenseDataLength != NULL);
|
||||||
|
ASSERT (HostAdapterStatus != NULL);
|
||||||
|
ASSERT (TargetStatus != NULL);
|
||||||
|
ASSERT (DataLength != NULL);
|
||||||
|
ASSERT (ScsiIo != NULL);
|
||||||
|
|
||||||
|
Context = AllocateZeroPool (sizeof (EFI_SCSI_LIB_ASYNC_CONTEXT));
|
||||||
|
if (Context == NULL) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
Cdb = AllocateZeroPool (EFI_SCSI_OP_LENGTH_TEN);
|
||||||
|
if (Cdb == NULL) {
|
||||||
|
Status = EFI_OUT_OF_RESOURCES;
|
||||||
|
goto ErrorExit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Context->SenseDataLength = SenseDataLength;
|
||||||
|
Context->HostAdapterStatus = HostAdapterStatus;
|
||||||
|
Context->TargetStatus = TargetStatus;
|
||||||
|
Context->CallerEvent = Event;
|
||||||
|
|
||||||
|
CommandPacket = &Context->CommandPacket;
|
||||||
|
CommandPacket->Timeout = Timeout;
|
||||||
|
CommandPacket->InDataBuffer = DataBuffer;
|
||||||
|
CommandPacket->SenseData = SenseData;
|
||||||
|
CommandPacket->InTransferLength = *DataLength;
|
||||||
|
CommandPacket->Cdb = Cdb;
|
||||||
|
//
|
||||||
|
// Fill Cdb for Read (10) Command
|
||||||
|
//
|
||||||
|
Cdb[0] = EFI_SCSI_OP_READ10;
|
||||||
|
WriteUnaligned32 ((UINT32 *)&Cdb[2], SwapBytes32 (StartLba));
|
||||||
|
WriteUnaligned16 ((UINT16 *)&Cdb[7], SwapBytes16 ((UINT16) SectorSize));
|
||||||
|
|
||||||
|
CommandPacket->CdbLength = EFI_SCSI_OP_LENGTH_TEN;
|
||||||
|
CommandPacket->DataDirection = EFI_SCSI_DATA_IN;
|
||||||
|
CommandPacket->SenseDataLength = *SenseDataLength;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Create Event
|
||||||
|
//
|
||||||
|
Status = gBS->CreateEvent (
|
||||||
|
EVT_NOTIFY_SIGNAL,
|
||||||
|
TPL_CALLBACK,
|
||||||
|
ScsiLibNotify,
|
||||||
|
Context,
|
||||||
|
&SelfEvent
|
||||||
|
);
|
||||||
|
if (EFI_ERROR(Status)) {
|
||||||
|
goto ErrorExit;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ScsiIo->ExecuteScsiCommand (ScsiIo, CommandPacket, SelfEvent);
|
||||||
|
|
||||||
|
ErrorExit:
|
||||||
|
if (Context != NULL) {
|
||||||
|
FreePool (Context);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Execute blocking/non-blocking Write(10) SCSI command on a specific SCSI
|
||||||
|
target.
|
||||||
|
|
||||||
|
Executes the SCSI Write(10) command on the SCSI target specified by ScsiIo.
|
||||||
|
When Event is NULL, blocking command will be executed. Otherwise non-blocking
|
||||||
|
command will be executed.
|
||||||
|
For blocking I/O, if Timeout is zero, this function will wait indefinitely
|
||||||
|
for the command to complete. If Timeout is greater than zero, then the
|
||||||
|
command is executed and will timeout after Timeout 100 ns units.
|
||||||
|
For non-blocking I/O, if Timeout is zero, Event will be signaled only after
|
||||||
|
the command to completes. If Timeout is greater than zero, Event will also be
|
||||||
|
signaled after Timeout 100 ns units.
|
||||||
|
The StartLba and SectorSize parameters are used to construct the CDB for this
|
||||||
|
SCSI command.
|
||||||
|
|
||||||
|
If ScsiIo is NULL, then ASSERT().
|
||||||
|
If SenseDataLength is NULL, then ASSERT().
|
||||||
|
If HostAdapterStatus is NULL, then ASSERT().
|
||||||
|
If TargetStatus is NULL, then ASSERT().
|
||||||
|
If DataLength is NULL, then ASSERT().
|
||||||
|
|
||||||
|
If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet
|
||||||
|
buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
|
||||||
|
EFI_INVALID_PARAMETER gets returned.
|
||||||
|
|
||||||
|
If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet
|
||||||
|
buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
|
||||||
|
EFI_INVALID_PARAMETER gets returned.
|
||||||
|
|
||||||
|
@param[in] ScsiIo SCSI IO Protocol to use
|
||||||
|
@param[in] Timeout The length of timeout period.
|
||||||
|
@param[in, out] SenseData A pointer to output sense data.
|
||||||
|
@param[in, out] SenseDataLength The length of output sense data.
|
||||||
|
@param[out] HostAdapterStatus The status of Host Adapter.
|
||||||
|
@param[out] TargetStatus The status of the target.
|
||||||
|
@param[in, out] DataBuffer A pointer to a data buffer.
|
||||||
|
@param[in, out] DataLength The length of data buffer.
|
||||||
|
@param[in] StartLba The start address of LBA.
|
||||||
|
@param[in] SectorSize The number of contiguous logical blocks
|
||||||
|
of data that shall be transferred.
|
||||||
|
@param[in] Event If the SCSI target does not support
|
||||||
|
non-blocking I/O, then Event is ignored,
|
||||||
|
and blocking I/O is performed. If Event
|
||||||
|
is NULL, then blocking I/O is performed.
|
||||||
|
If Event is not NULL and non-blocking
|
||||||
|
I/O is supported, then non-blocking I/O
|
||||||
|
is performed, and Event will be signaled
|
||||||
|
when the SCSI Write(10) command
|
||||||
|
completes.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Command is executed successfully.
|
||||||
|
@retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
|
||||||
|
but the entire DataBuffer could not be
|
||||||
|
transferred. The actual number of bytes
|
||||||
|
transferred is returned in DataLength.
|
||||||
|
@retval EFI_NOT_READY The SCSI Request Packet could not be
|
||||||
|
sent because there are too many SCSI
|
||||||
|
Command Packets already queued.
|
||||||
|
@retval EFI_DEVICE_ERROR A device error occurred while attempting
|
||||||
|
to send SCSI Request Packet.
|
||||||
|
@retval EFI_UNSUPPORTED The command described by the SCSI
|
||||||
|
Request Packet is not supported by the
|
||||||
|
SCSI initiator(i.e., SCSI Host
|
||||||
|
Controller)
|
||||||
|
@retval EFI_TIMEOUT A timeout occurred while waiting for the
|
||||||
|
SCSI Request Packet to execute.
|
||||||
|
@retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet
|
||||||
|
are invalid.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES The request could not be completed due
|
||||||
|
to a lack of resources.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
ScsiWrite10CommandEx (
|
||||||
|
IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
|
||||||
|
IN UINT64 Timeout,
|
||||||
|
IN OUT VOID *SenseData, OPTIONAL
|
||||||
|
IN OUT UINT8 *SenseDataLength,
|
||||||
|
OUT UINT8 *HostAdapterStatus,
|
||||||
|
OUT UINT8 *TargetStatus,
|
||||||
|
IN OUT VOID *DataBuffer, OPTIONAL
|
||||||
|
IN OUT UINT32 *DataLength,
|
||||||
|
IN UINT32 StartLba,
|
||||||
|
IN UINT32 SectorSize,
|
||||||
|
IN EFI_EVENT Event OPTIONAL
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_SCSI_LIB_ASYNC_CONTEXT *Context;
|
||||||
|
EFI_SCSI_IO_SCSI_REQUEST_PACKET *CommandPacket;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINT8 *Cdb;
|
||||||
|
EFI_EVENT SelfEvent;
|
||||||
|
|
||||||
|
if (Event == NULL) {
|
||||||
|
return ScsiWrite10Command (
|
||||||
|
ScsiIo,
|
||||||
|
Timeout,
|
||||||
|
SenseData,
|
||||||
|
SenseDataLength,
|
||||||
|
HostAdapterStatus,
|
||||||
|
TargetStatus,
|
||||||
|
DataBuffer,
|
||||||
|
DataLength,
|
||||||
|
StartLba,
|
||||||
|
SectorSize
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT (SenseDataLength != NULL);
|
||||||
|
ASSERT (HostAdapterStatus != NULL);
|
||||||
|
ASSERT (TargetStatus != NULL);
|
||||||
|
ASSERT (DataLength != NULL);
|
||||||
|
ASSERT (ScsiIo != NULL);
|
||||||
|
|
||||||
|
Context = AllocateZeroPool (sizeof (EFI_SCSI_LIB_ASYNC_CONTEXT));
|
||||||
|
if (Context == NULL) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
Cdb = AllocateZeroPool (EFI_SCSI_OP_LENGTH_TEN);
|
||||||
|
if (Cdb == NULL) {
|
||||||
|
Status = EFI_OUT_OF_RESOURCES;
|
||||||
|
goto ErrorExit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Context->SenseDataLength = SenseDataLength;
|
||||||
|
Context->HostAdapterStatus = HostAdapterStatus;
|
||||||
|
Context->TargetStatus = TargetStatus;
|
||||||
|
Context->CallerEvent = Event;
|
||||||
|
|
||||||
|
CommandPacket = &Context->CommandPacket;
|
||||||
|
CommandPacket->Timeout = Timeout;
|
||||||
|
CommandPacket->OutDataBuffer = DataBuffer;
|
||||||
|
CommandPacket->SenseData = SenseData;
|
||||||
|
CommandPacket->OutTransferLength = *DataLength;
|
||||||
|
CommandPacket->Cdb = Cdb;
|
||||||
|
//
|
||||||
|
// Fill Cdb for Write (10) Command
|
||||||
|
//
|
||||||
|
Cdb[0] = EFI_SCSI_OP_WRITE10;
|
||||||
|
WriteUnaligned32 ((UINT32 *)&Cdb[2], SwapBytes32 (StartLba));
|
||||||
|
WriteUnaligned16 ((UINT16 *)&Cdb[7], SwapBytes16 ((UINT16) SectorSize));
|
||||||
|
|
||||||
|
CommandPacket->CdbLength = EFI_SCSI_OP_LENGTH_TEN;
|
||||||
|
CommandPacket->DataDirection = EFI_SCSI_DATA_OUT;
|
||||||
|
CommandPacket->SenseDataLength = *SenseDataLength;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Create Event
|
||||||
|
//
|
||||||
|
Status = gBS->CreateEvent (
|
||||||
|
EVT_NOTIFY_SIGNAL,
|
||||||
|
TPL_CALLBACK,
|
||||||
|
ScsiLibNotify,
|
||||||
|
Context,
|
||||||
|
&SelfEvent
|
||||||
|
);
|
||||||
|
if (EFI_ERROR(Status)) {
|
||||||
|
goto ErrorExit;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ScsiIo->ExecuteScsiCommand (ScsiIo, CommandPacket, Event);
|
||||||
|
|
||||||
|
ErrorExit:
|
||||||
|
if (Context != NULL) {
|
||||||
|
FreePool (Context);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Execute blocking/non-blocking Read(16) SCSI command on a specific SCSI
|
||||||
|
target.
|
||||||
|
|
||||||
|
Executes the SCSI Read(16) command on the SCSI target specified by ScsiIo.
|
||||||
|
When Event is NULL, blocking command will be executed. Otherwise non-blocking
|
||||||
|
command will be executed.
|
||||||
|
For blocking I/O, if Timeout is zero, this function will wait indefinitely
|
||||||
|
for the command to complete. If Timeout is greater than zero, then the
|
||||||
|
command is executed and will timeout after Timeout 100 ns units.
|
||||||
|
For non-blocking I/O, if Timeout is zero, Event will be signaled only after
|
||||||
|
the command to completes. If Timeout is greater than zero, Event will also be
|
||||||
|
signaled after Timeout 100 ns units.
|
||||||
|
The StartLba and SectorSize parameters are used to construct the CDB for this
|
||||||
|
SCSI command.
|
||||||
|
|
||||||
|
If ScsiIo is NULL, then ASSERT().
|
||||||
|
If SenseDataLength is NULL, then ASSERT().
|
||||||
|
If HostAdapterStatus is NULL, then ASSERT().
|
||||||
|
If TargetStatus is NULL, then ASSERT().
|
||||||
|
If DataLength is NULL, then ASSERT().
|
||||||
|
|
||||||
|
If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet
|
||||||
|
buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
|
||||||
|
EFI_INVALID_PARAMETER gets returned.
|
||||||
|
|
||||||
|
If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet
|
||||||
|
buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
|
||||||
|
EFI_INVALID_PARAMETER gets returned.
|
||||||
|
|
||||||
|
@param[in] ScsiIo A pointer to SCSI IO protocol.
|
||||||
|
@param[in] Timeout The length of timeout period.
|
||||||
|
@param[in, out] SenseData A pointer to output sense data.
|
||||||
|
@param[in, out] SenseDataLength The length of output sense data.
|
||||||
|
@param[out] HostAdapterStatus The status of Host Adapter.
|
||||||
|
@param[out] TargetStatus The status of the target.
|
||||||
|
@param[in, out] DataBuffer Read 16 command data.
|
||||||
|
@param[in, out] DataLength The length of data buffer.
|
||||||
|
@param[in] StartLba The start address of LBA.
|
||||||
|
@param[in] SectorSize The number of contiguous logical blocks
|
||||||
|
of data that shall be transferred.
|
||||||
|
@param[in] Event If the SCSI target does not support
|
||||||
|
non-blocking I/O, then Event is ignored,
|
||||||
|
and blocking I/O is performed. If Event
|
||||||
|
is NULL, then blocking I/O is performed.
|
||||||
|
If Event is not NULL and non-blocking
|
||||||
|
I/O is supported, then non-blocking I/O
|
||||||
|
is performed, and Event will be signaled
|
||||||
|
when the SCSI Read(16) command
|
||||||
|
completes.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Command is executed successfully.
|
||||||
|
@retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
|
||||||
|
but the entire DataBuffer could not be
|
||||||
|
transferred. The actual number of bytes
|
||||||
|
transferred is returned in DataLength.
|
||||||
|
@retval EFI_NOT_READY The SCSI Request Packet could not be
|
||||||
|
sent because there are too many SCSI
|
||||||
|
Command Packets already queued.
|
||||||
|
@retval EFI_DEVICE_ERROR A device error occurred while attempting
|
||||||
|
to send SCSI Request Packet.
|
||||||
|
@retval EFI_UNSUPPORTED The command described by the SCSI
|
||||||
|
Request Packet is not supported by the
|
||||||
|
SCSI initiator(i.e., SCSI Host
|
||||||
|
Controller)
|
||||||
|
@retval EFI_TIMEOUT A timeout occurred while waiting for the
|
||||||
|
SCSI Request Packet to execute.
|
||||||
|
@retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet
|
||||||
|
are invalid.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES The request could not be completed due
|
||||||
|
to a lack of resources.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
ScsiRead16CommandEx (
|
||||||
|
IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
|
||||||
|
IN UINT64 Timeout,
|
||||||
|
IN OUT VOID *SenseData, OPTIONAL
|
||||||
|
IN OUT UINT8 *SenseDataLength,
|
||||||
|
OUT UINT8 *HostAdapterStatus,
|
||||||
|
OUT UINT8 *TargetStatus,
|
||||||
|
IN OUT VOID *DataBuffer, OPTIONAL
|
||||||
|
IN OUT UINT32 *DataLength,
|
||||||
|
IN UINT64 StartLba,
|
||||||
|
IN UINT32 SectorSize,
|
||||||
|
IN EFI_EVENT Event OPTIONAL
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_SCSI_LIB_ASYNC_CONTEXT *Context;
|
||||||
|
EFI_SCSI_IO_SCSI_REQUEST_PACKET *CommandPacket;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINT8 *Cdb;
|
||||||
|
EFI_EVENT SelfEvent;
|
||||||
|
|
||||||
|
if (Event == NULL) {
|
||||||
|
return ScsiRead16Command (
|
||||||
|
ScsiIo,
|
||||||
|
Timeout,
|
||||||
|
SenseData,
|
||||||
|
SenseDataLength,
|
||||||
|
HostAdapterStatus,
|
||||||
|
TargetStatus,
|
||||||
|
DataBuffer,
|
||||||
|
DataLength,
|
||||||
|
StartLba,
|
||||||
|
SectorSize
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT (SenseDataLength != NULL);
|
||||||
|
ASSERT (HostAdapterStatus != NULL);
|
||||||
|
ASSERT (TargetStatus != NULL);
|
||||||
|
ASSERT (DataLength != NULL);
|
||||||
|
ASSERT (ScsiIo != NULL);
|
||||||
|
|
||||||
|
Context = AllocateZeroPool (sizeof (EFI_SCSI_LIB_ASYNC_CONTEXT));
|
||||||
|
if (Context == NULL) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
Cdb = AllocateZeroPool (EFI_SCSI_OP_LENGTH_SIXTEEN);
|
||||||
|
if (Cdb == NULL) {
|
||||||
|
Status = EFI_OUT_OF_RESOURCES;
|
||||||
|
goto ErrorExit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Context->SenseDataLength = SenseDataLength;
|
||||||
|
Context->HostAdapterStatus = HostAdapterStatus;
|
||||||
|
Context->TargetStatus = TargetStatus;
|
||||||
|
Context->CallerEvent = Event;
|
||||||
|
|
||||||
|
CommandPacket = &Context->CommandPacket;
|
||||||
|
CommandPacket->Timeout = Timeout;
|
||||||
|
CommandPacket->InDataBuffer = DataBuffer;
|
||||||
|
CommandPacket->SenseData = SenseData;
|
||||||
|
CommandPacket->InTransferLength = *DataLength;
|
||||||
|
CommandPacket->Cdb = Cdb;
|
||||||
|
//
|
||||||
|
// Fill Cdb for Read (16) Command
|
||||||
|
//
|
||||||
|
Cdb[0] = EFI_SCSI_OP_READ16;
|
||||||
|
WriteUnaligned64 ((UINT64 *)&Cdb[2], SwapBytes64 (StartLba));
|
||||||
|
WriteUnaligned32 ((UINT32 *)&Cdb[10], SwapBytes32 (SectorSize));
|
||||||
|
|
||||||
|
CommandPacket->CdbLength = EFI_SCSI_OP_LENGTH_SIXTEEN;
|
||||||
|
CommandPacket->DataDirection = EFI_SCSI_DATA_IN;
|
||||||
|
CommandPacket->SenseDataLength = *SenseDataLength;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Create Event
|
||||||
|
//
|
||||||
|
Status = gBS->CreateEvent (
|
||||||
|
EVT_NOTIFY_SIGNAL,
|
||||||
|
TPL_CALLBACK,
|
||||||
|
ScsiLibNotify,
|
||||||
|
Context,
|
||||||
|
&SelfEvent
|
||||||
|
);
|
||||||
|
if (EFI_ERROR(Status)) {
|
||||||
|
goto ErrorExit;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ScsiIo->ExecuteScsiCommand (ScsiIo, CommandPacket, Event);
|
||||||
|
|
||||||
|
ErrorExit:
|
||||||
|
if (Context != NULL) {
|
||||||
|
FreePool (Context);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Execute blocking/non-blocking Write(16) SCSI command on a specific SCSI
|
||||||
|
target.
|
||||||
|
|
||||||
|
Executes the SCSI Write(16) command on the SCSI target specified by ScsiIo.
|
||||||
|
When Event is NULL, blocking command will be executed. Otherwise non-blocking
|
||||||
|
command will be executed.
|
||||||
|
For blocking I/O, if Timeout is zero, this function will wait indefinitely
|
||||||
|
for the command to complete. If Timeout is greater than zero, then the
|
||||||
|
command is executed and will timeout after Timeout 100 ns units.
|
||||||
|
For non-blocking I/O, if Timeout is zero, Event will be signaled only after
|
||||||
|
the command to completes. If Timeout is greater than zero, Event will also be
|
||||||
|
signaled after Timeout 100 ns units.
|
||||||
|
The StartLba and SectorSize parameters are used to construct the CDB for this
|
||||||
|
SCSI command.
|
||||||
|
|
||||||
|
If ScsiIo is NULL, then ASSERT().
|
||||||
|
If SenseDataLength is NULL, then ASSERT().
|
||||||
|
If HostAdapterStatus is NULL, then ASSERT().
|
||||||
|
If TargetStatus is NULL, then ASSERT().
|
||||||
|
If DataLength is NULL, then ASSERT().
|
||||||
|
|
||||||
|
If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet
|
||||||
|
buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
|
||||||
|
EFI_INVALID_PARAMETER gets returned.
|
||||||
|
|
||||||
|
If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet
|
||||||
|
buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise
|
||||||
|
EFI_INVALID_PARAMETER gets returned.
|
||||||
|
|
||||||
|
@param[in] ScsiIo SCSI IO Protocol to use
|
||||||
|
@param[in] Timeout The length of timeout period.
|
||||||
|
@param[in, out] SenseData A pointer to output sense data.
|
||||||
|
@param[in, out] SenseDataLength The length of output sense data.
|
||||||
|
@param[out] HostAdapterStatus The status of Host Adapter.
|
||||||
|
@param[out] TargetStatus The status of the target.
|
||||||
|
@param[in, out] DataBuffer A pointer to a data buffer.
|
||||||
|
@param[in, out] DataLength The length of data buffer.
|
||||||
|
@param[in] StartLba The start address of LBA.
|
||||||
|
@param[in] SectorSize The number of contiguous logical blocks
|
||||||
|
of data that shall be transferred.
|
||||||
|
@param[in] Event If the SCSI target does not support
|
||||||
|
non-blocking I/O, then Event is ignored,
|
||||||
|
and blocking I/O is performed. If Event
|
||||||
|
is NULL, then blocking I/O is performed.
|
||||||
|
If Event is not NULL and non-blocking
|
||||||
|
I/O is supported, then non-blocking I/O
|
||||||
|
is performed, and Event will be signaled
|
||||||
|
when the SCSI Write(16) command
|
||||||
|
completes.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Command is executed successfully.
|
||||||
|
@retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
|
||||||
|
but the entire DataBuffer could not be
|
||||||
|
transferred. The actual number of bytes
|
||||||
|
transferred is returned in DataLength.
|
||||||
|
@retval EFI_NOT_READY The SCSI Request Packet could not be
|
||||||
|
sent because there are too many SCSI
|
||||||
|
Command Packets already queued.
|
||||||
|
@retval EFI_DEVICE_ERROR A device error occurred while attempting
|
||||||
|
to send SCSI Request Packet.
|
||||||
|
@retval EFI_UNSUPPORTED The command described by the SCSI
|
||||||
|
Request Packet is not supported by the
|
||||||
|
SCSI initiator(i.e., SCSI Host
|
||||||
|
Controller)
|
||||||
|
@retval EFI_TIMEOUT A timeout occurred while waiting for the
|
||||||
|
SCSI Request Packet to execute.
|
||||||
|
@retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet
|
||||||
|
are invalid.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES The request could not be completed due
|
||||||
|
to a lack of resources.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
ScsiWrite16CommandEx (
|
||||||
|
IN EFI_SCSI_IO_PROTOCOL *ScsiIo,
|
||||||
|
IN UINT64 Timeout,
|
||||||
|
IN OUT VOID *SenseData, OPTIONAL
|
||||||
|
IN OUT UINT8 *SenseDataLength,
|
||||||
|
OUT UINT8 *HostAdapterStatus,
|
||||||
|
OUT UINT8 *TargetStatus,
|
||||||
|
IN OUT VOID *DataBuffer, OPTIONAL
|
||||||
|
IN OUT UINT32 *DataLength,
|
||||||
|
IN UINT64 StartLba,
|
||||||
|
IN UINT32 SectorSize,
|
||||||
|
IN EFI_EVENT Event OPTIONAL
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_SCSI_LIB_ASYNC_CONTEXT *Context;
|
||||||
|
EFI_SCSI_IO_SCSI_REQUEST_PACKET *CommandPacket;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINT8 *Cdb;
|
||||||
|
EFI_EVENT SelfEvent;
|
||||||
|
|
||||||
|
if (Event == NULL) {
|
||||||
|
return ScsiWrite16Command (
|
||||||
|
ScsiIo,
|
||||||
|
Timeout,
|
||||||
|
SenseData,
|
||||||
|
SenseDataLength,
|
||||||
|
HostAdapterStatus,
|
||||||
|
TargetStatus,
|
||||||
|
DataBuffer,
|
||||||
|
DataLength,
|
||||||
|
StartLba,
|
||||||
|
SectorSize
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT (SenseDataLength != NULL);
|
||||||
|
ASSERT (HostAdapterStatus != NULL);
|
||||||
|
ASSERT (TargetStatus != NULL);
|
||||||
|
ASSERT (DataLength != NULL);
|
||||||
|
ASSERT (ScsiIo != NULL);
|
||||||
|
|
||||||
|
Context = AllocateZeroPool (sizeof (EFI_SCSI_LIB_ASYNC_CONTEXT));
|
||||||
|
if (Context == NULL) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
Cdb = AllocateZeroPool (EFI_SCSI_OP_LENGTH_SIXTEEN);
|
||||||
|
if (Cdb == NULL) {
|
||||||
|
Status = EFI_OUT_OF_RESOURCES;
|
||||||
|
goto ErrorExit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Context->SenseDataLength = SenseDataLength;
|
||||||
|
Context->HostAdapterStatus = HostAdapterStatus;
|
||||||
|
Context->TargetStatus = TargetStatus;
|
||||||
|
Context->CallerEvent = Event;
|
||||||
|
|
||||||
|
CommandPacket = &Context->CommandPacket;
|
||||||
|
CommandPacket->Timeout = Timeout;
|
||||||
|
CommandPacket->OutDataBuffer = DataBuffer;
|
||||||
|
CommandPacket->SenseData = SenseData;
|
||||||
|
CommandPacket->OutTransferLength = *DataLength;
|
||||||
|
CommandPacket->Cdb = Cdb;
|
||||||
|
//
|
||||||
|
// Fill Cdb for Write (16) Command
|
||||||
|
//
|
||||||
|
Cdb[0] = EFI_SCSI_OP_WRITE16;
|
||||||
|
WriteUnaligned64 ((UINT64 *)&Cdb[2], SwapBytes64 (StartLba));
|
||||||
|
WriteUnaligned32 ((UINT32 *)&Cdb[10], SwapBytes32 (SectorSize));
|
||||||
|
|
||||||
|
CommandPacket->CdbLength = EFI_SCSI_OP_LENGTH_SIXTEEN;
|
||||||
|
CommandPacket->DataDirection = EFI_SCSI_DATA_OUT;
|
||||||
|
CommandPacket->SenseDataLength = *SenseDataLength;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Create Event
|
||||||
|
//
|
||||||
|
Status = gBS->CreateEvent (
|
||||||
|
EVT_NOTIFY_SIGNAL,
|
||||||
|
TPL_CALLBACK,
|
||||||
|
ScsiLibNotify,
|
||||||
|
Context,
|
||||||
|
&SelfEvent
|
||||||
|
);
|
||||||
|
if (EFI_ERROR(Status)) {
|
||||||
|
goto ErrorExit;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ScsiIo->ExecuteScsiCommand (ScsiIo, CommandPacket, Event);
|
||||||
|
|
||||||
|
ErrorExit:
|
||||||
|
if (Context != NULL) {
|
||||||
|
FreePool (Context);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
# This libarary provides the functions to submit Scsi commands defined
|
# This libarary provides the functions to submit Scsi commands defined
|
||||||
# in SCSI-2 specification for scsi device.
|
# in SCSI-2 specification for scsi device.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
|
# Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||||
#
|
#
|
||||||
# This program and the accompanying materials
|
# This program and the accompanying materials
|
||||||
# are licensed and made available under the terms and conditions of the BSD License
|
# are licensed and made available under the terms and conditions of the BSD License
|
||||||
|
@ -42,4 +42,6 @@
|
||||||
BaseMemoryLib
|
BaseMemoryLib
|
||||||
DebugLib
|
DebugLib
|
||||||
BaseLib
|
BaseLib
|
||||||
|
MemoryAllocationLib
|
||||||
|
UefiBootServicesTableLib
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue