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