2 UEFI SCSI Library implementation
4 Copyright (c) 2006 - 2007, 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/ScsiLib.h>
19 #include <Library/BaseMemoryLib.h>
21 #include <IndustryStandard/Scsi.h>
24 // bit5..7 are for Logical unit number
27 #define EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK 0xe0
30 // Scsi Command Length six or ten
32 #define EFI_SCSI_OP_LENGTH_SIX 0x6
33 #define EFI_SCSI_OP_LENGTH_TEN 0xa
36 Function test the ready status of the SCSI unit.
38 Submit SCSI test unit ready command with SCSI request packet specified by this scsi command, TimeOut
39 and SenseData, then get the status of the target Scsi unit.
41 If SenseDataLength is NULL, then ASSERT().
43 If HostAdapterStatus is NULL, then ASSERT().
45 If TargetStatus is NULL, then ASSERT().
47 @param[in] ScsiIo A pointer to SCSI IO protocol.
48 @param[in] Timeout The length of timeout period.
49 @param[in] SenseData A pointer to output sense data.
50 @param[out] SenseDataLength The length of output sense data.
51 @param[out] HostAdapterStatus The status of Host Adapter.
52 @param[out] TargetStatus The status of the target.
54 @retval EFI_SUCCESS The status of the unit is tested successfully.
55 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
56 but the entire DataBuffer could not be transferred.
57 The actual number of bytes transferred is returned
59 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
60 there are too many SCSI Command Packets already
62 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
63 the SCSI Request Packet.
64 @retval EFI_INVALID_PARAMETER ScsiIo is NULL.
65 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
66 is not supported by the SCSI initiator(i.e., SCSI
68 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
69 Request Packet to execute.
74 ScsiTestUnitReadyCommand (
75 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
78 OUT UINT8
*SenseDataLength
,
79 OUT UINT8
*HostAdapterStatus
,
80 OUT UINT8
*TargetStatus
83 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
86 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
88 UINT8 Cdb
[EFI_SCSI_OP_LENGTH_SIX
];
90 ASSERT (SenseDataLength
!= NULL
);
91 ASSERT (HostAdapterStatus
!= NULL
);
92 ASSERT (TargetStatus
!= NULL
);
95 return EFI_INVALID_PARAMETER
;
98 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
99 ZeroMem (Cdb
, EFI_SCSI_OP_LENGTH_SIX
);
101 CommandPacket
.Timeout
= Timeout
;
102 CommandPacket
.InDataBuffer
= NULL
;
103 CommandPacket
.InTransferLength
= 0;
104 CommandPacket
.OutDataBuffer
= NULL
;
105 CommandPacket
.OutTransferLength
= 0;
106 CommandPacket
.SenseData
= SenseData
;
107 CommandPacket
.Cdb
= Cdb
;
109 // Fill Cdb for Test Unit Ready Command
111 Target
= &TargetArray
[0];
112 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
114 Cdb
[0] = EFI_SCSI_OP_TEST_UNIT_READY
;
115 Cdb
[1] = (UINT8
) (Lun
& EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK
);
116 CommandPacket
.CdbLength
= (UINT8
) EFI_SCSI_OP_LENGTH_SIX
;
117 CommandPacket
.SenseDataLength
= *SenseDataLength
;
119 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
121 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
122 *TargetStatus
= CommandPacket
.TargetStatus
;
123 *SenseDataLength
= CommandPacket
.SenseDataLength
;
130 Function to submit SCSI inquiry command.
132 Submit SCSI inquiry command with the SCSI request packet specified by this SCSI command and input
133 parameters, then return the status of Scsi unit execution.
135 If SenseDataLength is NULL, then ASSERT().
137 If HostAdapterStatus is NULL, then ASSERT().
139 If TargetStatus is NULL, then ASSERT().
141 If InquiryDataLength is NULL, then ASSERT().
143 @param[in] ScsiIo SCSI IO Protocol to use
144 @param[in] Timeout The length of timeout period.
145 @param[in] SenseData A pointer to output sense data.
146 @param[in out] SenseDataLength The length of output sense data.
147 @param[out] HostAdapterStatus The status of Host Adapter.
148 @param[out] TargetStatus The status of the target.
149 @param[in out] InquirydataBuffer A pointer to inquiry data buffer.
150 @param[in out] InquiryDataLength The length of inquiry data buffer.
151 @param[in] EnableVitalProductData Boolean to enable Vital Product Data.
153 @retval EFI_SUCCESS Command is executed successfully.
154 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
155 but the entire DataBuffer could not be transferred.
156 The actual number of bytes transferred is returned
158 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
159 there are too many SCSI Command Packets already
161 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
162 the SCSI Request Packet.
163 @retval EFI_INVALID_PARAMETER ScsiIo is NULL.
164 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
165 is not supported by the SCSI initiator(i.e., SCSI
167 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
168 Request Packet to execute.
174 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
177 IN OUT UINT8
*SenseDataLength
,
178 OUT UINT8
*HostAdapterStatus
,
179 OUT UINT8
*TargetStatus
,
180 IN OUT VOID
*InquiryDataBuffer
,
181 IN OUT UINT32
*InquiryDataLength
,
182 IN BOOLEAN EnableVitalProductData
185 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
188 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
190 UINT8 Cdb
[EFI_SCSI_OP_LENGTH_SIX
];
192 ASSERT (SenseDataLength
!= NULL
);
193 ASSERT (HostAdapterStatus
!= NULL
);
194 ASSERT (TargetStatus
!= NULL
);
195 ASSERT (InquiryDataLength
!= NULL
);
197 if (ScsiIo
== NULL
) {
198 return EFI_INVALID_PARAMETER
;
201 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
202 ZeroMem (Cdb
, EFI_SCSI_OP_LENGTH_SIX
);
204 CommandPacket
.Timeout
= Timeout
;
205 CommandPacket
.InDataBuffer
= InquiryDataBuffer
;
206 CommandPacket
.InTransferLength
= *InquiryDataLength
;
207 CommandPacket
.SenseData
= SenseData
;
208 CommandPacket
.SenseDataLength
= *SenseDataLength
;
209 CommandPacket
.Cdb
= Cdb
;
211 Target
= &TargetArray
[0];
212 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
214 Cdb
[0] = EFI_SCSI_OP_INQUIRY
;
215 Cdb
[1] = (UINT8
) (Lun
& EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK
);
216 if (EnableVitalProductData
) {
220 if (*InquiryDataLength
> 0xff) {
221 *InquiryDataLength
= 0xff;
224 Cdb
[4] = (UINT8
) (*InquiryDataLength
);
225 CommandPacket
.CdbLength
= (UINT8
) EFI_SCSI_OP_LENGTH_SIX
;
226 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
228 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
230 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
231 *TargetStatus
= CommandPacket
.TargetStatus
;
232 *SenseDataLength
= CommandPacket
.SenseDataLength
;
233 *InquiryDataLength
= CommandPacket
.InTransferLength
;
240 Function to submit SCSI mode sense 10 command.
242 Submit SCSI Mode Sense (10) command with the SCSI request packet specified by this SCSI command and
243 the input parameters, then return the status of Scsi unit execution.
245 If SenseDataLength is NULL, then ASSERT().
247 If HostAdapterStatus is NULL, then ASSERT().
249 If TargetStatus is NULL, then ASSERT().
251 If DataLength is NULL, then ASSERT().
253 @param[in] ScsiIo A pointer to SCSI IO protocol.
254 @param[in] Timeout The length of timeout period.
255 @param[in] SenseData A pointer to output sense data.
256 @param[in out] SenseDataLength The length of output sense data.
257 @param[out] HostAdapterStatus The status of Host Adapter.
258 @param[out] TargetStatus The status of the target.
259 @param[in] DataBuffer A pointer to input data buffer.
260 @param[in out] DataLength The length of input data buffer.
261 @param[in] DBDField The DBD Field (Optional).
262 @param[in] PageControl Page Control.
263 @param[in] PageCode Page code.
265 @retval EFI_SUCCESS The status of the unit is tested successfully.
266 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
267 but the entire DataBuffer could not be transferred.
268 The actual number of bytes transferred is returned
270 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
271 there are too many SCSI Command Packets already
273 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
274 the SCSI Request Packet.
275 @retval EFI_INVALID_PARAMETER ScsiIo is NULL.
276 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
277 is not supported by the SCSI initiator(i.e., SCSI
279 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
280 Request Packet to execute.
285 ScsiModeSense10Command (
286 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
289 IN OUT UINT8
*SenseDataLength
,
290 OUT UINT8
*HostAdapterStatus
,
291 OUT UINT8
*TargetStatus
,
293 IN OUT UINT32
*DataLength
,
294 IN UINT8 DBDField
, OPTIONAL
295 IN UINT8 PageControl
,
299 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
302 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
304 UINT8 Cdb
[EFI_SCSI_OP_LENGTH_TEN
];
306 ASSERT (SenseDataLength
!= NULL
);
307 ASSERT (HostAdapterStatus
!= NULL
);
308 ASSERT (TargetStatus
!= NULL
);
309 ASSERT (DataLength
!= NULL
);
311 if (ScsiIo
== NULL
) {
312 return EFI_INVALID_PARAMETER
;
315 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
316 ZeroMem (Cdb
, EFI_SCSI_OP_LENGTH_TEN
);
318 CommandPacket
.Timeout
= Timeout
;
319 CommandPacket
.InDataBuffer
= DataBuffer
;
320 CommandPacket
.SenseData
= SenseData
;
321 CommandPacket
.InTransferLength
= *DataLength
;
322 CommandPacket
.Cdb
= Cdb
;
324 // Fill Cdb for Mode Sense (10) Command
326 Target
= &TargetArray
[0];
327 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
329 Cdb
[0] = EFI_SCSI_OP_MODE_SEN10
;
331 // DBDField is in Cdb[1] bit3 of (bit7..0)
333 Cdb
[1] = (UINT8
) ((Lun
& EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK
) + ((DBDField
<< 3) & 0x08));
335 // PageControl is in Cdb[2] bit7..6, PageCode is in Cdb[2] bit5..0
337 Cdb
[2] = (UINT8
) ((PageControl
& 0xc0) | (PageCode
& 0x3f));
338 Cdb
[7] = (UINT8
) (*DataLength
>> 8);
339 Cdb
[8] = (UINT8
) (*DataLength
);
341 CommandPacket
.CdbLength
= EFI_SCSI_OP_LENGTH_TEN
;
342 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
343 CommandPacket
.SenseDataLength
= *SenseDataLength
;
345 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
347 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
348 *TargetStatus
= CommandPacket
.TargetStatus
;
349 *SenseDataLength
= CommandPacket
.SenseDataLength
;
350 *DataLength
= CommandPacket
.InTransferLength
;
357 Function to submit SCSI request sense command.
359 Submit SCSI request sense command with the SCSI requested packet specified by this
360 SCSI command, TimeOut and SenseData, and then return the status of scsi unit execution.
362 If SenseDataLength is NULL, then ASSERT().
364 If HostAdapterStatus is NULL, then ASSERT().
366 If TargetStatus is NULL, then ASSERT().
368 @param[in] ScsiIo A pointer to SCSI IO protocol.
369 @param[in] Timeout The length of timeout period.
370 @param[in] SenseData A pointer to output sense data.
371 @param[in out] SenseDataLength The length of output sense data.
372 @param[out] HostAdapterStatus The status of Host Adapter.
373 @param[out] TargetStatus The status of the target.
375 @retval EFI_SUCCESS Command is executed successfully.
376 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are
377 too many SCSI Command Packets already queued.
378 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
379 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by
380 the SCSI initiator(i.e., SCSI Host Controller)
381 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
382 @retval EFI_INVALID_PARAMETER ScsiIo is NULL.
387 ScsiRequestSenseCommand (
388 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
391 IN OUT UINT8
*SenseDataLength
,
392 OUT UINT8
*HostAdapterStatus
,
393 OUT UINT8
*TargetStatus
396 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
399 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
401 UINT8 Cdb
[EFI_SCSI_OP_LENGTH_SIX
];
403 ASSERT (SenseDataLength
!= NULL
);
404 ASSERT (HostAdapterStatus
!= NULL
);
405 ASSERT (TargetStatus
!= NULL
);
407 if (ScsiIo
== NULL
) {
408 return EFI_INVALID_PARAMETER
;
411 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
412 ZeroMem (Cdb
, EFI_SCSI_OP_LENGTH_SIX
);
414 CommandPacket
.Timeout
= Timeout
;
415 CommandPacket
.InDataBuffer
= SenseData
;
416 CommandPacket
.SenseData
= NULL
;
417 CommandPacket
.InTransferLength
= *SenseDataLength
;
418 CommandPacket
.Cdb
= Cdb
;
420 // Fill Cdb for Request Sense Command
422 Target
= &TargetArray
[0];
423 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
425 Cdb
[0] = EFI_SCSI_OP_REQUEST_SENSE
;
426 Cdb
[1] = (UINT8
) (Lun
& EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK
);
427 Cdb
[4] = (UINT8
) (*SenseDataLength
);
429 CommandPacket
.CdbLength
= (UINT8
) EFI_SCSI_OP_LENGTH_SIX
;
430 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
431 CommandPacket
.SenseDataLength
= 0;
433 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
435 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
436 *TargetStatus
= CommandPacket
.TargetStatus
;
437 *SenseDataLength
= (UINT8
) CommandPacket
.InTransferLength
;
444 Function to submit read capacity command.
446 Submit SCSI read capacity command with the SCSI request packet specified by this SCSI
447 command and the input parameters, and then return the status of Scsi unit execution.
449 If SenseDataLength is NULL, then ASSERT().
451 If HostAdapterStatus is NULL, then ASSERT().
453 If TargetStatus is NULL, then ASSERT().
455 If DataLength is NULL, then ASSERT().
457 @param[in] ScsiIo A pointer to SCSI IO protocol.
458 @param[in] Timeout The length of timeout period.
459 @param[in] SenseData A pointer to output sense data.
460 @param[in out] SenseDataLength The length of output sense data.
461 @param[out] HostAdapterStatus The status of Host Adapter.
462 @param[out] TargetStatus The status of the target.
463 @param[out] DataBuffer A pointer to a data buffer.
464 @param[in out] DataLength The length of data buffer.
465 @param[in] PMI Partial medium indicator.
467 @retval EFI_SUCCESS Command is executed successfully.
468 @retval EFI_WARN_BUFFER_TOO_SMALL The SCSI Request Packet was executed, but the entire DataBuffer could
469 not be transferred. The actual number of bytes transferred is returned in DataLength.
470 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many
471 SCSI Command Packets already queued.
472 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
473 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by
474 the SCSI initiator(i.e., SCSI Host Controller)
475 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
476 @retval EFI_INVALID_PARAMETER ScsiIo is NULL.
481 ScsiReadCapacityCommand (
482 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
485 IN OUT UINT8
*SenseDataLength
,
486 OUT UINT8
*HostAdapterStatus
,
487 OUT UINT8
*TargetStatus
,
488 OUT VOID
*DataBuffer
,
489 IN OUT UINT32
*DataLength
,
493 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
496 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
498 UINT8 Cdb
[EFI_SCSI_OP_LENGTH_TEN
];
500 ASSERT (SenseDataLength
!= NULL
);
501 ASSERT (HostAdapterStatus
!= NULL
);
502 ASSERT (TargetStatus
!= NULL
);
503 ASSERT (DataLength
!= NULL
);
505 if (ScsiIo
== NULL
) {
506 return EFI_INVALID_PARAMETER
;
509 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
510 ZeroMem (Cdb
, EFI_SCSI_OP_LENGTH_TEN
);
512 CommandPacket
.Timeout
= Timeout
;
513 CommandPacket
.InDataBuffer
= DataBuffer
;
514 CommandPacket
.SenseData
= SenseData
;
515 CommandPacket
.InTransferLength
= *DataLength
;
516 CommandPacket
.Cdb
= Cdb
;
518 // Fill Cdb for Read Capacity Command
520 Target
= &TargetArray
[0];
521 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
523 Cdb
[0] = EFI_SCSI_OP_READ_CAPACITY
;
524 Cdb
[1] = (UINT8
) (Lun
& EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK
);
527 // Partial medium indicator,if PMI is FALSE, the Cdb.2 ~ Cdb.5 MUST BE ZERO.
529 ZeroMem ((Cdb
+ 2), 4);
534 CommandPacket
.CdbLength
= EFI_SCSI_OP_LENGTH_TEN
;
535 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
536 CommandPacket
.SenseDataLength
= *SenseDataLength
;
538 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
540 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
541 *TargetStatus
= CommandPacket
.TargetStatus
;
542 *SenseDataLength
= CommandPacket
.SenseDataLength
;
543 *DataLength
= CommandPacket
.InTransferLength
;
550 Function to submit read 10 command.
552 Submit SCSI read (10) command with the SCSI request packet specified by this SCSI command
553 and the input parameters, and then return the status of Scsi unit execution.
555 If SenseDataLength is NULL, then ASSERT().
557 If HostAdapterStatus is NULL, then ASSERT().
559 If TargetStatus is NULL, then ASSERT().
561 If DataLength is NULL, then ASSERT().
563 @param[in] ScsiIo A pointer to SCSI IO protocol.
564 @param[in] Timeout The length of timeout period.
565 @param[in] SenseData A pointer to output sense data.
566 @param[in out] SenseDataLength The length of output sense data.
567 @param[out] HostAdapterStatus The status of Host Adapter.
568 @param[out] TargetStatus The status of the target.
569 @param[out] DataBuffer Read 10 command data.
570 @param[in out] DataLength The length of data buffer.
571 @param[in] StartLba The start address of LBA.
572 @param[in] SectorSize The sector size.
574 @retval EFI_SUCCESS Command is executed successfully.
575 @retval EFI_WARN_BUFFER_TOO_SMALL The SCSI Request Packet was executed, but the entire DataBuffer could
576 not be transferred. The actual number of bytes transferred is returned in DataLength.
577 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many
578 SCSI Command Packets already queued.
579 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
580 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by
581 the SCSI initiator(i.e., SCSI Host Controller)
582 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
583 @retval EFI_INVALID_PARAMETER ScsiIo is NULL.
589 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
592 IN OUT UINT8
*SenseDataLength
,
593 OUT UINT8
*HostAdapterStatus
,
594 OUT UINT8
*TargetStatus
,
595 OUT VOID
*DataBuffer
,
596 IN OUT UINT32
*DataLength
,
601 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
604 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
606 UINT8 Cdb
[EFI_SCSI_OP_LENGTH_TEN
];
608 ASSERT (SenseDataLength
!= NULL
);
609 ASSERT (HostAdapterStatus
!= NULL
);
610 ASSERT (TargetStatus
!= NULL
);
611 ASSERT (DataLength
!= NULL
);
613 if (ScsiIo
== NULL
) {
614 return EFI_INVALID_PARAMETER
;
617 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
618 ZeroMem (Cdb
, EFI_SCSI_OP_LENGTH_TEN
);
620 CommandPacket
.Timeout
= Timeout
;
621 CommandPacket
.InDataBuffer
= DataBuffer
;
622 CommandPacket
.SenseData
= SenseData
;
623 CommandPacket
.InTransferLength
= *DataLength
;
624 CommandPacket
.Cdb
= Cdb
;
626 // Fill Cdb for Read (10) Command
628 Target
= &TargetArray
[0];
629 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
631 Cdb
[0] = EFI_SCSI_OP_READ10
;
632 Cdb
[1] = (UINT8
) (Lun
& EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK
);
633 Cdb
[2] = (UINT8
) (StartLba
>> 24);
634 Cdb
[3] = (UINT8
) (StartLba
>> 16);
635 Cdb
[4] = (UINT8
) (StartLba
>> 8);
636 Cdb
[5] = (UINT8
) (StartLba
& 0xff);
637 Cdb
[7] = (UINT8
) (SectorSize
>> 8);
638 Cdb
[8] = (UINT8
) (SectorSize
& 0xff);
640 CommandPacket
.CdbLength
= EFI_SCSI_OP_LENGTH_TEN
;
641 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
642 CommandPacket
.SenseDataLength
= *SenseDataLength
;
644 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
646 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
647 *TargetStatus
= CommandPacket
.TargetStatus
;
648 *SenseDataLength
= CommandPacket
.SenseDataLength
;
649 *DataLength
= CommandPacket
.InTransferLength
;
656 Function to submit SCSI write 10 command.
658 Submit SCSI write (10) command with the SCSI request packet specified by this SCSI command and the
659 input parameters, and then return the status of Scsi unit execution.
661 If SenseDataLength is NULL, then ASSERT().
663 If HostAdapterStatus is NULL, then ASSERT().
665 If TargetStatus is NULL, then ASSERT().
667 If DataLength is NULL, then ASSERT().
669 @param[in] ScsiIo SCSI IO Protocol to use
670 @param[in] Timeout The length of timeout period.
671 @param[in] SenseData A pointer to output sense data.
672 @param[in out] SenseDataLength The length of output sense data.
673 @param[out] HostAdapterStatus The status of Host Adapter.
674 @param[out] TargetStatus The status of the target.
675 @param[out] DataBuffer A pointer to a data buffer.
676 @param[in out] DataLength The length of data buffer.
677 @param[in] StartLba The start address of LBA.
678 @param[in] SectorSize The sector size.
680 @retval EFI_SUCCESS Command is executed successfully.
681 @retval EFI_WARN_BUFFER_TOO_SMALL The SCSI Request Packet was executed, but the entire DataBuffer could
682 not be transferred. The actual number of bytes transferred is returned in DataLength.
683 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many
684 SCSI Command Packets already queued.
685 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
686 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported by
687 the SCSI initiator(i.e., SCSI Host Controller)
688 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
689 @retval EFI_INVALID_PARAMETER ScsiIo is NULL.
695 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
698 IN OUT UINT8
*SenseDataLength
,
699 OUT UINT8
*HostAdapterStatus
,
700 OUT UINT8
*TargetStatus
,
701 OUT VOID
*DataBuffer
,
702 IN OUT UINT32
*DataLength
,
707 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
710 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
712 UINT8 Cdb
[EFI_SCSI_OP_LENGTH_TEN
];
714 ASSERT (SenseDataLength
!= NULL
);
715 ASSERT (HostAdapterStatus
!= NULL
);
716 ASSERT (TargetStatus
!= NULL
);
717 ASSERT (DataLength
!= NULL
);
719 if (ScsiIo
== NULL
) {
720 return EFI_INVALID_PARAMETER
;
723 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
724 ZeroMem (Cdb
, EFI_SCSI_OP_LENGTH_TEN
);
726 CommandPacket
.Timeout
= Timeout
;
727 CommandPacket
.OutDataBuffer
= DataBuffer
;
728 CommandPacket
.SenseData
= SenseData
;
729 CommandPacket
.OutTransferLength
= *DataLength
;
730 CommandPacket
.Cdb
= Cdb
;
732 // Fill Cdb for Write (10) Command
734 Target
= &TargetArray
[0];
735 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
737 Cdb
[0] = EFI_SCSI_OP_WRITE10
;
738 Cdb
[1] = (UINT8
) (Lun
& EFI_SCSI_LOGICAL_UNIT_NUMBER_MASK
);
739 Cdb
[2] = (UINT8
) (StartLba
>> 24);
740 Cdb
[3] = (UINT8
) (StartLba
>> 16);
741 Cdb
[4] = (UINT8
) (StartLba
>> 8);
742 Cdb
[5] = (UINT8
) StartLba
;
743 Cdb
[7] = (UINT8
) (SectorSize
>> 8);
744 Cdb
[8] = (UINT8
) SectorSize
;
746 CommandPacket
.CdbLength
= EFI_SCSI_OP_LENGTH_TEN
;
747 CommandPacket
.DataDirection
= EFI_SCSI_DATA_OUT
;
748 CommandPacket
.SenseDataLength
= *SenseDataLength
;
750 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
752 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
753 *TargetStatus
= CommandPacket
.TargetStatus
;
754 *SenseDataLength
= CommandPacket
.SenseDataLength
;
755 *DataLength
= CommandPacket
.OutTransferLength
;