| /*++ | |
| Copyright (c) 2006, Intel Corporation | |
| All rights reserved. This program and the accompanying materials | |
| are licensed and made available under the terms and conditions of the BSD License | |
| which accompanies this distribution. The full text of the license may be found at | |
| http://opensource.org/licenses/bsd-license.php | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
| Module Name: | |
| ScsiLib.c | |
| Abstract: | |
| Revision History | |
| --*/ | |
| #include <IndustryStandard/scsi.h> | |
| EFI_STATUS | |
| SubmitTestUnitReadyCommand ( | |
| IN EFI_SCSI_IO_PROTOCOL *ScsiIo, | |
| IN UINT64 Timeout, | |
| OUT VOID *SenseData, | |
| OUT UINT8 *SenseDataLength, | |
| OUT UINT8 *HostAdapterStatus, | |
| OUT UINT8 *TargetStatus | |
| ) | |
| /*++ | |
| Routine Description: | |
| Function tests the ready status of SCSI unit. | |
| Arguments: | |
| ScsiIo - A pointer to SCSI IO protocol. | |
| Timeout - The length of timeout period. | |
| SenseData - A pointer to output sense data. | |
| SenseDataLength - The length of output sense data. | |
| HostAdapterStatus - The status of Host Adapter. | |
| TargetStatus - The status of the target. | |
| Returns: | |
| Returns: | |
| EFI_SUCCESS - The status of the unit is tested successfully. | |
| EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed, | |
| but the entire DataBuffer could not be transferred. | |
| The actual number of bytes transferred is returned | |
| in InTransferLength. | |
| EFI_NOT_READY - The SCSI Request Packet could not be sent because | |
| there are too many SCSI Command Packets already | |
| queued. | |
| EFI_DEVICE_ERROR - A device error occurred while attempting to send | |
| the SCSI Request Packet. | |
| EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid. | |
| EFI_UNSUPPORTED - The command described by the SCSI Request Packet | |
| is not supported by the SCSI initiator(i.e., SCSI | |
| Host Controller). | |
| EFI_TIMEOUT - A timeout occurred while waiting for the SCSI | |
| Request Packet to execute. | |
| --*/ | |
| { | |
| EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket; | |
| UINT64 Lun; | |
| UINT32 Target; | |
| EFI_STATUS Status; | |
| UINT8 Cdb[6]; | |
| ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET)); | |
| ZeroMem (Cdb, 6); | |
| CommandPacket.Timeout = Timeout; | |
| CommandPacket.DataBuffer = NULL; | |
| CommandPacket.SenseData = SenseData; | |
| CommandPacket.TransferLength = 0; | |
| CommandPacket.Cdb = Cdb; | |
| // | |
| // Fill Cdb for Test Unit Ready Command | |
| // | |
| ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun); | |
| Cdb[0] = EFI_SCSI_OP_TEST_UNIT_READY; | |
| Cdb[1] = (UINT8) (Lun & 0xe0); | |
| CommandPacket.CdbLength = (UINT8) 6; | |
| CommandPacket.SenseDataLength = *SenseDataLength; | |
| Status = ScsiIo->ExecuteSCSICommand (ScsiIo, &CommandPacket, NULL); | |
| *HostAdapterStatus = CommandPacket.HostAdapterStatus; | |
| *TargetStatus = CommandPacket.TargetStatus; | |
| *SenseDataLength = CommandPacket.SenseDataLength; | |
| return Status; | |
| } | |
| EFI_STATUS | |
| SubmitInquiryCommand ( | |
| IN EFI_SCSI_IO_PROTOCOL *ScsiIo, | |
| IN UINT64 Timeout, | |
| IN VOID *SenseData, | |
| IN OUT UINT8 *SenseDataLength, | |
| OUT UINT8 *HostAdapterStatus, | |
| OUT UINT8 *TargetStatus, | |
| IN OUT VOID *InquiryDataBuffer, | |
| IN OUT UINT32 *InquiryDataLength, | |
| IN BOOLEAN EnableVitalProductData | |
| ) | |
| /*++ | |
| Routine Description: | |
| Function to submit SCSI inquiry command. | |
| Arguments: | |
| ScsiIo - A pointer to SCSI IO protocol. | |
| Timeout - The length of timeout period. | |
| SenseData - A pointer to output sense data. | |
| SenseDataLength - The length of output sense data. | |
| HostAdapterStatus - The status of Host Adapter. | |
| TargetStatus - The status of the target. | |
| InquiryDataBuffer - A pointer to inquiry data buffer. | |
| InquiryDataLength - The length of inquiry data buffer. | |
| EnableVitalProductData - Boolean to enable Vital Product Data. | |
| Returns: | |
| Returns: | |
| EFI_SUCCESS - The status of the unit is tested successfully. | |
| EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed, | |
| but the entire DataBuffer could not be transferred. | |
| The actual number of bytes transferred is returned | |
| in TransferLength. | |
| EFI_NOT_READY - The SCSI Request Packet could not be sent because | |
| there are too many SCSI Command Packets already | |
| queued. | |
| EFI_DEVICE_ERROR - A device error occurred while attempting to send | |
| the SCSI Request Packet. | |
| EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid. | |
| EFI_UNSUPPORTED - The command described by the SCSI Request Packet | |
| is not supported by the SCSI initiator(i.e., SCSI | |
| Host Controller). | |
| EFI_TIMEOUT - A timeout occurred while waiting for the SCSI | |
| Request Packet to execute. | |
| --*/ | |
| { | |
| EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket; | |
| UINT64 Lun; | |
| UINT32 Target; | |
| EFI_STATUS Status; | |
| UINT8 Cdb[6]; | |
| ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET)); | |
| ZeroMem (Cdb, 6); | |
| CommandPacket.Timeout = Timeout; | |
| CommandPacket.DataBuffer = InquiryDataBuffer; | |
| CommandPacket.TransferLength = *InquiryDataLength; | |
| CommandPacket.SenseData = SenseData; | |
| CommandPacket.SenseDataLength = *SenseDataLength; | |
| CommandPacket.Cdb = Cdb; | |
| ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun); | |
| Cdb[0] = EFI_SCSI_OP_INQUIRY; | |
| Cdb[1] = (UINT8) (Lun & 0xe0); | |
| if (EnableVitalProductData) { | |
| Cdb[1] |= 0x01; | |
| } | |
| if (*InquiryDataLength > 0xff) { | |
| *InquiryDataLength = 0xff; | |
| } | |
| Cdb[4] = (UINT8) (*InquiryDataLength); | |
| CommandPacket.CdbLength = (UINT8) 6; | |
| CommandPacket.DataDirection = EFI_SCSI_DATA_IN; | |
| Status = ScsiIo->ExecuteSCSICommand (ScsiIo, &CommandPacket, NULL); | |
| *HostAdapterStatus = CommandPacket.HostAdapterStatus; | |
| *TargetStatus = CommandPacket.TargetStatus; | |
| *SenseDataLength = CommandPacket.SenseDataLength; | |
| *InquiryDataLength = CommandPacket.TransferLength; | |
| return Status; | |
| } | |
| EFI_STATUS | |
| SubmitModeSense10Command ( | |
| IN EFI_SCSI_IO_PROTOCOL *ScsiIo, | |
| IN UINT64 Timeout, | |
| IN VOID *SenseData, | |
| IN OUT UINT8 *SenseDataLength, | |
| OUT UINT8 *HostAdapterStatus, | |
| OUT UINT8 *TargetStatus, | |
| IN VOID *DataBuffer, | |
| IN OUT UINT32 *DataLength, | |
| IN UINT8 DBDField, OPTIONAL | |
| IN UINT8 PageControl, | |
| IN UINT8 PageCode | |
| ) | |
| /*++ | |
| Routine Description: | |
| Function to submit SCSI mode sense 10 command. | |
| Arguments: | |
| ScsiIo - A pointer to SCSI IO protocol. | |
| Timeout - The length of timeout period. | |
| SenseData - A pointer to output sense data. | |
| SenseDataLength - The length of output sense data. | |
| HostAdapterStatus - The status of Host Adapter. | |
| TargetStatus - The status of the target. | |
| DataBuffer - A pointer to input data buffer. | |
| DataLength - The length of input data buffer. | |
| DBDField - The DBD Field (Optional). | |
| PageControl - Page Control. | |
| PageCode - Page code. | |
| Returns: | |
| Returns: | |
| EFI_SUCCESS - The status of the unit is tested successfully. | |
| EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed, | |
| but the entire DataBuffer could not be transferred. | |
| The actual number of bytes transferred is returned | |
| in TransferLength. | |
| EFI_NOT_READY - The SCSI Request Packet could not be sent because | |
| there are too many SCSI Command Packets already | |
| queued. | |
| EFI_DEVICE_ERROR - A device error occurred while attempting to send | |
| the SCSI Request Packet. | |
| EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid. | |
| EFI_UNSUPPORTED - The command described by the SCSI Request Packet | |
| is not supported by the SCSI initiator(i.e., SCSI | |
| Host Controller). | |
| EFI_TIMEOUT - A timeout occurred while waiting for the SCSI | |
| Request Packet to execute. | |
| --*/ | |
| { | |
| EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket; | |
| UINT64 Lun; | |
| UINT32 Target; | |
| EFI_STATUS Status; | |
| UINT8 Cdb[10]; | |
| ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET)); | |
| ZeroMem (Cdb, 10); | |
| CommandPacket.Timeout = Timeout; | |
| CommandPacket.DataBuffer = DataBuffer; | |
| CommandPacket.SenseData = SenseData; | |
| CommandPacket.TransferLength = *DataLength; | |
| CommandPacket.Cdb = Cdb; | |
| // | |
| // Fill Cdb for Mode Sense (10) Command | |
| // | |
| ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun); | |
| Cdb[0] = EFI_SCSI_OP_MODE_SEN10; | |
| Cdb[1] = (UINT8) ((Lun & 0xe0) + ((DBDField << 3) & 0x08)); | |
| Cdb[2] = (UINT8) ((PageControl & 0xc0) | (PageCode & 0x3f)); | |
| Cdb[7] = (UINT8) (*DataLength >> 8); | |
| Cdb[8] = (UINT8) (*DataLength); | |
| CommandPacket.CdbLength = 10; | |
| 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.TransferLength; | |
| return Status; | |
| } | |
| EFI_STATUS | |
| SubmitRequestSenseCommand ( | |
| IN EFI_SCSI_IO_PROTOCOL *ScsiIo, | |
| IN UINT64 Timeout, | |
| IN VOID *SenseData, | |
| IN OUT UINT8 *SenseDataLength, | |
| OUT UINT8 *HostAdapterStatus, | |
| OUT UINT8 *TargetStatus | |
| ) | |
| /*++ | |
| Routine Description: | |
| Function to submit SCSI request sense command. | |
| Arguments: | |
| ScsiIo - A pointer to SCSI IO protocol. | |
| Timeout - The length of timeout period. | |
| SenseData - A pointer to output sense data. | |
| SenseDataLength - The length of output sense data. | |
| HostAdapterStatus - The status of Host Adapter. | |
| TargetStatus - The status of the target. | |
| Returns: | |
| Returns: | |
| EFI_SUCCESS - The status of the unit is tested successfully. | |
| EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed, | |
| but the entire DataBuffer could not be transferred. | |
| The actual number of bytes transferred is returned | |
| in TransferLength. | |
| EFI_NOT_READY - The SCSI Request Packet could not be sent because | |
| there are too many SCSI Command Packets already | |
| queued. | |
| EFI_DEVICE_ERROR - A device error occurred while attempting to send | |
| the SCSI Request Packet. | |
| EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid. | |
| EFI_UNSUPPORTED - The command described by the SCSI Request Packet | |
| is not supported by the SCSI initiator(i.e., SCSI | |
| Host Controller). | |
| EFI_TIMEOUT - A timeout occurred while waiting for the SCSI | |
| Request Packet to execute. | |
| --*/ | |
| { | |
| EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket; | |
| UINT64 Lun; | |
| UINT32 Target; | |
| EFI_STATUS Status; | |
| UINT8 Cdb[6]; | |
| ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET)); | |
| ZeroMem (Cdb, 6); | |
| CommandPacket.Timeout = Timeout; | |
| CommandPacket.DataBuffer = SenseData; | |
| CommandPacket.SenseData = NULL; | |
| CommandPacket.TransferLength = *SenseDataLength; | |
| CommandPacket.Cdb = Cdb; | |
| // | |
| // Fill Cdb for Request Sense Command | |
| // | |
| ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun); | |
| Cdb[0] = EFI_SCSI_OP_REQUEST_SENSE; | |
| Cdb[1] = (UINT8) (Lun & 0xe0); | |
| Cdb[4] = (UINT8) (*SenseDataLength); | |
| CommandPacket.CdbLength = (UINT8) 6; | |
| CommandPacket.DataDirection = EFI_SCSI_DATA_IN; | |
| CommandPacket.SenseDataLength = 0; | |
| Status = ScsiIo->ExecuteSCSICommand (ScsiIo, &CommandPacket, NULL); | |
| *HostAdapterStatus = CommandPacket.HostAdapterStatus; | |
| *TargetStatus = CommandPacket.TargetStatus; | |
| *SenseDataLength = (UINT8) CommandPacket.TransferLength; | |
| return Status; | |
| } | |
| EFI_STATUS | |
| SubmitReadCapacityCommand ( | |
| IN EFI_SCSI_IO_PROTOCOL *ScsiIo, | |
| IN UINT64 Timeout, | |
| IN VOID *SenseData, | |
| IN OUT UINT8 *SenseDataLength, | |
| OUT UINT8 *HostAdapterStatus, | |
| OUT UINT8 *TargetStatus, | |
| OUT VOID *DataBuffer, | |
| IN OUT UINT32 *DataLength, | |
| IN BOOLEAN PMI | |
| ) | |
| /*++ | |
| Routine Description: | |
| Function to submit read capacity command. | |
| Arguments: | |
| ScsiIo - A pointer to SCSI IO protocol. | |
| Timeout - The length of timeout period. | |
| SenseData - A pointer to output sense data. | |
| SenseDataLength - The length of output sense data. | |
| HostAdapterStatus - The status of Host Adapter. | |
| TargetStatus - The status of the target. | |
| DataBuffer - A pointer to a data buffer. | |
| DataLength - The length of data buffer. | |
| PMI - Partial medium indicator. | |
| Returns: | |
| Returns: | |
| EFI_SUCCESS - The status of the unit is tested successfully. | |
| EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed, | |
| but the entire DataBuffer could not be transferred. | |
| The actual number of bytes transferred is returned | |
| in TransferLength. | |
| EFI_NOT_READY - The SCSI Request Packet could not be sent because | |
| there are too many SCSI Command Packets already | |
| queued. | |
| EFI_DEVICE_ERROR - A device error occurred while attempting to send | |
| the SCSI Request Packet. | |
| EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid. | |
| EFI_UNSUPPORTED - The command described by the SCSI Request Packet | |
| is not supported by the SCSI initiator(i.e., SCSI | |
| Host Controller). | |
| EFI_TIMEOUT - A timeout occurred while waiting for the SCSI | |
| Request Packet to execute. | |
| --*/ | |
| { | |
| EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket; | |
| UINT64 Lun; | |
| UINT32 Target; | |
| EFI_STATUS Status; | |
| UINT8 Cdb[10]; | |
| ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET)); | |
| ZeroMem (Cdb, 10); | |
| CommandPacket.Timeout = Timeout; | |
| CommandPacket.DataBuffer = DataBuffer; | |
| CommandPacket.SenseData = SenseData; | |
| CommandPacket.TransferLength = *DataLength; | |
| CommandPacket.Cdb = Cdb; | |
| // | |
| // Fill Cdb for Read Capacity Command | |
| // | |
| ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun); | |
| Cdb[0] = EFI_SCSI_OP_READ_CAPACITY; | |
| Cdb[1] = (UINT8) (Lun & 0xe0); | |
| 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 = 10; | |
| 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.TransferLength; | |
| return Status; | |
| } | |
| EFI_STATUS | |
| SubmitRead10Command ( | |
| IN EFI_SCSI_IO_PROTOCOL *ScsiIo, | |
| IN UINT64 Timeout, | |
| IN VOID *SenseData, | |
| IN OUT UINT8 *SenseDataLength, | |
| OUT UINT8 *HostAdapterStatus, | |
| OUT UINT8 *TargetStatus, | |
| OUT VOID *DataBuffer, | |
| IN OUT UINT32 *DataLength, | |
| IN UINT32 StartLba, | |
| IN UINT32 SectorSize | |
| ) | |
| /*++ | |
| Routine Description: | |
| Function to submit read 10 command. | |
| Arguments: | |
| ScsiIo - A pointer to SCSI IO protocol. | |
| Timeout - The length of timeout period. | |
| SenseData - A pointer to output sense data. | |
| SenseDataLength - The length of output sense data. | |
| HostAdapterStatus - The status of Host Adapter. | |
| TargetStatus - The status of the target. | |
| DataBuffer - A pointer to a data buffer. | |
| DataLength - The length of data buffer. | |
| StartLba - The start address of LBA. | |
| SectorSize - The sector size. | |
| Returns: | |
| Returns: | |
| EFI_SUCCESS - The status of the unit is tested successfully. | |
| EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed, | |
| but the entire DataBuffer could not be transferred. | |
| The actual number of bytes transferred is returned | |
| in TransferLength. | |
| EFI_NOT_READY - The SCSI Request Packet could not be sent because | |
| there are too many SCSI Command Packets already | |
| queued. | |
| EFI_DEVICE_ERROR - A device error occurred while attempting to send | |
| the SCSI Request Packet. | |
| EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid. | |
| EFI_UNSUPPORTED - The command described by the SCSI Request Packet | |
| is not supported by the SCSI initiator(i.e., SCSI | |
| Host Controller). | |
| EFI_TIMEOUT - A timeout occurred while waiting for the SCSI | |
| Request Packet to execute. | |
| --*/ | |
| { | |
| EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket; | |
| UINT64 Lun; | |
| UINT32 Target; | |
| EFI_STATUS Status; | |
| UINT8 Cdb[10]; | |
| ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET)); | |
| ZeroMem (Cdb, 10); | |
| CommandPacket.Timeout = Timeout; | |
| CommandPacket.DataBuffer = DataBuffer; | |
| CommandPacket.SenseData = SenseData; | |
| CommandPacket.TransferLength = *DataLength; | |
| CommandPacket.Cdb = Cdb; | |
| // | |
| // Fill Cdb for Read (10) Command | |
| // | |
| ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun); | |
| Cdb[0] = EFI_SCSI_OP_READ10; | |
| Cdb[1] = (UINT8) (Lun & 0xe0); | |
| Cdb[2] = (UINT8) (StartLba >> 24); | |
| Cdb[3] = (UINT8) (StartLba >> 16); | |
| Cdb[4] = (UINT8) (StartLba >> 8); | |
| Cdb[5] = (UINT8) StartLba; | |
| Cdb[7] = (UINT8) (SectorSize >> 8); | |
| Cdb[8] = (UINT8) SectorSize; | |
| CommandPacket.CdbLength = 10; | |
| 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.TransferLength; | |
| return Status; | |
| } | |
| EFI_STATUS | |
| SubmitWrite10Command ( | |
| IN EFI_SCSI_IO_PROTOCOL *ScsiIo, | |
| IN UINT64 Timeout, | |
| IN VOID *SenseData, | |
| IN OUT UINT8 *SenseDataLength, | |
| OUT UINT8 *HostAdapterStatus, | |
| OUT UINT8 *TargetStatus, | |
| OUT VOID *DataBuffer, | |
| IN OUT UINT32 *DataLength, | |
| IN UINT32 StartLba, | |
| IN UINT32 SectorSize | |
| ) | |
| /*++ | |
| Routine Description: | |
| Function to submit SCSI write 10 command. | |
| Arguments: | |
| ScsiIo - A pointer to SCSI IO protocol. | |
| Timeout - The length of timeout period. | |
| SenseData - A pointer to output sense data. | |
| SenseDataLength - The length of output sense data. | |
| HostAdapterStatus - The status of Host Adapter. | |
| TargetStatus - The status of the target. | |
| DataBuffer - A pointer to a data buffer. | |
| DataLength - The length of data buffer. | |
| StartLba - The start address of LBA. | |
| SectorSize - The sector size. | |
| Returns: | |
| Returns: | |
| EFI_SUCCESS - The status of the unit is tested successfully. | |
| EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed, | |
| but the entire DataBuffer could not be transferred. | |
| The actual number of bytes transferred is returned | |
| in InTransferLength. | |
| EFI_NOT_READY - The SCSI Request Packet could not be sent because | |
| there are too many SCSI Command Packets already | |
| queued. | |
| EFI_DEVICE_ERROR - A device error occurred while attempting to send | |
| the SCSI Request Packet. | |
| EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid. | |
| EFI_UNSUPPORTED - The command described by the SCSI Request Packet | |
| is not supported by the SCSI initiator(i.e., SCSI | |
| Host Controller). | |
| EFI_TIMEOUT - A timeout occurred while waiting for the SCSI | |
| Request Packet to execute. | |
| --*/ | |
| { | |
| EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket; | |
| UINT64 Lun; | |
| UINT32 Target; | |
| EFI_STATUS Status; | |
| UINT8 Cdb[10]; | |
| ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET)); | |
| ZeroMem (Cdb, 10); | |
| CommandPacket.Timeout = Timeout; | |
| CommandPacket.DataBuffer = DataBuffer; | |
| CommandPacket.SenseData = SenseData; | |
| CommandPacket.TransferLength = *DataLength; | |
| CommandPacket.Cdb = Cdb; | |
| // | |
| // Fill Cdb for Write (10) Command | |
| // | |
| ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun); | |
| Cdb[0] = EFI_SCSI_OP_WRITE10; | |
| Cdb[1] = (UINT8) (Lun & 0xe0); | |
| Cdb[2] = (UINT8) (StartLba >> 24); | |
| Cdb[3] = (UINT8) (StartLba >> 16); | |
| Cdb[4] = (UINT8) (StartLba >> 8); | |
| Cdb[5] = (UINT8) StartLba; | |
| Cdb[7] = (UINT8) (SectorSize >> 8); | |
| Cdb[8] = (UINT8) SectorSize; | |
| CommandPacket.CdbLength = 10; | |
| 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.TransferLength; | |
| return Status; | |
| } |