]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/UefiScsiLib/UefiScsiLib.c
Minor grammatical work--mostly adding periods. Items with ONLY period added did...
[mirror_edk2.git] / MdePkg / Library / UefiScsiLib / UefiScsiLib.c
CommitLineData
bf231ea6
A
1/** @file\r
2 UEFI SCSI Library implementation\r
3\r
a24faca3 4 Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
19388d29 5 This program and the accompanying materials \r
bf231ea6
A
6 are licensed and made available under the terms and conditions of the BSD License \r
7 which accompanies this distribution. The full text of the license may be found at \r
2fc59a00 8 http://opensource.org/licenses/bsd-license.php. \r
bf231ea6
A
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
12\r
13**/\r
a02e796b 14\r
bf231ea6 15\r
60c93673 16#include <Uefi.h>\r
3e0c79b5 17#include <Library/BaseLib.h>\r
306431f7 18#include <Library/DebugLib.h>\r
172ea7c7 19#include <Library/UefiScsiLib.h>\r
a02e796b 20#include <Library/BaseMemoryLib.h>\r
d5954c61 21 \r
a3589760 22#include <IndustryStandard/Scsi.h>\r
d5954c61 23 \r
24 \r
25 //\r
26 // Max bytes needed to represent ID of a SCSI device\r
27 //\r
dfc5aca1 28#define EFI_SCSI_TARGET_MAX_BYTES (0x10)\r
d5954c61 29 \r
30 //\r
31 // bit5..7 are for Logical unit number\r
32 // 11100000b (0xe0)\r
33 //\r
52cd71dc 34#define EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK 0xe0\r
d5954c61 35 \r
36 //\r
a24faca3 37 // Scsi Command Length\r
d5954c61 38 //\r
a24faca3 39#define EFI_SCSI_OP_LENGTH_SIX 0x6\r
40#define EFI_SCSI_OP_LENGTH_TEN 0xa\r
41#define EFI_SCSI_OP_LENGTH_SIXTEEN 0x10\r
bf231ea6 42\r
b91d5eca 43\r
b91d5eca 44\r
d5954c61 45/**\r
46 Execute Test Unit Ready SCSI command on a specific SCSI target.\r
b91d5eca 47\r
d5954c61 48 Executes the Test Unit Ready command on the SCSI target specified by ScsiIo.\r
49 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
50 If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.\r
51 If ScsiIo is NULL, then ASSERT().\r
52 If SenseDataLength is NULL, then ASSERT().\r
52cd71dc
LG
53 If HostAdapterStatus is NULL, then ASSERT().\r
54 If TargetStatus is NULL, then ASSERT().\r
a3589760 55\r
d5954c61 56\r
57 @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance\r
58 for the specific SCSI target.\r
59 @param[in] Timeout The timeout in 100 ns units to use for the execution\r
60 of this SCSI Request Packet. A Timeout value of\r
61 zero means that this function will wait indefinitely\r
62 for the SCSI Request Packet to execute. If Timeout\r
63 is greater than zero, then this function will return\r
64 EFI_TIMEOUT if the time required to execute the SCSI\r
65 Request Packet is greater than Timeout.\r
66 @param[in, out] SenseData A pointer to sense data that was generated by\r
67 the execution of the SCSI Request Packet. This\r
68 buffer must be allocated by the caller.\r
69 If SenseDataLength is 0, then this parameter is\r
70 optional and may be NULL.\r
71 @param[in, out] SenseDataLength On input, a pointer to the length in bytes of\r
9ccbe812 72 the SenseData buffer. On output, a pointer to\r
d5954c61 73 the number of bytes written to the SenseData buffer. \r
74 @param[out] HostAdapterStatus The status of the SCSI Host Controller that produces\r
75 the SCSI bus containing the SCSI target specified by\r
76 ScsiIo when the SCSI Request Packet was executed.\r
77 See the EFI SCSI I/O Protocol in the UEFI Specification\r
78 for details on the possible return values.\r
79 @param[out] TargetStatus The status returned by the SCSI target specified\r
9ccbe812 80 by ScsiIo when the SCSI Request Packet was executed\r
d5954c61 81 on the SCSI Host Controller. See the EFI SCSI I/O\r
82 Protocol in the UEFI Specification for details on\r
83 the possible return values. \r
84\r
85 @retval EFI_SUCCESS The command was executed successfully.\r
86 See HostAdapterStatus, TargetStatus, SenseDataLength,\r
87 and SenseData in that order for additional status\r
88 information.\r
89 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because\r
90 there are too many SCSI Command Packets already\r
91 queued. The SCSI Request Packet was not sent, so\r
92 no additional status information is available.\r
93 The caller may retry again later.\r
94 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send\r
95 SCSI Request Packet. See HostAdapterStatus,\r
96 TargetStatus, SenseDataLength, and SenseData in that\r
97 order for additional status information.\r
98 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet\r
99 is not supported by the SCSI initiator(i.e., SCSI\r
100 Host Controller). The SCSI Request Packet was not\r
101 sent, so no additional status information is available.\r
102 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request\r
103 Packet to execute. See HostAdapterStatus, TargetStatus,\r
104 SenseDataLength, and SenseData in that order for\r
105 additional status information.\r
a3589760 106\r
bf231ea6 107**/\r
a02e796b 108EFI_STATUS\r
373b5cf9 109EFIAPI\r
d35be2a4 110ScsiTestUnitReadyCommand (\r
d5954c61 111 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
112 IN UINT64 Timeout,\r
113 IN OUT VOID *SenseData, OPTIONAL\r
114 IN OUT UINT8 *SenseDataLength,\r
115 OUT UINT8 *HostAdapterStatus,\r
116 OUT UINT8 *TargetStatus\r
a02e796b 117 )\r
a02e796b 118{\r
119 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
6b3ecf5c 120 UINT64 Lun;\r
121 UINT8 *Target;\r
122 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];\r
a02e796b 123 EFI_STATUS Status;\r
52cd71dc 124 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];\r
a02e796b 125\r
8069d49e
LG
126 ASSERT (SenseDataLength != NULL);\r
127 ASSERT (HostAdapterStatus != NULL);\r
128 ASSERT (TargetStatus != NULL);\r
d5954c61 129 ASSERT (ScsiIo != NULL);\r
a02e796b 130\r
131 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
52cd71dc 132 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX);\r
a02e796b 133\r
134 CommandPacket.Timeout = Timeout;\r
135 CommandPacket.InDataBuffer = NULL;\r
136 CommandPacket.InTransferLength= 0;\r
137 CommandPacket.OutDataBuffer = NULL;\r
138 CommandPacket.OutTransferLength= 0;\r
139 CommandPacket.SenseData = SenseData;\r
140 CommandPacket.Cdb = Cdb;\r
141 //\r
142 // Fill Cdb for Test Unit Ready Command\r
143 //\r
6b3ecf5c 144 Target = &TargetArray[0];\r
145 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);\r
146\r
a02e796b 147 Cdb[0] = EFI_SCSI_OP_TEST_UNIT_READY;\r
3e0c79b5 148 Cdb[1] = (UINT8) (LShiftU64 (Lun, 5) & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);\r
52cd71dc 149 CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX;\r
a02e796b 150 CommandPacket.SenseDataLength = *SenseDataLength;\r
151\r
152 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
153\r
154 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
155 *TargetStatus = CommandPacket.TargetStatus;\r
156 *SenseDataLength = CommandPacket.SenseDataLength;\r
157\r
158 return Status;\r
159}\r
160\r
bf231ea6 161\r
a3589760 162/**\r
d5954c61 163 Execute Inquiry SCSI command on a specific SCSI target.\r
b91d5eca 164\r
d5954c61 165 Executes the Inquiry command on the SCSI target specified by ScsiIo.\r
166 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
167 If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.\r
168 If ScsiIo is NULL, then ASSERT().\r
52cd71dc
LG
169 If SenseDataLength is NULL, then ASSERT().\r
170 If HostAdapterStatus is NULL, then ASSERT().\r
171 If TargetStatus is NULL, then ASSERT().\r
172 If InquiryDataLength is NULL, then ASSERT().\r
a3589760 173\r
d5954c61 174 @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance\r
175 for the specific SCSI target.\r
176 @param[in] Timeout The timeout in 100 ns units to use for the\r
177 execution of this SCSI Request Packet. A Timeout\r
178 value of zero means that this function will wait\r
179 indefinitely for the SCSI Request Packet to execute.\r
180 If Timeout is greater than zero, then this function\r
181 will return EFI_TIMEOUT if the time required to\r
182 execute the SCSI Request Packet is greater than Timeout.\r
183 @param[in, out] SenseData A pointer to sense data that was generated\r
184 by the execution of the SCSI Request Packet.\r
185 This buffer must be allocated by the caller.\r
186 If SenseDataLength is 0, then this parameter\r
187 is optional and may be NULL.\r
188 @param[in, out] SenseDataLength On input, the length in bytes of the SenseData buffer.\r
189 On output, the number of bytes written to the SenseData buffer. \r
190 @param[out] HostAdapterStatus The status of the SCSI Host Controller that\r
191 produces the SCSI bus containing the SCSI\r
192 target specified by ScsiIo when the SCSI\r
193 Request Packet was executed. See the EFI\r
194 SCSI I/O Protocol in the UEFI Specification\r
195 for details on the possible return values.\r
196 @param[out] TargetStatus The status returned by the SCSI target specified\r
070a76b1 197 by ScsiIo when the SCSI Request Packet was\r
d5954c61 198 executed on the SCSI Host Controller.\r
199 See the EFI SCSI I/O Protocol in the UEFI\r
200 Specification for details on the possible\r
201 return values. \r
202 @param[in, out] InquiryDataBuffer A pointer to inquiry data that was generated\r
203 by the execution of the SCSI Request Packet.\r
204 This buffer must be allocated by the caller.\r
205 If InquiryDataLength is 0, then this parameter\r
206 is optional and may be NULL. \r
207 @param[in, out] InquiryDataLength On input, a pointer to the length in bytes\r
208 of the InquiryDataBuffer buffer.\r
209 On output, a pointer to the number of bytes\r
210 written to the InquiryDataBuffer buffer.\r
211 @param[in] EnableVitalProductData If TRUE, then the supported vital product\r
212 data is returned in InquiryDataBuffer.\r
213 If FALSE, then the standard inquiry data is\r
214 returned in InquiryDataBuffer. \r
215\r
216 @retval EFI_SUCCESS The command was executed successfully. See HostAdapterStatus,\r
217 TargetStatus, SenseDataLength, and SenseData in that order\r
218 for additional status information.\r
219 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire\r
220 InquiryDataBuffer could not be transferred. The actual\r
221 number of bytes transferred is returned in InquiryDataLength.\r
222 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there\r
223 are too many SCSI Command Packets already queued.\r
224 The SCSI Request Packet was not sent, so no additional\r
225 status information is available. The caller may retry again later.\r
226 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI\r
227 Request Packet. See HostAdapterStatus, TargetStatus,\r
228 SenseDataLength, and SenseData in that order for additional\r
229 status information.\r
230 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not\r
231 supported by the SCSI initiator(i.e., SCSI Host Controller).\r
232 The SCSI Request Packet was not sent, so no additional\r
233 status information is available.\r
234 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request\r
235 Packet to execute. See HostAdapterStatus, TargetStatus,\r
236 SenseDataLength, and SenseData in that order for\r
237 additional status information.\r
a3589760 238\r
bf231ea6 239**/\r
a02e796b 240EFI_STATUS\r
373b5cf9 241EFIAPI\r
d35be2a4 242ScsiInquiryCommand (\r
d5954c61 243 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
244 IN UINT64 Timeout,\r
245 IN OUT VOID *SenseData, OPTIONAL\r
246 IN OUT UINT8 *SenseDataLength,\r
247 OUT UINT8 *HostAdapterStatus,\r
248 OUT UINT8 *TargetStatus,\r
249 IN OUT VOID *InquiryDataBuffer, OPTIONAL\r
250 IN OUT UINT32 *InquiryDataLength,\r
251 IN BOOLEAN EnableVitalProductData\r
a02e796b 252 )\r
a02e796b 253{\r
254 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
6b3ecf5c 255 UINT64 Lun;\r
256 UINT8 *Target;\r
257 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];\r
a02e796b 258 EFI_STATUS Status;\r
52cd71dc 259 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];\r
a02e796b 260\r
8069d49e
LG
261 ASSERT (SenseDataLength != NULL);\r
262 ASSERT (HostAdapterStatus != NULL);\r
263 ASSERT (TargetStatus != NULL);\r
264 ASSERT (InquiryDataLength != NULL);\r
d5954c61 265 ASSERT (ScsiIo != NULL);\r
8069d49e 266\r
a02e796b 267 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
52cd71dc 268 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX);\r
a02e796b 269\r
270 CommandPacket.Timeout = Timeout;\r
271 CommandPacket.InDataBuffer = InquiryDataBuffer;\r
272 CommandPacket.InTransferLength= *InquiryDataLength;\r
273 CommandPacket.SenseData = SenseData;\r
274 CommandPacket.SenseDataLength = *SenseDataLength;\r
275 CommandPacket.Cdb = Cdb;\r
276\r
6b3ecf5c 277 Target = &TargetArray[0];\r
278 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);\r
279\r
a02e796b 280 Cdb[0] = EFI_SCSI_OP_INQUIRY;\r
3e0c79b5 281 Cdb[1] = (UINT8) (LShiftU64 (Lun, 5) & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);\r
a02e796b 282 if (EnableVitalProductData) {\r
283 Cdb[1] |= 0x01;\r
284 }\r
285\r
286 if (*InquiryDataLength > 0xff) {\r
287 *InquiryDataLength = 0xff;\r
288 }\r
289\r
290 Cdb[4] = (UINT8) (*InquiryDataLength);\r
52cd71dc 291 CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX;\r
a02e796b 292 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
293\r
294 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
295\r
296 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
297 *TargetStatus = CommandPacket.TargetStatus;\r
298 *SenseDataLength = CommandPacket.SenseDataLength;\r
299 *InquiryDataLength = CommandPacket.InTransferLength;\r
300\r
301 return Status;\r
302}\r
303\r
bf231ea6 304\r
a3589760 305/**\r
d5954c61 306 Execute Mode Sense(10) SCSI command on a specific SCSI target.\r
307\r
308 Executes the SCSI Mode Sense(10) command on the SCSI target specified by ScsiIo.\r
309 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
310 If Timeout is greater than zero, then the command is executed and will timeout\r
311 after Timeout 100 ns units. The DBDField, PageControl, and PageCode parameters\r
312 are used to construct the CDB for this SCSI command.\r
313 If ScsiIo is NULL, then ASSERT().\r
52cd71dc
LG
314 If SenseDataLength is NULL, then ASSERT().\r
315 If HostAdapterStatus is NULL, then ASSERT().\r
316 If TargetStatus is NULL, then ASSERT().\r
317 If DataLength is NULL, then ASSERT().\r
a3589760 318\r
d5954c61 319\r
320 @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance\r
321 for the specific SCSI target.\r
322 @param[in] Timeout The timeout in 100 ns units to use for the\r
323 execution of this SCSI Request Packet. A Timeout\r
324 value of zero means that this function will wait\r
325 indefinitely for the SCSI Request Packet to execute.\r
326 If Timeout is greater than zero, then this function\r
327 will return EFI_TIMEOUT if the time required to\r
328 execute the SCSI Request Packet is greater than Timeout.\r
6089ba62 329 @param[in, out] SenseData A pointer to sense data that was generated\r
d5954c61 330 by the execution of the SCSI Request Packet.\r
331 This buffer must be allocated by the caller.\r
332 If SenseDataLength is 0, then this parameter\r
333 is optional and may be NULL.\r
6089ba62 334 @param[in, out] SenseDataLength On input, the length in bytes of the SenseData buffer.\r
d5954c61 335 On output, the number of bytes written to the SenseData buffer. \r
336 @param[out] HostAdapterStatus The status of the SCSI Host Controller that\r
337 produces the SCSI bus containing the SCSI target\r
338 specified by ScsiIo when the SCSI Request Packet\r
339 was executed. See the EFI SCSI I/O Protocol in the\r
340 UEFI Specification for details on the possible\r
341 return values.\r
342 @param[out] TargetStatus The status returned by the SCSI target specified\r
070a76b1 343 by ScsiIo when the SCSI Request Packet was executed\r
d5954c61 344 on the SCSI Host Controller. See the EFI SCSI\r
345 I/O Protocol in the UEFI Specification for details\r
346 on the possible return values.\r
347 @param[in, out] DataBuffer A pointer to data that was generated by the\r
348 execution of the SCSI Request Packet. This\r
349 buffer must be allocated by the caller. If\r
350 DataLength is 0, then this parameter is optional\r
351 and may be NULL. \r
352 @param[in, out] DataLength On input, a pointer to the length in bytes of\r
353 the DataBuffer buffer. On output, a pointer\r
354 to the number of bytes written to the DataBuffer\r
355 buffer. \r
356 @param[in] DBDField Specifies the DBD field of the CDB for this SCSI Command.\r
357 @param[in] PageControl Specifies the PC field of the CDB for this SCSI Command. \r
358 @param[in] PageCode Specifies the Page Control field of the CDB for this SCSI Command. \r
359\r
360 @retval EFI_SUCCESS The command was executed successfully.\r
361 See HostAdapterStatus, TargetStatus, SenseDataLength,\r
362 and SenseData in that order for additional status information.\r
363 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the\r
364 entire DataBuffer could not be transferred.\r
bf231ea6 365 The actual number of bytes transferred is returned\r
d5954c61 366 in DataLength.\r
367 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because\r
368 there are too many SCSI Command Packets already queued.\r
369 The SCSI Request Packet was not sent, so no additional\r
370 status information is available. The caller may retry\r
371 again later.\r
372 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send\r
373 SCSI Request Packet. See HostAdapterStatus, TargetStatus,\r
374 SenseDataLength, and SenseData in that order for\r
375 additional status information.\r
bf231ea6 376 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet\r
d5954c61 377 is not supported by the SCSI initiator(i.e., SCSI\r
378 Host Controller). The SCSI Request Packet was not\r
379 sent, so no additional status information is available.\r
380 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI\r
381 Request Packet to execute. See HostAdapterStatus,\r
382 TargetStatus, SenseDataLength, and SenseData in that\r
383 order for additional status information.\r
a3589760 384\r
bf231ea6 385**/\r
a02e796b 386EFI_STATUS\r
373b5cf9 387EFIAPI\r
d35be2a4 388ScsiModeSense10Command (\r
d5954c61 389 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
390 IN UINT64 Timeout,\r
391 IN OUT VOID *SenseData, OPTIONAL\r
392 IN OUT UINT8 *SenseDataLength,\r
393 OUT UINT8 *HostAdapterStatus,\r
394 OUT UINT8 *TargetStatus,\r
395 IN OUT VOID *DataBuffer, OPTIONAL\r
396 IN OUT UINT32 *DataLength,\r
397 IN UINT8 DBDField, OPTIONAL\r
398 IN UINT8 PageControl,\r
399 IN UINT8 PageCode\r
a02e796b 400 )\r
a02e796b 401{\r
402 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
6b3ecf5c 403 UINT64 Lun;\r
404 UINT8 *Target;\r
405 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];\r
a02e796b 406 EFI_STATUS Status;\r
52cd71dc 407 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];\r
a02e796b 408\r
8069d49e
LG
409 ASSERT (SenseDataLength != NULL);\r
410 ASSERT (HostAdapterStatus != NULL);\r
411 ASSERT (TargetStatus != NULL);\r
412 ASSERT (DataLength != NULL);\r
d5954c61 413 ASSERT (ScsiIo != NULL);\r
8069d49e 414\r
a02e796b 415 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
52cd71dc 416 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);\r
a02e796b 417\r
418 CommandPacket.Timeout = Timeout;\r
419 CommandPacket.InDataBuffer = DataBuffer;\r
420 CommandPacket.SenseData = SenseData;\r
421 CommandPacket.InTransferLength= *DataLength;\r
422 CommandPacket.Cdb = Cdb;\r
423 //\r
424 // Fill Cdb for Mode Sense (10) Command\r
425 //\r
6b3ecf5c 426 Target = &TargetArray[0];\r
427 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);\r
428\r
a02e796b 429 Cdb[0] = EFI_SCSI_OP_MODE_SEN10;\r
52cd71dc
LG
430 //\r
431 // DBDField is in Cdb[1] bit3 of (bit7..0)\r
432 //\r
3e0c79b5 433 Cdb[1] = (UINT8) ((LShiftU64 (Lun, 5) & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK) + ((DBDField << 3) & 0x08));\r
52cd71dc
LG
434 //\r
435 // PageControl is in Cdb[2] bit7..6, PageCode is in Cdb[2] bit5..0\r
436 //\r
6b3ecf5c 437 Cdb[2] = (UINT8) (((PageControl << 6) & 0xc0) | (PageCode & 0x3f));\r
a02e796b 438 Cdb[7] = (UINT8) (*DataLength >> 8);\r
439 Cdb[8] = (UINT8) (*DataLength);\r
440\r
52cd71dc 441 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;\r
a02e796b 442 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
443 CommandPacket.SenseDataLength = *SenseDataLength;\r
444\r
445 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
446\r
447 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
448 *TargetStatus = CommandPacket.TargetStatus;\r
449 *SenseDataLength = CommandPacket.SenseDataLength;\r
450 *DataLength = CommandPacket.InTransferLength;\r
451\r
452 return Status;\r
453}\r
454\r
bf231ea6 455\r
a3589760 456/**\r
d5954c61 457 Execute Request Sense SCSI command on a specific SCSI target.\r
b91d5eca 458\r
d5954c61 459 Executes the Request Sense command on the SCSI target specified by ScsiIo.\r
460 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
461 If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.\r
462 If ScsiIo is NULL, then ASSERT().\r
52cd71dc
LG
463 If SenseDataLength is NULL, then ASSERT().\r
464 If HostAdapterStatus is NULL, then ASSERT().\r
465 If TargetStatus is NULL, then ASSERT().\r
a3589760 466\r
b91d5eca 467 @param[in] ScsiIo A pointer to SCSI IO protocol.\r
468 @param[in] Timeout The length of timeout period.\r
d5954c61 469 @param[in, out] SenseData A pointer to output sense data.\r
470 @param[in, out] SenseDataLength The length of output sense data.\r
b91d5eca 471 @param[out] HostAdapterStatus The status of Host Adapter.\r
472 @param[out] TargetStatus The status of the target.\r
473\r
474 @retval EFI_SUCCESS Command is executed successfully.\r
475 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are\r
476 too many SCSI Command Packets already queued.\r
477 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
478 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by\r
479 the SCSI initiator(i.e., SCSI Host Controller)\r
480 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
a3589760 481\r
bf231ea6 482**/\r
a02e796b 483EFI_STATUS\r
373b5cf9 484EFIAPI\r
d35be2a4 485ScsiRequestSenseCommand (\r
d5954c61 486 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
487 IN UINT64 Timeout,\r
488 IN OUT VOID *SenseData, OPTIONAL\r
489 IN OUT UINT8 *SenseDataLength,\r
490 OUT UINT8 *HostAdapterStatus,\r
491 OUT UINT8 *TargetStatus\r
a02e796b 492 )\r
a02e796b 493{\r
494 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
6b3ecf5c 495 UINT64 Lun;\r
496 UINT8 *Target;\r
497 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];\r
a02e796b 498 EFI_STATUS Status;\r
52cd71dc 499 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];\r
a02e796b 500\r
8069d49e
LG
501 ASSERT (SenseDataLength != NULL);\r
502 ASSERT (HostAdapterStatus != NULL);\r
503 ASSERT (TargetStatus != NULL);\r
d5954c61 504 ASSERT (ScsiIo != NULL);\r
8069d49e 505\r
a02e796b 506 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
52cd71dc 507 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX);\r
a02e796b 508\r
509 CommandPacket.Timeout = Timeout;\r
510 CommandPacket.InDataBuffer = SenseData;\r
511 CommandPacket.SenseData = NULL;\r
512 CommandPacket.InTransferLength= *SenseDataLength;\r
513 CommandPacket.Cdb = Cdb;\r
514 //\r
515 // Fill Cdb for Request Sense Command\r
516 //\r
6b3ecf5c 517 Target = &TargetArray[0];\r
518 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);\r
519\r
a02e796b 520 Cdb[0] = EFI_SCSI_OP_REQUEST_SENSE;\r
3e0c79b5 521 Cdb[1] = (UINT8) (LShiftU64 (Lun, 5) & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);\r
a02e796b 522 Cdb[4] = (UINT8) (*SenseDataLength);\r
523\r
52cd71dc 524 CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX;\r
a02e796b 525 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
526 CommandPacket.SenseDataLength = 0;\r
527\r
528 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
529\r
530 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
531 *TargetStatus = CommandPacket.TargetStatus;\r
532 *SenseDataLength = (UINT8) CommandPacket.InTransferLength;\r
533\r
534 return Status;\r
535}\r
536\r
bf231ea6 537\r
a3589760 538/**\r
d5954c61 539 Execute Read Capacity SCSI command on a specific SCSI target.\r
b91d5eca 540\r
d5954c61 541 Executes the SCSI Read Capacity command on the SCSI target specified by ScsiIo.\r
542 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
543 If Timeout is greater than zero, then the command is executed and will timeout after\r
51969ecb 544 Timeout 100 ns units. The Pmi parameter is used to construct the CDB for this SCSI command.\r
d5954c61 545 If ScsiIo is NULL, then ASSERT().\r
52cd71dc
LG
546 If SenseDataLength is NULL, then ASSERT().\r
547 If HostAdapterStatus is NULL, then ASSERT().\r
548 If TargetStatus is NULL, then ASSERT().\r
549 If DataLength is NULL, then ASSERT().\r
bf231ea6 550\r
d5954c61 551 @param[in] ScsiIo A pointer to SCSI IO protocol.\r
552 @param[in] Timeout The length of timeout period.\r
553 @param[in, out] SenseData A pointer to output sense data.\r
ee256e2c 554 @param[in, out] SenseDataLength The length of output sense data.\r
d5954c61 555 @param[out] HostAdapterStatus The status of Host Adapter.\r
556 @param[out] TargetStatus The status of the target.\r
557 @param[in, out] DataBuffer A pointer to a data buffer.\r
ee256e2c 558 @param[in, out] DataLength The length of data buffer.\r
51969ecb 559 @param[in] Pmi Partial medium indicator.\r
b91d5eca 560\r
6089ba62 561 @retval EFI_SUCCESS Command is executed successfully.\r
562 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire\r
563 DataBuffer could not be transferred. The actual\r
564 number of bytes transferred is returned in DataLength.\r
565 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because\r
566 there are too many SCSI Command Packets already queued.\r
567 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
568 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet\r
569 is not supported by the SCSI initiator(i.e., SCSI Host Controller)\r
570 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
a3589760 571\r
bf231ea6 572**/\r
a02e796b 573EFI_STATUS\r
373b5cf9 574EFIAPI\r
d35be2a4 575ScsiReadCapacityCommand (\r
d5954c61 576 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
577 IN UINT64 Timeout,\r
578 IN OUT VOID *SenseData, OPTIONAL\r
579 IN OUT UINT8 *SenseDataLength,\r
580 OUT UINT8 *HostAdapterStatus,\r
581 OUT UINT8 *TargetStatus,\r
582 IN OUT VOID *DataBuffer, OPTIONAL\r
583 IN OUT UINT32 *DataLength,\r
51969ecb 584 IN BOOLEAN Pmi\r
a02e796b 585 )\r
a02e796b 586{\r
587 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
6b3ecf5c 588 UINT64 Lun;\r
589 UINT8 *Target;\r
590 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];\r
a02e796b 591 EFI_STATUS Status;\r
52cd71dc 592 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];\r
a02e796b 593\r
8069d49e
LG
594 ASSERT (SenseDataLength != NULL);\r
595 ASSERT (HostAdapterStatus != NULL);\r
596 ASSERT (TargetStatus != NULL);\r
597 ASSERT (DataLength != NULL);\r
d5954c61 598 ASSERT (ScsiIo != NULL);\r
8069d49e 599\r
a02e796b 600 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
52cd71dc 601 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);\r
a02e796b 602\r
603 CommandPacket.Timeout = Timeout;\r
604 CommandPacket.InDataBuffer = DataBuffer;\r
605 CommandPacket.SenseData = SenseData;\r
606 CommandPacket.InTransferLength= *DataLength;\r
607 CommandPacket.Cdb = Cdb;\r
608 //\r
609 // Fill Cdb for Read Capacity Command\r
610 //\r
6b3ecf5c 611 Target = &TargetArray[0];\r
612 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);\r
613\r
a02e796b 614 Cdb[0] = EFI_SCSI_OP_READ_CAPACITY;\r
3e0c79b5 615 Cdb[1] = (UINT8) (LShiftU64 (Lun, 5) & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);\r
51969ecb 616 if (!Pmi) {\r
a02e796b 617 //\r
51969ecb 618 // Partial medium indicator,if Pmi is FALSE, the Cdb.2 ~ Cdb.5 MUST BE ZERO.\r
a02e796b 619 //\r
620 ZeroMem ((Cdb + 2), 4);\r
621 } else {\r
622 Cdb[8] |= 0x01;\r
623 }\r
624\r
52cd71dc 625 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;\r
a02e796b 626 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
627 CommandPacket.SenseDataLength = *SenseDataLength;\r
628\r
629 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
630\r
631 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
632 *TargetStatus = CommandPacket.TargetStatus;\r
633 *SenseDataLength = CommandPacket.SenseDataLength;\r
634 *DataLength = CommandPacket.InTransferLength;\r
635\r
636 return Status;\r
637}\r
638\r
bf231ea6 639\r
ccb491c8 640/**\r
5e11e7c6 641 Execute Read Capacity SCSI 16 command on a specific SCSI target.\r
642\r
643 Executes the SCSI Read Capacity 16 command on the SCSI target specified by ScsiIo.\r
644 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
645 If Timeout is greater than zero, then the command is executed and will timeout after\r
646 Timeout 100 ns units. The Pmi parameter is used to construct the CDB for this SCSI command.\r
647 If ScsiIo is NULL, then ASSERT().\r
648 If SenseDataLength is NULL, then ASSERT().\r
649 If HostAdapterStatus is NULL, then ASSERT().\r
650 If TargetStatus is NULL, then ASSERT().\r
651 If DataLength is NULL, then ASSERT().\r
652\r
653 @param[in] ScsiIo A pointer to SCSI IO protocol.\r
654 @param[in] Timeout The length of timeout period.\r
655 @param[in, out] SenseData A pointer to output sense data.\r
656 @param[in, out] SenseDataLength The length of output sense data.\r
657 @param[out] HostAdapterStatus The status of Host Adapter.\r
658 @param[out] TargetStatus The status of the target.\r
659 @param[in, out] DataBuffer A pointer to a data buffer.\r
660 @param[in, out] DataLength The length of data buffer.\r
661 @param[in] Pmi Partial medium indicator.\r
662\r
663 @retval EFI_SUCCESS Command is executed successfully.\r
664 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire\r
665 DataBuffer could not be transferred. The actual\r
666 number of bytes transferred is returned in DataLength.\r
667 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because\r
668 there are too many SCSI Command Packets already queued.\r
669 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
670 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet\r
671 is not supported by the SCSI initiator(i.e., SCSI Host Controller)\r
672 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
ccb491c8 673\r
674**/\r
ccb491c8 675EFI_STATUS\r
676EFIAPI\r
677ScsiReadCapacity16Command (\r
f158ee67 678 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
679 IN UINT64 Timeout,\r
680 IN OUT VOID *SenseData, OPTIONAL\r
681 IN OUT UINT8 *SenseDataLength,\r
682 OUT UINT8 *HostAdapterStatus,\r
683 OUT UINT8 *TargetStatus,\r
684 IN OUT VOID *DataBuffer, OPTIONAL\r
685 IN OUT UINT32 *DataLength,\r
686 IN BOOLEAN Pmi\r
ccb491c8 687 )\r
688{\r
689 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
6b3ecf5c 690 UINT64 Lun;\r
691 UINT8 *Target;\r
692 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];\r
ccb491c8 693 EFI_STATUS Status;\r
694 UINT8 Cdb[16];\r
695\r
5fe71b5f 696 ASSERT (SenseDataLength != NULL);\r
697 ASSERT (HostAdapterStatus != NULL);\r
698 ASSERT (TargetStatus != NULL);\r
699 ASSERT (DataLength != NULL);\r
700 ASSERT (ScsiIo != NULL);\r
701\r
ccb491c8 702 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
703 ZeroMem (Cdb, 16);\r
704\r
705 CommandPacket.Timeout = Timeout;\r
706 CommandPacket.InDataBuffer = DataBuffer;\r
707 CommandPacket.SenseData = SenseData;\r
708 CommandPacket.InTransferLength= *DataLength;\r
709 CommandPacket.Cdb = Cdb;\r
710 //\r
711 // Fill Cdb for Read Capacity Command\r
712 //\r
6b3ecf5c 713 Target = &TargetArray[0];\r
714 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);\r
715\r
ccb491c8 716 Cdb[0] = EFI_SCSI_OP_READ_CAPACITY16;\r
717 Cdb[1] = 0x10;\r
51969ecb 718 if (!Pmi) {\r
ccb491c8 719 //\r
51969ecb 720 // Partial medium indicator,if Pmi is FALSE, the Cdb.2 ~ Cdb.9 MUST BE ZERO.\r
ccb491c8 721 //\r
722 ZeroMem ((Cdb + 2), 8);\r
723 } else {\r
724 Cdb[14] |= 0x01;\r
725 }\r
726\r
727 Cdb[13] = 0x20;\r
728 CommandPacket.CdbLength = 16;\r
729 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
730 CommandPacket.SenseDataLength = *SenseDataLength;\r
731\r
732 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
733\r
734 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
735 *TargetStatus = CommandPacket.TargetStatus;\r
736 *SenseDataLength = CommandPacket.SenseDataLength;\r
737 *DataLength = CommandPacket.InTransferLength;\r
738\r
739 return Status;\r
740}\r
741\r
742\r
a3589760 743/**\r
d5954c61 744 Execute Read(10) SCSI command on a specific SCSI target.\r
745\r
746 Executes the SCSI Read(10) command on the SCSI target specified by ScsiIo.\r
747 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
748 If Timeout is greater than zero, then the command is executed and will timeout\r
749 after Timeout 100 ns units. The StartLba and SectorSize parameters are used to\r
750 construct the CDB for this SCSI command.\r
751 If ScsiIo is NULL, then ASSERT().\r
52cd71dc
LG
752 If SenseDataLength is NULL, then ASSERT().\r
753 If HostAdapterStatus is NULL, then ASSERT().\r
754 If TargetStatus is NULL, then ASSERT().\r
b91d5eca 755 If DataLength is NULL, then ASSERT().\r
a3589760 756\r
d5954c61 757\r
758 @param[in] ScsiIo A pointer to SCSI IO protocol.\r
759 @param[in] Timeout The length of timeout period.\r
760 @param[in, out] SenseData A pointer to output sense data.\r
ee256e2c 761 @param[in, out] SenseDataLength The length of output sense data.\r
d5954c61 762 @param[out] HostAdapterStatus The status of Host Adapter.\r
763 @param[out] TargetStatus The status of the target.\r
764 @param[in, out] DataBuffer Read 10 command data.\r
ee256e2c 765 @param[in, out] DataLength The length of data buffer.\r
d5954c61 766 @param[in] StartLba The start address of LBA.\r
767 @param[in] SectorSize The sector size.\r
b91d5eca 768\r
6089ba62 769 @retval EFI_SUCCESS Command is executed successfully.\r
770 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could\r
771 not be transferred. The actual number of bytes transferred is returned in DataLength.\r
772 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many \r
773 SCSI Command Packets already queued.\r
774 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
775 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by \r
776 the SCSI initiator(i.e., SCSI Host Controller)\r
777 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
a3589760 778\r
bf231ea6 779**/\r
a02e796b 780EFI_STATUS\r
373b5cf9 781EFIAPI\r
d35be2a4 782ScsiRead10Command (\r
d5954c61 783 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
784 IN UINT64 Timeout,\r
785 IN OUT VOID *SenseData, OPTIONAL\r
786 IN OUT UINT8 *SenseDataLength,\r
787 OUT UINT8 *HostAdapterStatus,\r
788 OUT UINT8 *TargetStatus,\r
789 IN OUT VOID *DataBuffer, OPTIONAL\r
790 IN OUT UINT32 *DataLength,\r
791 IN UINT32 StartLba,\r
792 IN UINT32 SectorSize\r
a02e796b 793 )\r
a02e796b 794{\r
795 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
6b3ecf5c 796 UINT64 Lun;\r
797 UINT8 *Target;\r
798 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];\r
a02e796b 799 EFI_STATUS Status;\r
52cd71dc 800 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];\r
a02e796b 801\r
8069d49e
LG
802 ASSERT (SenseDataLength != NULL);\r
803 ASSERT (HostAdapterStatus != NULL);\r
804 ASSERT (TargetStatus != NULL);\r
805 ASSERT (DataLength != NULL);\r
d5954c61 806 ASSERT (ScsiIo != NULL);\r
8069d49e 807\r
a02e796b 808 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
52cd71dc 809 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);\r
a02e796b 810\r
811 CommandPacket.Timeout = Timeout;\r
812 CommandPacket.InDataBuffer = DataBuffer;\r
813 CommandPacket.SenseData = SenseData;\r
814 CommandPacket.InTransferLength= *DataLength;\r
815 CommandPacket.Cdb = Cdb;\r
816 //\r
817 // Fill Cdb for Read (10) Command\r
818 //\r
6b3ecf5c 819 Target = &TargetArray[0];\r
820 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);\r
821\r
a02e796b 822 Cdb[0] = EFI_SCSI_OP_READ10;\r
3e0c79b5 823 Cdb[1] = (UINT8) (LShiftU64 (Lun, 5) & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);\r
a24faca3 824 WriteUnaligned32 ((UINT32 *)&Cdb[2], SwapBytes32 (StartLba));\r
825 WriteUnaligned16 ((UINT16 *)&Cdb[7], SwapBytes16 ((UINT16) SectorSize));\r
a02e796b 826\r
52cd71dc 827 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;\r
a02e796b 828 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
829 CommandPacket.SenseDataLength = *SenseDataLength;\r
830\r
831 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
832\r
833 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
834 *TargetStatus = CommandPacket.TargetStatus;\r
835 *SenseDataLength = CommandPacket.SenseDataLength;\r
836 *DataLength = CommandPacket.InTransferLength;\r
837\r
838 return Status;\r
839}\r
840\r
bf231ea6 841\r
a3589760 842/**\r
d5954c61 843 Execute Write(10) SCSI command on a specific SCSI target.\r
844\r
845 Executes the SCSI Write(10) command on the SCSI target specified by ScsiIo.\r
846 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
847 If Timeout is greater than zero, then the command is executed and will timeout after\r
848 Timeout 100 ns units. The StartLba and SectorSize parameters are used to construct\r
849 the CDB for this SCSI command.\r
850 If ScsiIo is NULL, then ASSERT().\r
52cd71dc
LG
851 If SenseDataLength is NULL, then ASSERT().\r
852 If HostAdapterStatus is NULL, then ASSERT().\r
853 If TargetStatus is NULL, then ASSERT().\r
b91d5eca 854 If DataLength is NULL, then ASSERT().\r
a3589760 855\r
d5954c61 856 @param[in] ScsiIo SCSI IO Protocol to use\r
857 @param[in] Timeout The length of timeout period.\r
858 @param[in, out] SenseData A pointer to output sense data.\r
6089ba62 859 @param[in, out] SenseDataLength The length of output sense data.\r
d5954c61 860 @param[out] HostAdapterStatus The status of Host Adapter.\r
861 @param[out] TargetStatus The status of the target.\r
862 @param[in, out] DataBuffer A pointer to a data buffer.\r
6089ba62 863 @param[in, out] DataLength The length of data buffer.\r
d5954c61 864 @param[in] StartLba The start address of LBA.\r
865 @param[in] SectorSize The sector size.\r
b91d5eca 866\r
6089ba62 867 @retval EFI_SUCCESS Command is executed successfully.\r
868 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could\r
869 not be transferred. The actual number of bytes transferred is returned in DataLength.\r
870 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many \r
871 SCSI Command Packets already queued.\r
872 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
873 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by \r
874 the SCSI initiator(i.e., SCSI Host Controller)\r
875 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
a3589760 876\r
bf231ea6 877**/\r
a02e796b 878EFI_STATUS\r
373b5cf9 879EFIAPI\r
d35be2a4 880ScsiWrite10Command (\r
d5954c61 881 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
882 IN UINT64 Timeout,\r
883 IN OUT VOID *SenseData, OPTIONAL\r
884 IN OUT UINT8 *SenseDataLength,\r
885 OUT UINT8 *HostAdapterStatus,\r
886 OUT UINT8 *TargetStatus,\r
887 IN OUT VOID *DataBuffer, OPTIONAL\r
888 IN OUT UINT32 *DataLength,\r
889 IN UINT32 StartLba,\r
890 IN UINT32 SectorSize\r
a02e796b 891 )\r
a02e796b 892{\r
893 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
6b3ecf5c 894 UINT64 Lun;\r
895 UINT8 *Target;\r
896 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];\r
a02e796b 897 EFI_STATUS Status;\r
52cd71dc 898 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];\r
a02e796b 899\r
8069d49e
LG
900 ASSERT (SenseDataLength != NULL);\r
901 ASSERT (HostAdapterStatus != NULL);\r
902 ASSERT (TargetStatus != NULL);\r
903 ASSERT (DataLength != NULL);\r
d5954c61 904 ASSERT (ScsiIo != NULL);\r
8069d49e 905\r
a02e796b 906 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
52cd71dc 907 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);\r
a02e796b 908\r
909 CommandPacket.Timeout = Timeout;\r
910 CommandPacket.OutDataBuffer = DataBuffer;\r
911 CommandPacket.SenseData = SenseData;\r
912 CommandPacket.OutTransferLength= *DataLength;\r
913 CommandPacket.Cdb = Cdb;\r
914 //\r
915 // Fill Cdb for Write (10) Command\r
916 //\r
6b3ecf5c 917 Target = &TargetArray[0];\r
918 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);\r
919\r
a02e796b 920 Cdb[0] = EFI_SCSI_OP_WRITE10;\r
3e0c79b5 921 Cdb[1] = (UINT8) (LShiftU64 (Lun, 5) & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);\r
a24faca3 922 WriteUnaligned32 ((UINT32 *)&Cdb[2], SwapBytes32 (StartLba));\r
923 WriteUnaligned16 ((UINT16 *)&Cdb[7], SwapBytes16 ((UINT16) SectorSize));\r
a02e796b 924\r
52cd71dc 925 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;\r
a02e796b 926 CommandPacket.DataDirection = EFI_SCSI_DATA_OUT;\r
927 CommandPacket.SenseDataLength = *SenseDataLength;\r
928\r
929 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
930\r
931 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
932 *TargetStatus = CommandPacket.TargetStatus;\r
933 *SenseDataLength = CommandPacket.SenseDataLength;\r
ba7e162e 934 *DataLength = CommandPacket.OutTransferLength;\r
a02e796b 935\r
936 return Status;\r
937}\r
373b5cf9 938\r
a24faca3 939/**\r
940 Execute Read(16) SCSI command on a specific SCSI target.\r
941\r
942 Executes the SCSI Read(16) command on the SCSI target specified by ScsiIo.\r
943 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
944 If Timeout is greater than zero, then the command is executed and will timeout\r
945 after Timeout 100 ns units. The StartLba and SectorSize parameters are used to\r
946 construct the CDB for this SCSI command.\r
947 If ScsiIo is NULL, then ASSERT().\r
948 If SenseDataLength is NULL, then ASSERT().\r
949 If HostAdapterStatus is NULL, then ASSERT().\r
950 If TargetStatus is NULL, then ASSERT().\r
951 If DataLength is NULL, then ASSERT().\r
952\r
953\r
954 @param[in] ScsiIo A pointer to SCSI IO protocol.\r
955 @param[in] Timeout The length of timeout period.\r
956 @param[in, out] SenseData A pointer to output sense data.\r
957 @param[in, out] SenseDataLength The length of output sense data.\r
958 @param[out] HostAdapterStatus The status of Host Adapter.\r
959 @param[out] TargetStatus The status of the target.\r
960 @param[in, out] DataBuffer Read 16 command data.\r
961 @param[in, out] DataLength The length of data buffer.\r
962 @param[in] StartLba The start address of LBA.\r
963 @param[in] SectorSize The sector size.\r
964\r
965 @retval EFI_SUCCESS Command is executed successfully.\r
966 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could\r
967 not be transferred. The actual number of bytes transferred is returned in DataLength.\r
968 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many \r
969 SCSI Command Packets already queued.\r
970 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
971 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by \r
972 the SCSI initiator(i.e., SCSI Host Controller)\r
973 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
974\r
975**/\r
976EFI_STATUS\r
977EFIAPI\r
978ScsiRead16Command (\r
979 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
980 IN UINT64 Timeout,\r
981 IN OUT VOID *SenseData, OPTIONAL\r
982 IN OUT UINT8 *SenseDataLength,\r
983 OUT UINT8 *HostAdapterStatus,\r
984 OUT UINT8 *TargetStatus,\r
985 IN OUT VOID *DataBuffer, OPTIONAL\r
986 IN OUT UINT32 *DataLength,\r
987 IN UINT64 StartLba,\r
988 IN UINT32 SectorSize\r
989 )\r
990{\r
991 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
992 UINT64 Lun;\r
993 UINT8 *Target;\r
994 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];\r
995 EFI_STATUS Status;\r
996 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIXTEEN];\r
997\r
998 ASSERT (SenseDataLength != NULL);\r
999 ASSERT (HostAdapterStatus != NULL);\r
1000 ASSERT (TargetStatus != NULL);\r
1001 ASSERT (DataLength != NULL);\r
1002 ASSERT (ScsiIo != NULL);\r
1003\r
1004 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
1005 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIXTEEN);\r
1006\r
1007 CommandPacket.Timeout = Timeout;\r
1008 CommandPacket.InDataBuffer = DataBuffer;\r
1009 CommandPacket.SenseData = SenseData;\r
1010 CommandPacket.InTransferLength = *DataLength;\r
1011 CommandPacket.Cdb = Cdb;\r
1012 //\r
1013 // Fill Cdb for Read (16) Command\r
1014 //\r
1015 Target = &TargetArray[0];\r
1016 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);\r
1017\r
1018 Cdb[0] = EFI_SCSI_OP_READ16;\r
1019 Cdb[1] = (UINT8) (LShiftU64 (Lun, 5) & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);\r
1020 WriteUnaligned64 ((UINT64 *)&Cdb[2], SwapBytes64 (StartLba));\r
1021 WriteUnaligned32 ((UINT32 *)&Cdb[10], SwapBytes32 (SectorSize));\r
1022\r
1023 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_SIXTEEN;\r
1024 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
1025 CommandPacket.SenseDataLength = *SenseDataLength;\r
1026\r
1027 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
1028\r
1029 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
1030 *TargetStatus = CommandPacket.TargetStatus;\r
1031 *SenseDataLength = CommandPacket.SenseDataLength;\r
1032 *DataLength = CommandPacket.InTransferLength;\r
1033\r
1034 return Status;\r
1035}\r
1036\r
1037\r
1038/**\r
1039 Execute Write(16) SCSI command on a specific SCSI target.\r
1040\r
1041 Executes the SCSI Write(16) command on the SCSI target specified by ScsiIo.\r
1042 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
1043 If Timeout is greater than zero, then the command is executed and will timeout after\r
1044 Timeout 100 ns units. The StartLba and SectorSize parameters are used to construct\r
1045 the CDB for this SCSI command.\r
1046 If ScsiIo is NULL, then ASSERT().\r
1047 If SenseDataLength is NULL, then ASSERT().\r
1048 If HostAdapterStatus is NULL, then ASSERT().\r
1049 If TargetStatus is NULL, then ASSERT().\r
1050 If DataLength is NULL, then ASSERT().\r
1051\r
1052 @param[in] ScsiIo SCSI IO Protocol to use\r
1053 @param[in] Timeout The length of timeout period.\r
1054 @param[in, out] SenseData A pointer to output sense data.\r
1055 @param[in, out] SenseDataLength The length of output sense data.\r
1056 @param[out] HostAdapterStatus The status of Host Adapter.\r
1057 @param[out] TargetStatus The status of the target.\r
1058 @param[in, out] DataBuffer A pointer to a data buffer.\r
1059 @param[in, out] DataLength The length of data buffer.\r
1060 @param[in] StartLba The start address of LBA.\r
1061 @param[in] SectorSize The sector size.\r
1062\r
1063 @retval EFI_SUCCESS Command is executed successfully.\r
1064 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could\r
1065 not be transferred. The actual number of bytes transferred is returned in DataLength.\r
1066 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many \r
1067 SCSI Command Packets already queued.\r
1068 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
1069 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by \r
1070 the SCSI initiator(i.e., SCSI Host Controller)\r
1071 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
1072\r
1073**/\r
1074EFI_STATUS\r
1075EFIAPI\r
1076ScsiWrite16Command (\r
1077 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
1078 IN UINT64 Timeout,\r
1079 IN OUT VOID *SenseData, OPTIONAL\r
1080 IN OUT UINT8 *SenseDataLength,\r
1081 OUT UINT8 *HostAdapterStatus,\r
1082 OUT UINT8 *TargetStatus,\r
1083 IN OUT VOID *DataBuffer, OPTIONAL\r
1084 IN OUT UINT32 *DataLength,\r
1085 IN UINT64 StartLba,\r
1086 IN UINT32 SectorSize\r
1087 )\r
1088{\r
1089 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
1090 UINT64 Lun;\r
1091 UINT8 *Target;\r
1092 UINT8 TargetArray[EFI_SCSI_TARGET_MAX_BYTES];\r
1093 EFI_STATUS Status;\r
1094 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIXTEEN];\r
1095\r
1096 ASSERT (SenseDataLength != NULL);\r
1097 ASSERT (HostAdapterStatus != NULL);\r
1098 ASSERT (TargetStatus != NULL);\r
1099 ASSERT (DataLength != NULL);\r
1100 ASSERT (ScsiIo != NULL);\r
1101\r
1102 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
1103 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIXTEEN);\r
1104\r
1105 CommandPacket.Timeout = Timeout;\r
1106 CommandPacket.OutDataBuffer = DataBuffer;\r
1107 CommandPacket.SenseData = SenseData;\r
1108 CommandPacket.OutTransferLength = *DataLength;\r
1109 CommandPacket.Cdb = Cdb;\r
1110 //\r
1111 // Fill Cdb for Write (16) Command\r
1112 //\r
1113 Target = &TargetArray[0];\r
1114 ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun);\r
1115\r
1116 Cdb[0] = EFI_SCSI_OP_WRITE16;\r
1117 Cdb[1] = (UINT8) (LShiftU64 (Lun, 5) & EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK);\r
1118 WriteUnaligned64 ((UINT64 *)&Cdb[2], SwapBytes64 (StartLba));\r
1119 WriteUnaligned32 ((UINT32 *)&Cdb[10], SwapBytes32 (SectorSize));\r
1120\r
1121 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_SIXTEEN;\r
1122 CommandPacket.DataDirection = EFI_SCSI_DATA_OUT;\r
1123 CommandPacket.SenseDataLength = *SenseDataLength;\r
1124\r
1125 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
1126\r
1127 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
1128 *TargetStatus = CommandPacket.TargetStatus;\r
1129 *SenseDataLength = CommandPacket.SenseDataLength;\r
1130 *DataLength = CommandPacket.OutTransferLength;\r
1131\r
1132 return Status;\r
1133}\r