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