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