]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/UefiScsiLib/UefiScsiLib.c
MdePkg DebugLib: Enable FILE NAME as DEBUG ASSERT for CLANG
[mirror_edk2.git] / MdePkg / Library / UefiScsiLib / UefiScsiLib.c
CommitLineData
bf231ea6
A
1/** @file\r
2 UEFI SCSI Library implementation\r
3\r
9b14509b 4 Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>\r
9344f092 5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
bf231ea6
A
6\r
7**/\r
a02e796b 8\r
bf231ea6 9\r
60c93673 10#include <Uefi.h>\r
3e0c79b5 11#include <Library/BaseLib.h>\r
306431f7 12#include <Library/DebugLib.h>\r
172ea7c7 13#include <Library/UefiScsiLib.h>\r
a02e796b 14#include <Library/BaseMemoryLib.h>\r
9c581939
HW
15#include <Library/MemoryAllocationLib.h>\r
16#include <Library/UefiBootServicesTableLib.h>\r
9095d37b 17\r
a3589760 18#include <IndustryStandard/Scsi.h>\r
9095d37b
LG
19\r
20\r
d5954c61 21 //\r
a24faca3 22 // Scsi Command Length\r
d5954c61 23 //\r
a24faca3 24#define EFI_SCSI_OP_LENGTH_SIX 0x6\r
25#define EFI_SCSI_OP_LENGTH_TEN 0xa\r
9b14509b 26#define EFI_SCSI_OP_LENGTH_TWELVE 0xc\r
a24faca3 27#define EFI_SCSI_OP_LENGTH_SIXTEEN 0x10\r
bf231ea6 28\r
9c581939
HW
29//\r
30// The context structure used when non-blocking SCSI read/write operation\r
31// completes.\r
32//\r
33typedef struct {\r
34 ///\r
35 /// The SCSI request packet to send to the SCSI controller specified by\r
36 /// the device handle.\r
37 ///\r
38 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
39 ///\r
40 /// The length of the output sense data.\r
41 ///\r
42 UINT8 *SenseDataLength;\r
43 ///\r
44 /// The status of the SCSI host adapter.\r
45 ///\r
46 UINT8 *HostAdapterStatus;\r
47 ///\r
48 /// The status of the target SCSI device.\r
49 ///\r
50 UINT8 *TargetStatus;\r
51 ///\r
52 /// The length of the data buffer for the SCSI read/write command.\r
53 ///\r
54 UINT32 *DataLength;\r
55 ///\r
56 /// The caller event to be signaled when the SCSI read/write command\r
57 /// completes.\r
58 ///\r
59 EFI_EVENT CallerEvent;\r
60} EFI_SCSI_LIB_ASYNC_CONTEXT;\r
61\r
b91d5eca 62\r
b91d5eca 63\r
d5954c61 64/**\r
65 Execute Test Unit Ready SCSI command on a specific SCSI target.\r
b91d5eca 66\r
d5954c61 67 Executes the Test Unit Ready command on the SCSI target specified by ScsiIo.\r
68 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
69 If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.\r
70 If ScsiIo is NULL, then ASSERT().\r
71 If SenseDataLength is NULL, then ASSERT().\r
52cd71dc
LG
72 If HostAdapterStatus is NULL, then ASSERT().\r
73 If TargetStatus is NULL, then ASSERT().\r
a3589760 74\r
d658727b
FT
75 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer\r
76 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
77 gets returned.\r
d5954c61 78\r
79 @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance\r
80 for the specific SCSI target.\r
81 @param[in] Timeout The timeout in 100 ns units to use for the execution\r
82 of this SCSI Request Packet. A Timeout value of\r
83 zero means that this function will wait indefinitely\r
84 for the SCSI Request Packet to execute. If Timeout\r
85 is greater than zero, then this function will return\r
86 EFI_TIMEOUT if the time required to execute the SCSI\r
87 Request Packet is greater than Timeout.\r
88 @param[in, out] SenseData A pointer to sense data that was generated by\r
89 the execution of the SCSI Request Packet. This\r
90 buffer must be allocated by the caller.\r
91 If SenseDataLength is 0, then this parameter is\r
92 optional and may be NULL.\r
93 @param[in, out] SenseDataLength On input, a pointer to the length in bytes of\r
9ccbe812 94 the SenseData buffer. On output, a pointer to\r
9095d37b 95 the number of bytes written to the SenseData buffer.\r
d5954c61 96 @param[out] HostAdapterStatus The status of the SCSI Host Controller that produces\r
97 the SCSI bus containing the SCSI target specified by\r
98 ScsiIo when the SCSI Request Packet was executed.\r
99 See the EFI SCSI I/O Protocol in the UEFI Specification\r
100 for details on the possible return values.\r
101 @param[out] TargetStatus The status returned by the SCSI target specified\r
9ccbe812 102 by ScsiIo when the SCSI Request Packet was executed\r
d5954c61 103 on the SCSI Host Controller. See the EFI SCSI I/O\r
104 Protocol in the UEFI Specification for details on\r
9095d37b 105 the possible return values.\r
d5954c61 106\r
d658727b
FT
107 @retval EFI_SUCCESS The command was executed successfully.\r
108 See HostAdapterStatus, TargetStatus, SenseDataLength,\r
109 and SenseData in that order for additional status\r
110 information.\r
111 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because\r
112 there are too many SCSI Command Packets already\r
113 queued. The SCSI Request Packet was not sent, so\r
114 no additional status information is available.\r
115 The caller may retry again later.\r
116 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send\r
117 SCSI Request Packet. See HostAdapterStatus,\r
118 TargetStatus, SenseDataLength, and SenseData in that\r
119 order for additional status information.\r
120 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet\r
121 is not supported by the SCSI initiator(i.e., SCSI\r
122 Host Controller). The SCSI Request Packet was not\r
123 sent, so no additional status information is available.\r
124 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request\r
125 Packet to execute. See HostAdapterStatus, TargetStatus,\r
126 SenseDataLength, and SenseData in that order for\r
127 additional status information.\r
128 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.\r
a3589760 129\r
bf231ea6 130**/\r
a02e796b 131EFI_STATUS\r
373b5cf9 132EFIAPI\r
d35be2a4 133ScsiTestUnitReadyCommand (\r
d5954c61 134 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
135 IN UINT64 Timeout,\r
136 IN OUT VOID *SenseData, OPTIONAL\r
137 IN OUT UINT8 *SenseDataLength,\r
138 OUT UINT8 *HostAdapterStatus,\r
139 OUT UINT8 *TargetStatus\r
a02e796b 140 )\r
a02e796b 141{\r
142 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
a02e796b 143 EFI_STATUS Status;\r
52cd71dc 144 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];\r
a02e796b 145\r
8069d49e
LG
146 ASSERT (SenseDataLength != NULL);\r
147 ASSERT (HostAdapterStatus != NULL);\r
148 ASSERT (TargetStatus != NULL);\r
d5954c61 149 ASSERT (ScsiIo != NULL);\r
a02e796b 150\r
151 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
52cd71dc 152 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX);\r
a02e796b 153\r
154 CommandPacket.Timeout = Timeout;\r
155 CommandPacket.InDataBuffer = NULL;\r
156 CommandPacket.InTransferLength= 0;\r
157 CommandPacket.OutDataBuffer = NULL;\r
158 CommandPacket.OutTransferLength= 0;\r
159 CommandPacket.SenseData = SenseData;\r
160 CommandPacket.Cdb = Cdb;\r
161 //\r
162 // Fill Cdb for Test Unit Ready Command\r
163 //\r
a02e796b 164 Cdb[0] = EFI_SCSI_OP_TEST_UNIT_READY;\r
52cd71dc 165 CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX;\r
a02e796b 166 CommandPacket.SenseDataLength = *SenseDataLength;\r
167\r
168 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
169\r
170 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
171 *TargetStatus = CommandPacket.TargetStatus;\r
172 *SenseDataLength = CommandPacket.SenseDataLength;\r
173\r
174 return Status;\r
175}\r
176\r
bf231ea6 177\r
a3589760 178/**\r
d5954c61 179 Execute Inquiry SCSI command on a specific SCSI target.\r
b91d5eca 180\r
d5954c61 181 Executes the Inquiry command on the SCSI target specified by ScsiIo.\r
182 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
183 If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.\r
184 If ScsiIo is NULL, then ASSERT().\r
52cd71dc
LG
185 If SenseDataLength is NULL, then ASSERT().\r
186 If HostAdapterStatus is NULL, then ASSERT().\r
187 If TargetStatus is NULL, then ASSERT().\r
188 If InquiryDataLength is NULL, then ASSERT().\r
a3589760 189\r
d658727b
FT
190 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer\r
191 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
192 gets returned.\r
193\r
194 If InquiryDataLength is non-zero and InquiryDataBuffer is not NULL, InquiryDataBuffer\r
195 must meet buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise\r
196 EFI_INVALID_PARAMETER gets returned.\r
197\r
d5954c61 198 @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance\r
199 for the specific SCSI target.\r
200 @param[in] Timeout The timeout in 100 ns units to use for the\r
201 execution of this SCSI Request Packet. A Timeout\r
202 value of zero means that this function will wait\r
203 indefinitely for the SCSI Request Packet to execute.\r
204 If Timeout is greater than zero, then this function\r
205 will return EFI_TIMEOUT if the time required to\r
206 execute the SCSI Request Packet is greater than Timeout.\r
207 @param[in, out] SenseData A pointer to sense data that was generated\r
208 by the execution of the SCSI Request Packet.\r
209 This buffer must be allocated by the caller.\r
210 If SenseDataLength is 0, then this parameter\r
211 is optional and may be NULL.\r
212 @param[in, out] SenseDataLength On input, the length in bytes of the SenseData buffer.\r
9095d37b 213 On output, the number of bytes written to the SenseData buffer.\r
d5954c61 214 @param[out] HostAdapterStatus The status of the SCSI Host Controller that\r
215 produces the SCSI bus containing the SCSI\r
216 target specified by ScsiIo when the SCSI\r
217 Request Packet was executed. See the EFI\r
218 SCSI I/O Protocol in the UEFI Specification\r
219 for details on the possible return values.\r
220 @param[out] TargetStatus The status returned by the SCSI target specified\r
070a76b1 221 by ScsiIo when the SCSI Request Packet was\r
d5954c61 222 executed on the SCSI Host Controller.\r
223 See the EFI SCSI I/O Protocol in the UEFI\r
224 Specification for details on the possible\r
9095d37b 225 return values.\r
d5954c61 226 @param[in, out] InquiryDataBuffer A pointer to inquiry data that was generated\r
227 by the execution of the SCSI Request Packet.\r
228 This buffer must be allocated by the caller.\r
229 If InquiryDataLength is 0, then this parameter\r
9095d37b 230 is optional and may be NULL.\r
d5954c61 231 @param[in, out] InquiryDataLength On input, a pointer to the length in bytes\r
232 of the InquiryDataBuffer buffer.\r
233 On output, a pointer to the number of bytes\r
234 written to the InquiryDataBuffer buffer.\r
235 @param[in] EnableVitalProductData If TRUE, then the supported vital product\r
b8a62661 236 data for the PageCode is returned in InquiryDataBuffer.\r
d5954c61 237 If FALSE, then the standard inquiry data is\r
b8a62661
RN
238 returned in InquiryDataBuffer and PageCode is ignored.\r
239 @param[in] PageCode The page code of the vital product data.\r
240 It's ignored if EnableVitalProductData is FALSE.\r
d5954c61 241\r
d658727b
FT
242 @retval EFI_SUCCESS The command executed successfully. See HostAdapterStatus,\r
243 TargetStatus, SenseDataLength, and SenseData in that order\r
244 for additional status information.\r
245 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire\r
246 InquiryDataBuffer could not be transferred. The actual\r
247 number of bytes transferred is returned in InquiryDataLength.\r
248 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there\r
249 are too many SCSI Command Packets already queued.\r
250 The SCSI Request Packet was not sent, so no additional\r
251 status information is available. The caller may retry again later.\r
252 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI\r
253 Request Packet. See HostAdapterStatus, TargetStatus,\r
254 SenseDataLength, and SenseData in that order for additional\r
255 status information.\r
256 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not\r
257 supported by the SCSI initiator(i.e., SCSI Host Controller).\r
258 The SCSI Request Packet was not sent, so no additional\r
259 status information is available.\r
260 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request\r
261 Packet to execute. See HostAdapterStatus, TargetStatus,\r
262 SenseDataLength, and SenseData in that order for\r
263 additional status information.\r
264 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.\r
a3589760 265\r
bf231ea6 266**/\r
a02e796b 267EFI_STATUS\r
373b5cf9 268EFIAPI\r
b8a62661 269ScsiInquiryCommandEx (\r
d5954c61 270 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
271 IN UINT64 Timeout,\r
272 IN OUT VOID *SenseData, OPTIONAL\r
273 IN OUT UINT8 *SenseDataLength,\r
274 OUT UINT8 *HostAdapterStatus,\r
275 OUT UINT8 *TargetStatus,\r
276 IN OUT VOID *InquiryDataBuffer, OPTIONAL\r
277 IN OUT UINT32 *InquiryDataLength,\r
b8a62661
RN
278 IN BOOLEAN EnableVitalProductData,\r
279 IN UINT8 PageCode\r
a02e796b 280 )\r
a02e796b 281{\r
282 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
a02e796b 283 EFI_STATUS Status;\r
52cd71dc 284 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];\r
a02e796b 285\r
8069d49e
LG
286 ASSERT (SenseDataLength != NULL);\r
287 ASSERT (HostAdapterStatus != NULL);\r
288 ASSERT (TargetStatus != NULL);\r
289 ASSERT (InquiryDataLength != NULL);\r
d5954c61 290 ASSERT (ScsiIo != NULL);\r
8069d49e 291\r
a02e796b 292 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
52cd71dc 293 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX);\r
a02e796b 294\r
295 CommandPacket.Timeout = Timeout;\r
296 CommandPacket.InDataBuffer = InquiryDataBuffer;\r
297 CommandPacket.InTransferLength= *InquiryDataLength;\r
298 CommandPacket.SenseData = SenseData;\r
299 CommandPacket.SenseDataLength = *SenseDataLength;\r
300 CommandPacket.Cdb = Cdb;\r
301\r
a02e796b 302 Cdb[0] = EFI_SCSI_OP_INQUIRY;\r
a02e796b 303 if (EnableVitalProductData) {\r
304 Cdb[1] |= 0x01;\r
b8a62661 305 Cdb[2] = PageCode;\r
a02e796b 306 }\r
307\r
308 if (*InquiryDataLength > 0xff) {\r
309 *InquiryDataLength = 0xff;\r
310 }\r
311\r
312 Cdb[4] = (UINT8) (*InquiryDataLength);\r
52cd71dc 313 CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX;\r
a02e796b 314 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
315\r
316 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
317\r
318 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
319 *TargetStatus = CommandPacket.TargetStatus;\r
320 *SenseDataLength = CommandPacket.SenseDataLength;\r
321 *InquiryDataLength = CommandPacket.InTransferLength;\r
322\r
323 return Status;\r
324}\r
325\r
bf231ea6 326\r
b8a62661
RN
327/**\r
328 Execute Inquiry SCSI command on a specific SCSI target.\r
329\r
330 Executes the Inquiry command on the SCSI target specified by ScsiIo.\r
331 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
332 If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.\r
333 If ScsiIo is NULL, then ASSERT().\r
334 If SenseDataLength is NULL, then ASSERT().\r
335 If HostAdapterStatus is NULL, then ASSERT().\r
336 If TargetStatus is NULL, then ASSERT().\r
337 If InquiryDataLength is NULL, then ASSERT().\r
338\r
d658727b
FT
339 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer\r
340 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
341 gets returned.\r
342\r
343 If InquiryDataLength is non-zero and InquiryDataBuffer is not NULL, InquiryDataBuffer\r
344 must meet buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise\r
345 EFI_INVALID_PARAMETER gets returned.\r
346\r
b8a62661
RN
347 @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance\r
348 for the specific SCSI target.\r
349 @param[in] Timeout The timeout in 100 ns units to use for the\r
350 execution of this SCSI Request Packet. A Timeout\r
351 value of zero means that this function will wait\r
352 indefinitely for the SCSI Request Packet to execute.\r
353 If Timeout is greater than zero, then this function\r
354 will return EFI_TIMEOUT if the time required to\r
355 execute the SCSI Request Packet is greater than Timeout.\r
356 @param[in, out] SenseData A pointer to sense data that was generated\r
357 by the execution of the SCSI Request Packet.\r
358 This buffer must be allocated by the caller.\r
359 If SenseDataLength is 0, then this parameter\r
360 is optional and may be NULL.\r
361 @param[in, out] SenseDataLength On input, the length in bytes of the SenseData buffer.\r
9095d37b 362 On output, the number of bytes written to the SenseData buffer.\r
b8a62661
RN
363 @param[out] HostAdapterStatus The status of the SCSI Host Controller that\r
364 produces the SCSI bus containing the SCSI\r
365 target specified by ScsiIo when the SCSI\r
366 Request Packet was executed. See the EFI\r
367 SCSI I/O Protocol in the UEFI Specification\r
368 for details on the possible return values.\r
369 @param[out] TargetStatus The status returned by the SCSI target specified\r
370 by ScsiIo when the SCSI Request Packet was\r
371 executed on the SCSI Host Controller.\r
372 See the EFI SCSI I/O Protocol in the UEFI\r
373 Specification for details on the possible\r
9095d37b 374 return values.\r
b8a62661
RN
375 @param[in, out] InquiryDataBuffer A pointer to inquiry data that was generated\r
376 by the execution of the SCSI Request Packet.\r
377 This buffer must be allocated by the caller.\r
378 If InquiryDataLength is 0, then this parameter\r
9095d37b 379 is optional and may be NULL.\r
b8a62661
RN
380 @param[in, out] InquiryDataLength On input, a pointer to the length in bytes\r
381 of the InquiryDataBuffer buffer.\r
382 On output, a pointer to the number of bytes\r
383 written to the InquiryDataBuffer buffer.\r
384 @param[in] EnableVitalProductData If TRUE, then the supported vital product\r
385 data is returned in InquiryDataBuffer.\r
386 If FALSE, then the standard inquiry data is\r
9095d37b 387 returned in InquiryDataBuffer.\r
b8a62661 388\r
d658727b
FT
389 @retval EFI_SUCCESS The command was executed successfully. See HostAdapterStatus,\r
390 TargetStatus, SenseDataLength, and SenseData in that order\r
391 for additional status information.\r
392 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire\r
393 InquiryDataBuffer could not be transferred. The actual\r
394 number of bytes transferred is returned in InquiryDataLength.\r
395 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there\r
396 are too many SCSI Command Packets already queued.\r
397 The SCSI Request Packet was not sent, so no additional\r
398 status information is available. The caller may retry again later.\r
399 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI\r
400 Request Packet. See HostAdapterStatus, TargetStatus,\r
401 SenseDataLength, and SenseData in that order for additional\r
402 status information.\r
403 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not\r
404 supported by the SCSI initiator(i.e., SCSI Host Controller).\r
405 The SCSI Request Packet was not sent, so no additional\r
406 status information is available.\r
407 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request\r
408 Packet to execute. See HostAdapterStatus, TargetStatus,\r
409 SenseDataLength, and SenseData in that order for\r
410 additional status information.\r
411 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.\r
b8a62661
RN
412\r
413**/\r
414EFI_STATUS\r
415EFIAPI\r
416ScsiInquiryCommand (\r
417 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
418 IN UINT64 Timeout,\r
419 IN OUT VOID *SenseData, OPTIONAL\r
420 IN OUT UINT8 *SenseDataLength,\r
421 OUT UINT8 *HostAdapterStatus,\r
422 OUT UINT8 *TargetStatus,\r
423 IN OUT VOID *InquiryDataBuffer, OPTIONAL\r
424 IN OUT UINT32 *InquiryDataLength,\r
425 IN BOOLEAN EnableVitalProductData\r
426 )\r
427{\r
428 return ScsiInquiryCommandEx (\r
429 ScsiIo,\r
430 Timeout,\r
431 SenseData,\r
432 SenseDataLength,\r
433 HostAdapterStatus,\r
434 TargetStatus,\r
435 InquiryDataBuffer,\r
436 InquiryDataLength,\r
437 EnableVitalProductData,\r
438 0\r
439 );\r
440}\r
441\r
a3589760 442/**\r
d5954c61 443 Execute Mode Sense(10) SCSI command on a specific SCSI target.\r
444\r
445 Executes the SCSI Mode Sense(10) command on the SCSI target specified by ScsiIo.\r
446 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
447 If Timeout is greater than zero, then the command is executed and will timeout\r
448 after Timeout 100 ns units. The DBDField, PageControl, and PageCode parameters\r
449 are used to construct the CDB for this SCSI command.\r
450 If ScsiIo is NULL, then ASSERT().\r
52cd71dc
LG
451 If SenseDataLength is NULL, then ASSERT().\r
452 If HostAdapterStatus is NULL, then ASSERT().\r
453 If TargetStatus is NULL, then ASSERT().\r
454 If DataLength is NULL, then ASSERT().\r
a3589760 455\r
d658727b
FT
456 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer\r
457 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
458 gets returned.\r
459\r
460 If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer\r
461 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
462 gets returned.\r
d5954c61 463\r
464 @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance\r
465 for the specific SCSI target.\r
466 @param[in] Timeout The timeout in 100 ns units to use for the\r
467 execution of this SCSI Request Packet. A Timeout\r
468 value of zero means that this function will wait\r
469 indefinitely for the SCSI Request Packet to execute.\r
470 If Timeout is greater than zero, then this function\r
471 will return EFI_TIMEOUT if the time required to\r
472 execute the SCSI Request Packet is greater than Timeout.\r
6089ba62 473 @param[in, out] SenseData A pointer to sense data that was generated\r
d5954c61 474 by the execution of the SCSI Request Packet.\r
475 This buffer must be allocated by the caller.\r
476 If SenseDataLength is 0, then this parameter\r
477 is optional and may be NULL.\r
6089ba62 478 @param[in, out] SenseDataLength On input, the length in bytes of the SenseData buffer.\r
9095d37b 479 On output, the number of bytes written to the SenseData buffer.\r
d5954c61 480 @param[out] HostAdapterStatus The status of the SCSI Host Controller that\r
481 produces the SCSI bus containing the SCSI target\r
482 specified by ScsiIo when the SCSI Request Packet\r
483 was executed. See the EFI SCSI I/O Protocol in the\r
484 UEFI Specification for details on the possible\r
485 return values.\r
486 @param[out] TargetStatus The status returned by the SCSI target specified\r
070a76b1 487 by ScsiIo when the SCSI Request Packet was executed\r
d5954c61 488 on the SCSI Host Controller. See the EFI SCSI\r
489 I/O Protocol in the UEFI Specification for details\r
490 on the possible return values.\r
491 @param[in, out] DataBuffer A pointer to data that was generated by the\r
492 execution of the SCSI Request Packet. This\r
493 buffer must be allocated by the caller. If\r
494 DataLength is 0, then this parameter is optional\r
9095d37b 495 and may be NULL.\r
d5954c61 496 @param[in, out] DataLength On input, a pointer to the length in bytes of\r
497 the DataBuffer buffer. On output, a pointer\r
498 to the number of bytes written to the DataBuffer\r
9095d37b 499 buffer.\r
d5954c61 500 @param[in] DBDField Specifies the DBD field of the CDB for this SCSI Command.\r
9095d37b
LG
501 @param[in] PageControl Specifies the PC field of the CDB for this SCSI Command.\r
502 @param[in] PageCode Specifies the Page Control field of the CDB for this SCSI Command.\r
d5954c61 503\r
d658727b
FT
504 @retval EFI_SUCCESS The command was executed successfully.\r
505 See HostAdapterStatus, TargetStatus, SenseDataLength,\r
506 and SenseData in that order for additional status information.\r
507 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the\r
508 entire DataBuffer could not be transferred.\r
509 The actual number of bytes transferred is returned\r
510 in DataLength.\r
511 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because\r
512 there are too many SCSI Command Packets already queued.\r
513 The SCSI Request Packet was not sent, so no additional\r
514 status information is available. The caller may retry\r
515 again later.\r
516 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send\r
517 SCSI Request Packet. See HostAdapterStatus, TargetStatus,\r
518 SenseDataLength, and SenseData in that order for\r
519 additional status information.\r
520 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet\r
521 is not supported by the SCSI initiator(i.e., SCSI\r
522 Host Controller). The SCSI Request Packet was not\r
523 sent, so no additional status information is available.\r
524 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI\r
525 Request Packet to execute. See HostAdapterStatus,\r
526 TargetStatus, SenseDataLength, and SenseData in that\r
527 order for additional status information.\r
528 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.\r
a3589760 529\r
bf231ea6 530**/\r
a02e796b 531EFI_STATUS\r
373b5cf9 532EFIAPI\r
d35be2a4 533ScsiModeSense10Command (\r
d5954c61 534 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
535 IN UINT64 Timeout,\r
536 IN OUT VOID *SenseData, OPTIONAL\r
537 IN OUT UINT8 *SenseDataLength,\r
538 OUT UINT8 *HostAdapterStatus,\r
539 OUT UINT8 *TargetStatus,\r
540 IN OUT VOID *DataBuffer, OPTIONAL\r
541 IN OUT UINT32 *DataLength,\r
542 IN UINT8 DBDField, OPTIONAL\r
543 IN UINT8 PageControl,\r
544 IN UINT8 PageCode\r
a02e796b 545 )\r
a02e796b 546{\r
547 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
a02e796b 548 EFI_STATUS Status;\r
52cd71dc 549 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];\r
a02e796b 550\r
8069d49e
LG
551 ASSERT (SenseDataLength != NULL);\r
552 ASSERT (HostAdapterStatus != NULL);\r
553 ASSERT (TargetStatus != NULL);\r
554 ASSERT (DataLength != NULL);\r
d5954c61 555 ASSERT (ScsiIo != NULL);\r
8069d49e 556\r
a02e796b 557 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
52cd71dc 558 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);\r
a02e796b 559\r
560 CommandPacket.Timeout = Timeout;\r
561 CommandPacket.InDataBuffer = DataBuffer;\r
562 CommandPacket.SenseData = SenseData;\r
563 CommandPacket.InTransferLength= *DataLength;\r
564 CommandPacket.Cdb = Cdb;\r
565 //\r
566 // Fill Cdb for Mode Sense (10) Command\r
567 //\r
a02e796b 568 Cdb[0] = EFI_SCSI_OP_MODE_SEN10;\r
52cd71dc
LG
569 //\r
570 // DBDField is in Cdb[1] bit3 of (bit7..0)\r
571 //\r
b04a63ac 572 Cdb[1] = (UINT8) ((DBDField << 3) & 0x08);\r
52cd71dc
LG
573 //\r
574 // PageControl is in Cdb[2] bit7..6, PageCode is in Cdb[2] bit5..0\r
575 //\r
6b3ecf5c 576 Cdb[2] = (UINT8) (((PageControl << 6) & 0xc0) | (PageCode & 0x3f));\r
a02e796b 577 Cdb[7] = (UINT8) (*DataLength >> 8);\r
578 Cdb[8] = (UINT8) (*DataLength);\r
579\r
52cd71dc 580 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;\r
a02e796b 581 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
582 CommandPacket.SenseDataLength = *SenseDataLength;\r
583\r
584 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
585\r
586 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
587 *TargetStatus = CommandPacket.TargetStatus;\r
588 *SenseDataLength = CommandPacket.SenseDataLength;\r
589 *DataLength = CommandPacket.InTransferLength;\r
590\r
591 return Status;\r
592}\r
593\r
bf231ea6 594\r
a3589760 595/**\r
d5954c61 596 Execute Request Sense SCSI command on a specific SCSI target.\r
b91d5eca 597\r
d5954c61 598 Executes the Request Sense command on the SCSI target specified by ScsiIo.\r
599 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
600 If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.\r
601 If ScsiIo is NULL, then ASSERT().\r
52cd71dc
LG
602 If SenseDataLength is NULL, then ASSERT().\r
603 If HostAdapterStatus is NULL, then ASSERT().\r
604 If TargetStatus is NULL, then ASSERT().\r
a3589760 605\r
d658727b
FT
606 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer\r
607 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
608 gets returned.\r
609\r
b91d5eca 610 @param[in] ScsiIo A pointer to SCSI IO protocol.\r
611 @param[in] Timeout The length of timeout period.\r
d5954c61 612 @param[in, out] SenseData A pointer to output sense data.\r
613 @param[in, out] SenseDataLength The length of output sense data.\r
b91d5eca 614 @param[out] HostAdapterStatus The status of Host Adapter.\r
615 @param[out] TargetStatus The status of the target.\r
616\r
d658727b 617 @retval EFI_SUCCESS Command is executed successfully.\r
b91d5eca 618 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are\r
619 too many SCSI Command Packets already queued.\r
620 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
621 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by\r
622 the SCSI initiator(i.e., SCSI Host Controller)\r
623 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
d658727b 624 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.\r
a3589760 625\r
bf231ea6 626**/\r
a02e796b 627EFI_STATUS\r
373b5cf9 628EFIAPI\r
d35be2a4 629ScsiRequestSenseCommand (\r
d5954c61 630 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
631 IN UINT64 Timeout,\r
632 IN OUT VOID *SenseData, OPTIONAL\r
633 IN OUT UINT8 *SenseDataLength,\r
634 OUT UINT8 *HostAdapterStatus,\r
635 OUT UINT8 *TargetStatus\r
a02e796b 636 )\r
a02e796b 637{\r
638 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
a02e796b 639 EFI_STATUS Status;\r
52cd71dc 640 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIX];\r
a02e796b 641\r
8069d49e
LG
642 ASSERT (SenseDataLength != NULL);\r
643 ASSERT (HostAdapterStatus != NULL);\r
644 ASSERT (TargetStatus != NULL);\r
d5954c61 645 ASSERT (ScsiIo != NULL);\r
8069d49e 646\r
a02e796b 647 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
52cd71dc 648 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIX);\r
a02e796b 649\r
650 CommandPacket.Timeout = Timeout;\r
651 CommandPacket.InDataBuffer = SenseData;\r
652 CommandPacket.SenseData = NULL;\r
653 CommandPacket.InTransferLength= *SenseDataLength;\r
654 CommandPacket.Cdb = Cdb;\r
655 //\r
656 // Fill Cdb for Request Sense Command\r
657 //\r
a02e796b 658 Cdb[0] = EFI_SCSI_OP_REQUEST_SENSE;\r
a02e796b 659 Cdb[4] = (UINT8) (*SenseDataLength);\r
660\r
52cd71dc 661 CommandPacket.CdbLength = (UINT8) EFI_SCSI_OP_LENGTH_SIX;\r
a02e796b 662 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
663 CommandPacket.SenseDataLength = 0;\r
664\r
665 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
666\r
667 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
668 *TargetStatus = CommandPacket.TargetStatus;\r
669 *SenseDataLength = (UINT8) CommandPacket.InTransferLength;\r
670\r
671 return Status;\r
672}\r
673\r
bf231ea6 674\r
a3589760 675/**\r
d5954c61 676 Execute Read Capacity SCSI command on a specific SCSI target.\r
b91d5eca 677\r
d5954c61 678 Executes the SCSI Read Capacity command on the SCSI target specified by ScsiIo.\r
679 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
680 If Timeout is greater than zero, then the command is executed and will timeout after\r
51969ecb 681 Timeout 100 ns units. The Pmi parameter is used to construct the CDB for this SCSI command.\r
d5954c61 682 If ScsiIo is NULL, then ASSERT().\r
52cd71dc
LG
683 If SenseDataLength is NULL, then ASSERT().\r
684 If HostAdapterStatus is NULL, then ASSERT().\r
685 If TargetStatus is NULL, then ASSERT().\r
686 If DataLength is NULL, then ASSERT().\r
bf231ea6 687\r
d658727b
FT
688 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer\r
689 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
690 gets returned.\r
691\r
692 If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer\r
693 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
694 gets returned.\r
695\r
d5954c61 696 @param[in] ScsiIo A pointer to SCSI IO protocol.\r
697 @param[in] Timeout The length of timeout period.\r
698 @param[in, out] SenseData A pointer to output sense data.\r
ee256e2c 699 @param[in, out] SenseDataLength The length of output sense data.\r
d5954c61 700 @param[out] HostAdapterStatus The status of Host Adapter.\r
701 @param[out] TargetStatus The status of the target.\r
702 @param[in, out] DataBuffer A pointer to a data buffer.\r
ee256e2c 703 @param[in, out] DataLength The length of data buffer.\r
d658727b
FT
704 @param[in] Pmi Partial medium indicator.\r
705\r
706 @retval EFI_SUCCESS Command is executed successfully.\r
707 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire\r
708 DataBuffer could not be transferred. The actual\r
709 number of bytes transferred is returned in DataLength.\r
710 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because\r
711 there are too many SCSI Command Packets already queued.\r
712 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
713 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet\r
714 is not supported by the SCSI initiator(i.e., SCSI Host Controller)\r
715 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
716 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.\r
a3589760 717\r
bf231ea6 718**/\r
a02e796b 719EFI_STATUS\r
373b5cf9 720EFIAPI\r
d35be2a4 721ScsiReadCapacityCommand (\r
d5954c61 722 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
723 IN UINT64 Timeout,\r
724 IN OUT VOID *SenseData, OPTIONAL\r
725 IN OUT UINT8 *SenseDataLength,\r
726 OUT UINT8 *HostAdapterStatus,\r
727 OUT UINT8 *TargetStatus,\r
728 IN OUT VOID *DataBuffer, OPTIONAL\r
729 IN OUT UINT32 *DataLength,\r
51969ecb 730 IN BOOLEAN Pmi\r
a02e796b 731 )\r
a02e796b 732{\r
733 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
a02e796b 734 EFI_STATUS Status;\r
52cd71dc 735 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];\r
a02e796b 736\r
8069d49e
LG
737 ASSERT (SenseDataLength != NULL);\r
738 ASSERT (HostAdapterStatus != NULL);\r
739 ASSERT (TargetStatus != NULL);\r
740 ASSERT (DataLength != NULL);\r
d5954c61 741 ASSERT (ScsiIo != NULL);\r
8069d49e 742\r
a02e796b 743 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
52cd71dc 744 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);\r
a02e796b 745\r
746 CommandPacket.Timeout = Timeout;\r
747 CommandPacket.InDataBuffer = DataBuffer;\r
748 CommandPacket.SenseData = SenseData;\r
749 CommandPacket.InTransferLength= *DataLength;\r
750 CommandPacket.Cdb = Cdb;\r
751 //\r
752 // Fill Cdb for Read Capacity Command\r
753 //\r
a02e796b 754 Cdb[0] = EFI_SCSI_OP_READ_CAPACITY;\r
51969ecb 755 if (!Pmi) {\r
a02e796b 756 //\r
51969ecb 757 // Partial medium indicator,if Pmi is FALSE, the Cdb.2 ~ Cdb.5 MUST BE ZERO.\r
a02e796b 758 //\r
759 ZeroMem ((Cdb + 2), 4);\r
760 } else {\r
761 Cdb[8] |= 0x01;\r
762 }\r
763\r
52cd71dc 764 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;\r
a02e796b 765 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
766 CommandPacket.SenseDataLength = *SenseDataLength;\r
767\r
768 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
769\r
770 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
771 *TargetStatus = CommandPacket.TargetStatus;\r
772 *SenseDataLength = CommandPacket.SenseDataLength;\r
773 *DataLength = CommandPacket.InTransferLength;\r
774\r
775 return Status;\r
776}\r
777\r
bf231ea6 778\r
ccb491c8 779/**\r
5e11e7c6 780 Execute Read Capacity SCSI 16 command on a specific SCSI target.\r
781\r
782 Executes the SCSI Read Capacity 16 command on the SCSI target specified by ScsiIo.\r
783 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
784 If Timeout is greater than zero, then the command is executed and will timeout after\r
785 Timeout 100 ns units. The Pmi parameter is used to construct the CDB for this SCSI command.\r
786 If ScsiIo is NULL, then ASSERT().\r
787 If SenseDataLength is NULL, then ASSERT().\r
788 If HostAdapterStatus is NULL, then ASSERT().\r
789 If TargetStatus is NULL, then ASSERT().\r
790 If DataLength is NULL, then ASSERT().\r
791\r
d658727b
FT
792 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer\r
793 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
794 gets returned.\r
795\r
796 If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer\r
797 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
798 gets returned.\r
799\r
5e11e7c6 800 @param[in] ScsiIo A pointer to SCSI IO protocol.\r
801 @param[in] Timeout The length of timeout period.\r
802 @param[in, out] SenseData A pointer to output sense data.\r
803 @param[in, out] SenseDataLength The length of output sense data.\r
804 @param[out] HostAdapterStatus The status of Host Adapter.\r
805 @param[out] TargetStatus The status of the target.\r
806 @param[in, out] DataBuffer A pointer to a data buffer.\r
807 @param[in, out] DataLength The length of data buffer.\r
808 @param[in] Pmi Partial medium indicator.\r
809\r
d658727b
FT
810 @retval EFI_SUCCESS Command is executed successfully.\r
811 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire\r
812 DataBuffer could not be transferred. The actual\r
813 number of bytes transferred is returned in DataLength.\r
814 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because\r
815 there are too many SCSI Command Packets already queued.\r
816 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
817 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet\r
818 is not supported by the SCSI initiator(i.e., SCSI Host Controller)\r
819 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
820 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.\r
ccb491c8 821\r
822**/\r
ccb491c8 823EFI_STATUS\r
824EFIAPI\r
825ScsiReadCapacity16Command (\r
f158ee67 826 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
827 IN UINT64 Timeout,\r
828 IN OUT VOID *SenseData, OPTIONAL\r
829 IN OUT UINT8 *SenseDataLength,\r
830 OUT UINT8 *HostAdapterStatus,\r
831 OUT UINT8 *TargetStatus,\r
832 IN OUT VOID *DataBuffer, OPTIONAL\r
833 IN OUT UINT32 *DataLength,\r
834 IN BOOLEAN Pmi\r
ccb491c8 835 )\r
836{\r
837 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
ccb491c8 838 EFI_STATUS Status;\r
839 UINT8 Cdb[16];\r
840\r
5fe71b5f 841 ASSERT (SenseDataLength != NULL);\r
842 ASSERT (HostAdapterStatus != NULL);\r
843 ASSERT (TargetStatus != NULL);\r
844 ASSERT (DataLength != NULL);\r
845 ASSERT (ScsiIo != NULL);\r
846\r
ccb491c8 847 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
848 ZeroMem (Cdb, 16);\r
849\r
850 CommandPacket.Timeout = Timeout;\r
851 CommandPacket.InDataBuffer = DataBuffer;\r
852 CommandPacket.SenseData = SenseData;\r
853 CommandPacket.InTransferLength= *DataLength;\r
854 CommandPacket.Cdb = Cdb;\r
855 //\r
856 // Fill Cdb for Read Capacity Command\r
857 //\r
ccb491c8 858 Cdb[0] = EFI_SCSI_OP_READ_CAPACITY16;\r
859 Cdb[1] = 0x10;\r
51969ecb 860 if (!Pmi) {\r
ccb491c8 861 //\r
51969ecb 862 // Partial medium indicator,if Pmi is FALSE, the Cdb.2 ~ Cdb.9 MUST BE ZERO.\r
ccb491c8 863 //\r
864 ZeroMem ((Cdb + 2), 8);\r
865 } else {\r
866 Cdb[14] |= 0x01;\r
867 }\r
868\r
869 Cdb[13] = 0x20;\r
870 CommandPacket.CdbLength = 16;\r
871 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
872 CommandPacket.SenseDataLength = *SenseDataLength;\r
873\r
874 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
875\r
876 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
877 *TargetStatus = CommandPacket.TargetStatus;\r
878 *SenseDataLength = CommandPacket.SenseDataLength;\r
879 *DataLength = CommandPacket.InTransferLength;\r
880\r
881 return Status;\r
882}\r
883\r
884\r
a3589760 885/**\r
d5954c61 886 Execute Read(10) SCSI command on a specific SCSI target.\r
887\r
888 Executes the SCSI Read(10) command on the SCSI target specified by ScsiIo.\r
889 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
890 If Timeout is greater than zero, then the command is executed and will timeout\r
891 after Timeout 100 ns units. The StartLba and SectorSize parameters are used to\r
892 construct the CDB for this SCSI command.\r
893 If ScsiIo is NULL, then ASSERT().\r
52cd71dc
LG
894 If SenseDataLength is NULL, then ASSERT().\r
895 If HostAdapterStatus is NULL, then ASSERT().\r
896 If TargetStatus is NULL, then ASSERT().\r
b91d5eca 897 If DataLength is NULL, then ASSERT().\r
a3589760 898\r
d658727b
FT
899 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer\r
900 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
901 gets returned.\r
902\r
903 If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer\r
904 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
905 gets returned.\r
d5954c61 906\r
907 @param[in] ScsiIo A pointer to SCSI IO protocol.\r
908 @param[in] Timeout The length of timeout period.\r
909 @param[in, out] SenseData A pointer to output sense data.\r
ee256e2c 910 @param[in, out] SenseDataLength The length of output sense data.\r
d5954c61 911 @param[out] HostAdapterStatus The status of Host Adapter.\r
912 @param[out] TargetStatus The status of the target.\r
913 @param[in, out] DataBuffer Read 10 command data.\r
ee256e2c 914 @param[in, out] DataLength The length of data buffer.\r
d5954c61 915 @param[in] StartLba The start address of LBA.\r
b95eb5e0 916 @param[in] SectorSize The number of contiguous logical blocks of data that shall be transferred.\r
b91d5eca 917\r
d658727b
FT
918 @retval EFI_SUCCESS Command is executed successfully.\r
919 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could\r
920 not be transferred. The actual number of bytes transferred is returned in DataLength.\r
921 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many\r
922 SCSI Command Packets already queued.\r
923 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
924 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by\r
925 the SCSI initiator(i.e., SCSI Host Controller)\r
926 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
927 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.\r
a3589760 928\r
bf231ea6 929**/\r
a02e796b 930EFI_STATUS\r
373b5cf9 931EFIAPI\r
d35be2a4 932ScsiRead10Command (\r
d5954c61 933 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
934 IN UINT64 Timeout,\r
935 IN OUT VOID *SenseData, OPTIONAL\r
936 IN OUT UINT8 *SenseDataLength,\r
937 OUT UINT8 *HostAdapterStatus,\r
938 OUT UINT8 *TargetStatus,\r
939 IN OUT VOID *DataBuffer, OPTIONAL\r
940 IN OUT UINT32 *DataLength,\r
941 IN UINT32 StartLba,\r
942 IN UINT32 SectorSize\r
a02e796b 943 )\r
a02e796b 944{\r
945 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
a02e796b 946 EFI_STATUS Status;\r
52cd71dc 947 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];\r
a02e796b 948\r
8069d49e
LG
949 ASSERT (SenseDataLength != NULL);\r
950 ASSERT (HostAdapterStatus != NULL);\r
951 ASSERT (TargetStatus != NULL);\r
952 ASSERT (DataLength != NULL);\r
d5954c61 953 ASSERT (ScsiIo != NULL);\r
8069d49e 954\r
a02e796b 955 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
52cd71dc 956 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);\r
a02e796b 957\r
958 CommandPacket.Timeout = Timeout;\r
959 CommandPacket.InDataBuffer = DataBuffer;\r
960 CommandPacket.SenseData = SenseData;\r
961 CommandPacket.InTransferLength= *DataLength;\r
962 CommandPacket.Cdb = Cdb;\r
963 //\r
964 // Fill Cdb for Read (10) Command\r
965 //\r
a02e796b 966 Cdb[0] = EFI_SCSI_OP_READ10;\r
a24faca3 967 WriteUnaligned32 ((UINT32 *)&Cdb[2], SwapBytes32 (StartLba));\r
968 WriteUnaligned16 ((UINT16 *)&Cdb[7], SwapBytes16 ((UINT16) SectorSize));\r
a02e796b 969\r
52cd71dc 970 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;\r
a02e796b 971 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
972 CommandPacket.SenseDataLength = *SenseDataLength;\r
973\r
974 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
975\r
976 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
977 *TargetStatus = CommandPacket.TargetStatus;\r
978 *SenseDataLength = CommandPacket.SenseDataLength;\r
979 *DataLength = CommandPacket.InTransferLength;\r
980\r
981 return Status;\r
982}\r
983\r
bf231ea6 984\r
a3589760 985/**\r
d5954c61 986 Execute Write(10) SCSI command on a specific SCSI target.\r
987\r
988 Executes the SCSI Write(10) command on the SCSI target specified by ScsiIo.\r
989 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
990 If Timeout is greater than zero, then the command is executed and will timeout after\r
991 Timeout 100 ns units. The StartLba and SectorSize parameters are used to construct\r
992 the CDB for this SCSI command.\r
993 If ScsiIo is NULL, then ASSERT().\r
52cd71dc
LG
994 If SenseDataLength is NULL, then ASSERT().\r
995 If HostAdapterStatus is NULL, then ASSERT().\r
996 If TargetStatus is NULL, then ASSERT().\r
b91d5eca 997 If DataLength is NULL, then ASSERT().\r
a3589760 998\r
d658727b
FT
999 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer\r
1000 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
1001 gets returned.\r
1002\r
1003 If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer\r
1004 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
1005 gets returned.\r
1006\r
d5954c61 1007 @param[in] ScsiIo SCSI IO Protocol to use\r
1008 @param[in] Timeout The length of timeout period.\r
1009 @param[in, out] SenseData A pointer to output sense data.\r
6089ba62 1010 @param[in, out] SenseDataLength The length of output sense data.\r
d5954c61 1011 @param[out] HostAdapterStatus The status of Host Adapter.\r
1012 @param[out] TargetStatus The status of the target.\r
1013 @param[in, out] DataBuffer A pointer to a data buffer.\r
6089ba62 1014 @param[in, out] DataLength The length of data buffer.\r
d5954c61 1015 @param[in] StartLba The start address of LBA.\r
b95eb5e0 1016 @param[in] SectorSize The number of contiguous logical blocks of data that shall be transferred.\r
b91d5eca 1017\r
d658727b
FT
1018 @retval EFI_SUCCESS Command is executed successfully.\r
1019 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could\r
1020 not be transferred. The actual number of bytes transferred is returned in DataLength.\r
1021 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many\r
1022 SCSI Command Packets already queued.\r
1023 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
1024 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by\r
1025 the SCSI initiator(i.e., SCSI Host Controller)\r
1026 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
1027 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.\r
a3589760 1028\r
bf231ea6 1029**/\r
a02e796b 1030EFI_STATUS\r
373b5cf9 1031EFIAPI\r
d35be2a4 1032ScsiWrite10Command (\r
d5954c61 1033 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
1034 IN UINT64 Timeout,\r
1035 IN OUT VOID *SenseData, OPTIONAL\r
1036 IN OUT UINT8 *SenseDataLength,\r
1037 OUT UINT8 *HostAdapterStatus,\r
1038 OUT UINT8 *TargetStatus,\r
1039 IN OUT VOID *DataBuffer, OPTIONAL\r
1040 IN OUT UINT32 *DataLength,\r
1041 IN UINT32 StartLba,\r
1042 IN UINT32 SectorSize\r
a02e796b 1043 )\r
a02e796b 1044{\r
1045 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
a02e796b 1046 EFI_STATUS Status;\r
52cd71dc 1047 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TEN];\r
a02e796b 1048\r
8069d49e
LG
1049 ASSERT (SenseDataLength != NULL);\r
1050 ASSERT (HostAdapterStatus != NULL);\r
1051 ASSERT (TargetStatus != NULL);\r
1052 ASSERT (DataLength != NULL);\r
d5954c61 1053 ASSERT (ScsiIo != NULL);\r
8069d49e 1054\r
a02e796b 1055 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
52cd71dc 1056 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TEN);\r
a02e796b 1057\r
1058 CommandPacket.Timeout = Timeout;\r
1059 CommandPacket.OutDataBuffer = DataBuffer;\r
1060 CommandPacket.SenseData = SenseData;\r
1061 CommandPacket.OutTransferLength= *DataLength;\r
1062 CommandPacket.Cdb = Cdb;\r
1063 //\r
1064 // Fill Cdb for Write (10) Command\r
1065 //\r
a02e796b 1066 Cdb[0] = EFI_SCSI_OP_WRITE10;\r
a24faca3 1067 WriteUnaligned32 ((UINT32 *)&Cdb[2], SwapBytes32 (StartLba));\r
1068 WriteUnaligned16 ((UINT16 *)&Cdb[7], SwapBytes16 ((UINT16) SectorSize));\r
a02e796b 1069\r
52cd71dc 1070 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TEN;\r
a02e796b 1071 CommandPacket.DataDirection = EFI_SCSI_DATA_OUT;\r
1072 CommandPacket.SenseDataLength = *SenseDataLength;\r
1073\r
1074 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
1075\r
1076 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
1077 *TargetStatus = CommandPacket.TargetStatus;\r
1078 *SenseDataLength = CommandPacket.SenseDataLength;\r
ba7e162e 1079 *DataLength = CommandPacket.OutTransferLength;\r
a02e796b 1080\r
1081 return Status;\r
1082}\r
373b5cf9 1083\r
a24faca3 1084/**\r
1085 Execute Read(16) SCSI command on a specific SCSI target.\r
1086\r
1087 Executes the SCSI Read(16) command on the SCSI target specified by ScsiIo.\r
1088 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
1089 If Timeout is greater than zero, then the command is executed and will timeout\r
1090 after Timeout 100 ns units. The StartLba and SectorSize parameters are used to\r
1091 construct the CDB for this SCSI command.\r
1092 If ScsiIo is NULL, then ASSERT().\r
1093 If SenseDataLength is NULL, then ASSERT().\r
1094 If HostAdapterStatus is NULL, then ASSERT().\r
1095 If TargetStatus is NULL, then ASSERT().\r
1096 If DataLength is NULL, then ASSERT().\r
1097\r
d658727b
FT
1098 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer\r
1099 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
1100 gets returned.\r
1101\r
1102 If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer\r
1103 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
1104 gets returned.\r
a24faca3 1105\r
1106 @param[in] ScsiIo A pointer to SCSI IO protocol.\r
1107 @param[in] Timeout The length of timeout period.\r
1108 @param[in, out] SenseData A pointer to output sense data.\r
1109 @param[in, out] SenseDataLength The length of output sense data.\r
1110 @param[out] HostAdapterStatus The status of Host Adapter.\r
1111 @param[out] TargetStatus The status of the target.\r
1112 @param[in, out] DataBuffer Read 16 command data.\r
1113 @param[in, out] DataLength The length of data buffer.\r
1114 @param[in] StartLba The start address of LBA.\r
b95eb5e0 1115 @param[in] SectorSize The number of contiguous logical blocks of data that shall be transferred.\r
a24faca3 1116\r
d658727b
FT
1117 @retval EFI_SUCCESS Command is executed successfully.\r
1118 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could\r
1119 not be transferred. The actual number of bytes transferred is returned in DataLength.\r
1120 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many\r
1121 SCSI Command Packets already queued.\r
1122 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
1123 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by\r
1124 the SCSI initiator(i.e., SCSI Host Controller)\r
1125 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
1126 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.\r
a24faca3 1127\r
1128**/\r
1129EFI_STATUS\r
1130EFIAPI\r
1131ScsiRead16Command (\r
1132 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
1133 IN UINT64 Timeout,\r
1134 IN OUT VOID *SenseData, OPTIONAL\r
1135 IN OUT UINT8 *SenseDataLength,\r
1136 OUT UINT8 *HostAdapterStatus,\r
1137 OUT UINT8 *TargetStatus,\r
1138 IN OUT VOID *DataBuffer, OPTIONAL\r
1139 IN OUT UINT32 *DataLength,\r
1140 IN UINT64 StartLba,\r
1141 IN UINT32 SectorSize\r
1142 )\r
1143{\r
1144 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
a24faca3 1145 EFI_STATUS Status;\r
1146 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIXTEEN];\r
1147\r
1148 ASSERT (SenseDataLength != NULL);\r
1149 ASSERT (HostAdapterStatus != NULL);\r
1150 ASSERT (TargetStatus != NULL);\r
1151 ASSERT (DataLength != NULL);\r
1152 ASSERT (ScsiIo != NULL);\r
1153\r
1154 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
1155 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIXTEEN);\r
1156\r
1157 CommandPacket.Timeout = Timeout;\r
1158 CommandPacket.InDataBuffer = DataBuffer;\r
1159 CommandPacket.SenseData = SenseData;\r
1160 CommandPacket.InTransferLength = *DataLength;\r
1161 CommandPacket.Cdb = Cdb;\r
1162 //\r
1163 // Fill Cdb for Read (16) Command\r
1164 //\r
a24faca3 1165 Cdb[0] = EFI_SCSI_OP_READ16;\r
a24faca3 1166 WriteUnaligned64 ((UINT64 *)&Cdb[2], SwapBytes64 (StartLba));\r
1167 WriteUnaligned32 ((UINT32 *)&Cdb[10], SwapBytes32 (SectorSize));\r
1168\r
1169 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_SIXTEEN;\r
1170 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
1171 CommandPacket.SenseDataLength = *SenseDataLength;\r
1172\r
1173 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
1174\r
1175 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
1176 *TargetStatus = CommandPacket.TargetStatus;\r
1177 *SenseDataLength = CommandPacket.SenseDataLength;\r
1178 *DataLength = CommandPacket.InTransferLength;\r
1179\r
1180 return Status;\r
1181}\r
1182\r
1183\r
1184/**\r
1185 Execute Write(16) SCSI command on a specific SCSI target.\r
1186\r
1187 Executes the SCSI Write(16) command on the SCSI target specified by ScsiIo.\r
1188 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
1189 If Timeout is greater than zero, then the command is executed and will timeout after\r
1190 Timeout 100 ns units. The StartLba and SectorSize parameters are used to construct\r
1191 the CDB for this SCSI command.\r
1192 If ScsiIo is NULL, then ASSERT().\r
1193 If SenseDataLength is NULL, then ASSERT().\r
1194 If HostAdapterStatus is NULL, then ASSERT().\r
1195 If TargetStatus is NULL, then ASSERT().\r
1196 If DataLength is NULL, then ASSERT().\r
1197\r
d658727b
FT
1198 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer\r
1199 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
1200 gets returned.\r
1201\r
1202 If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer\r
1203 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
1204 gets returned.\r
1205\r
a24faca3 1206 @param[in] ScsiIo SCSI IO Protocol to use\r
1207 @param[in] Timeout The length of timeout period.\r
1208 @param[in, out] SenseData A pointer to output sense data.\r
1209 @param[in, out] SenseDataLength The length of output sense data.\r
1210 @param[out] HostAdapterStatus The status of Host Adapter.\r
1211 @param[out] TargetStatus The status of the target.\r
1212 @param[in, out] DataBuffer A pointer to a data buffer.\r
1213 @param[in, out] DataLength The length of data buffer.\r
1214 @param[in] StartLba The start address of LBA.\r
b95eb5e0 1215 @param[in] SectorSize The number of contiguous logical blocks of data that shall be transferred.\r
a24faca3 1216\r
d658727b
FT
1217 @retval EFI_SUCCESS Command is executed successfully.\r
1218 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could\r
1219 not be transferred. The actual number of bytes transferred is returned in DataLength.\r
1220 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many\r
1221 SCSI Command Packets already queued.\r
1222 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
1223 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by\r
1224 the SCSI initiator(i.e., SCSI Host Controller)\r
1225 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
1226 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.\r
a24faca3 1227\r
1228**/\r
1229EFI_STATUS\r
1230EFIAPI\r
1231ScsiWrite16Command (\r
1232 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
1233 IN UINT64 Timeout,\r
1234 IN OUT VOID *SenseData, OPTIONAL\r
1235 IN OUT UINT8 *SenseDataLength,\r
1236 OUT UINT8 *HostAdapterStatus,\r
1237 OUT UINT8 *TargetStatus,\r
1238 IN OUT VOID *DataBuffer, OPTIONAL\r
1239 IN OUT UINT32 *DataLength,\r
1240 IN UINT64 StartLba,\r
1241 IN UINT32 SectorSize\r
1242 )\r
1243{\r
1244 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
a24faca3 1245 EFI_STATUS Status;\r
1246 UINT8 Cdb[EFI_SCSI_OP_LENGTH_SIXTEEN];\r
1247\r
1248 ASSERT (SenseDataLength != NULL);\r
1249 ASSERT (HostAdapterStatus != NULL);\r
1250 ASSERT (TargetStatus != NULL);\r
1251 ASSERT (DataLength != NULL);\r
1252 ASSERT (ScsiIo != NULL);\r
1253\r
1254 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
1255 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_SIXTEEN);\r
1256\r
1257 CommandPacket.Timeout = Timeout;\r
1258 CommandPacket.OutDataBuffer = DataBuffer;\r
1259 CommandPacket.SenseData = SenseData;\r
1260 CommandPacket.OutTransferLength = *DataLength;\r
1261 CommandPacket.Cdb = Cdb;\r
1262 //\r
1263 // Fill Cdb for Write (16) Command\r
1264 //\r
a24faca3 1265 Cdb[0] = EFI_SCSI_OP_WRITE16;\r
a24faca3 1266 WriteUnaligned64 ((UINT64 *)&Cdb[2], SwapBytes64 (StartLba));\r
1267 WriteUnaligned32 ((UINT32 *)&Cdb[10], SwapBytes32 (SectorSize));\r
1268\r
1269 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_SIXTEEN;\r
1270 CommandPacket.DataDirection = EFI_SCSI_DATA_OUT;\r
1271 CommandPacket.SenseDataLength = *SenseDataLength;\r
1272\r
1273 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
1274\r
1275 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
1276 *TargetStatus = CommandPacket.TargetStatus;\r
1277 *SenseDataLength = CommandPacket.SenseDataLength;\r
1278 *DataLength = CommandPacket.OutTransferLength;\r
9b14509b
CZ
1279\r
1280 return Status;\r
1281}\r
1282\r
1283\r
1284/**\r
1285 Execute Security Protocol In SCSI command on a specific SCSI target.\r
1286\r
1287 Executes the SCSI Security Protocol In command on the SCSI target specified by ScsiIo.\r
1288 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
1289 If Timeout is greater than zero, then the command is executed and will timeout after\r
1290 Timeout 100 ns units.\r
1291 If ScsiIo is NULL, then ASSERT().\r
1292 If SenseDataLength is NULL, then ASSERT().\r
1293 If HostAdapterStatus is NULL, then ASSERT().\r
1294 If TargetStatus is NULL, then ASSERT().\r
1295 If TransferLength is NULL, then ASSERT().\r
1296\r
1297 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer\r
1298 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
1299 gets returned.\r
1300\r
1301 If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer\r
1302 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
1303 gets returned.\r
1304\r
1305 @param[in] ScsiIo SCSI IO Protocol to use.\r
1306 @param[in] Timeout The length of timeout period.\r
1307 @param[in, out] SenseData A pointer to output sense data.\r
1308 @param[in, out] SenseDataLength The length of output sense data.\r
1309 @param[out] HostAdapterStatus The status of Host Adapter.\r
1310 @param[out] TargetStatus The status of the target.\r
1311 @param[in] SecurityProtocol The Security Protocol to use.\r
1312 @param[in] SecurityProtocolSpecific The Security Protocol Specific data.\r
1313 @param[in] Inc512 If TRUE, 512 increment (INC_512) bit will be set for the\r
1314 SECURITY PROTOCOL IN command.\r
1315 @param[in] DataLength The size in bytes of the data buffer.\r
1316 @param[in, out] DataBuffer A pointer to a data buffer.\r
1317 @param[out] TransferLength A pointer to a buffer to store the size in\r
1318 bytes of the data written to the data buffer.\r
1319\r
1320 @retval EFI_SUCCESS Command is executed successfully.\r
1321 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could\r
1322 not be transferred. The actual number of bytes transferred is returned in TransferLength.\r
1323 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many\r
1324 SCSI Command Packets already queued.\r
1325 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
1326 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by\r
1327 the SCSI initiator(i.e., SCSI Host Controller)\r
1328 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
1329 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.\r
1330\r
1331**/\r
1332EFI_STATUS\r
1333EFIAPI\r
1334ScsiSecurityProtocolInCommand (\r
1335 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
1336 IN UINT64 Timeout,\r
1337 IN OUT VOID *SenseData, OPTIONAL\r
1338 IN OUT UINT8 *SenseDataLength,\r
1339 OUT UINT8 *HostAdapterStatus,\r
1340 OUT UINT8 *TargetStatus,\r
1341 IN UINT8 SecurityProtocol,\r
1342 IN UINT16 SecurityProtocolSpecific,\r
1343 IN BOOLEAN Inc512,\r
1344 IN UINTN DataLength,\r
1345 IN OUT VOID *DataBuffer, OPTIONAL\r
1346 OUT UINTN *TransferLength\r
1347 )\r
1348{\r
1349 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
1350 EFI_STATUS Status;\r
1351 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TWELVE];\r
1352\r
1353 ASSERT (SenseDataLength != NULL);\r
1354 ASSERT (HostAdapterStatus != NULL);\r
1355 ASSERT (TargetStatus != NULL);\r
1356 ASSERT (ScsiIo != NULL);\r
1357 ASSERT (TransferLength != NULL);\r
1358 ASSERT (DataLength <= MAX_UINT32);\r
1359\r
1360 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
1361 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TWELVE);\r
1362\r
1363 CommandPacket.Timeout = Timeout;\r
1364 CommandPacket.InDataBuffer = DataBuffer;\r
1365 CommandPacket.SenseData = SenseData;\r
1366 CommandPacket.InTransferLength = (UINT32) DataLength;\r
1367 CommandPacket.Cdb = Cdb;\r
1368 //\r
1369 // Fill Cdb for Security Protocol In Command\r
1370 //\r
1371 Cdb[0] = EFI_SCSI_OP_SECURITY_PROTOCOL_IN;\r
1372 Cdb[1] = SecurityProtocol;\r
1373 WriteUnaligned16 ((UINT16 *)&Cdb[2], SwapBytes16 (SecurityProtocolSpecific));\r
1374\r
1375 if (Inc512) {\r
1376 if (DataLength % 512 != 0) {\r
1377 return EFI_INVALID_PARAMETER;\r
1378 }\r
1379 Cdb[4] = BIT7;\r
1380 WriteUnaligned32 ((UINT32 *)&Cdb[6], SwapBytes32 ((UINT32) DataLength / 512));\r
1381 } else {\r
1382 WriteUnaligned32 ((UINT32 *)&Cdb[6], SwapBytes32 ((UINT32) DataLength));\r
1383 }\r
1384\r
1385 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TWELVE;\r
1386 CommandPacket.DataDirection = EFI_SCSI_DATA_IN;\r
1387 CommandPacket.SenseDataLength = *SenseDataLength;\r
1388\r
1389 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
1390\r
1391 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
1392 *TargetStatus = CommandPacket.TargetStatus;\r
1393 *SenseDataLength = CommandPacket.SenseDataLength;\r
1394 *TransferLength = (UINTN) CommandPacket.InTransferLength;\r
1395\r
1396 return Status;\r
1397}\r
1398\r
1399\r
1400/**\r
1401 Execute Security Protocol Out SCSI command on a specific SCSI target.\r
1402\r
1403 Executes the SCSI Security Protocol Out command on the SCSI target specified by ScsiIo.\r
1404 If Timeout is zero, then this function waits indefinitely for the command to complete.\r
1405 If Timeout is greater than zero, then the command is executed and will timeout after\r
1406 Timeout 100 ns units.\r
1407 If ScsiIo is NULL, then ASSERT().\r
1408 If SenseDataLength is NULL, then ASSERT().\r
1409 If HostAdapterStatus is NULL, then ASSERT().\r
1410 If TargetStatus is NULL, then ASSERT().\r
1411\r
1412 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet buffer\r
1413 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
1414 gets returned.\r
1415\r
1416 If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet buffer\r
1417 alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise EFI_INVALID_PARAMETER\r
1418 gets returned.\r
1419\r
1420 @param[in] ScsiIo SCSI IO Protocol to use.\r
1421 @param[in] Timeout The length of timeout period.\r
1422 @param[in, out] SenseData A pointer to output sense data.\r
1423 @param[in, out] SenseDataLength The length of output sense data.\r
1424 @param[out] HostAdapterStatus The status of Host Adapter.\r
1425 @param[out] TargetStatus The status of the target.\r
1426 @param[in] SecurityProtocol The Security Protocol to use.\r
1427 @param[in] SecurityProtocolSpecific The Security Protocol Specific data.\r
1428 @param[in] Inc512 If TRUE, 512 increment (INC_512) bit will be set for the\r
1429 SECURITY PROTOCOL OUT command.\r
1430 @param[in] DataLength The size in bytes of the transfer data.\r
1431 @param[in, out] DataBuffer A pointer to a data buffer.\r
1432\r
1433 @retval EFI_SUCCESS Command is executed successfully.\r
1434 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could\r
1435 not be transferred. The actual number of bytes transferred is returned in DataLength.\r
1436 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many\r
1437 SCSI Command Packets already queued.\r
1438 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
1439 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by\r
1440 the SCSI initiator(i.e., SCSI Host Controller)\r
1441 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
1442 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet are invalid.\r
1443\r
1444**/\r
1445EFI_STATUS\r
1446EFIAPI\r
1447ScsiSecurityProtocolOutCommand (\r
1448 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
1449 IN UINT64 Timeout,\r
1450 IN OUT VOID *SenseData, OPTIONAL\r
1451 IN OUT UINT8 *SenseDataLength,\r
1452 OUT UINT8 *HostAdapterStatus,\r
1453 OUT UINT8 *TargetStatus,\r
1454 IN UINT8 SecurityProtocol,\r
1455 IN UINT16 SecurityProtocolSpecific,\r
1456 IN BOOLEAN Inc512,\r
1457 IN UINTN DataLength,\r
1458 IN OUT VOID *DataBuffer OPTIONAL\r
1459 )\r
1460{\r
1461 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket;\r
1462 EFI_STATUS Status;\r
1463 UINT8 Cdb[EFI_SCSI_OP_LENGTH_TWELVE];\r
1464\r
1465 ASSERT (SenseDataLength != NULL);\r
1466 ASSERT (HostAdapterStatus != NULL);\r
1467 ASSERT (TargetStatus != NULL);\r
1468 ASSERT (ScsiIo != NULL);\r
1469 ASSERT (DataLength <= MAX_UINT32);\r
1470\r
1471 ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET));\r
1472 ZeroMem (Cdb, EFI_SCSI_OP_LENGTH_TWELVE);\r
1473\r
1474 CommandPacket.Timeout = Timeout;\r
1475 CommandPacket.OutDataBuffer = DataBuffer;\r
1476 CommandPacket.SenseData = SenseData;\r
1477 CommandPacket.OutTransferLength = (UINT32) DataLength;\r
1478 CommandPacket.Cdb = Cdb;\r
1479 //\r
1480 // Fill Cdb for Security Protocol Out Command\r
1481 //\r
1482 Cdb[0] = EFI_SCSI_OP_SECURITY_PROTOCOL_OUT;\r
1483 Cdb[1] = SecurityProtocol;\r
1484 WriteUnaligned16 ((UINT16 *)&Cdb[2], SwapBytes16 (SecurityProtocolSpecific));\r
1485\r
1486 if (Inc512) {\r
1487 if (DataLength % 512 != 0) {\r
1488 return EFI_INVALID_PARAMETER;\r
1489 }\r
1490 Cdb[4] = BIT7;\r
1491 WriteUnaligned32 ((UINT32 *)&Cdb[6], SwapBytes32 ((UINT32) DataLength / 512));\r
1492 } else {\r
1493 WriteUnaligned32 ((UINT32 *)&Cdb[6], SwapBytes32 ((UINT32) DataLength));\r
1494 }\r
1495\r
1496 CommandPacket.CdbLength = EFI_SCSI_OP_LENGTH_TWELVE;\r
1497 CommandPacket.DataDirection = EFI_SCSI_DATA_OUT;\r
1498 CommandPacket.SenseDataLength = *SenseDataLength;\r
1499\r
1500 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, &CommandPacket, NULL);\r
1501\r
1502 *HostAdapterStatus = CommandPacket.HostAdapterStatus;\r
1503 *TargetStatus = CommandPacket.TargetStatus;\r
1504 *SenseDataLength = CommandPacket.SenseDataLength;\r
a24faca3 1505\r
1506 return Status;\r
1507}\r
9c581939
HW
1508\r
1509\r
1510/**\r
1511 Internal helper notify function in which update the result of the\r
1512 non-blocking SCSI Read/Write commands and signal caller event.\r
1513\r
1514 @param Event The instance of EFI_EVENT.\r
1515 @param Context The parameter passed in.\r
1516\r
1517**/\r
1518VOID\r
1519EFIAPI\r
1520ScsiLibNotify (\r
1521 IN EFI_EVENT Event,\r
1522 IN VOID *Context\r
1523 )\r
1524{\r
1525 EFI_SCSI_LIB_ASYNC_CONTEXT *LibContext;\r
1526 EFI_SCSI_IO_SCSI_REQUEST_PACKET *CommandPacket;\r
1527 EFI_EVENT CallerEvent;\r
1528\r
1529 LibContext = (EFI_SCSI_LIB_ASYNC_CONTEXT *) Context;\r
1530 CommandPacket = &LibContext->CommandPacket;\r
1531 CallerEvent = LibContext->CallerEvent;\r
1532\r
1533 //\r
1534 // Update SCSI Read/Write operation results\r
1535 //\r
1536 *LibContext->SenseDataLength = CommandPacket->SenseDataLength;\r
1537 *LibContext->HostAdapterStatus = CommandPacket->HostAdapterStatus;\r
1538 *LibContext->TargetStatus = CommandPacket->TargetStatus;\r
1539 if (CommandPacket->InDataBuffer != NULL) {\r
1540 *LibContext->DataLength = CommandPacket->InTransferLength;\r
1541 } else {\r
1542 *LibContext->DataLength = CommandPacket->OutTransferLength;\r
1543 }\r
1544\r
1545 if (CommandPacket->Cdb != NULL) {\r
1546 FreePool (CommandPacket->Cdb);\r
1547 }\r
1548 FreePool (Context);\r
1549\r
1550 gBS->CloseEvent (Event);\r
1551 gBS->SignalEvent (CallerEvent);\r
1552}\r
1553\r
1554\r
1555/**\r
1556 Execute blocking/non-blocking Read(10) SCSI command on a specific SCSI\r
1557 target.\r
1558\r
1559 Executes the SCSI Read(10) command on the SCSI target specified by ScsiIo.\r
1560 When Event is NULL, blocking command will be executed. Otherwise non-blocking\r
1561 command will be executed.\r
1562 For blocking I/O, if Timeout is zero, this function will wait indefinitely\r
1563 for the command to complete. If Timeout is greater than zero, then the\r
1564 command is executed and will timeout after Timeout 100 ns units.\r
1565 For non-blocking I/O, if Timeout is zero, Event will be signaled only after\r
1566 the command to completes. If Timeout is greater than zero, Event will also be\r
1567 signaled after Timeout 100 ns units.\r
1568 The StartLba and SectorSize parameters are used to construct the CDB for this\r
1569 SCSI command.\r
1570\r
1571 If ScsiIo is NULL, then ASSERT().\r
1572 If SenseDataLength is NULL, then ASSERT().\r
1573 If HostAdapterStatus is NULL, then ASSERT().\r
1574 If TargetStatus is NULL, then ASSERT().\r
1575 If DataLength is NULL, then ASSERT().\r
1576\r
1577 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet\r
1578 buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise\r
1579 EFI_INVALID_PARAMETER gets returned.\r
1580\r
1581 If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet\r
1582 buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise\r
1583 EFI_INVALID_PARAMETER gets returned.\r
1584\r
1585 @param[in] ScsiIo A pointer to SCSI IO protocol.\r
1586 @param[in] Timeout The length of timeout period.\r
1587 @param[in, out] SenseData A pointer to output sense data.\r
1588 @param[in, out] SenseDataLength The length of output sense data.\r
1589 @param[out] HostAdapterStatus The status of Host Adapter.\r
1590 @param[out] TargetStatus The status of the target.\r
1591 @param[in, out] DataBuffer Read 16 command data.\r
1592 @param[in, out] DataLength The length of data buffer.\r
1593 @param[in] StartLba The start address of LBA.\r
1594 @param[in] SectorSize The number of contiguous logical blocks\r
1595 of data that shall be transferred.\r
1596 @param[in] Event If the SCSI target does not support\r
1597 non-blocking I/O, then Event is ignored,\r
1598 and blocking I/O is performed. If Event\r
1599 is NULL, then blocking I/O is performed.\r
1600 If Event is not NULL and non-blocking\r
1601 I/O is supported, then non-blocking I/O\r
1602 is performed, and Event will be signaled\r
1603 when the SCSI Read(10) command\r
1604 completes.\r
1605\r
1606 @retval EFI_SUCCESS Command is executed successfully.\r
1607 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,\r
1608 but the entire DataBuffer could not be\r
1609 transferred. The actual number of bytes\r
1610 transferred is returned in DataLength.\r
1611 @retval EFI_NOT_READY The SCSI Request Packet could not be\r
1612 sent because there are too many SCSI\r
1613 Command Packets already queued.\r
1614 @retval EFI_DEVICE_ERROR A device error occurred while attempting\r
1615 to send SCSI Request Packet.\r
1616 @retval EFI_UNSUPPORTED The command described by the SCSI\r
1617 Request Packet is not supported by the\r
1618 SCSI initiator(i.e., SCSI Host\r
1619 Controller)\r
1620 @retval EFI_TIMEOUT A timeout occurred while waiting for the\r
1621 SCSI Request Packet to execute.\r
1622 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet\r
1623 are invalid.\r
1624 @retval EFI_OUT_OF_RESOURCES The request could not be completed due\r
1625 to a lack of resources.\r
1626\r
1627**/\r
1628EFI_STATUS\r
1629EFIAPI\r
1630ScsiRead10CommandEx (\r
1631 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
1632 IN UINT64 Timeout,\r
1633 IN OUT VOID *SenseData, OPTIONAL\r
1634 IN OUT UINT8 *SenseDataLength,\r
1635 OUT UINT8 *HostAdapterStatus,\r
1636 OUT UINT8 *TargetStatus,\r
1637 IN OUT VOID *DataBuffer, OPTIONAL\r
1638 IN OUT UINT32 *DataLength,\r
1639 IN UINT32 StartLba,\r
1640 IN UINT32 SectorSize,\r
1641 IN EFI_EVENT Event OPTIONAL\r
1642 )\r
1643{\r
1644 EFI_SCSI_LIB_ASYNC_CONTEXT *Context;\r
1645 EFI_SCSI_IO_SCSI_REQUEST_PACKET *CommandPacket;\r
1646 EFI_STATUS Status;\r
1647 UINT8 *Cdb;\r
1648 EFI_EVENT SelfEvent;\r
1649\r
1650 if (Event == NULL) {\r
1651 return ScsiRead10Command (\r
1652 ScsiIo,\r
1653 Timeout,\r
1654 SenseData,\r
1655 SenseDataLength,\r
1656 HostAdapterStatus,\r
1657 TargetStatus,\r
1658 DataBuffer,\r
1659 DataLength,\r
1660 StartLba,\r
1661 SectorSize\r
1662 );\r
1663 }\r
1664\r
1665 ASSERT (SenseDataLength != NULL);\r
1666 ASSERT (HostAdapterStatus != NULL);\r
1667 ASSERT (TargetStatus != NULL);\r
1668 ASSERT (DataLength != NULL);\r
1669 ASSERT (ScsiIo != NULL);\r
1670\r
1671 Context = AllocateZeroPool (sizeof (EFI_SCSI_LIB_ASYNC_CONTEXT));\r
1672 if (Context == NULL) {\r
1673 return EFI_OUT_OF_RESOURCES;\r
1674 }\r
1675\r
1676 Cdb = AllocateZeroPool (EFI_SCSI_OP_LENGTH_TEN);\r
1677 if (Cdb == NULL) {\r
1678 Status = EFI_OUT_OF_RESOURCES;\r
1679 goto ErrorExit;\r
1680 }\r
1681\r
1682 Context->SenseDataLength = SenseDataLength;\r
1683 Context->HostAdapterStatus = HostAdapterStatus;\r
1684 Context->TargetStatus = TargetStatus;\r
1685 Context->CallerEvent = Event;\r
1686\r
1687 CommandPacket = &Context->CommandPacket;\r
1688 CommandPacket->Timeout = Timeout;\r
1689 CommandPacket->InDataBuffer = DataBuffer;\r
1690 CommandPacket->SenseData = SenseData;\r
1691 CommandPacket->InTransferLength = *DataLength;\r
1692 CommandPacket->Cdb = Cdb;\r
1693 //\r
1694 // Fill Cdb for Read (10) Command\r
1695 //\r
1696 Cdb[0] = EFI_SCSI_OP_READ10;\r
1697 WriteUnaligned32 ((UINT32 *)&Cdb[2], SwapBytes32 (StartLba));\r
1698 WriteUnaligned16 ((UINT16 *)&Cdb[7], SwapBytes16 ((UINT16) SectorSize));\r
1699\r
1700 CommandPacket->CdbLength = EFI_SCSI_OP_LENGTH_TEN;\r
1701 CommandPacket->DataDirection = EFI_SCSI_DATA_IN;\r
1702 CommandPacket->SenseDataLength = *SenseDataLength;\r
1703\r
1704 //\r
1705 // Create Event\r
1706 //\r
1707 Status = gBS->CreateEvent (\r
1708 EVT_NOTIFY_SIGNAL,\r
c018a257 1709 TPL_NOTIFY,\r
9c581939
HW
1710 ScsiLibNotify,\r
1711 Context,\r
1712 &SelfEvent\r
1713 );\r
1714 if (EFI_ERROR(Status)) {\r
1715 goto ErrorExit;\r
1716 }\r
1717\r
fbbb3ff3
HW
1718 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, CommandPacket, SelfEvent);\r
1719 if (EFI_ERROR(Status)) {\r
1720 //\r
1721 // Since ScsiLibNotify() will not be signaled if ExecuteScsiCommand()\r
1722 // returns with error, close the event here.\r
1723 //\r
1724 gBS->CloseEvent (SelfEvent);\r
1725 goto ErrorExit;\r
1726 } else {\r
1727 return EFI_SUCCESS;\r
1728 }\r
9c581939
HW
1729\r
1730ErrorExit:\r
1731 if (Context != NULL) {\r
1732 FreePool (Context);\r
1733 }\r
1734\r
1735 return Status;\r
1736}\r
1737\r
1738\r
1739/**\r
1740 Execute blocking/non-blocking Write(10) SCSI command on a specific SCSI\r
1741 target.\r
1742\r
1743 Executes the SCSI Write(10) command on the SCSI target specified by ScsiIo.\r
1744 When Event is NULL, blocking command will be executed. Otherwise non-blocking\r
1745 command will be executed.\r
1746 For blocking I/O, if Timeout is zero, this function will wait indefinitely\r
1747 for the command to complete. If Timeout is greater than zero, then the\r
1748 command is executed and will timeout after Timeout 100 ns units.\r
1749 For non-blocking I/O, if Timeout is zero, Event will be signaled only after\r
1750 the command to completes. If Timeout is greater than zero, Event will also be\r
1751 signaled after Timeout 100 ns units.\r
1752 The StartLba and SectorSize parameters are used to construct the CDB for this\r
1753 SCSI command.\r
1754\r
1755 If ScsiIo is NULL, then ASSERT().\r
1756 If SenseDataLength is NULL, then ASSERT().\r
1757 If HostAdapterStatus is NULL, then ASSERT().\r
1758 If TargetStatus is NULL, then ASSERT().\r
1759 If DataLength is NULL, then ASSERT().\r
1760\r
1761 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet\r
1762 buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise\r
1763 EFI_INVALID_PARAMETER gets returned.\r
1764\r
1765 If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet\r
1766 buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise\r
1767 EFI_INVALID_PARAMETER gets returned.\r
1768\r
1769 @param[in] ScsiIo SCSI IO Protocol to use\r
1770 @param[in] Timeout The length of timeout period.\r
1771 @param[in, out] SenseData A pointer to output sense data.\r
1772 @param[in, out] SenseDataLength The length of output sense data.\r
1773 @param[out] HostAdapterStatus The status of Host Adapter.\r
1774 @param[out] TargetStatus The status of the target.\r
1775 @param[in, out] DataBuffer A pointer to a data buffer.\r
1776 @param[in, out] DataLength The length of data buffer.\r
1777 @param[in] StartLba The start address of LBA.\r
1778 @param[in] SectorSize The number of contiguous logical blocks\r
1779 of data that shall be transferred.\r
1780 @param[in] Event If the SCSI target does not support\r
1781 non-blocking I/O, then Event is ignored,\r
1782 and blocking I/O is performed. If Event\r
1783 is NULL, then blocking I/O is performed.\r
1784 If Event is not NULL and non-blocking\r
1785 I/O is supported, then non-blocking I/O\r
1786 is performed, and Event will be signaled\r
1787 when the SCSI Write(10) command\r
1788 completes.\r
1789\r
1790 @retval EFI_SUCCESS Command is executed successfully.\r
1791 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,\r
1792 but the entire DataBuffer could not be\r
1793 transferred. The actual number of bytes\r
1794 transferred is returned in DataLength.\r
1795 @retval EFI_NOT_READY The SCSI Request Packet could not be\r
1796 sent because there are too many SCSI\r
1797 Command Packets already queued.\r
1798 @retval EFI_DEVICE_ERROR A device error occurred while attempting\r
1799 to send SCSI Request Packet.\r
1800 @retval EFI_UNSUPPORTED The command described by the SCSI\r
1801 Request Packet is not supported by the\r
1802 SCSI initiator(i.e., SCSI Host\r
1803 Controller)\r
1804 @retval EFI_TIMEOUT A timeout occurred while waiting for the\r
1805 SCSI Request Packet to execute.\r
1806 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet\r
1807 are invalid.\r
1808 @retval EFI_OUT_OF_RESOURCES The request could not be completed due\r
1809 to a lack of resources.\r
1810\r
1811**/\r
1812EFI_STATUS\r
1813EFIAPI\r
1814ScsiWrite10CommandEx (\r
1815 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
1816 IN UINT64 Timeout,\r
1817 IN OUT VOID *SenseData, OPTIONAL\r
1818 IN OUT UINT8 *SenseDataLength,\r
1819 OUT UINT8 *HostAdapterStatus,\r
1820 OUT UINT8 *TargetStatus,\r
1821 IN OUT VOID *DataBuffer, OPTIONAL\r
1822 IN OUT UINT32 *DataLength,\r
1823 IN UINT32 StartLba,\r
1824 IN UINT32 SectorSize,\r
1825 IN EFI_EVENT Event OPTIONAL\r
1826 )\r
1827{\r
1828 EFI_SCSI_LIB_ASYNC_CONTEXT *Context;\r
1829 EFI_SCSI_IO_SCSI_REQUEST_PACKET *CommandPacket;\r
1830 EFI_STATUS Status;\r
1831 UINT8 *Cdb;\r
1832 EFI_EVENT SelfEvent;\r
1833\r
1834 if (Event == NULL) {\r
1835 return ScsiWrite10Command (\r
1836 ScsiIo,\r
1837 Timeout,\r
1838 SenseData,\r
1839 SenseDataLength,\r
1840 HostAdapterStatus,\r
1841 TargetStatus,\r
1842 DataBuffer,\r
1843 DataLength,\r
1844 StartLba,\r
1845 SectorSize\r
1846 );\r
1847 }\r
1848\r
1849 ASSERT (SenseDataLength != NULL);\r
1850 ASSERT (HostAdapterStatus != NULL);\r
1851 ASSERT (TargetStatus != NULL);\r
1852 ASSERT (DataLength != NULL);\r
1853 ASSERT (ScsiIo != NULL);\r
1854\r
1855 Context = AllocateZeroPool (sizeof (EFI_SCSI_LIB_ASYNC_CONTEXT));\r
1856 if (Context == NULL) {\r
1857 return EFI_OUT_OF_RESOURCES;\r
1858 }\r
1859\r
1860 Cdb = AllocateZeroPool (EFI_SCSI_OP_LENGTH_TEN);\r
1861 if (Cdb == NULL) {\r
1862 Status = EFI_OUT_OF_RESOURCES;\r
1863 goto ErrorExit;\r
1864 }\r
1865\r
1866 Context->SenseDataLength = SenseDataLength;\r
1867 Context->HostAdapterStatus = HostAdapterStatus;\r
1868 Context->TargetStatus = TargetStatus;\r
1869 Context->CallerEvent = Event;\r
1870\r
1871 CommandPacket = &Context->CommandPacket;\r
1872 CommandPacket->Timeout = Timeout;\r
1873 CommandPacket->OutDataBuffer = DataBuffer;\r
1874 CommandPacket->SenseData = SenseData;\r
1875 CommandPacket->OutTransferLength = *DataLength;\r
1876 CommandPacket->Cdb = Cdb;\r
1877 //\r
1878 // Fill Cdb for Write (10) Command\r
1879 //\r
1880 Cdb[0] = EFI_SCSI_OP_WRITE10;\r
1881 WriteUnaligned32 ((UINT32 *)&Cdb[2], SwapBytes32 (StartLba));\r
1882 WriteUnaligned16 ((UINT16 *)&Cdb[7], SwapBytes16 ((UINT16) SectorSize));\r
1883\r
1884 CommandPacket->CdbLength = EFI_SCSI_OP_LENGTH_TEN;\r
1885 CommandPacket->DataDirection = EFI_SCSI_DATA_OUT;\r
1886 CommandPacket->SenseDataLength = *SenseDataLength;\r
1887\r
1888 //\r
1889 // Create Event\r
1890 //\r
1891 Status = gBS->CreateEvent (\r
1892 EVT_NOTIFY_SIGNAL,\r
c018a257 1893 TPL_NOTIFY,\r
9c581939
HW
1894 ScsiLibNotify,\r
1895 Context,\r
1896 &SelfEvent\r
1897 );\r
1898 if (EFI_ERROR(Status)) {\r
1899 goto ErrorExit;\r
1900 }\r
1901\r
fbbb3ff3
HW
1902 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, CommandPacket, SelfEvent);\r
1903 if (EFI_ERROR(Status)) {\r
1904 //\r
1905 // Since ScsiLibNotify() will not be signaled if ExecuteScsiCommand()\r
1906 // returns with error, close the event here.\r
1907 //\r
1908 gBS->CloseEvent (SelfEvent);\r
1909 goto ErrorExit;\r
1910 } else {\r
1911 return EFI_SUCCESS;\r
1912 }\r
9c581939
HW
1913\r
1914ErrorExit:\r
1915 if (Context != NULL) {\r
1916 FreePool (Context);\r
1917 }\r
1918\r
1919 return Status;\r
1920}\r
1921\r
1922\r
1923/**\r
1924 Execute blocking/non-blocking Read(16) SCSI command on a specific SCSI\r
1925 target.\r
1926\r
1927 Executes the SCSI Read(16) command on the SCSI target specified by ScsiIo.\r
1928 When Event is NULL, blocking command will be executed. Otherwise non-blocking\r
1929 command will be executed.\r
1930 For blocking I/O, if Timeout is zero, this function will wait indefinitely\r
1931 for the command to complete. If Timeout is greater than zero, then the\r
1932 command is executed and will timeout after Timeout 100 ns units.\r
1933 For non-blocking I/O, if Timeout is zero, Event will be signaled only after\r
1934 the command to completes. If Timeout is greater than zero, Event will also be\r
1935 signaled after Timeout 100 ns units.\r
1936 The StartLba and SectorSize parameters are used to construct the CDB for this\r
1937 SCSI command.\r
1938\r
1939 If ScsiIo is NULL, then ASSERT().\r
1940 If SenseDataLength is NULL, then ASSERT().\r
1941 If HostAdapterStatus is NULL, then ASSERT().\r
1942 If TargetStatus is NULL, then ASSERT().\r
1943 If DataLength is NULL, then ASSERT().\r
1944\r
1945 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet\r
1946 buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise\r
1947 EFI_INVALID_PARAMETER gets returned.\r
1948\r
1949 If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet\r
1950 buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise\r
1951 EFI_INVALID_PARAMETER gets returned.\r
1952\r
1953 @param[in] ScsiIo A pointer to SCSI IO protocol.\r
1954 @param[in] Timeout The length of timeout period.\r
1955 @param[in, out] SenseData A pointer to output sense data.\r
1956 @param[in, out] SenseDataLength The length of output sense data.\r
1957 @param[out] HostAdapterStatus The status of Host Adapter.\r
1958 @param[out] TargetStatus The status of the target.\r
1959 @param[in, out] DataBuffer Read 16 command data.\r
1960 @param[in, out] DataLength The length of data buffer.\r
1961 @param[in] StartLba The start address of LBA.\r
1962 @param[in] SectorSize The number of contiguous logical blocks\r
1963 of data that shall be transferred.\r
1964 @param[in] Event If the SCSI target does not support\r
1965 non-blocking I/O, then Event is ignored,\r
1966 and blocking I/O is performed. If Event\r
1967 is NULL, then blocking I/O is performed.\r
1968 If Event is not NULL and non-blocking\r
1969 I/O is supported, then non-blocking I/O\r
1970 is performed, and Event will be signaled\r
1971 when the SCSI Read(16) command\r
1972 completes.\r
1973\r
1974 @retval EFI_SUCCESS Command is executed successfully.\r
1975 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,\r
1976 but the entire DataBuffer could not be\r
1977 transferred. The actual number of bytes\r
1978 transferred is returned in DataLength.\r
1979 @retval EFI_NOT_READY The SCSI Request Packet could not be\r
1980 sent because there are too many SCSI\r
1981 Command Packets already queued.\r
1982 @retval EFI_DEVICE_ERROR A device error occurred while attempting\r
1983 to send SCSI Request Packet.\r
1984 @retval EFI_UNSUPPORTED The command described by the SCSI\r
1985 Request Packet is not supported by the\r
1986 SCSI initiator(i.e., SCSI Host\r
1987 Controller)\r
1988 @retval EFI_TIMEOUT A timeout occurred while waiting for the\r
1989 SCSI Request Packet to execute.\r
1990 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet\r
1991 are invalid.\r
1992 @retval EFI_OUT_OF_RESOURCES The request could not be completed due\r
1993 to a lack of resources.\r
1994\r
1995**/\r
1996EFI_STATUS\r
1997EFIAPI\r
1998ScsiRead16CommandEx (\r
1999 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
2000 IN UINT64 Timeout,\r
2001 IN OUT VOID *SenseData, OPTIONAL\r
2002 IN OUT UINT8 *SenseDataLength,\r
2003 OUT UINT8 *HostAdapterStatus,\r
2004 OUT UINT8 *TargetStatus,\r
2005 IN OUT VOID *DataBuffer, OPTIONAL\r
2006 IN OUT UINT32 *DataLength,\r
2007 IN UINT64 StartLba,\r
2008 IN UINT32 SectorSize,\r
2009 IN EFI_EVENT Event OPTIONAL\r
2010 )\r
2011{\r
2012 EFI_SCSI_LIB_ASYNC_CONTEXT *Context;\r
2013 EFI_SCSI_IO_SCSI_REQUEST_PACKET *CommandPacket;\r
2014 EFI_STATUS Status;\r
2015 UINT8 *Cdb;\r
2016 EFI_EVENT SelfEvent;\r
2017\r
2018 if (Event == NULL) {\r
2019 return ScsiRead16Command (\r
2020 ScsiIo,\r
2021 Timeout,\r
2022 SenseData,\r
2023 SenseDataLength,\r
2024 HostAdapterStatus,\r
2025 TargetStatus,\r
2026 DataBuffer,\r
2027 DataLength,\r
2028 StartLba,\r
2029 SectorSize\r
2030 );\r
2031 }\r
2032\r
2033 ASSERT (SenseDataLength != NULL);\r
2034 ASSERT (HostAdapterStatus != NULL);\r
2035 ASSERT (TargetStatus != NULL);\r
2036 ASSERT (DataLength != NULL);\r
2037 ASSERT (ScsiIo != NULL);\r
2038\r
2039 Context = AllocateZeroPool (sizeof (EFI_SCSI_LIB_ASYNC_CONTEXT));\r
2040 if (Context == NULL) {\r
2041 return EFI_OUT_OF_RESOURCES;\r
2042 }\r
2043\r
2044 Cdb = AllocateZeroPool (EFI_SCSI_OP_LENGTH_SIXTEEN);\r
2045 if (Cdb == NULL) {\r
2046 Status = EFI_OUT_OF_RESOURCES;\r
2047 goto ErrorExit;\r
2048 }\r
2049\r
2050 Context->SenseDataLength = SenseDataLength;\r
2051 Context->HostAdapterStatus = HostAdapterStatus;\r
2052 Context->TargetStatus = TargetStatus;\r
2053 Context->CallerEvent = Event;\r
2054\r
2055 CommandPacket = &Context->CommandPacket;\r
2056 CommandPacket->Timeout = Timeout;\r
2057 CommandPacket->InDataBuffer = DataBuffer;\r
2058 CommandPacket->SenseData = SenseData;\r
2059 CommandPacket->InTransferLength = *DataLength;\r
2060 CommandPacket->Cdb = Cdb;\r
2061 //\r
2062 // Fill Cdb for Read (16) Command\r
2063 //\r
2064 Cdb[0] = EFI_SCSI_OP_READ16;\r
2065 WriteUnaligned64 ((UINT64 *)&Cdb[2], SwapBytes64 (StartLba));\r
2066 WriteUnaligned32 ((UINT32 *)&Cdb[10], SwapBytes32 (SectorSize));\r
2067\r
2068 CommandPacket->CdbLength = EFI_SCSI_OP_LENGTH_SIXTEEN;\r
2069 CommandPacket->DataDirection = EFI_SCSI_DATA_IN;\r
2070 CommandPacket->SenseDataLength = *SenseDataLength;\r
2071\r
2072 //\r
2073 // Create Event\r
2074 //\r
2075 Status = gBS->CreateEvent (\r
2076 EVT_NOTIFY_SIGNAL,\r
c018a257 2077 TPL_NOTIFY,\r
9c581939
HW
2078 ScsiLibNotify,\r
2079 Context,\r
2080 &SelfEvent\r
2081 );\r
2082 if (EFI_ERROR(Status)) {\r
2083 goto ErrorExit;\r
2084 }\r
2085\r
fbbb3ff3
HW
2086 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, CommandPacket, SelfEvent);\r
2087 if (EFI_ERROR(Status)) {\r
2088 //\r
2089 // Since ScsiLibNotify() will not be signaled if ExecuteScsiCommand()\r
2090 // returns with error, close the event here.\r
2091 //\r
2092 gBS->CloseEvent (SelfEvent);\r
2093 goto ErrorExit;\r
2094 } else {\r
2095 return EFI_SUCCESS;\r
2096 }\r
9c581939
HW
2097\r
2098ErrorExit:\r
2099 if (Context != NULL) {\r
2100 FreePool (Context);\r
2101 }\r
2102\r
2103 return Status;\r
2104}\r
2105\r
2106\r
2107/**\r
2108 Execute blocking/non-blocking Write(16) SCSI command on a specific SCSI\r
2109 target.\r
2110\r
2111 Executes the SCSI Write(16) command on the SCSI target specified by ScsiIo.\r
2112 When Event is NULL, blocking command will be executed. Otherwise non-blocking\r
2113 command will be executed.\r
2114 For blocking I/O, if Timeout is zero, this function will wait indefinitely\r
2115 for the command to complete. If Timeout is greater than zero, then the\r
2116 command is executed and will timeout after Timeout 100 ns units.\r
2117 For non-blocking I/O, if Timeout is zero, Event will be signaled only after\r
2118 the command to completes. If Timeout is greater than zero, Event will also be\r
2119 signaled after Timeout 100 ns units.\r
2120 The StartLba and SectorSize parameters are used to construct the CDB for this\r
2121 SCSI command.\r
2122\r
2123 If ScsiIo is NULL, then ASSERT().\r
2124 If SenseDataLength is NULL, then ASSERT().\r
2125 If HostAdapterStatus is NULL, then ASSERT().\r
2126 If TargetStatus is NULL, then ASSERT().\r
2127 If DataLength is NULL, then ASSERT().\r
2128\r
2129 If SenseDataLength is non-zero and SenseData is not NULL, SenseData must meet\r
2130 buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise\r
2131 EFI_INVALID_PARAMETER gets returned.\r
2132\r
2133 If DataLength is non-zero and DataBuffer is not NULL, DataBuffer must meet\r
2134 buffer alignment requirement defined in EFI_SCSI_IO_PROTOCOL. Otherwise\r
2135 EFI_INVALID_PARAMETER gets returned.\r
2136\r
2137 @param[in] ScsiIo SCSI IO Protocol to use\r
2138 @param[in] Timeout The length of timeout period.\r
2139 @param[in, out] SenseData A pointer to output sense data.\r
2140 @param[in, out] SenseDataLength The length of output sense data.\r
2141 @param[out] HostAdapterStatus The status of Host Adapter.\r
2142 @param[out] TargetStatus The status of the target.\r
2143 @param[in, out] DataBuffer A pointer to a data buffer.\r
2144 @param[in, out] DataLength The length of data buffer.\r
2145 @param[in] StartLba The start address of LBA.\r
2146 @param[in] SectorSize The number of contiguous logical blocks\r
2147 of data that shall be transferred.\r
2148 @param[in] Event If the SCSI target does not support\r
2149 non-blocking I/O, then Event is ignored,\r
2150 and blocking I/O is performed. If Event\r
2151 is NULL, then blocking I/O is performed.\r
2152 If Event is not NULL and non-blocking\r
2153 I/O is supported, then non-blocking I/O\r
2154 is performed, and Event will be signaled\r
2155 when the SCSI Write(16) command\r
2156 completes.\r
2157\r
2158 @retval EFI_SUCCESS Command is executed successfully.\r
2159 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,\r
2160 but the entire DataBuffer could not be\r
2161 transferred. The actual number of bytes\r
2162 transferred is returned in DataLength.\r
2163 @retval EFI_NOT_READY The SCSI Request Packet could not be\r
2164 sent because there are too many SCSI\r
2165 Command Packets already queued.\r
2166 @retval EFI_DEVICE_ERROR A device error occurred while attempting\r
2167 to send SCSI Request Packet.\r
2168 @retval EFI_UNSUPPORTED The command described by the SCSI\r
2169 Request Packet is not supported by the\r
2170 SCSI initiator(i.e., SCSI Host\r
2171 Controller)\r
2172 @retval EFI_TIMEOUT A timeout occurred while waiting for the\r
2173 SCSI Request Packet to execute.\r
2174 @retval EFI_INVALID_PARAMETER The contents of the SCSI Request Packet\r
2175 are invalid.\r
2176 @retval EFI_OUT_OF_RESOURCES The request could not be completed due\r
2177 to a lack of resources.\r
2178\r
2179**/\r
2180EFI_STATUS\r
2181EFIAPI\r
2182ScsiWrite16CommandEx (\r
2183 IN EFI_SCSI_IO_PROTOCOL *ScsiIo,\r
2184 IN UINT64 Timeout,\r
2185 IN OUT VOID *SenseData, OPTIONAL\r
2186 IN OUT UINT8 *SenseDataLength,\r
2187 OUT UINT8 *HostAdapterStatus,\r
2188 OUT UINT8 *TargetStatus,\r
2189 IN OUT VOID *DataBuffer, OPTIONAL\r
2190 IN OUT UINT32 *DataLength,\r
2191 IN UINT64 StartLba,\r
2192 IN UINT32 SectorSize,\r
2193 IN EFI_EVENT Event OPTIONAL\r
2194 )\r
2195{\r
2196 EFI_SCSI_LIB_ASYNC_CONTEXT *Context;\r
2197 EFI_SCSI_IO_SCSI_REQUEST_PACKET *CommandPacket;\r
2198 EFI_STATUS Status;\r
2199 UINT8 *Cdb;\r
2200 EFI_EVENT SelfEvent;\r
2201\r
2202 if (Event == NULL) {\r
2203 return ScsiWrite16Command (\r
2204 ScsiIo,\r
2205 Timeout,\r
2206 SenseData,\r
2207 SenseDataLength,\r
2208 HostAdapterStatus,\r
2209 TargetStatus,\r
2210 DataBuffer,\r
2211 DataLength,\r
2212 StartLba,\r
2213 SectorSize\r
2214 );\r
2215 }\r
2216\r
2217 ASSERT (SenseDataLength != NULL);\r
2218 ASSERT (HostAdapterStatus != NULL);\r
2219 ASSERT (TargetStatus != NULL);\r
2220 ASSERT (DataLength != NULL);\r
2221 ASSERT (ScsiIo != NULL);\r
2222\r
2223 Context = AllocateZeroPool (sizeof (EFI_SCSI_LIB_ASYNC_CONTEXT));\r
2224 if (Context == NULL) {\r
2225 return EFI_OUT_OF_RESOURCES;\r
2226 }\r
2227\r
2228 Cdb = AllocateZeroPool (EFI_SCSI_OP_LENGTH_SIXTEEN);\r
2229 if (Cdb == NULL) {\r
2230 Status = EFI_OUT_OF_RESOURCES;\r
2231 goto ErrorExit;\r
2232 }\r
2233\r
2234 Context->SenseDataLength = SenseDataLength;\r
2235 Context->HostAdapterStatus = HostAdapterStatus;\r
2236 Context->TargetStatus = TargetStatus;\r
2237 Context->CallerEvent = Event;\r
2238\r
2239 CommandPacket = &Context->CommandPacket;\r
2240 CommandPacket->Timeout = Timeout;\r
2241 CommandPacket->OutDataBuffer = DataBuffer;\r
2242 CommandPacket->SenseData = SenseData;\r
2243 CommandPacket->OutTransferLength = *DataLength;\r
2244 CommandPacket->Cdb = Cdb;\r
2245 //\r
2246 // Fill Cdb for Write (16) Command\r
2247 //\r
2248 Cdb[0] = EFI_SCSI_OP_WRITE16;\r
2249 WriteUnaligned64 ((UINT64 *)&Cdb[2], SwapBytes64 (StartLba));\r
2250 WriteUnaligned32 ((UINT32 *)&Cdb[10], SwapBytes32 (SectorSize));\r
2251\r
2252 CommandPacket->CdbLength = EFI_SCSI_OP_LENGTH_SIXTEEN;\r
2253 CommandPacket->DataDirection = EFI_SCSI_DATA_OUT;\r
2254 CommandPacket->SenseDataLength = *SenseDataLength;\r
2255\r
2256 //\r
2257 // Create Event\r
2258 //\r
2259 Status = gBS->CreateEvent (\r
2260 EVT_NOTIFY_SIGNAL,\r
c018a257 2261 TPL_NOTIFY,\r
9c581939
HW
2262 ScsiLibNotify,\r
2263 Context,\r
2264 &SelfEvent\r
2265 );\r
2266 if (EFI_ERROR(Status)) {\r
2267 goto ErrorExit;\r
2268 }\r
2269\r
fbbb3ff3
HW
2270 Status = ScsiIo->ExecuteScsiCommand (ScsiIo, CommandPacket, SelfEvent);\r
2271 if (EFI_ERROR(Status)) {\r
2272 //\r
2273 // Since ScsiLibNotify() will not be signaled if ExecuteScsiCommand()\r
2274 // returns with error, close the event here.\r
2275 //\r
2276 gBS->CloseEvent (SelfEvent);\r
2277 goto ErrorExit;\r
2278 } else {\r
2279 return EFI_SUCCESS;\r
2280 }\r
9c581939
HW
2281\r
2282ErrorExit:\r
2283 if (Context != NULL) {\r
2284 FreePool (Context);\r
2285 }\r
2286\r
2287 return Status;\r
2288}\r