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
;
120 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
122 UINT8 Cdb
[EFI_SCSI_OP_LENGTH_SIX
];
124 ASSERT (SenseDataLength
!= NULL
);
125 ASSERT (HostAdapterStatus
!= NULL
);
126 ASSERT (TargetStatus
!= NULL
);
127 ASSERT (ScsiIo
!= NULL
);
129 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
130 ZeroMem (Cdb
, EFI_SCSI_OP_LENGTH_SIX
);
132 CommandPacket
.Timeout
= Timeout
;
133 CommandPacket
.InDataBuffer
= NULL
;
134 CommandPacket
.InTransferLength
= 0;
135 CommandPacket
.OutDataBuffer
= NULL
;
136 CommandPacket
.OutTransferLength
= 0;
137 CommandPacket
.SenseData
= SenseData
;
138 CommandPacket
.Cdb
= Cdb
;
140 // Fill Cdb for Test Unit Ready Command
142 Target
= &TargetArray
[0];
143 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
145 Cdb
[0] = EFI_SCSI_OP_TEST_UNIT_READY
;
146 Cdb
[1] = (UINT8
) (Lun
& EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK
);
147 CommandPacket
.CdbLength
= (UINT8
) EFI_SCSI_OP_LENGTH_SIX
;
148 CommandPacket
.SenseDataLength
= *SenseDataLength
;
150 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
152 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
153 *TargetStatus
= CommandPacket
.TargetStatus
;
154 *SenseDataLength
= CommandPacket
.SenseDataLength
;
161 Execute Inquiry SCSI command on a specific SCSI target.
163 Executes the Inquiry command on the SCSI target specified by ScsiIo.
164 If Timeout is zero, then this function waits indefinitely for the command to complete.
165 If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.
166 If ScsiIo is NULL, then ASSERT().
167 If SenseDataLength is NULL, then ASSERT().
168 If HostAdapterStatus is NULL, then ASSERT().
169 If TargetStatus is NULL, then ASSERT().
170 If InquiryDataLength is NULL, then ASSERT().
172 @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance
173 for the specific SCSI target.
174 @param[in] Timeout The timeout in 100 ns units to use for the
175 execution of this SCSI Request Packet. A Timeout
176 value of zero means that this function will wait
177 indefinitely for the SCSI Request Packet to execute.
178 If Timeout is greater than zero, then this function
179 will return EFI_TIMEOUT if the time required to
180 execute the SCSI Request Packet is greater than Timeout.
181 @param[in, out] SenseData A pointer to sense data that was generated
182 by the execution of the SCSI Request Packet.
183 This buffer must be allocated by the caller.
184 If SenseDataLength is 0, then this parameter
185 is optional and may be NULL.
186 @param[in, out] SenseDataLength On input, the length in bytes of the SenseData buffer.
187 On output, the number of bytes written to the SenseData buffer.
188 @param[out] HostAdapterStatus The status of the SCSI Host Controller that
189 produces the SCSI bus containing the SCSI
190 target specified by ScsiIo when the SCSI
191 Request Packet was executed. See the EFI
192 SCSI I/O Protocol in the UEFI Specification
193 for details on the possible return values.
194 @param[out] TargetStatus The status returned by the SCSI target specified
195 by ScsiIo when the SCSI Request Packet was
196 executed on the SCSI Host Controller.
197 See the EFI SCSI I/O Protocol in the UEFI
198 Specification for details on the possible
200 @param[in, out] InquiryDataBuffer A pointer to inquiry data that was generated
201 by the execution of the SCSI Request Packet.
202 This buffer must be allocated by the caller.
203 If InquiryDataLength is 0, then this parameter
204 is optional and may be NULL.
205 @param[in, out] InquiryDataLength On input, a pointer to the length in bytes
206 of the InquiryDataBuffer buffer.
207 On output, a pointer to the number of bytes
208 written to the InquiryDataBuffer buffer.
209 @param[in] EnableVitalProductData If TRUE, then the supported vital product
210 data is returned in InquiryDataBuffer.
211 If FALSE, then the standard inquiry data is
212 returned in InquiryDataBuffer.
214 @retval EFI_SUCCESS The command was executed successfully. See HostAdapterStatus,
215 TargetStatus, SenseDataLength, and SenseData in that order
216 for additional status information.
217 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire
218 InquiryDataBuffer could not be transferred. The actual
219 number of bytes transferred is returned in InquiryDataLength.
220 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there
221 are too many SCSI Command Packets already queued.
222 The SCSI Request Packet was not sent, so no additional
223 status information is available. The caller may retry again later.
224 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI
225 Request Packet. See HostAdapterStatus, TargetStatus,
226 SenseDataLength, and SenseData in that order for additional
228 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not
229 supported by the SCSI initiator(i.e., SCSI Host Controller).
230 The SCSI Request Packet was not sent, so no additional
231 status information is available.
232 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request
233 Packet to execute. See HostAdapterStatus, TargetStatus,
234 SenseDataLength, and SenseData in that order for
235 additional status information.
241 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
243 IN OUT VOID
*SenseData
, OPTIONAL
244 IN OUT UINT8
*SenseDataLength
,
245 OUT UINT8
*HostAdapterStatus
,
246 OUT UINT8
*TargetStatus
,
247 IN OUT VOID
*InquiryDataBuffer
, OPTIONAL
248 IN OUT UINT32
*InquiryDataLength
,
249 IN BOOLEAN EnableVitalProductData
252 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
255 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
257 UINT8 Cdb
[EFI_SCSI_OP_LENGTH_SIX
];
259 ASSERT (SenseDataLength
!= NULL
);
260 ASSERT (HostAdapterStatus
!= NULL
);
261 ASSERT (TargetStatus
!= NULL
);
262 ASSERT (InquiryDataLength
!= NULL
);
263 ASSERT (ScsiIo
!= NULL
);
265 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
266 ZeroMem (Cdb
, EFI_SCSI_OP_LENGTH_SIX
);
268 CommandPacket
.Timeout
= Timeout
;
269 CommandPacket
.InDataBuffer
= InquiryDataBuffer
;
270 CommandPacket
.InTransferLength
= *InquiryDataLength
;
271 CommandPacket
.SenseData
= SenseData
;
272 CommandPacket
.SenseDataLength
= *SenseDataLength
;
273 CommandPacket
.Cdb
= Cdb
;
275 Target
= &TargetArray
[0];
276 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
278 Cdb
[0] = EFI_SCSI_OP_INQUIRY
;
279 Cdb
[1] = (UINT8
) (Lun
& EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK
);
280 if (EnableVitalProductData
) {
284 if (*InquiryDataLength
> 0xff) {
285 *InquiryDataLength
= 0xff;
288 Cdb
[4] = (UINT8
) (*InquiryDataLength
);
289 CommandPacket
.CdbLength
= (UINT8
) EFI_SCSI_OP_LENGTH_SIX
;
290 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
292 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
294 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
295 *TargetStatus
= CommandPacket
.TargetStatus
;
296 *SenseDataLength
= CommandPacket
.SenseDataLength
;
297 *InquiryDataLength
= CommandPacket
.InTransferLength
;
304 Execute Mode Sense(10) SCSI command on a specific SCSI target.
306 Executes the SCSI Mode Sense(10) command on the SCSI target specified by ScsiIo.
307 If Timeout is zero, then this function waits indefinitely for the command to complete.
308 If Timeout is greater than zero, then the command is executed and will timeout
309 after Timeout 100 ns units. The DBDField, PageControl, and PageCode parameters
310 are used to construct the CDB for this SCSI command.
311 If ScsiIo is NULL, then ASSERT().
312 If SenseDataLength is NULL, then ASSERT().
313 If HostAdapterStatus is NULL, then ASSERT().
314 If TargetStatus is NULL, then ASSERT().
315 If DataLength is NULL, then ASSERT().
318 @param[in] ScsiIo A pointer to the SCSI I/O Protocol instance
319 for the specific SCSI target.
320 @param[in] Timeout The timeout in 100 ns units to use for the
321 execution of this SCSI Request Packet. A Timeout
322 value of zero means that this function will wait
323 indefinitely for the SCSI Request Packet to execute.
324 If Timeout is greater than zero, then this function
325 will return EFI_TIMEOUT if the time required to
326 execute the SCSI Request Packet is greater than Timeout.
327 @param[in, out] SenseData A pointer to sense data that was generated
328 by the execution of the SCSI Request Packet.
329 This buffer must be allocated by the caller.
330 If SenseDataLength is 0, then this parameter
331 is optional and may be NULL.
332 @param[in, out] SenseDataLength On input, the length in bytes of the SenseData buffer.
333 On output, the number of bytes written to the SenseData buffer.
334 @param[out] HostAdapterStatus The status of the SCSI Host Controller that
335 produces the SCSI bus containing the SCSI target
336 specified by ScsiIo when the SCSI Request Packet
337 was executed. See the EFI SCSI I/O Protocol in the
338 UEFI Specification for details on the possible
340 @param[out] TargetStatus The status returned by the SCSI target specified
341 by ScsiIo when the SCSI Request Packet was executed
342 on the SCSI Host Controller. See the EFI SCSI
343 I/O Protocol in the UEFI Specification for details
344 on the possible return values.
345 @param[in, out] DataBuffer A pointer to data that was generated by the
346 execution of the SCSI Request Packet. This
347 buffer must be allocated by the caller. If
348 DataLength is 0, then this parameter is optional
350 @param[in, out] DataLength On input, a pointer to the length in bytes of
351 the DataBuffer buffer. On output, a pointer
352 to the number of bytes written to the DataBuffer
354 @param[in] DBDField Specifies the DBD field of the CDB for this SCSI Command.
355 @param[in] PageControl Specifies the PC field of the CDB for this SCSI Command.
356 @param[in] PageCode Specifies the Page Control field of the CDB for this SCSI Command.
358 @retval EFI_SUCCESS The command was executed successfully.
359 See HostAdapterStatus, TargetStatus, SenseDataLength,
360 and SenseData in that order for additional status information.
361 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the
362 entire DataBuffer could not be transferred.
363 The actual number of bytes transferred is returned
365 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
366 there are too many SCSI Command Packets already queued.
367 The SCSI Request Packet was not sent, so no additional
368 status information is available. The caller may retry
370 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
371 SCSI Request Packet. See HostAdapterStatus, TargetStatus,
372 SenseDataLength, and SenseData in that order for
373 additional status information.
374 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
375 is not supported by the SCSI initiator(i.e., SCSI
376 Host Controller). The SCSI Request Packet was not
377 sent, so no additional status information is available.
378 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
379 Request Packet to execute. See HostAdapterStatus,
380 TargetStatus, SenseDataLength, and SenseData in that
381 order for additional status information.
386 ScsiModeSense10Command (
387 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
389 IN OUT VOID
*SenseData
, OPTIONAL
390 IN OUT UINT8
*SenseDataLength
,
391 OUT UINT8
*HostAdapterStatus
,
392 OUT UINT8
*TargetStatus
,
393 IN OUT VOID
*DataBuffer
, OPTIONAL
394 IN OUT UINT32
*DataLength
,
395 IN UINT8 DBDField
, OPTIONAL
396 IN UINT8 PageControl
,
400 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
403 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
405 UINT8 Cdb
[EFI_SCSI_OP_LENGTH_TEN
];
407 ASSERT (SenseDataLength
!= NULL
);
408 ASSERT (HostAdapterStatus
!= NULL
);
409 ASSERT (TargetStatus
!= NULL
);
410 ASSERT (DataLength
!= NULL
);
411 ASSERT (ScsiIo
!= NULL
);
413 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
414 ZeroMem (Cdb
, EFI_SCSI_OP_LENGTH_TEN
);
416 CommandPacket
.Timeout
= Timeout
;
417 CommandPacket
.InDataBuffer
= DataBuffer
;
418 CommandPacket
.SenseData
= SenseData
;
419 CommandPacket
.InTransferLength
= *DataLength
;
420 CommandPacket
.Cdb
= Cdb
;
422 // Fill Cdb for Mode Sense (10) Command
424 Target
= &TargetArray
[0];
425 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
427 Cdb
[0] = EFI_SCSI_OP_MODE_SEN10
;
429 // DBDField is in Cdb[1] bit3 of (bit7..0)
431 Cdb
[1] = (UINT8
) ((Lun
& EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK
) + ((DBDField
<< 3) & 0x08));
433 // PageControl is in Cdb[2] bit7..6, PageCode is in Cdb[2] bit5..0
435 Cdb
[2] = (UINT8
) ((PageControl
& 0xc0) | (PageCode
& 0x3f));
436 Cdb
[7] = (UINT8
) (*DataLength
>> 8);
437 Cdb
[8] = (UINT8
) (*DataLength
);
439 CommandPacket
.CdbLength
= EFI_SCSI_OP_LENGTH_TEN
;
440 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
441 CommandPacket
.SenseDataLength
= *SenseDataLength
;
443 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
445 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
446 *TargetStatus
= CommandPacket
.TargetStatus
;
447 *SenseDataLength
= CommandPacket
.SenseDataLength
;
448 *DataLength
= CommandPacket
.InTransferLength
;
455 Execute Request Sense SCSI command on a specific SCSI target.
457 Executes the Request Sense command on the SCSI target specified by ScsiIo.
458 If Timeout is zero, then this function waits indefinitely for the command to complete.
459 If Timeout is greater than zero, then the command is executed and will timeout after Timeout 100 ns units.
460 If ScsiIo is NULL, then ASSERT().
461 If SenseDataLength is NULL, then ASSERT().
462 If HostAdapterStatus is NULL, then ASSERT().
463 If TargetStatus is NULL, then ASSERT().
465 @param[in] ScsiIo A pointer to SCSI IO protocol.
466 @param[in] Timeout The length of timeout period.
467 @param[in, out] SenseData A pointer to output sense data.
468 @param[in, out] SenseDataLength The length of output sense data.
469 @param[out] HostAdapterStatus The status of Host Adapter.
470 @param[out] TargetStatus The status of the target.
472 @retval EFI_SUCCESS Command is executed successfully.
473 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are
474 too many SCSI Command Packets already queued.
475 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
476 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by
477 the SCSI initiator(i.e., SCSI Host Controller)
478 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
483 ScsiRequestSenseCommand (
484 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
486 IN OUT VOID
*SenseData
, OPTIONAL
487 IN OUT UINT8
*SenseDataLength
,
488 OUT UINT8
*HostAdapterStatus
,
489 OUT UINT8
*TargetStatus
492 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
495 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
497 UINT8 Cdb
[EFI_SCSI_OP_LENGTH_SIX
];
499 ASSERT (SenseDataLength
!= NULL
);
500 ASSERT (HostAdapterStatus
!= NULL
);
501 ASSERT (TargetStatus
!= NULL
);
502 ASSERT (ScsiIo
!= NULL
);
504 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
505 ZeroMem (Cdb
, EFI_SCSI_OP_LENGTH_SIX
);
507 CommandPacket
.Timeout
= Timeout
;
508 CommandPacket
.InDataBuffer
= SenseData
;
509 CommandPacket
.SenseData
= NULL
;
510 CommandPacket
.InTransferLength
= *SenseDataLength
;
511 CommandPacket
.Cdb
= Cdb
;
513 // Fill Cdb for Request Sense Command
515 Target
= &TargetArray
[0];
516 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
518 Cdb
[0] = EFI_SCSI_OP_REQUEST_SENSE
;
519 Cdb
[1] = (UINT8
) (Lun
& EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK
);
520 Cdb
[4] = (UINT8
) (*SenseDataLength
);
522 CommandPacket
.CdbLength
= (UINT8
) EFI_SCSI_OP_LENGTH_SIX
;
523 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
524 CommandPacket
.SenseDataLength
= 0;
526 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
528 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
529 *TargetStatus
= CommandPacket
.TargetStatus
;
530 *SenseDataLength
= (UINT8
) CommandPacket
.InTransferLength
;
537 Execute Read Capacity SCSI command on a specific SCSI target.
539 Executes the SCSI Read Capacity command on the SCSI target specified by ScsiIo.
540 If Timeout is zero, then this function waits indefinitely for the command to complete.
541 If Timeout is greater than zero, then the command is executed and will timeout after
542 Timeout 100 ns units. The Pmi parameter is used to construct the CDB for this SCSI command.
543 If ScsiIo is NULL, then ASSERT().
544 If SenseDataLength is NULL, then ASSERT().
545 If HostAdapterStatus is NULL, then ASSERT().
546 If TargetStatus is NULL, then ASSERT().
547 If DataLength is NULL, then ASSERT().
549 @param[in] ScsiIo A pointer to SCSI IO protocol.
550 @param[in] Timeout The length of timeout period.
551 @param[in, out] SenseData A pointer to output sense data.
552 @param[in, out] SenseDataLength The length of output sense data.
553 @param[out] HostAdapterStatus The status of Host Adapter.
554 @param[out] TargetStatus The status of the target.
555 @param[in, out] DataBuffer A pointer to a data buffer.
556 @param[in, out] DataLength The length of data buffer.
557 @param[in] Pmi Partial medium indicator.
559 @retval EFI_SUCCESS Command is executed successfully.
560 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire
561 DataBuffer could not be transferred. The actual
562 number of bytes transferred is returned in DataLength.
563 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
564 there are too many SCSI Command Packets already queued.
565 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
566 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
567 is not supported by the SCSI initiator(i.e., SCSI Host Controller)
568 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
573 ScsiReadCapacityCommand (
574 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
576 IN OUT VOID
*SenseData
, OPTIONAL
577 IN OUT UINT8
*SenseDataLength
,
578 OUT UINT8
*HostAdapterStatus
,
579 OUT UINT8
*TargetStatus
,
580 IN OUT VOID
*DataBuffer
, OPTIONAL
581 IN OUT UINT32
*DataLength
,
585 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
588 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
590 UINT8 Cdb
[EFI_SCSI_OP_LENGTH_TEN
];
592 ASSERT (SenseDataLength
!= NULL
);
593 ASSERT (HostAdapterStatus
!= NULL
);
594 ASSERT (TargetStatus
!= NULL
);
595 ASSERT (DataLength
!= NULL
);
596 ASSERT (ScsiIo
!= NULL
);
598 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
599 ZeroMem (Cdb
, EFI_SCSI_OP_LENGTH_TEN
);
601 CommandPacket
.Timeout
= Timeout
;
602 CommandPacket
.InDataBuffer
= DataBuffer
;
603 CommandPacket
.SenseData
= SenseData
;
604 CommandPacket
.InTransferLength
= *DataLength
;
605 CommandPacket
.Cdb
= Cdb
;
607 // Fill Cdb for Read Capacity Command
609 Target
= &TargetArray
[0];
610 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
612 Cdb
[0] = EFI_SCSI_OP_READ_CAPACITY
;
613 Cdb
[1] = (UINT8
) (Lun
& EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK
);
616 // Partial medium indicator,if Pmi is FALSE, the Cdb.2 ~ Cdb.5 MUST BE ZERO.
618 ZeroMem ((Cdb
+ 2), 4);
623 CommandPacket
.CdbLength
= EFI_SCSI_OP_LENGTH_TEN
;
624 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
625 CommandPacket
.SenseDataLength
= *SenseDataLength
;
627 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
629 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
630 *TargetStatus
= CommandPacket
.TargetStatus
;
631 *SenseDataLength
= CommandPacket
.SenseDataLength
;
632 *DataLength
= CommandPacket
.InTransferLength
;
639 Execute Read Capacity SCSI 16 command on a specific SCSI target.
641 Executes the SCSI Read Capacity 16 command on the SCSI target specified by ScsiIo.
642 If Timeout is zero, then this function waits indefinitely for the command to complete.
643 If Timeout is greater than zero, then the command is executed and will timeout after
644 Timeout 100 ns units. The Pmi parameter is used to construct the CDB for this SCSI command.
645 If ScsiIo is NULL, then ASSERT().
646 If SenseDataLength is NULL, then ASSERT().
647 If HostAdapterStatus is NULL, then ASSERT().
648 If TargetStatus is NULL, then ASSERT().
649 If DataLength is NULL, then ASSERT().
651 @param[in] ScsiIo A pointer to SCSI IO protocol.
652 @param[in] Timeout The length of timeout period.
653 @param[in, out] SenseData A pointer to output sense data.
654 @param[in, out] SenseDataLength The length of output sense data.
655 @param[out] HostAdapterStatus The status of Host Adapter.
656 @param[out] TargetStatus The status of the target.
657 @param[in, out] DataBuffer A pointer to a data buffer.
658 @param[in, out] DataLength The length of data buffer.
659 @param[in] Pmi Partial medium indicator.
661 @retval EFI_SUCCESS Command is executed successfully.
662 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire
663 DataBuffer could not be transferred. The actual
664 number of bytes transferred is returned in DataLength.
665 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
666 there are too many SCSI Command Packets already queued.
667 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
668 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
669 is not supported by the SCSI initiator(i.e., SCSI Host Controller)
670 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
675 ScsiReadCapacity16Command (
676 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
679 IN OUT UINT8
*SenseDataLength
,
680 OUT UINT8
*HostAdapterStatus
,
681 OUT UINT8
*TargetStatus
,
682 OUT VOID
*DataBuffer
,
683 IN OUT UINT32
*DataLength
,
687 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
690 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
694 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
697 CommandPacket
.Timeout
= Timeout
;
698 CommandPacket
.InDataBuffer
= DataBuffer
;
699 CommandPacket
.SenseData
= SenseData
;
700 CommandPacket
.InTransferLength
= *DataLength
;
701 CommandPacket
.Cdb
= Cdb
;
703 // Fill Cdb for Read Capacity Command
705 Target
= &TargetArray
[0];
706 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
708 Cdb
[0] = EFI_SCSI_OP_READ_CAPACITY16
;
712 // Partial medium indicator,if Pmi is FALSE, the Cdb.2 ~ Cdb.9 MUST BE ZERO.
714 ZeroMem ((Cdb
+ 2), 8);
720 CommandPacket
.CdbLength
= 16;
721 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
722 CommandPacket
.SenseDataLength
= *SenseDataLength
;
724 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
726 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
727 *TargetStatus
= CommandPacket
.TargetStatus
;
728 *SenseDataLength
= CommandPacket
.SenseDataLength
;
729 *DataLength
= CommandPacket
.InTransferLength
;
736 Execute Read(10) SCSI command on a specific SCSI target.
738 Executes the SCSI Read(10) command on the SCSI target specified by ScsiIo.
739 If Timeout is zero, then this function waits indefinitely for the command to complete.
740 If Timeout is greater than zero, then the command is executed and will timeout
741 after Timeout 100 ns units. The StartLba and SectorSize parameters are used to
742 construct the CDB for this SCSI command.
743 If ScsiIo is NULL, then ASSERT().
744 If SenseDataLength is NULL, then ASSERT().
745 If HostAdapterStatus is NULL, then ASSERT().
746 If TargetStatus is NULL, then ASSERT().
747 If DataLength is NULL, then ASSERT().
750 @param[in] ScsiIo A pointer to SCSI IO protocol.
751 @param[in] Timeout The length of timeout period.
752 @param[in, out] SenseData A pointer to output sense data.
753 @param[in, out] SenseDataLength The length of output sense data.
754 @param[out] HostAdapterStatus The status of Host Adapter.
755 @param[out] TargetStatus The status of the target.
756 @param[in, out] DataBuffer Read 10 command data.
757 @param[in, out] DataLength The length of data buffer.
758 @param[in] StartLba The start address of LBA.
759 @param[in] SectorSize The sector size.
761 @retval EFI_SUCCESS Command is executed successfully.
762 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could
763 not be transferred. The actual number of bytes transferred is returned in DataLength.
764 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many
765 SCSI Command Packets already queued.
766 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
767 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by
768 the SCSI initiator(i.e., SCSI Host Controller)
769 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
775 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
777 IN OUT VOID
*SenseData
, OPTIONAL
778 IN OUT UINT8
*SenseDataLength
,
779 OUT UINT8
*HostAdapterStatus
,
780 OUT UINT8
*TargetStatus
,
781 IN OUT VOID
*DataBuffer
, OPTIONAL
782 IN OUT UINT32
*DataLength
,
787 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
790 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
792 UINT8 Cdb
[EFI_SCSI_OP_LENGTH_TEN
];
794 ASSERT (SenseDataLength
!= NULL
);
795 ASSERT (HostAdapterStatus
!= NULL
);
796 ASSERT (TargetStatus
!= NULL
);
797 ASSERT (DataLength
!= NULL
);
798 ASSERT (ScsiIo
!= NULL
);
800 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
801 ZeroMem (Cdb
, EFI_SCSI_OP_LENGTH_TEN
);
803 CommandPacket
.Timeout
= Timeout
;
804 CommandPacket
.InDataBuffer
= DataBuffer
;
805 CommandPacket
.SenseData
= SenseData
;
806 CommandPacket
.InTransferLength
= *DataLength
;
807 CommandPacket
.Cdb
= Cdb
;
809 // Fill Cdb for Read (10) Command
811 Target
= &TargetArray
[0];
812 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
814 Cdb
[0] = EFI_SCSI_OP_READ10
;
815 Cdb
[1] = (UINT8
) (Lun
& EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK
);
816 Cdb
[2] = (UINT8
) (StartLba
>> 24);
817 Cdb
[3] = (UINT8
) (StartLba
>> 16);
818 Cdb
[4] = (UINT8
) (StartLba
>> 8);
819 Cdb
[5] = (UINT8
) (StartLba
& 0xff);
820 Cdb
[7] = (UINT8
) (SectorSize
>> 8);
821 Cdb
[8] = (UINT8
) (SectorSize
& 0xff);
823 CommandPacket
.CdbLength
= EFI_SCSI_OP_LENGTH_TEN
;
824 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
825 CommandPacket
.SenseDataLength
= *SenseDataLength
;
827 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
829 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
830 *TargetStatus
= CommandPacket
.TargetStatus
;
831 *SenseDataLength
= CommandPacket
.SenseDataLength
;
832 *DataLength
= CommandPacket
.InTransferLength
;
839 Execute Write(10) SCSI command on a specific SCSI target.
841 Executes the SCSI Write(10) command on the SCSI target specified by ScsiIo.
842 If Timeout is zero, then this function waits indefinitely for the command to complete.
843 If Timeout is greater than zero, then the command is executed and will timeout after
844 Timeout 100 ns units. The StartLba and SectorSize parameters are used to construct
845 the CDB for this SCSI command.
846 If ScsiIo is NULL, then ASSERT().
847 If SenseDataLength is NULL, then ASSERT().
848 If HostAdapterStatus is NULL, then ASSERT().
849 If TargetStatus is NULL, then ASSERT().
850 If DataLength is NULL, then ASSERT().
852 @param[in] ScsiIo SCSI IO Protocol to use
853 @param[in] Timeout The length of timeout period.
854 @param[in, out] SenseData A pointer to output sense data.
855 @param[in, out] SenseDataLength The length of output sense data.
856 @param[out] HostAdapterStatus The status of Host Adapter.
857 @param[out] TargetStatus The status of the target.
858 @param[in, out] DataBuffer A pointer to a data buffer.
859 @param[in, out] DataLength The length of data buffer.
860 @param[in] StartLba The start address of LBA.
861 @param[in] SectorSize The sector size.
863 @retval EFI_SUCCESS Command is executed successfully.
864 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could
865 not be transferred. The actual number of bytes transferred is returned in DataLength.
866 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many
867 SCSI Command Packets already queued.
868 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
869 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by
870 the SCSI initiator(i.e., SCSI Host Controller)
871 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
877 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
879 IN OUT VOID
*SenseData
, OPTIONAL
880 IN OUT UINT8
*SenseDataLength
,
881 OUT UINT8
*HostAdapterStatus
,
882 OUT UINT8
*TargetStatus
,
883 IN OUT VOID
*DataBuffer
, OPTIONAL
884 IN OUT UINT32
*DataLength
,
889 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
892 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
894 UINT8 Cdb
[EFI_SCSI_OP_LENGTH_TEN
];
896 ASSERT (SenseDataLength
!= NULL
);
897 ASSERT (HostAdapterStatus
!= NULL
);
898 ASSERT (TargetStatus
!= NULL
);
899 ASSERT (DataLength
!= NULL
);
900 ASSERT (ScsiIo
!= NULL
);
902 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
903 ZeroMem (Cdb
, EFI_SCSI_OP_LENGTH_TEN
);
905 CommandPacket
.Timeout
= Timeout
;
906 CommandPacket
.OutDataBuffer
= DataBuffer
;
907 CommandPacket
.SenseData
= SenseData
;
908 CommandPacket
.OutTransferLength
= *DataLength
;
909 CommandPacket
.Cdb
= Cdb
;
911 // Fill Cdb for Write (10) Command
913 Target
= &TargetArray
[0];
914 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
916 Cdb
[0] = EFI_SCSI_OP_WRITE10
;
917 Cdb
[1] = (UINT8
) (Lun
& EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK
);
918 Cdb
[2] = (UINT8
) (StartLba
>> 24);
919 Cdb
[3] = (UINT8
) (StartLba
>> 16);
920 Cdb
[4] = (UINT8
) (StartLba
>> 8);
921 Cdb
[5] = (UINT8
) StartLba
;
922 Cdb
[7] = (UINT8
) (SectorSize
>> 8);
923 Cdb
[8] = (UINT8
) SectorSize
;
925 CommandPacket
.CdbLength
= EFI_SCSI_OP_LENGTH_TEN
;
926 CommandPacket
.DataDirection
= EFI_SCSI_DATA_OUT
;
927 CommandPacket
.SenseDataLength
= *SenseDataLength
;
929 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
931 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
932 *TargetStatus
= CommandPacket
.TargetStatus
;
933 *SenseDataLength
= CommandPacket
.SenseDataLength
;
934 *DataLength
= CommandPacket
.OutTransferLength
;