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