+/**\r
+ Function to submit read capacity16 command.\r
+\r
+ @param ScsiIo A pointer to SCSI IO protocol.\r
+ @param Timeout The length of timeout period.\r
+ @param SenseData A pointer to output sense data.\r
+ @param SenseDataLength The length of output sense data.\r
+ @param HostAdapterStatus The status of Host Adapter.\r
+ @param TargetStatus The status of the target.\r
+ @param DataBuffer A pointer to a data buffer.\r
+ @param DataLength The length of data buffer.\r
+ @param PMI Partial medium indicator.\r
+\r
+ @retval EFI_SUCCESS The status of the unit is tested successfully.\r
+ @retval 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
+ @retval EFI_NOT_READY The SCSI Request Packet could not be sent because \r
+ there are too many SCSI Command Packets already \r
+ queued.\r
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to send \r
+ the SCSI Request Packet.\r
+ @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid. \r
+ @retval 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
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI \r
+ Request Packet to execute.\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ScsiReadCapacity16Command (\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
+ 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[16];\r
+\r
+ ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
+ ZeroMem (Cdb, 16);\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_CAPACITY16;\r
+ Cdb[1] = 0x10;\r
+ if (!PMI) {\r
+ //\r
+ // Partial medium indicator,if PMI is FALSE, the Cdb.2 ~ Cdb.9 MUST BE ZERO.\r
+ //\r
+ ZeroMem ((Cdb + 2), 8);\r
+ } else {\r
+ Cdb[14] |= 0x01;\r
+ }\r
+\r
+ Cdb[13] = 0x20;\r
+ CommandPacket.CdbLength = 16;\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
+\r