2 UEFI SCSI Library implementation
4 Copyright (c) 2006 - 2008, Intel Corporation.<BR>
5 All rights reserved. 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
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.
17 #include <Library/DebugLib.h>
18 #include <Library/UefiScsiLib.h>
19 #include <Library/BaseMemoryLib.h>
21 #include <IndustryStandard/Scsi.h>
25 // Max bytes needed to represent ID of a SCSI device
27 #define EFI_SCSI_TARGET_MAX_BYTES (0x10)
30 // bit5..7 are for Logical unit number
33 #define EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK 0xe0
36 // Scsi Command Length six or ten
38 #define EFI_SCSI_OP_LENGTH_SIX 0x6
39 #define EFI_SCSI_OP_LENGTH_TEN 0xa
44 Execute Test Unit Ready SCSI command on a specific SCSI target.
46 Executes the Test Unit Ready command on the SCSI target specified by ScsiIo.
47 If Timeout is zero, then this function waits indefinitely for the command to complete.
48 If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.
49 If ScsiIo is NULL, then ASSERT().
50 If SenseDataLength is NULL, then ASSERT().
51 If HostAdapterStatus is NULL, then ASSERT().
52 If TargetStatus is NULL, then ASSERT().
55 @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance
56 for the specific SCSI target.
57 @param[in] Timeout The timeout in 100 ns units to use for the execution
58 of this SCSI Request Packet. A Timeout value of
59 zero means that this function will wait indefinitely
60 for the SCSI Request Packet to execute. If Timeout
61 is greater than zero, then this function will return
62 EFI_TIMEOUT if the time required to execute the SCSI
63 Request Packet is greater than Timeout.
64 @param[in, out] SenseData A pointer to sense data that was generated by
65 the execution of the SCSI Request Packet. This
66 buffer must be allocated by the caller.
67 If SenseDataLength is 0, then this parameter is
68 optional and may be NULL.
69 @param[in, out] SenseDataLength On input, a pointer to the length in bytes of
70 the SenseData buffer. On output, a pointer to
71 the number of bytes written to the SenseData buffer.
72 @param[out] HostAdapterStatus The status of the SCSI Host Controller that produces
73 the SCSI bus containing the SCSI target specified by
74 ScsiIo when the SCSI Request Packet was executed.
75 See the EFI SCSI I/O Protocol in the UEFI Specification
76 for details on the possible return values.
77 @param[out] TargetStatus The status returned by the SCSI target specified
78 by ScsiIo when the SCSI Request Packet was executed
79 on the SCSI Host Controller. See the EFI SCSI I/O
80 Protocol in the UEFI Specification for details on
81 the possible return values.
83 @retval EFI_SUCCESS The command was executed successfully.
84 See HostAdapterStatus, TargetStatus, SenseDataLength,
85 and SenseData in that order for additional status
87 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
88 there are too many SCSI Command Packets already
89 queued. The SCSI Request Packet was not sent, so
90 no additional status information is available.
91 The caller may retry again later.
92 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
93 SCSI Request Packet. See HostAdapterStatus,
94 TargetStatus, SenseDataLength, and SenseData in that
95 order for additional status information.
96 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
97 is not supported by the SCSI initiator(i.e., SCSI
98 Host Controller). The SCSI Request Packet was not
99 sent, so no additional status information is available.
100 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request
101 Packet to execute. See HostAdapterStatus, TargetStatus,
102 SenseDataLength, and SenseData in that order for
103 additional status information.
108 ScsiTestUnitReadyCommand (
109 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
111 IN OUT VOID
*SenseData
, OPTIONAL
112 IN OUT UINT8
*SenseDataLength
,
113 OUT UINT8
*HostAdapterStatus
,
114 OUT UINT8
*TargetStatus
117 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
119 UINT8 Cdb
[EFI_SCSI_OP_LENGTH_SIX
];
121 ASSERT (SenseDataLength
!= NULL
);
122 ASSERT (HostAdapterStatus
!= NULL
);
123 ASSERT (TargetStatus
!= NULL
);
124 ASSERT (ScsiIo
!= NULL
);
126 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
127 ZeroMem (Cdb
, EFI_SCSI_OP_LENGTH_SIX
);
129 CommandPacket
.Timeout
= Timeout
;
130 CommandPacket
.InDataBuffer
= NULL
;
131 CommandPacket
.InTransferLength
= 0;
132 CommandPacket
.OutDataBuffer
= NULL
;
133 CommandPacket
.OutTransferLength
= 0;
134 CommandPacket
.SenseData
= SenseData
;
135 CommandPacket
.Cdb
= Cdb
;
137 // Fill Cdb for Test Unit Ready Command
139 Cdb
[0] = EFI_SCSI_OP_TEST_UNIT_READY
;
140 CommandPacket
.CdbLength
= (UINT8
) EFI_SCSI_OP_LENGTH_SIX
;
141 CommandPacket
.SenseDataLength
= *SenseDataLength
;
143 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
145 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
146 *TargetStatus
= CommandPacket
.TargetStatus
;
147 *SenseDataLength
= CommandPacket
.SenseDataLength
;
154 Execute Inquiry SCSI command on a specific SCSI target.
156 Executes the Inquiry command on the SCSI target specified by ScsiIo.
157 If Timeout is zero, then this function waits indefinitely for the command to complete.
158 If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.
159 If ScsiIo is NULL, then ASSERT().
160 If SenseDataLength is NULL, then ASSERT().
161 If HostAdapterStatus is NULL, then ASSERT().
162 If TargetStatus is NULL, then ASSERT().
163 If InquiryDataLength is NULL, then ASSERT().
165 @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance
166 for the specific SCSI target.
167 @param[in] Timeout The timeout in 100 ns units to use for the
168 execution of this SCSI Request Packet. A Timeout
169 value of zero means that this function will wait
170 indefinitely for the SCSI Request Packet to execute.
171 If Timeout is greater than zero, then this function
172 will return EFI_TIMEOUT if the time required to
173 execute the SCSI Request Packet is greater than Timeout.
174 @param[in, out] SenseData A pointer to sense data that was generated
175 by the execution of the SCSI Request Packet.
176 This buffer must be allocated by the caller.
177 If SenseDataLength is 0, then this parameter
178 is optional and may be NULL.
179 @param[in, out] SenseDataLength On input, the length in bytes of the SenseData buffer.
180 On output, the number of bytes written to the SenseData buffer.
181 @param[out] HostAdapterStatus The status of the SCSI Host Controller that
182 produces the SCSI bus containing the SCSI
183 target specified by ScsiIo when the SCSI
184 Request Packet was executed. See the EFI
185 SCSI I/O Protocol in the UEFI Specification
186 for details on the possible return values.
187 @param[out] TargetStatus The status returned by the SCSI target specified
188 by ScsiIo when the SCSI Request Packet was
189 executed on the SCSI Host Controller.
190 See the EFI SCSI I/O Protocol in the UEFI
191 Specification for details on the possible
193 @param[in, out] InquiryDataBuffer A pointer to inquiry data that was generated
194 by the execution of the SCSI Request Packet.
195 This buffer must be allocated by the caller.
196 If InquiryDataLength is 0, then this parameter
197 is optional and may be NULL.
198 @param[in, out] InquiryDataLength On input, a pointer to the length in bytes
199 of the InquiryDataBuffer buffer.
200 On output, a pointer to the number of bytes
201 written to the InquiryDataBuffer buffer.
202 @param[in] EnableVitalProductData If TRUE, then the supported vital product
203 data is returned in InquiryDataBuffer.
204 If FALSE, then the standard inquiry data is
205 returned in InquiryDataBuffer.
207 @retval EFI_SUCCESS The command was executed successfully. See HostAdapterStatus,
208 TargetStatus, SenseDataLength, and SenseData in that order
209 for additional status information.
210 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire
211 InquiryDataBuffer could not be transferred. The actual
212 number of bytes transferred is returned in InquiryDataLength.
213 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there
214 are too many SCSI Command Packets already queued.
215 The SCSI Request Packet was not sent, so no additional
216 status information is available. The caller may retry again later.
217 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI
218 Request Packet. See HostAdapterStatus, TargetStatus,
219 SenseDataLength, and SenseData in that order for additional
221 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not
222 supported by the SCSI initiator(i.e., SCSI Host Controller).
223 The SCSI Request Packet was not sent, so no additional
224 status information is available.
225 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request
226 Packet to execute. See HostAdapterStatus, TargetStatus,
227 SenseDataLength, and SenseData in that order for
228 additional status information.
234 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
236 IN OUT VOID
*SenseData
, OPTIONAL
237 IN OUT UINT8
*SenseDataLength
,
238 OUT UINT8
*HostAdapterStatus
,
239 OUT UINT8
*TargetStatus
,
240 IN OUT VOID
*InquiryDataBuffer
, OPTIONAL
241 IN OUT UINT32
*InquiryDataLength
,
242 IN BOOLEAN EnableVitalProductData
245 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
247 UINT8 Cdb
[EFI_SCSI_OP_LENGTH_SIX
];
249 ASSERT (SenseDataLength
!= NULL
);
250 ASSERT (HostAdapterStatus
!= NULL
);
251 ASSERT (TargetStatus
!= NULL
);
252 ASSERT (InquiryDataLength
!= NULL
);
253 ASSERT (ScsiIo
!= NULL
);
255 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
256 ZeroMem (Cdb
, EFI_SCSI_OP_LENGTH_SIX
);
258 CommandPacket
.Timeout
= Timeout
;
259 CommandPacket
.InDataBuffer
= InquiryDataBuffer
;
260 CommandPacket
.InTransferLength
= *InquiryDataLength
;
261 CommandPacket
.SenseData
= SenseData
;
262 CommandPacket
.SenseDataLength
= *SenseDataLength
;
263 CommandPacket
.Cdb
= Cdb
;
265 Cdb
[0] = EFI_SCSI_OP_INQUIRY
;
266 if (EnableVitalProductData
) {
270 if (*InquiryDataLength
> 0xff) {
271 *InquiryDataLength
= 0xff;
274 Cdb
[4] = (UINT8
) (*InquiryDataLength
);
275 CommandPacket
.CdbLength
= (UINT8
) EFI_SCSI_OP_LENGTH_SIX
;
276 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
278 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
280 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
281 *TargetStatus
= CommandPacket
.TargetStatus
;
282 *SenseDataLength
= CommandPacket
.SenseDataLength
;
283 *InquiryDataLength
= CommandPacket
.InTransferLength
;
290 Execute Mode Sense(10) SCSI command on a specific SCSI target.
292 Executes the SCSI Mode Sense(10) command on the SCSI target specified by ScsiIo.
293 If Timeout is zero, then this function waits indefinitely for the command to complete.
294 If Timeout is greater than zero, then the command is executed and will timeout
295 after Timeout 100 ns units. The DBDField, PageControl, and PageCode parameters
296 are used to construct the CDB for this SCSI command.
297 If ScsiIo is NULL, then ASSERT().
298 If SenseDataLength is NULL, then ASSERT().
299 If HostAdapterStatus is NULL, then ASSERT().
300 If TargetStatus is NULL, then ASSERT().
301 If DataLength is NULL, then ASSERT().
304 @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance
305 for the specific SCSI target.
306 @param[in] Timeout The timeout in 100 ns units to use for the
307 execution of this SCSI Request Packet. A Timeout
308 value of zero means that this function will wait
309 indefinitely for the SCSI Request Packet to execute.
310 If Timeout is greater than zero, then this function
311 will return EFI_TIMEOUT if the time required to
312 execute the SCSI Request Packet is greater than Timeout.
313 @param[in, out] SenseData A pointer to sense data that was generated
314 by the execution of the SCSI Request Packet.
315 This buffer must be allocated by the caller.
316 If SenseDataLength is 0, then this parameter
317 is optional and may be NULL.
318 @param[in, out] SenseDataLength On input, the length in bytes of the SenseData buffer.
319 On output, the number of bytes written to the SenseData buffer.
320 @param[out] HostAdapterStatus The status of the SCSI Host Controller that
321 produces the SCSI bus containing the SCSI target
322 specified by ScsiIo when the SCSI Request Packet
323 was executed. See the EFI SCSI I/O Protocol in the
324 UEFI Specification for details on the possible
326 @param[out] TargetStatus The status returned by the SCSI target specified
327 by ScsiIo when the SCSI Request Packet was executed
328 on the SCSI Host Controller. See the EFI SCSI
329 I/O Protocol in the UEFI Specification for details
330 on the possible return values.
331 @param[in, out] DataBuffer A pointer to data that was generated by the
332 execution of the SCSI Request Packet. This
333 buffer must be allocated by the caller. If
334 DataLength is 0, then this parameter is optional
336 @param[in, out] DataLength On input, a pointer to the length in bytes of
337 the DataBuffer buffer. On output, a pointer
338 to the number of bytes written to the DataBuffer
340 @param[in] DBDField Specifies the DBD field of the CDB for this SCSI Command.
341 @param[in] PageControl Specifies the PC field of the CDB for this SCSI Command.
342 @param[in] PageCode Specifies the Page Control field of the CDB for this SCSI Command.
344 @retval EFI_SUCCESS The command was executed successfully.
345 See HostAdapterStatus, TargetStatus, SenseDataLength,
346 and SenseData in that order for additional status information.
347 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the
348 entire DataBuffer could not be transferred.
349 The actual number of bytes transferred is returned
351 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
352 there are too many SCSI Command Packets already queued.
353 The SCSI Request Packet was not sent, so no additional
354 status information is available. The caller may retry
356 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
357 SCSI Request Packet. See HostAdapterStatus, TargetStatus,
358 SenseDataLength, and SenseData in that order for
359 additional status information.
360 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
361 is not supported by the SCSI initiator(i.e., SCSI
362 Host Controller). The SCSI Request Packet was not
363 sent, so no additional status information is available.
364 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
365 Request Packet to execute. See HostAdapterStatus,
366 TargetStatus, SenseDataLength, and SenseData in that
367 order for additional status information.
372 ScsiModeSense10Command (
373 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
375 IN OUT VOID
*SenseData
, OPTIONAL
376 IN OUT UINT8
*SenseDataLength
,
377 OUT UINT8
*HostAdapterStatus
,
378 OUT UINT8
*TargetStatus
,
379 IN OUT VOID
*DataBuffer
, OPTIONAL
380 IN OUT UINT32
*DataLength
,
381 IN UINT8 DBDField
, OPTIONAL
382 IN UINT8 PageControl
,
386 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
388 UINT8 Cdb
[EFI_SCSI_OP_LENGTH_TEN
];
390 ASSERT (SenseDataLength
!= NULL
);
391 ASSERT (HostAdapterStatus
!= NULL
);
392 ASSERT (TargetStatus
!= NULL
);
393 ASSERT (DataLength
!= NULL
);
394 ASSERT (ScsiIo
!= NULL
);
396 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
397 ZeroMem (Cdb
, EFI_SCSI_OP_LENGTH_TEN
);
399 CommandPacket
.Timeout
= Timeout
;
400 CommandPacket
.InDataBuffer
= DataBuffer
;
401 CommandPacket
.SenseData
= SenseData
;
402 CommandPacket
.InTransferLength
= *DataLength
;
403 CommandPacket
.Cdb
= Cdb
;
405 // Fill Cdb for Mode Sense (10) Command
407 Cdb
[0] = EFI_SCSI_OP_MODE_SEN10
;
409 // DBDField is in Cdb[1] bit3 of (bit7..0)
411 Cdb
[1] = (UINT8
) ((DBDField
<< 3) & 0x08);
413 // PageControl is in Cdb[2] bit7..6, PageCode is in Cdb[2] bit5..0
415 Cdb
[2] = (UINT8
) (((PageControl
& 0x3) << 6) | (PageCode
& 0x3f));
416 Cdb
[7] = (UINT8
) (*DataLength
>> 8);
417 Cdb
[8] = (UINT8
) (*DataLength
);
419 CommandPacket
.CdbLength
= EFI_SCSI_OP_LENGTH_TEN
;
420 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
421 CommandPacket
.SenseDataLength
= *SenseDataLength
;
423 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
425 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
426 *TargetStatus
= CommandPacket
.TargetStatus
;
427 *SenseDataLength
= CommandPacket
.SenseDataLength
;
428 *DataLength
= CommandPacket
.InTransferLength
;
435 Execute Request Sense SCSI command on a specific SCSI target.
437 Executes the Request Sense command on the SCSI target specified by ScsiIo.
438 If Timeout is zero, then this function waits indefinitely for the command to complete.
439 If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.
440 If ScsiIo is NULL, then ASSERT().
441 If SenseDataLength is NULL, then ASSERT().
442 If HostAdapterStatus is NULL, then ASSERT().
443 If TargetStatus is NULL, then ASSERT().
445 @param[in] ScsiIo A pointer to SCSI IO protocol.
446 @param[in] Timeout The length of timeout period.
447 @param[in, out] SenseData A pointer to output sense data.
448 @param[in, out] SenseDataLength The length of output sense data.
449 @param[out] HostAdapterStatus The status of Host Adapter.
450 @param[out] TargetStatus The status of the target.
452 @retval EFI_SUCCESS Command is executed successfully.
453 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are
454 too many SCSI Command Packets already queued.
455 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
456 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by
457 the SCSI initiator(i.e., SCSI Host Controller)
458 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
463 ScsiRequestSenseCommand (
464 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
466 IN OUT VOID
*SenseData
, OPTIONAL
467 IN OUT UINT8
*SenseDataLength
,
468 OUT UINT8
*HostAdapterStatus
,
469 OUT UINT8
*TargetStatus
472 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
474 UINT8 Cdb
[EFI_SCSI_OP_LENGTH_SIX
];
476 ASSERT (SenseDataLength
!= NULL
);
477 ASSERT (HostAdapterStatus
!= NULL
);
478 ASSERT (TargetStatus
!= NULL
);
479 ASSERT (ScsiIo
!= NULL
);
481 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
482 ZeroMem (Cdb
, EFI_SCSI_OP_LENGTH_SIX
);
484 CommandPacket
.Timeout
= Timeout
;
485 CommandPacket
.InDataBuffer
= SenseData
;
486 CommandPacket
.SenseData
= NULL
;
487 CommandPacket
.InTransferLength
= *SenseDataLength
;
488 CommandPacket
.Cdb
= Cdb
;
490 // Fill Cdb for Request Sense Command
492 Cdb
[0] = EFI_SCSI_OP_REQUEST_SENSE
;
493 Cdb
[4] = (UINT8
) (*SenseDataLength
);
495 CommandPacket
.CdbLength
= (UINT8
) EFI_SCSI_OP_LENGTH_SIX
;
496 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
497 CommandPacket
.SenseDataLength
= 0;
499 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
501 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
502 *TargetStatus
= CommandPacket
.TargetStatus
;
503 *SenseDataLength
= (UINT8
) CommandPacket
.InTransferLength
;
510 Execute Read Capacity SCSI command on a specific SCSI target.
512 Executes the SCSI Read Capacity command on the SCSI target specified by ScsiIo.
513 If Timeout is zero, then this function waits indefinitely for the command to complete.
514 If Timeout is greater than zero, then the command is executed and will timeout after
515 Timeout 100 ns units. The Pmi parameter is used to construct the CDB for this SCSI command.
516 If ScsiIo is NULL, then ASSERT().
517 If SenseDataLength is NULL, then ASSERT().
518 If HostAdapterStatus is NULL, then ASSERT().
519 If TargetStatus is NULL, then ASSERT().
520 If DataLength is NULL, then ASSERT().
522 @param[in] ScsiIo A pointer to SCSI IO protocol.
523 @param[in] Timeout The length of timeout period.
524 @param[in, out] SenseData A pointer to output sense data.
525 @param[in, out] SenseDataLength The length of output sense data.
526 @param[out] HostAdapterStatus The status of Host Adapter.
527 @param[out] TargetStatus The status of the target.
528 @param[in, out] DataBuffer A pointer to a data buffer.
529 @param[in, out] DataLength The length of data buffer.
530 @param[in] Pmi Partial medium indicator.
532 @retval EFI_SUCCESS Command is executed successfully.
533 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire
534 DataBuffer could not be transferred. The actual
535 number of bytes transferred is returned in DataLength.
536 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
537 there are too many SCSI Command Packets already queued.
538 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
539 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
540 is not supported by the SCSI initiator(i.e., SCSI Host Controller)
541 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
546 ScsiReadCapacityCommand (
547 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
549 IN OUT VOID
*SenseData
, OPTIONAL
550 IN OUT UINT8
*SenseDataLength
,
551 OUT UINT8
*HostAdapterStatus
,
552 OUT UINT8
*TargetStatus
,
553 IN OUT VOID
*DataBuffer
, OPTIONAL
554 IN OUT UINT32
*DataLength
,
558 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
560 UINT8 Cdb
[EFI_SCSI_OP_LENGTH_TEN
];
562 ASSERT (SenseDataLength
!= NULL
);
563 ASSERT (HostAdapterStatus
!= NULL
);
564 ASSERT (TargetStatus
!= NULL
);
565 ASSERT (DataLength
!= NULL
);
566 ASSERT (ScsiIo
!= NULL
);
568 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
569 ZeroMem (Cdb
, EFI_SCSI_OP_LENGTH_TEN
);
571 CommandPacket
.Timeout
= Timeout
;
572 CommandPacket
.InDataBuffer
= DataBuffer
;
573 CommandPacket
.SenseData
= SenseData
;
574 CommandPacket
.InTransferLength
= *DataLength
;
575 CommandPacket
.Cdb
= Cdb
;
577 // Fill Cdb for Read Capacity Command
579 Cdb
[0] = EFI_SCSI_OP_READ_CAPACITY
;
582 // Partial medium indicator,if Pmi is FALSE, the Cdb.2 ~ Cdb.5 MUST BE ZERO.
584 ZeroMem ((Cdb
+ 2), 4);
589 CommandPacket
.CdbLength
= EFI_SCSI_OP_LENGTH_TEN
;
590 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
591 CommandPacket
.SenseDataLength
= *SenseDataLength
;
593 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
595 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
596 *TargetStatus
= CommandPacket
.TargetStatus
;
597 *SenseDataLength
= CommandPacket
.SenseDataLength
;
598 *DataLength
= CommandPacket
.InTransferLength
;
605 Execute Read Capacity SCSI 16 command on a specific SCSI target.
607 Executes the SCSI Read Capacity 16 command on the SCSI target specified by ScsiIo.
608 If Timeout is zero, then this function waits indefinitely for the command to complete.
609 If Timeout is greater than zero, then the command is executed and will timeout after
610 Timeout 100 ns units. The Pmi parameter is used to construct the CDB for this SCSI command.
611 If ScsiIo is NULL, then ASSERT().
612 If SenseDataLength is NULL, then ASSERT().
613 If HostAdapterStatus is NULL, then ASSERT().
614 If TargetStatus is NULL, then ASSERT().
615 If DataLength is NULL, then ASSERT().
617 @param[in] ScsiIo A pointer to SCSI IO protocol.
618 @param[in] Timeout The length of timeout period.
619 @param[in, out] SenseData A pointer to output sense data.
620 @param[in, out] SenseDataLength The length of output sense data.
621 @param[out] HostAdapterStatus The status of Host Adapter.
622 @param[out] TargetStatus The status of the target.
623 @param[in, out] DataBuffer A pointer to a data buffer.
624 @param[in, out] DataLength The length of data buffer.
625 @param[in] Pmi Partial medium indicator.
627 @retval EFI_SUCCESS Command is executed successfully.
628 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire
629 DataBuffer could not be transferred. The actual
630 number of bytes transferred is returned in DataLength.
631 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
632 there are too many SCSI Command Packets already queued.
633 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
634 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
635 is not supported by the SCSI initiator(i.e., SCSI Host Controller)
636 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
641 ScsiReadCapacity16Command (
642 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
644 IN OUT VOID
*SenseData
, OPTIONAL
645 IN OUT UINT8
*SenseDataLength
,
646 OUT UINT8
*HostAdapterStatus
,
647 OUT UINT8
*TargetStatus
,
648 IN OUT VOID
*DataBuffer
, OPTIONAL
649 IN OUT UINT32
*DataLength
,
653 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
657 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
660 CommandPacket
.Timeout
= Timeout
;
661 CommandPacket
.InDataBuffer
= DataBuffer
;
662 CommandPacket
.SenseData
= SenseData
;
663 CommandPacket
.InTransferLength
= *DataLength
;
664 CommandPacket
.Cdb
= Cdb
;
666 // Fill Cdb for Read Capacity Command
668 Cdb
[0] = EFI_SCSI_OP_READ_CAPACITY16
;
672 // Partial medium indicator,if Pmi is FALSE, the Cdb.2 ~ Cdb.9 MUST BE ZERO.
674 ZeroMem ((Cdb
+ 2), 8);
680 CommandPacket
.CdbLength
= 16;
681 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
682 CommandPacket
.SenseDataLength
= *SenseDataLength
;
684 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
686 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
687 *TargetStatus
= CommandPacket
.TargetStatus
;
688 *SenseDataLength
= CommandPacket
.SenseDataLength
;
689 *DataLength
= CommandPacket
.InTransferLength
;
696 Execute Read(10) SCSI command on a specific SCSI target.
698 Executes the SCSI Read(10) command on the SCSI target specified by ScsiIo.
699 If Timeout is zero, then this function waits indefinitely for the command to complete.
700 If Timeout is greater than zero, then the command is executed and will timeout
701 after Timeout 100 ns units. The StartLba and SectorSize parameters are used to
702 construct the CDB for this SCSI command.
703 If ScsiIo is NULL, then ASSERT().
704 If SenseDataLength is NULL, then ASSERT().
705 If HostAdapterStatus is NULL, then ASSERT().
706 If TargetStatus is NULL, then ASSERT().
707 If DataLength is NULL, then ASSERT().
710 @param[in] ScsiIo A pointer to SCSI IO protocol.
711 @param[in] Timeout The length of timeout period.
712 @param[in, out] SenseData A pointer to output sense data.
713 @param[in, out] SenseDataLength The length of output sense data.
714 @param[out] HostAdapterStatus The status of Host Adapter.
715 @param[out] TargetStatus The status of the target.
716 @param[in, out] DataBuffer Read 10 command data.
717 @param[in, out] DataLength The length of data buffer.
718 @param[in] StartLba The start address of LBA.
719 @param[in] SectorSize The sector size.
721 @retval EFI_SUCCESS Command is executed successfully.
722 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could
723 not be transferred. The actual number of bytes transferred is returned in DataLength.
724 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many
725 SCSI Command Packets already queued.
726 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
727 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by
728 the SCSI initiator(i.e., SCSI Host Controller)
729 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
735 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
737 IN OUT VOID
*SenseData
, OPTIONAL
738 IN OUT UINT8
*SenseDataLength
,
739 OUT UINT8
*HostAdapterStatus
,
740 OUT UINT8
*TargetStatus
,
741 IN OUT VOID
*DataBuffer
, OPTIONAL
742 IN OUT UINT32
*DataLength
,
747 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
749 UINT8 Cdb
[EFI_SCSI_OP_LENGTH_TEN
];
751 ASSERT (SenseDataLength
!= NULL
);
752 ASSERT (HostAdapterStatus
!= NULL
);
753 ASSERT (TargetStatus
!= NULL
);
754 ASSERT (DataLength
!= NULL
);
755 ASSERT (ScsiIo
!= NULL
);
757 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
758 ZeroMem (Cdb
, EFI_SCSI_OP_LENGTH_TEN
);
760 CommandPacket
.Timeout
= Timeout
;
761 CommandPacket
.InDataBuffer
= DataBuffer
;
762 CommandPacket
.SenseData
= SenseData
;
763 CommandPacket
.InTransferLength
= *DataLength
;
764 CommandPacket
.Cdb
= Cdb
;
766 // Fill Cdb for Read (10) Command
768 Cdb
[0] = EFI_SCSI_OP_READ10
;
769 Cdb
[2] = (UINT8
) (StartLba
>> 24);
770 Cdb
[3] = (UINT8
) (StartLba
>> 16);
771 Cdb
[4] = (UINT8
) (StartLba
>> 8);
772 Cdb
[5] = (UINT8
) (StartLba
& 0xff);
773 Cdb
[7] = (UINT8
) (SectorSize
>> 8);
774 Cdb
[8] = (UINT8
) (SectorSize
& 0xff);
776 CommandPacket
.CdbLength
= EFI_SCSI_OP_LENGTH_TEN
;
777 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
778 CommandPacket
.SenseDataLength
= *SenseDataLength
;
780 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
782 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
783 *TargetStatus
= CommandPacket
.TargetStatus
;
784 *SenseDataLength
= CommandPacket
.SenseDataLength
;
785 *DataLength
= CommandPacket
.InTransferLength
;
792 Execute Write(10) SCSI command on a specific SCSI target.
794 Executes the SCSI Write(10) command on the SCSI target specified by ScsiIo.
795 If Timeout is zero, then this function waits indefinitely for the command to complete.
796 If Timeout is greater than zero, then the command is executed and will timeout after
797 Timeout 100 ns units. The StartLba and SectorSize parameters are used to construct
798 the CDB for this SCSI command.
799 If ScsiIo is NULL, then ASSERT().
800 If SenseDataLength is NULL, then ASSERT().
801 If HostAdapterStatus is NULL, then ASSERT().
802 If TargetStatus is NULL, then ASSERT().
803 If DataLength is NULL, then ASSERT().
805 @param[in] ScsiIo SCSI IO Protocol to use
806 @param[in] Timeout The length of timeout period.
807 @param[in, out] SenseData A pointer to output sense data.
808 @param[in, out] SenseDataLength The length of output sense data.
809 @param[out] HostAdapterStatus The status of Host Adapter.
810 @param[out] TargetStatus The status of the target.
811 @param[in, out] DataBuffer A pointer to a data buffer.
812 @param[in, out] DataLength The length of data buffer.
813 @param[in] StartLba The start address of LBA.
814 @param[in] SectorSize The sector size.
816 @retval EFI_SUCCESS Command is executed successfully.
817 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could
818 not be transferred. The actual number of bytes transferred is returned in DataLength.
819 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many
820 SCSI Command Packets already queued.
821 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
822 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by
823 the SCSI initiator(i.e., SCSI Host Controller)
824 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
830 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
832 IN OUT VOID
*SenseData
, OPTIONAL
833 IN OUT UINT8
*SenseDataLength
,
834 OUT UINT8
*HostAdapterStatus
,
835 OUT UINT8
*TargetStatus
,
836 IN OUT VOID
*DataBuffer
, OPTIONAL
837 IN OUT UINT32
*DataLength
,
842 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
844 UINT8 Cdb
[EFI_SCSI_OP_LENGTH_TEN
];
846 ASSERT (SenseDataLength
!= NULL
);
847 ASSERT (HostAdapterStatus
!= NULL
);
848 ASSERT (TargetStatus
!= NULL
);
849 ASSERT (DataLength
!= NULL
);
850 ASSERT (ScsiIo
!= NULL
);
852 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
853 ZeroMem (Cdb
, EFI_SCSI_OP_LENGTH_TEN
);
855 CommandPacket
.Timeout
= Timeout
;
856 CommandPacket
.OutDataBuffer
= DataBuffer
;
857 CommandPacket
.SenseData
= SenseData
;
858 CommandPacket
.OutTransferLength
= *DataLength
;
859 CommandPacket
.Cdb
= Cdb
;
861 // Fill Cdb for Write (10) Command
863 Cdb
[0] = EFI_SCSI_OP_WRITE10
;
864 Cdb
[2] = (UINT8
) (StartLba
>> 24);
865 Cdb
[3] = (UINT8
) (StartLba
>> 16);
866 Cdb
[4] = (UINT8
) (StartLba
>> 8);
867 Cdb
[5] = (UINT8
) StartLba
;
868 Cdb
[7] = (UINT8
) (SectorSize
>> 8);
869 Cdb
[8] = (UINT8
) SectorSize
;
871 CommandPacket
.CdbLength
= EFI_SCSI_OP_LENGTH_TEN
;
872 CommandPacket
.DataDirection
= EFI_SCSI_DATA_OUT
;
873 CommandPacket
.SenseDataLength
= *SenseDataLength
;
875 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
877 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
878 *TargetStatus
= CommandPacket
.TargetStatus
;
879 *SenseDataLength
= CommandPacket
.SenseDataLength
;
880 *DataLength
= CommandPacket
.OutTransferLength
;