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 Function to submit read capacity16 command.
641 @param ScsiIo A pointer to SCSI IO protocol.
642 @param Timeout The length of timeout period.
643 @param SenseData A pointer to output sense data.
644 @param SenseDataLength The length of output sense data.
645 @param HostAdapterStatus The status of Host Adapter.
646 @param TargetStatus The status of the target.
647 @param DataBuffer A pointer to a data buffer.
648 @param DataLength The length of data buffer.
649 @param PMI Partial medium indicator.
651 @retval EFI_SUCCESS The status of the unit is tested successfully.
652 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
653 but the entire DataBuffer could not be transferred.
654 The actual number of bytes transferred is returned
656 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
657 there are too many SCSI Command Packets already
659 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
660 the SCSI Request Packet.
661 @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid.
662 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
663 is not supported by the SCSI initiator(i.e., SCSI
665 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
666 Request Packet to execute.
672 ScsiReadCapacity16Command (
673 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
676 IN OUT UINT8
*SenseDataLength
,
677 OUT UINT8
*HostAdapterStatus
,
678 OUT UINT8
*TargetStatus
,
679 OUT VOID
*DataBuffer
,
680 IN OUT UINT32
*DataLength
,
684 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
687 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
691 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
694 CommandPacket
.Timeout
= Timeout
;
695 CommandPacket
.InDataBuffer
= DataBuffer
;
696 CommandPacket
.SenseData
= SenseData
;
697 CommandPacket
.InTransferLength
= *DataLength
;
698 CommandPacket
.Cdb
= Cdb
;
700 // Fill Cdb for Read Capacity Command
702 Target
= &TargetArray
[0];
703 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
705 Cdb
[0] = EFI_SCSI_OP_READ_CAPACITY16
;
709 // Partial medium indicator,if PMI is FALSE, the Cdb.2 ~ Cdb.9 MUST BE ZERO.
711 ZeroMem ((Cdb
+ 2), 8);
717 CommandPacket
.CdbLength
= 16;
718 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
719 CommandPacket
.SenseDataLength
= *SenseDataLength
;
721 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
723 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
724 *TargetStatus
= CommandPacket
.TargetStatus
;
725 *SenseDataLength
= CommandPacket
.SenseDataLength
;
726 *DataLength
= CommandPacket
.InTransferLength
;
733 Execute Read(10) SCSI command on a specific SCSI target.
735 Executes the SCSI Read(10) command on the SCSI target specified by ScsiIo.
736 If Timeout is zero, then this function waits indefinitely for the command to complete.
737 If Timeout is greater than zero, then the command is executed and will timeout
738 after Timeout 100 ns units. The StartLba and SectorSize parameters are used to
739 construct the CDB for this SCSI command.
740 If ScsiIo is NULL, then ASSERT().
741 If SenseDataLength is NULL, then ASSERT().
742 If HostAdapterStatus is NULL, then ASSERT().
743 If TargetStatus is NULL, then ASSERT().
744 If DataLength is NULL, then ASSERT().
747 @param[in] ScsiIo A pointer to SCSI IO protocol.
748 @param[in] Timeout The length of timeout period.
749 @param[in, out] SenseData A pointer to output sense data.
750 @param[in, out] SenseDataLength The length of output sense data.
751 @param[out] HostAdapterStatus The status of Host Adapter.
752 @param[out] TargetStatus The status of the target.
753 @param[in, out] DataBuffer Read 10 command data.
754 @param[in, out] DataLength The length of data buffer.
755 @param[in] StartLba The start address of LBA.
756 @param[in] SectorSize The sector size.
758 @retval EFI_SUCCESS Command is executed successfully.
759 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could
760 not be transferred. The actual number of bytes transferred is returned in DataLength.
761 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many
762 SCSI Command Packets already queued.
763 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
764 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by
765 the SCSI initiator(i.e., SCSI Host Controller)
766 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
772 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
774 IN OUT VOID
*SenseData
, OPTIONAL
775 IN OUT UINT8
*SenseDataLength
,
776 OUT UINT8
*HostAdapterStatus
,
777 OUT UINT8
*TargetStatus
,
778 IN OUT VOID
*DataBuffer
, OPTIONAL
779 IN OUT UINT32
*DataLength
,
784 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
787 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
789 UINT8 Cdb
[EFI_SCSI_OP_LENGTH_TEN
];
791 ASSERT (SenseDataLength
!= NULL
);
792 ASSERT (HostAdapterStatus
!= NULL
);
793 ASSERT (TargetStatus
!= NULL
);
794 ASSERT (DataLength
!= NULL
);
795 ASSERT (ScsiIo
!= NULL
);
797 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
798 ZeroMem (Cdb
, EFI_SCSI_OP_LENGTH_TEN
);
800 CommandPacket
.Timeout
= Timeout
;
801 CommandPacket
.InDataBuffer
= DataBuffer
;
802 CommandPacket
.SenseData
= SenseData
;
803 CommandPacket
.InTransferLength
= *DataLength
;
804 CommandPacket
.Cdb
= Cdb
;
806 // Fill Cdb for Read (10) Command
808 Target
= &TargetArray
[0];
809 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
811 Cdb
[0] = EFI_SCSI_OP_READ10
;
812 Cdb
[1] = (UINT8
) (Lun
& EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK
);
813 Cdb
[2] = (UINT8
) (StartLba
>> 24);
814 Cdb
[3] = (UINT8
) (StartLba
>> 16);
815 Cdb
[4] = (UINT8
) (StartLba
>> 8);
816 Cdb
[5] = (UINT8
) (StartLba
& 0xff);
817 Cdb
[7] = (UINT8
) (SectorSize
>> 8);
818 Cdb
[8] = (UINT8
) (SectorSize
& 0xff);
820 CommandPacket
.CdbLength
= EFI_SCSI_OP_LENGTH_TEN
;
821 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
822 CommandPacket
.SenseDataLength
= *SenseDataLength
;
824 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
826 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
827 *TargetStatus
= CommandPacket
.TargetStatus
;
828 *SenseDataLength
= CommandPacket
.SenseDataLength
;
829 *DataLength
= CommandPacket
.InTransferLength
;
836 Execute Write(10) SCSI command on a specific SCSI target.
838 Executes the SCSI Write(10) command on the SCSI target specified by ScsiIo.
839 If Timeout is zero, then this function waits indefinitely for the command to complete.
840 If Timeout is greater than zero, then the command is executed and will timeout after
841 Timeout 100 ns units. The StartLba and SectorSize parameters are used to construct
842 the CDB for this SCSI command.
843 If ScsiIo is NULL, then ASSERT().
844 If SenseDataLength is NULL, then ASSERT().
845 If HostAdapterStatus is NULL, then ASSERT().
846 If TargetStatus is NULL, then ASSERT().
847 If DataLength is NULL, then ASSERT().
849 @param[in] ScsiIo SCSI IO Protocol to use
850 @param[in] Timeout The length of timeout period.
851 @param[in, out] SenseData A pointer to output sense data.
852 @param[in, out] SenseDataLength The length of output sense data.
853 @param[out] HostAdapterStatus The status of Host Adapter.
854 @param[out] TargetStatus The status of the target.
855 @param[in, out] DataBuffer A pointer to a data buffer.
856 @param[in, out] DataLength The length of data buffer.
857 @param[in] StartLba The start address of LBA.
858 @param[in] SectorSize The sector size.
860 @retval EFI_SUCCESS Command is executed successfully.
861 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, but the entire DataBuffer could
862 not be transferred. The actual number of bytes transferred is returned in DataLength.
863 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many
864 SCSI Command Packets already queued.
865 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
866 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by
867 the SCSI initiator(i.e., SCSI Host Controller)
868 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
874 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
876 IN OUT VOID
*SenseData
, OPTIONAL
877 IN OUT UINT8
*SenseDataLength
,
878 OUT UINT8
*HostAdapterStatus
,
879 OUT UINT8
*TargetStatus
,
880 IN OUT VOID
*DataBuffer
, OPTIONAL
881 IN OUT UINT32
*DataLength
,
886 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
889 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
891 UINT8 Cdb
[EFI_SCSI_OP_LENGTH_TEN
];
893 ASSERT (SenseDataLength
!= NULL
);
894 ASSERT (HostAdapterStatus
!= NULL
);
895 ASSERT (TargetStatus
!= NULL
);
896 ASSERT (DataLength
!= NULL
);
897 ASSERT (ScsiIo
!= NULL
);
899 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
900 ZeroMem (Cdb
, EFI_SCSI_OP_LENGTH_TEN
);
902 CommandPacket
.Timeout
= Timeout
;
903 CommandPacket
.OutDataBuffer
= DataBuffer
;
904 CommandPacket
.SenseData
= SenseData
;
905 CommandPacket
.OutTransferLength
= *DataLength
;
906 CommandPacket
.Cdb
= Cdb
;
908 // Fill Cdb for Write (10) Command
910 Target
= &TargetArray
[0];
911 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
913 Cdb
[0] = EFI_SCSI_OP_WRITE10
;
914 Cdb
[1] = (UINT8
) (Lun
& EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK
);
915 Cdb
[2] = (UINT8
) (StartLba
>> 24);
916 Cdb
[3] = (UINT8
) (StartLba
>> 16);
917 Cdb
[4] = (UINT8
) (StartLba
>> 8);
918 Cdb
[5] = (UINT8
) StartLba
;
919 Cdb
[7] = (UINT8
) (SectorSize
>> 8);
920 Cdb
[8] = (UINT8
) SectorSize
;
922 CommandPacket
.CdbLength
= EFI_SCSI_OP_LENGTH_TEN
;
923 CommandPacket
.DataDirection
= EFI_SCSI_DATA_OUT
;
924 CommandPacket
.SenseDataLength
= *SenseDataLength
;
926 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
928 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
929 *TargetStatus
= CommandPacket
.TargetStatus
;
930 *SenseDataLength
= CommandPacket
.SenseDataLength
;
931 *DataLength
= CommandPacket
.OutTransferLength
;