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