/** @file | |
UEFI SCSI Library implementation | |
Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR> | |
This program and the accompanying materials | |
are licensed and made available under the terms and conditions of the BSD License | |
which accompanies this distribution. The full text of the license may be found at | |
http://opensource.org/licenses/bsd-license.php. | |
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
**/ | |
#include <Uefi.h> | |
#include <Library/BaseLib.h> | |
#include <Library/DebugLib.h> | |
#include <Library/UefiScsiLib.h> | |
#include <Library/BaseMemoryLib.h> | |
#include <IndustryStandard/Scsi.h> | |
// | |
// Scsi Command Length | |
// | |
#define EFI_SCSI_OP_LENGTH_SIX 0x6 | |
#define EFI_SCSI_OP_LENGTH_TEN 0xa | |
#define EFI_SCSI_OP_LENGTH_SIXTEEN 0x10 | |
/** | |
Execute Test Unit Ready SCSI command on a specific SCSI target. | |
Executes the Test Unit Ready command on the SCSI target specified by ScsiIo. | |
If Timeout is zero, then this function waits indefinitely for the command to complete. | |
If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units. | |
If ScsiIo is NULL, then ASSERT(). | |
If SenseDataLength is NULL, then ASSERT(). | |
If HostAdapterStatus is NULL, then ASSERT(). | |
If TargetStatus is NULL, then ASSERT(). | |
@param[in] ScsiIo A pointer to the SCSI I/O Protocol instance | |
for the specific SCSI target. | |
@param[in] Timeout The timeout in 100 ns units to use for the execution | |
of this SCSI Request Packet. A Timeout value of | |
zero means that this function will wait indefinitely | |
for the SCSI Request Packet to execute. If Timeout | |
is greater than zero, then this function will return | |
EFI_TIMEOUT if the time required to execute the SCSI | |
Request Packet is greater than Timeout. | |
@param[in, out] SenseData A pointer to sense data that was generated by | |
the execution of the SCSI Request Packet. This | |
buffer must be allocated by the caller. | |
If SenseDataLength is 0, then this parameter is | |
optional and may be NULL. | |
@param[in, out] SenseDataLength On input, a pointer to the length in bytes of | |
the SenseData buffer. On output, a pointer to | |
the number of bytes written to the SenseData buffer. | |
@param[out] HostAdapterStatus The status of the SCSI Host Controller that produces | |
the SCSI bus containing the SCSI target specified by | |
ScsiIo when the SCSI Request Packet was executed. | |
See the EFI SCSI I/O Protocol in the UEFI Specification | |
for details on the possible return values. | |
@param[out] TargetStatus The status returned by the SCSI target specified | |
by ScsiIo when the SCSI Request Packet was executed | |
on the SCSI Host Controller. See the EFI SCSI I/O | |
Protocol in the UEFI Specification for details on | |
the possible return values. | |
@retval EFI_SUCCESS The command was executed successfully. | |
See HostAdapterStatus, TargetStatus, SenseDataLength, | |
and SenseData in that order for additional status | |
information. | |
@retval EFI_NOT_READY The SCSI Request Packet could not be sent because | |
there are too many SCSI Command Packets already | |
queued. The SCSI Request Packet was not sent, so | |
no additional status information is available. | |
The caller may retry again later. | |
@retval EFI_DEVICE_ERROR A device error occurred while attempting to send | |
SCSI Request Packet. See HostAdapterStatus, | |
TargetStatus, SenseDataLength, and SenseData in that | |
order for additional status information. | |
@retval EFI_UNSUPPORTED The command described by the SCSI Request Packet | |
is not supported by the SCSI initiator(i.e., SCSI | |
Host Controller). The SCSI Request Packet was not | |
sent, so no additional status information is available. | |
@retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request | |
Packet to execute. See HostAdapterStatus, TargetStatus, | |
SenseDataLength, and SenseData in that order for | |
additional status information. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
ScsiTestUnitReadyCommand ( | |
IN EFI_SCSI_IO_PROTOCOL *ScsiIo, | |
IN UINT64 Timeout, | |
IN OUT VOID *SenseData, OPTIONAL | |
IN OUT UINT8 *SenseDataLength, | |
OUT UINT8 *HostAdapterStatus, | |
OUT UINT8 *TargetStatus | |
) | |
{ | |
EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket; | |
EFI_STATUS Status; | |
UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX]; | |
ASSERT (SenseDataLength != NULL); | |
ASSERT (HostAdapterStatus != NULL); | |
ASSERT (TargetStatus != NULL); | |
ASSERT (ScsiIo != NULL); | |
ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET)); | |
ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX); | |
CommandPacket.Timeout = Timeout; | |
CommandPacket.InDataBuffer = NULL; | |
CommandPacket.InTransferLength= 0; | |
CommandPacket.OutDataBuffer = NULL; | |
CommandPacket.OutTransferLength= 0; | |
CommandPacket.SenseData = SenseData; | |
CommandPacket.Cdb = Cdb; | |
// | |
// Fill Cdb for Test Unit Ready Command | |
// | |
Cdb[0] = EFI_SCSI_OP_TEST_UNIT_READY; | |
CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX; | |
CommandPacket.SenseDataLength = *SenseDataLength; | |
Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL); | |
*HostAdapterStatus = CommandPacket.HostAdapterStatus; | |
*TargetStatus = CommandPacket.TargetStatus; | |
*SenseDataLength = CommandPacket.SenseDataLength; | |
return Status; | |
} | |
/** | |
Execute Inquiry SCSI command on a specific SCSI target. | |
Executes the Inquiry command on the SCSI target specified by ScsiIo. | |
If Timeout is zero, then this function waits indefinitely for the command to complete. | |
If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units. | |
If ScsiIo is NULL, then ASSERT(). | |
If SenseDataLength is NULL, then ASSERT(). | |
If HostAdapterStatus is NULL, then ASSERT(). | |
If TargetStatus is NULL, then ASSERT(). | |
If InquiryDataLength is NULL, then ASSERT(). | |
@param[in] ScsiIo A pointer to the SCSI I/O Protocol instance | |
for the specific SCSI target. | |
@param[in] Timeout The timeout in 100 ns units to use for the | |
execution of this SCSI Request Packet. A Timeout | |
value of zero means that this function will wait | |
indefinitely for the SCSI Request Packet to execute. | |
If Timeout is greater than zero, then this function | |
will return EFI_TIMEOUT if the time required to | |
execute the SCSI Request Packet is greater than Timeout. | |
@param[in, out] SenseData A pointer to sense data that was generated | |
by the execution of the SCSI Request Packet. | |
This buffer must be allocated by the caller. | |
If SenseDataLength is 0, then this parameter | |
is optional and may be NULL. | |
@param[in, out] SenseDataLength On input, the length in bytes of the SenseData buffer. | |
On output, the number of bytes written to the SenseData buffer. | |
@param[out] HostAdapterStatus The status of the SCSI Host Controller that | |
produces the SCSI bus containing the SCSI | |
target specified by ScsiIo when the SCSI | |
Request Packet was executed. See the EFI | |
SCSI I/O Protocol in the UEFI Specification | |
for details on the possible return values. | |
@param[out] TargetStatus The status returned by the SCSI target specified | |
by ScsiIo when the SCSI Request Packet was | |
executed on the SCSI Host Controller. | |
See the EFI SCSI I/O Protocol in the UEFI | |
Specification for details on the possible | |
return values. | |
@param[in, out] InquiryDataBuffer A pointer to inquiry data that was generated | |
by the execution of the SCSI Request Packet. | |
This buffer must be allocated by the caller. | |
If InquiryDataLength is 0, then this parameter | |
is optional and may be NULL. | |
@param[in, out] InquiryDataLength On input, a pointer to the length in bytes | |
of the InquiryDataBuffer buffer. | |
On output, a pointer to the number of bytes | |
written to the InquiryDataBuffer buffer. | |
@param[in] EnableVitalProductData If TRUE, then the supported vital product | |
data for the PageCode is returned in InquiryDataBuffer. | |
If FALSE, then the standard inquiry data is | |
returned in InquiryDataBuffer and PageCode is ignored. | |
@param[in] PageCode The page code of the vital product data. | |
It's ignored if EnableVitalProductData is FALSE. | |
@retval EFI_SUCCESS The command executed successfully. See HostAdapterStatus, | |
TargetStatus, SenseDataLength, and SenseData in that order | |
for additional status information. | |
@retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire | |
InquiryDataBuffer could not be transferred. The actual | |
number of bytes transferred is returned in InquiryDataLength. | |
@retval EFI_NOT_READY The SCSI Request Packet could not be sent because there | |
are too many SCSI Command Packets already queued. | |
The SCSI Request Packet was not sent, so no additional | |
status information is available. The caller may retry again later. | |
@retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI | |
Request Packet. See HostAdapterStatus, TargetStatus, | |
SenseDataLength, and SenseData in that order for additional | |
status information. | |
@retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not | |
supported by the SCSI initiator(i.e., SCSI Host Controller). | |
The SCSI Request Packet was not sent, so no additional | |
status information is available. | |
@retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request | |
Packet to execute. See HostAdapterStatus, TargetStatus, | |
SenseDataLength, and SenseData in that order for | |
additional status information. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
ScsiInquiryCommandEx ( | |
IN EFI_SCSI_IO_PROTOCOL *ScsiIo, | |
IN UINT64 Timeout, | |
IN OUT VOID *SenseData, OPTIONAL | |
IN OUT UINT8 *SenseDataLength, | |
OUT UINT8 *HostAdapterStatus, | |
OUT UINT8 *TargetStatus, | |
IN OUT VOID *InquiryDataBuffer, OPTIONAL | |
IN OUT UINT32 *InquiryDataLength, | |
IN BOOLEAN EnableVitalProductData, | |
IN UINT8 PageCode | |
) | |
{ | |
EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket; | |
EFI_STATUS Status; | |
UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX]; | |
ASSERT (SenseDataLength != NULL); | |
ASSERT (HostAdapterStatus != NULL); | |
ASSERT (TargetStatus != NULL); | |
ASSERT (InquiryDataLength != NULL); | |
ASSERT (ScsiIo != NULL); | |
ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET)); | |
ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX); | |
CommandPacket.Timeout = Timeout; | |
CommandPacket.InDataBuffer = InquiryDataBuffer; | |
CommandPacket.InTransferLength= *InquiryDataLength; | |
CommandPacket.SenseData = SenseData; | |
CommandPacket.SenseDataLength = *SenseDataLength; | |
CommandPacket.Cdb = Cdb; | |
Cdb[0] = EFI_SCSI_OP_INQUIRY; | |
if (EnableVitalProductData) { | |
Cdb[1] |= 0x01; | |
Cdb[2] = PageCode; | |
} | |
if (*InquiryDataLength > 0xff) { | |
*InquiryDataLength = 0xff; | |
} | |
Cdb[4] = (UINT8) (*InquiryDataLength); | |
CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX; | |
CommandPacket.DataDirection = EFI_SCSI_DATA_IN; | |
Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL); | |
*HostAdapterStatus = CommandPacket.HostAdapterStatus; | |
*TargetStatus = CommandPacket.TargetStatus; | |
*SenseDataLength = CommandPacket.SenseDataLength; | |
*InquiryDataLength = CommandPacket.InTransferLength; | |
return Status; | |
} | |
/** | |
Execute Inquiry SCSI command on a specific SCSI target. | |
Executes the Inquiry command on the SCSI target specified by ScsiIo. | |
If Timeout is zero, then this function waits indefinitely for the command to complete. | |
If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units. | |
If ScsiIo is NULL, then ASSERT(). | |
If SenseDataLength is NULL, then ASSERT(). | |
If HostAdapterStatus is NULL, then ASSERT(). | |
If TargetStatus is NULL, then ASSERT(). | |
If InquiryDataLength is NULL, then ASSERT(). | |
@param[in] ScsiIo A pointer to the SCSI I/O Protocol instance | |
for the specific SCSI target. | |
@param[in] Timeout The timeout in 100 ns units to use for the | |
execution of this SCSI Request Packet. A Timeout | |
value of zero means that this function will wait | |
indefinitely for the SCSI Request Packet to execute. | |
If Timeout is greater than zero, then this function | |
will return EFI_TIMEOUT if the time required to | |
execute the SCSI Request Packet is greater than Timeout. | |
@param[in, out] SenseData A pointer to sense data that was generated | |
by the execution of the SCSI Request Packet. | |
This buffer must be allocated by the caller. | |
If SenseDataLength is 0, then this parameter | |
is optional and may be NULL. | |
@param[in, out] SenseDataLength On input, the length in bytes of the SenseData buffer. | |
On output, the number of bytes written to the SenseData buffer. | |
@param[out] HostAdapterStatus The status of the SCSI Host Controller that | |
produces the SCSI bus containing the SCSI | |
target specified by ScsiIo when the SCSI | |
Request Packet was executed. See the EFI | |
SCSI I/O Protocol in the UEFI Specification | |
for details on the possible return values. | |
@param[out] TargetStatus The status returned by the SCSI target specified | |
by ScsiIo when the SCSI Request Packet was | |
executed on the SCSI Host Controller. | |
See the EFI SCSI I/O Protocol in the UEFI | |
Specification for details on the possible | |
return values. | |
@param[in, out] InquiryDataBuffer A pointer to inquiry data that was generated | |
by the execution of the SCSI Request Packet. | |
This buffer must be allocated by the caller. | |
If InquiryDataLength is 0, then this parameter | |
is optional and may be NULL. | |
@param[in, out] InquiryDataLength On input, a pointer to the length in bytes | |
of the InquiryDataBuffer buffer. | |
On output, a pointer to the number of bytes | |
written to the InquiryDataBuffer buffer. | |
@param[in] EnableVitalProductData If TRUE, then the supported vital product | |
data is returned in InquiryDataBuffer. | |
If FALSE, then the standard inquiry data is | |
returned in InquiryDataBuffer. | |
@retval EFI_SUCCESS The command executed successfully. See HostAdapterStatus, | |
TargetStatus, SenseDataLength, and SenseData in that order | |
for additional status information. | |
@retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire | |
InquiryDataBuffer could not be transferred. The actual | |
number of bytes transferred is returned in InquiryDataLength. | |
@retval EFI_NOT_READY The SCSI Request Packet could not be sent because there | |
are too many SCSI Command Packets already queued. | |
The SCSI Request Packet was not sent, so no additional | |
status information is available. The caller may retry again later. | |
@retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI | |
Request Packet. See HostAdapterStatus, TargetStatus, | |
SenseDataLength, and SenseData in that order for additional | |
status information. | |
@retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not | |
supported by the SCSI initiator(i.e., SCSI Host Controller). | |
The SCSI Request Packet was not sent, so no additional | |
status information is available. | |
@retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request | |
Packet to execute. See HostAdapterStatus, TargetStatus, | |
SenseDataLength, and SenseData in that order for | |
additional status information. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
ScsiInquiryCommand ( | |
IN EFI_SCSI_IO_PROTOCOL *ScsiIo, | |
IN UINT64 Timeout, | |
IN OUT VOID *SenseData, OPTIONAL | |
IN OUT UINT8 *SenseDataLength, | |
OUT UINT8 *HostAdapterStatus, | |
OUT UINT8 *TargetStatus, | |
IN OUT VOID *InquiryDataBuffer, OPTIONAL | |
IN OUT UINT32 *InquiryDataLength, | |
IN BOOLEAN EnableVitalProductData | |
) | |
{ | |
return ScsiInquiryCommandEx ( | |
ScsiIo, | |
Timeout, | |
SenseData, | |
SenseDataLength, | |
HostAdapterStatus, | |
TargetStatus, | |
InquiryDataBuffer, | |
InquiryDataLength, | |
EnableVitalProductData, | |
0 | |
); | |
} | |
/** | |
Execute Mode Sense(10) SCSI command on a specific SCSI target. | |
Executes the SCSI Mode Sense(10) command on the SCSI target specified by ScsiIo. | |
If Timeout is zero, then this function waits indefinitely for the command to complete. | |
If Timeout is greater than zero, then the command is executed and will timeout | |
after Timeout 100 ns units. The DBDField, PageControl, and PageCode parameters | |
are used to construct the CDB for this SCSI command. | |
If ScsiIo is NULL, then ASSERT(). | |
If SenseDataLength is NULL, then ASSERT(). | |
If HostAdapterStatus is NULL, then ASSERT(). | |
If TargetStatus is NULL, then ASSERT(). | |
If DataLength is NULL, then ASSERT(). | |
@param[in] ScsiIo A pointer to the SCSI I/O Protocol instance | |
for the specific SCSI target. | |
@param[in] Timeout The timeout in 100 ns units to use for the | |
execution of this SCSI Request Packet. A Timeout | |
value of zero means that this function will wait | |
indefinitely for the SCSI Request Packet to execute. | |
If Timeout is greater than zero, then this function | |
will return EFI_TIMEOUT if the time required to | |
execute the SCSI Request Packet is greater than Timeout. | |
@param[in, out] SenseData A pointer to sense data that was generated | |
by the execution of the SCSI Request Packet. | |
This buffer must be allocated by the caller. | |
If SenseDataLength is 0, then this parameter | |
is optional and may be NULL. | |
@param[in, out] SenseDataLength On input, the length in bytes of the SenseData buffer. | |
On output, the number of bytes written to the SenseData buffer. | |
@param[out] HostAdapterStatus The status of the SCSI Host Controller that | |
produces the SCSI bus containing the SCSI target | |
specified by ScsiIo when the SCSI Request Packet | |
was executed. See the EFI SCSI I/O Protocol in the | |
UEFI Specification for details on the possible | |
return values. | |
@param[out] TargetStatus The status returned by the SCSI target specified | |
by ScsiIo when the SCSI Request Packet was executed | |
on the SCSI Host Controller. See the EFI SCSI | |
I/O Protocol in the UEFI Specification for details | |
on the possible return values. | |
@param[in, out] DataBuffer A pointer to data that was generated by the | |
execution of the SCSI Request Packet. This | |
buffer must be allocated by the caller. If | |
DataLength is 0, then this parameter is optional | |
and may be NULL. | |
@param[in, out] DataLength On input, a pointer to the length in bytes of | |
the DataBuffer buffer. On output, a pointer | |
to the number of bytes written to the DataBuffer | |
buffer. | |
@param[in] DBDField Specifies the DBD field of the CDB for this SCSI Command. | |
@param[in] PageControl Specifies the PC field of the CDB for this SCSI Command. | |
@param[in] PageCode Specifies the Page Control field of the CDB for this SCSI Command. | |
@retval EFI_SUCCESS The command executed successfully. | |
See HostAdapterStatus, TargetStatus, SenseDataLength, | |
and SenseData in that order for additional status information. | |
@retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the | |
entire DataBuffer could not be transferred. | |
The actual number of bytes transferred is returned | |
in DataLength. | |
@retval EFI_NOT_READY The SCSI Request Packet could not be sent because | |
there are too many SCSI Command Packets already queued. | |
The SCSI Request Packet was not sent, so no additional | |
status information is available. The caller may retry | |
again later. | |
@retval EFI_DEVICE_ERROR A device error occurred while attempting to send | |
SCSI Request Packet. See HostAdapterStatus, TargetStatus, | |
SenseDataLength, and SenseData in that order for | |
additional status information. | |
@retval EFI_UNSUPPORTED The command described by the SCSI Request Packet | |
is not supported by the SCSI initiator(i.e., SCSI | |
Host Controller). The SCSI Request Packet was not | |
sent, so no additional status information is available. | |
@retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI | |
Request Packet to execute. See HostAdapterStatus, | |
TargetStatus, SenseDataLength, and SenseData in that | |
order for additional status information. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
ScsiModeSense10Command ( | |
IN EFI_SCSI_IO_PROTOCOL *ScsiIo, | |
IN UINT64 Timeout, | |
IN OUT VOID *SenseData, OPTIONAL | |
IN OUT UINT8 *SenseDataLength, | |
OUT UINT8 *HostAdapterStatus, | |
OUT UINT8 *TargetStatus, | |
IN OUT VOID *DataBuffer, OPTIONAL | |
IN OUT UINT32 *DataLength, | |
IN UINT8 DBDField, OPTIONAL | |
IN UINT8 PageControl, | |
IN UINT8 PageCode | |
) | |
{ | |
EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket; | |
EFI_STATUS Status; | |
UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN]; | |
ASSERT (SenseDataLength != NULL); | |
ASSERT (HostAdapterStatus != NULL); | |
ASSERT (TargetStatus != NULL); | |
ASSERT (DataLength != NULL); | |
ASSERT (ScsiIo != NULL); | |
ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET)); | |
ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN); | |
CommandPacket.Timeout = Timeout; | |
CommandPacket.InDataBuffer = DataBuffer; | |
CommandPacket.SenseData = SenseData; | |
CommandPacket.InTransferLength= *DataLength; | |
CommandPacket.Cdb = Cdb; | |
// | |
// Fill Cdb for Mode Sense (10) Command | |
// | |
Cdb[0] = EFI_SCSI_OP_MODE_SEN10; | |
// | |
// DBDField is in Cdb[1] bit3 of (bit7..0) | |
// | |
Cdb[1] = (UINT8) ((DBDField << 3) & 0x08); | |
// | |
// PageControl is in Cdb[2] bit7..6, PageCode is in Cdb[2] bit5..0 | |
// | |
Cdb[2] = (UINT8) (((PageControl << 6) & 0xc0) | (PageCode & 0x3f)); | |
Cdb[7] = (UINT8) (*DataLength >> 8); | |
Cdb[8] = (UINT8) (*DataLength); | |
CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN; | |
CommandPacket.DataDirection = EFI_SCSI_DATA_IN; | |
CommandPacket.SenseDataLength = *SenseDataLength; | |
Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL); | |
*HostAdapterStatus = CommandPacket.HostAdapterStatus; | |
*TargetStatus = CommandPacket.TargetStatus; | |
*SenseDataLength = CommandPacket.SenseDataLength; | |
*DataLength = CommandPacket.InTransferLength; | |
return Status; | |
} | |
/** | |
Execute Request Sense SCSI command on a specific SCSI target. | |
Executes the Request Sense command on the SCSI target specified by ScsiIo. | |
If Timeout is zero, then this function waits indefinitely for the command to complete. | |
If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units. | |
If ScsiIo is NULL, then ASSERT(). | |
If SenseDataLength is NULL, then ASSERT(). | |
If HostAdapterStatus is NULL, then ASSERT(). | |
If TargetStatus is NULL, then ASSERT(). | |
@param[in] ScsiIo A pointer to SCSI IO protocol. | |
@param[in] Timeout The length of timeout period. | |
@param[in, out] SenseData A pointer to output sense data. | |
@param[in, out] SenseDataLength The length of output sense data. | |
@param[out] HostAdapterStatus The status of Host Adapter. | |
@param[out] TargetStatus The status of the target. | |
@retval EFI_SUCCESS The command executed successfully. | |
@retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are | |
too many SCSI Command Packets already queued. | |
@retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet. | |
@retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by | |
the SCSI initiator(i.e., SCSI Host Controller) | |
@retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
ScsiRequestSenseCommand ( | |
IN EFI_SCSI_IO_PROTOCOL *ScsiIo, | |
IN UINT64 Timeout, | |
IN OUT VOID *SenseData, OPTIONAL | |
IN OUT UINT8 *SenseDataLength, | |
OUT UINT8 *HostAdapterStatus, | |
OUT UINT8 *TargetStatus | |
) | |
{ | |
EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket; | |
EFI_STATUS Status; | |
UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX]; | |
ASSERT (SenseDataLength != NULL); | |
ASSERT (HostAdapterStatus != NULL); | |
ASSERT (TargetStatus != NULL); | |
ASSERT (ScsiIo != NULL); | |
ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET)); | |
ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX); | |
CommandPacket.Timeout = Timeout; | |
CommandPacket.InDataBuffer = SenseData; | |
CommandPacket.SenseData = NULL; | |
CommandPacket.InTransferLength= *SenseDataLength; | |
CommandPacket.Cdb = Cdb; | |
// | |
// Fill Cdb for Request Sense Command | |
// | |
Cdb[0] = EFI_SCSI_OP_REQUEST_SENSE; | |
Cdb[4] = (UINT8) (*SenseDataLength); | |
CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX; | |
CommandPacket.DataDirection = EFI_SCSI_DATA_IN; | |
CommandPacket.SenseDataLength = 0; | |
Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL); | |
*HostAdapterStatus = CommandPacket.HostAdapterStatus; | |
*TargetStatus = CommandPacket.TargetStatus; | |
*SenseDataLength = (UINT8) CommandPacket.InTransferLength; | |
return Status; | |
} | |
/** | |
Execute Read Capacity SCSI command on a specific SCSI target. | |
Executes the SCSI Read Capacity command on the SCSI target specified by ScsiIo. | |
If Timeout is zero, then this function waits indefinitely for the command to complete. | |
If Timeout is greater than zero, then the command is executed and will timeout after | |
Timeout 100 ns units. The Pmi parameter is used to construct the CDB for this SCSI command. | |
If ScsiIo is NULL, then ASSERT(). | |
If SenseDataLength is NULL, then ASSERT(). | |
If HostAdapterStatus is NULL, then ASSERT(). | |
If TargetStatus is NULL, then ASSERT(). | |
If DataLength is NULL, then ASSERT(). | |
@param[in] ScsiIo A pointer to SCSI IO protocol. | |
@param[in] Timeout The length of timeout period. | |
@param[in, out] SenseData A pointer to output sense data. | |
@param[in, out] SenseDataLength The length of output sense data. | |
@param[out] HostAdapterStatus The status of Host Adapter. | |
@param[out] TargetStatus The status of the target. | |
@param[in, out] DataBuffer A pointer to a data buffer. | |
@param[in, out] DataLength The length of data buffer. | |
@param[in] Pmi A partial medium indicator. | |
@retval EFI_SUCCESS The command 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. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
ScsiReadCapacityCommand ( | |
IN EFI_SCSI_IO_PROTOCOL *ScsiIo, | |
IN UINT64 Timeout, | |
IN OUT VOID *SenseData, OPTIONAL | |
IN OUT UINT8 *SenseDataLength, | |
OUT UINT8 *HostAdapterStatus, | |
OUT UINT8 *TargetStatus, | |
IN OUT VOID *DataBuffer, OPTIONAL | |
IN OUT UINT32 *DataLength, | |
IN BOOLEAN Pmi | |
) | |
{ | |
EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket; | |
EFI_STATUS Status; | |
UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN]; | |
ASSERT (SenseDataLength != NULL); | |
ASSERT (HostAdapterStatus != NULL); | |
ASSERT (TargetStatus != NULL); | |
ASSERT (DataLength != NULL); | |
ASSERT (ScsiIo != NULL); | |
ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET)); | |
ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN); | |
CommandPacket.Timeout = Timeout; | |
CommandPacket.InDataBuffer = DataBuffer; | |
CommandPacket.SenseData = SenseData; | |
CommandPacket.InTransferLength= *DataLength; | |
CommandPacket.Cdb = Cdb; | |
// | |
// Fill Cdb for Read Capacity Command | |
// | |
Cdb[0] = EFI_SCSI_OP_READ_CAPACITY; | |
if (!Pmi) { | |
// | |
// Partial medium indicator,if Pmi is FALSE, the Cdb.2 ~ Cdb.5 MUST BE ZERO. | |
// | |
ZeroMem ((Cdb + 2), 4); | |
} else { | |
Cdb[8] |= 0x01; | |
} | |
CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN; | |
CommandPacket.DataDirection = EFI_SCSI_DATA_IN; | |
CommandPacket.SenseDataLength = *SenseDataLength; | |
Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL); | |
*HostAdapterStatus = CommandPacket.HostAdapterStatus; | |
*TargetStatus = CommandPacket.TargetStatus; | |
*SenseDataLength = CommandPacket.SenseDataLength; | |
*DataLength = CommandPacket.InTransferLength; | |
return Status; | |
} | |
/** | |
Execute Read Capacity SCSI 16 command on a specific SCSI target. | |
Executes the SCSI Read Capacity 16 command on the SCSI target specified by ScsiIo. | |
If Timeout is zero, then this function waits indefinitely for the command to complete. | |
If Timeout is greater than zero, then the command is executed and will timeout after | |
Timeout 100 ns units. The Pmi parameter is used to construct the CDB for this SCSI command. | |
If ScsiIo is NULL, then ASSERT(). | |
If SenseDataLength is NULL, then ASSERT(). | |
If HostAdapterStatus is NULL, then ASSERT(). | |
If TargetStatus is NULL, then ASSERT(). | |
If DataLength is NULL, then ASSERT(). | |
@param[in] ScsiIo A pointer to SCSI IO protocol. | |
@param[in] Timeout The length of timeout period. | |
@param[in, out] SenseData A pointer to output sense data. | |
@param[in, out] SenseDataLength The length of output sense data. | |
@param[out] HostAdapterStatus The status of Host Adapter. | |
@param[out] TargetStatus The status of the target. | |
@param[in, out] DataBuffer A pointer to a data buffer. | |
@param[in, out] DataLength The length of data buffer. | |
@param[in] Pmi Partial medium indicator. | |
@retval EFI_SUCCESS The command 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. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
ScsiReadCapacity16Command ( | |
IN EFI_SCSI_IO_PROTOCOL *ScsiIo, | |
IN UINT64 Timeout, | |
IN OUT VOID *SenseData, OPTIONAL | |
IN OUT UINT8 *SenseDataLength, | |
OUT UINT8 *HostAdapterStatus, | |
OUT UINT8 *TargetStatus, | |
IN OUT VOID *DataBuffer, OPTIONAL | |
IN OUT UINT32 *DataLength, | |
IN BOOLEAN Pmi | |
) | |
{ | |
EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket; | |
EFI_STATUS Status; | |
UINT8 Cdb[16]; | |
ASSERT (SenseDataLength != NULL); | |
ASSERT (HostAdapterStatus != NULL); | |
ASSERT (TargetStatus != NULL); | |
ASSERT (DataLength != NULL); | |
ASSERT (ScsiIo != NULL); | |
ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET)); | |
ZeroMem (Cdb, 16); | |
CommandPacket.Timeout = Timeout; | |
CommandPacket.InDataBuffer = DataBuffer; | |
CommandPacket.SenseData = SenseData; | |
CommandPacket.InTransferLength= *DataLength; | |
CommandPacket.Cdb = Cdb; | |
// | |
// Fill Cdb for Read Capacity Command | |
// | |
Cdb[0] = EFI_SCSI_OP_READ_CAPACITY16; | |
Cdb[1] = 0x10; | |
if (!Pmi) { | |
// | |
// Partial medium indicator,if Pmi is FALSE, the Cdb.2 ~ Cdb.9 MUST BE ZERO. | |
// | |
ZeroMem ((Cdb + 2), 8); | |
} else { | |
Cdb[14] |= 0x01; | |
} | |
Cdb[13] = 0x20; | |
CommandPacket.CdbLength = 16; | |
CommandPacket.DataDirection = EFI_SCSI_DATA_IN; | |
CommandPacket.SenseDataLength = *SenseDataLength; | |
Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL); | |
*HostAdapterStatus = CommandPacket.HostAdapterStatus; | |
*TargetStatus = CommandPacket.TargetStatus; | |
*SenseDataLength = CommandPacket.SenseDataLength; | |
*DataLength = CommandPacket.InTransferLength; | |
return Status; | |
} | |
/** | |
Execute Read(10) SCSI command on a specific SCSI target. | |
Executes the SCSI Read(10) command on the SCSI target specified by ScsiIo. | |
If Timeout is zero, then this function waits indefinitely for the command to complete. | |
If Timeout is greater than zero, then the command is executed and will timeout | |
after Timeout 100 ns units. The StartLba and SectorSize parameters are used to | |
construct the CDB for this SCSI command. | |
If ScsiIo is NULL, then ASSERT(). | |
If SenseDataLength is NULL, then ASSERT(). | |
If HostAdapterStatus is NULL, then ASSERT(). | |
If TargetStatus is NULL, then ASSERT(). | |
If DataLength is NULL, then ASSERT(). | |
@param[in] ScsiIo A pointer to SCSI IO protocol. | |
@param[in] Timeout The length of timeout period. | |
@param[in, out] SenseData A pointer to output sense data. | |
@param[in, out] SenseDataLength The length of output sense data. | |
@param[out] HostAdapterStatus The status of Host Adapter. | |
@param[out] TargetStatus The status of the target. | |
@param[in, out] DataBuffer Read 10 command data. | |
@param[in, out] DataLength The length of data buffer. | |
@param[in] StartLba The start address of LBA. | |
@param[in] SectorSize The number of contiguous logical blocks of data that shall be transferred. | |
@retval EFI_SUCCESS The 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. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
ScsiRead10Command ( | |
IN EFI_SCSI_IO_PROTOCOL *ScsiIo, | |
IN UINT64 Timeout, | |
IN OUT VOID *SenseData, OPTIONAL | |
IN OUT UINT8 *SenseDataLength, | |
OUT UINT8 *HostAdapterStatus, | |
OUT UINT8 *TargetStatus, | |
IN OUT VOID *DataBuffer, OPTIONAL | |
IN OUT UINT32 *DataLength, | |
IN UINT32 StartLba, | |
IN UINT32 SectorSize | |
) | |
{ | |
EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket; | |
EFI_STATUS Status; | |
UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN]; | |
ASSERT (SenseDataLength != NULL); | |
ASSERT (HostAdapterStatus != NULL); | |
ASSERT (TargetStatus != NULL); | |
ASSERT (DataLength != NULL); | |
ASSERT (ScsiIo != NULL); | |
ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET)); | |
ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN); | |
CommandPacket.Timeout = Timeout; | |
CommandPacket.InDataBuffer = DataBuffer; | |
CommandPacket.SenseData = SenseData; | |
CommandPacket.InTransferLength= *DataLength; | |
CommandPacket.Cdb = Cdb; | |
// | |
// Fill Cdb for Read (10) Command | |
// | |
Cdb[0] = EFI_SCSI_OP_READ10; | |
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; | |
Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL); | |
*HostAdapterStatus = CommandPacket.HostAdapterStatus; | |
*TargetStatus = CommandPacket.TargetStatus; | |
*SenseDataLength = CommandPacket.SenseDataLength; | |
*DataLength = CommandPacket.InTransferLength; | |
return Status; | |
} | |
/** | |
Execute Write(10) SCSI command on a specific SCSI target. | |
Executes the SCSI Write(10) command on the SCSI target specified by ScsiIo. | |
If Timeout is zero, then this function waits indefinitely for the command to complete. | |
If Timeout is greater than zero, then the command is executed and will timeout after | |
Timeout 100 ns units. The StartLba and SectorSize parameters are used to construct | |
the CDB for this SCSI command. | |
If ScsiIo is NULL, then ASSERT(). | |
If SenseDataLength is NULL, then ASSERT(). | |
If HostAdapterStatus is NULL, then ASSERT(). | |
If TargetStatus is NULL, then ASSERT(). | |
If DataLength is NULL, then ASSERT(). | |
@param[in] ScsiIo SCSI IO Protocol to use | |
@param[in] Timeout The length of timeout period. | |
@param[in, out] SenseData A pointer to output sense data. | |
@param[in, out] SenseDataLength The length of output sense data. | |
@param[out] HostAdapterStatus The status of Host Adapter. | |
@param[out] TargetStatus The status of the target. | |
@param[in, out] DataBuffer A pointer to a data buffer. | |
@param[in, out] DataLength The length of data buffer. | |
@param[in] StartLba The start address of LBA. | |
@param[in] SectorSize The number of contiguous logical blocks of data that shall be transferred. | |
@retval EFI_SUCCESS The command 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. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
ScsiWrite10Command ( | |
IN EFI_SCSI_IO_PROTOCOL *ScsiIo, | |
IN UINT64 Timeout, | |
IN OUT VOID *SenseData, OPTIONAL | |
IN OUT UINT8 *SenseDataLength, | |
OUT UINT8 *HostAdapterStatus, | |
OUT UINT8 *TargetStatus, | |
IN OUT VOID *DataBuffer, OPTIONAL | |
IN OUT UINT32 *DataLength, | |
IN UINT32 StartLba, | |
IN UINT32 SectorSize | |
) | |
{ | |
EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket; | |
EFI_STATUS Status; | |
UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN]; | |
ASSERT (SenseDataLength != NULL); | |
ASSERT (HostAdapterStatus != NULL); | |
ASSERT (TargetStatus != NULL); | |
ASSERT (DataLength != NULL); | |
ASSERT (ScsiIo != NULL); | |
ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET)); | |
ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN); | |
CommandPacket.Timeout = Timeout; | |
CommandPacket.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; | |
Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL); | |
*HostAdapterStatus = CommandPacket.HostAdapterStatus; | |
*TargetStatus = CommandPacket.TargetStatus; | |
*SenseDataLength = CommandPacket.SenseDataLength; | |
*DataLength = CommandPacket.OutTransferLength; | |
return Status; | |
} | |
/** | |
Execute Read(16) SCSI command on a specific SCSI target. | |
Executes the SCSI Read(16) command on the SCSI target specified by ScsiIo. | |
If Timeout is zero, then this function waits indefinitely for the command to complete. | |
If Timeout is greater than zero, then the command is executed and will timeout | |
after Timeout 100 ns units. The StartLba and SectorSize parameters are used to | |
construct the CDB for this SCSI command. | |
If ScsiIo is NULL, then ASSERT(). | |
If SenseDataLength is NULL, then ASSERT(). | |
If HostAdapterStatus is NULL, then ASSERT(). | |
If TargetStatus is NULL, then ASSERT(). | |
If DataLength is NULL, then ASSERT(). | |
@param[in] ScsiIo A pointer to SCSI IO protocol. | |
@param[in] Timeout The length of timeout period. | |
@param[in, out] SenseData A pointer to output sense data. | |
@param[in, out] SenseDataLength The length of output sense data. | |
@param[out] HostAdapterStatus The status of Host Adapter. | |
@param[out] TargetStatus The status of the target. | |
@param[in, out] DataBuffer Read 16 command data. | |
@param[in, out] DataLength The length of data buffer. | |
@param[in] StartLba The start address of LBA. | |
@param[in] SectorSize The number of contiguous logical blocks of data that shall be transferred. | |
@retval EFI_SUCCESS The command 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. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
ScsiRead16Command ( | |
IN EFI_SCSI_IO_PROTOCOL *ScsiIo, | |
IN UINT64 Timeout, | |
IN OUT VOID *SenseData, OPTIONAL | |
IN OUT UINT8 *SenseDataLength, | |
OUT UINT8 *HostAdapterStatus, | |
OUT UINT8 *TargetStatus, | |
IN OUT VOID *DataBuffer, OPTIONAL | |
IN OUT UINT32 *DataLength, | |
IN UINT64 StartLba, | |
IN UINT32 SectorSize | |
) | |
{ | |
EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket; | |
EFI_STATUS Status; | |
UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIXTEEN]; | |
ASSERT (SenseDataLength != NULL); | |
ASSERT (HostAdapterStatus != NULL); | |
ASSERT (TargetStatus != NULL); | |
ASSERT (DataLength != NULL); | |
ASSERT (ScsiIo != NULL); | |
ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET)); | |
ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIXTEEN); | |
CommandPacket.Timeout = Timeout; | |
CommandPacket.InDataBuffer = DataBuffer; | |
CommandPacket.SenseData = SenseData; | |
CommandPacket.InTransferLength = *DataLength; | |
CommandPacket.Cdb = Cdb; | |
// | |
// Fill Cdb for Read (16) Command | |
// | |
Cdb[0] = EFI_SCSI_OP_READ16; | |
WriteUnaligned64 ((UINT64 *)&Cdb[2], SwapBytes64 (StartLba)); | |
WriteUnaligned32 ((UINT32 *)&Cdb[10], SwapBytes32 (SectorSize)); | |
CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_SIXTEEN; | |
CommandPacket.DataDirection = EFI_SCSI_DATA_IN; | |
CommandPacket.SenseDataLength = *SenseDataLength; | |
Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL); | |
*HostAdapterStatus = CommandPacket.HostAdapterStatus; | |
*TargetStatus = CommandPacket.TargetStatus; | |
*SenseDataLength = CommandPacket.SenseDataLength; | |
*DataLength = CommandPacket.InTransferLength; | |
return Status; | |
} | |
/** | |
Execute Write(16) SCSI command on a specific SCSI target. | |
Executes the SCSI Write(16) command on the SCSI target specified by ScsiIo. | |
If Timeout is zero, then this function waits indefinitely for the command to complete. | |
If Timeout is greater than zero, then the command is executed and will timeout after | |
Timeout 100 ns units. The StartLba and SectorSize parameters are used to construct | |
the CDB for this SCSI command. | |
If ScsiIo is NULL, then ASSERT(). | |
If SenseDataLength is NULL, then ASSERT(). | |
If HostAdapterStatus is NULL, then ASSERT(). | |
If TargetStatus is NULL, then ASSERT(). | |
If DataLength is NULL, then ASSERT(). | |
@param[in] ScsiIo SCSI IO Protocol to use | |
@param[in] Timeout The length of timeout period. | |
@param[in, out] SenseData A pointer to output sense data. | |
@param[in, out] SenseDataLength The length of output sense data. | |
@param[out] HostAdapterStatus The status of Host Adapter. | |
@param[out] TargetStatus The status of the target. | |
@param[in, out] DataBuffer A pointer to a data buffer. | |
@param[in, out] DataLength The length of data buffer. | |
@param[in] StartLba The start address of LBA. | |
@param[in] SectorSize The number of contiguous logical blocks of data that shall be transferred. | |
@retval EFI_SUCCESS The 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. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
ScsiWrite16Command ( | |
IN EFI_SCSI_IO_PROTOCOL *ScsiIo, | |
IN UINT64 Timeout, | |
IN OUT VOID *SenseData, OPTIONAL | |
IN OUT UINT8 *SenseDataLength, | |
OUT UINT8 *HostAdapterStatus, | |
OUT UINT8 *TargetStatus, | |
IN OUT VOID *DataBuffer, OPTIONAL | |
IN OUT UINT32 *DataLength, | |
IN UINT64 StartLba, | |
IN UINT32 SectorSize | |
) | |
{ | |
EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket; | |
EFI_STATUS Status; | |
UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIXTEEN]; | |
ASSERT (SenseDataLength != NULL); | |
ASSERT (HostAdapterStatus != NULL); | |
ASSERT (TargetStatus != NULL); | |
ASSERT (DataLength != NULL); | |
ASSERT (ScsiIo != NULL); | |
ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET)); | |
ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIXTEEN); | |
CommandPacket.Timeout = Timeout; | |
CommandPacket.OutDataBuffer = DataBuffer; | |
CommandPacket.SenseData = SenseData; | |
CommandPacket.OutTransferLength = *DataLength; | |
CommandPacket.Cdb = Cdb; | |
// | |
// Fill Cdb for Write (16) Command | |
// | |
Cdb[0] = EFI_SCSI_OP_WRITE16; | |
WriteUnaligned64 ((UINT64 *)&Cdb[2], SwapBytes64 (StartLba)); | |
WriteUnaligned32 ((UINT32 *)&Cdb[10], SwapBytes32 (SectorSize)); | |
CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_SIXTEEN; | |
CommandPacket.DataDirection = EFI_SCSI_DATA_OUT; | |
CommandPacket.SenseDataLength = *SenseDataLength; | |
Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL); | |
*HostAdapterStatus = CommandPacket.HostAdapterStatus; | |
*TargetStatus = CommandPacket.TargetStatus; | |
*SenseDataLength = CommandPacket.SenseDataLength; | |
*DataLength = CommandPacket.OutTransferLength; | |
return Status; | |
} |