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