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/ScsiLib.h>
18 #include <Library/BaseMemoryLib.h>
20 #include <IndustryStandard/Scsi.h>
24 Function test the ready status of the SCSI unit.
26 @param[in] ScsiIo A pointer to SCSI IO protocol.
27 @param[in] Timeout The length of timeout period.
28 @param[in out] SenseData A pointer to the sense data that
29 was generated by the execution of the SCSI Request Packet.
30 @param[in out] SenseDataLength On input, the length in bytes of the SenseData buffer. On
31 output, the number of bytes written to the SenseData buffer.
32 @param[out] HostAdapterStatus The status of Host Adapter.
33 @param[out] TargetStatus The status of the target.
35 @retval EFI_SUCCESS The status of the unit is tested successfully.
36 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
37 but the entire DataBuffer could not be transferred.
38 The actual number of bytes transferred is returned
40 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
41 there are too many SCSI Command Packets already
43 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
44 the SCSI Request Packet.
45 @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid, or ScsiIo is NULL.
46 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
47 is not supported by the SCSI initiator(i.e., SCSI
49 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
50 Request Packet to execute.
54 ScsiTestUnitReadyCommand (
55 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
57 IN OUT VOID
*SenseData
,
58 IN OUT UINT8
*SenseDataLength
,
59 OUT UINT8
*HostAdapterStatus
,
60 OUT UINT8
*TargetStatus
63 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
66 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
70 ASSERT (SenseDataLength
!= NULL
);
71 ASSERT (HostAdapterStatus
!= NULL
);
72 ASSERT (TargetStatus
!= NULL
);
75 return EFI_INVALID_PARAMETER
;
78 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
81 CommandPacket
.Timeout
= Timeout
;
82 CommandPacket
.InDataBuffer
= NULL
;
83 CommandPacket
.InTransferLength
= 0;
84 CommandPacket
.OutDataBuffer
= NULL
;
85 CommandPacket
.OutTransferLength
= 0;
86 CommandPacket
.SenseData
= SenseData
;
87 CommandPacket
.Cdb
= Cdb
;
89 // Fill Cdb for Test Unit Ready Command
91 Target
= &TargetArray
[0];
92 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
94 Cdb
[0] = EFI_SCSI_OP_TEST_UNIT_READY
;
95 Cdb
[1] = (UINT8
) (Lun
& 0xe0);
96 CommandPacket
.CdbLength
= (UINT8
) 6;
97 CommandPacket
.SenseDataLength
= *SenseDataLength
;
99 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
101 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
102 *TargetStatus
= CommandPacket
.TargetStatus
;
103 *SenseDataLength
= CommandPacket
.SenseDataLength
;
110 Function to submit SCSI inquiry command.
112 @param[in] ScsiIo SCSI IO Protocol to use
113 @param[in] Timeout The length of timeout period.
114 @param[out] SenseData A pointer to output sense data.
115 @param[in out] SenseDataLength On input, the length in bytes of the SenseData buffer. On
116 output, the number of bytes written to the SenseData buffer.
117 @param[out] HostAdapterStatus The status of Host Adapter.
118 @param[out] TargetStatus The status of the target.
119 @param[in] InquirydataBuffer A pointer to inquiry data buffer.
120 @param[in,out] InquiryDataLength The length of inquiry data buffer.
121 @param[in] EnableVitalProductData Boolean to enable Vital Product Data.
123 @retval EFI_SUCCESS The status of the unit is tested successfully.
124 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
125 but the entire DataBuffer could not be transferred.
126 The actual number of bytes transferred is returned
128 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
129 there are too many SCSI Command Packets already
131 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
132 the SCSI Request Packet.
133 @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid, or ScsiIo is NULL.
134 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
135 is not supported by the SCSI initiator(i.e., SCSI
137 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
138 Request Packet to execute.
143 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
146 IN OUT UINT8
*SenseDataLength
,
147 OUT UINT8
*HostAdapterStatus
,
148 OUT UINT8
*TargetStatus
,
149 IN VOID
*InquiryDataBuffer
,
150 IN OUT UINT32
*InquiryDataLength
,
151 IN BOOLEAN EnableVitalProductData
154 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
157 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
161 ASSERT (SenseDataLength
!= NULL
);
162 ASSERT (HostAdapterStatus
!= NULL
);
163 ASSERT (TargetStatus
!= NULL
);
164 ASSERT (InquiryDataLength
!= NULL
);
166 if (ScsiIo
== NULL
) {
167 return EFI_INVALID_PARAMETER
;
170 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
173 CommandPacket
.Timeout
= Timeout
;
174 CommandPacket
.InDataBuffer
= InquiryDataBuffer
;
175 CommandPacket
.InTransferLength
= *InquiryDataLength
;
176 CommandPacket
.SenseData
= SenseData
;
177 CommandPacket
.SenseDataLength
= *SenseDataLength
;
178 CommandPacket
.Cdb
= Cdb
;
180 Target
= &TargetArray
[0];
181 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
183 Cdb
[0] = EFI_SCSI_OP_INQUIRY
;
184 Cdb
[1] = (UINT8
) (Lun
& 0xe0);
185 if (EnableVitalProductData
) {
189 if (*InquiryDataLength
> 0xff) {
190 *InquiryDataLength
= 0xff;
193 Cdb
[4] = (UINT8
) (*InquiryDataLength
);
194 CommandPacket
.CdbLength
= (UINT8
) 6;
195 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
197 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
199 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
200 *TargetStatus
= CommandPacket
.TargetStatus
;
201 *SenseDataLength
= CommandPacket
.SenseDataLength
;
202 *InquiryDataLength
= CommandPacket
.InTransferLength
;
209 Function to submit SCSI mode sense 10 command.
211 @param[in] ScsiIo A pointer to SCSI IO protocol.
212 @param[in] Timeout The length of timeout period.
213 @param[out] SenseData A pointer to output sense data.
214 @param[in out] SenseDataLength On input, the length in bytes of the SenseData buffer. On
215 output, the number of bytes written to the SenseData buffer.
216 @param[out] HostAdapterStatus The status of Host Adapter.
217 @param[out] TargetStatus The status of the target.
218 @param[in] DataBuffer A pointer to input data buffer.
219 @param[in,out] DataLength The length of input data buffer.
220 @param[in] DBDField The DBD Field (Optional).
221 @param[in] PageControl Page Control.
222 @param[in] PageCode Page code.
224 @retval EFI_SUCCESS The status of the unit is tested successfully.
225 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
226 but the entire DataBuffer could not be transferred.
227 The actual number of bytes transferred is returned
229 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
230 there are too many SCSI Command Packets already
232 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
233 the SCSI Request Packet.
234 @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid, or ScsiIo is NULL.
235 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
236 is not supported by the SCSI initiator(i.e., SCSI
238 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
239 Request Packet to execute.
243 ScsiModeSense10Command (
244 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
247 IN OUT UINT8
*SenseDataLength
,
248 OUT UINT8
*HostAdapterStatus
,
249 OUT UINT8
*TargetStatus
,
251 IN OUT UINT32
*DataLength
,
252 IN UINT8 DBDField
, OPTIONAL
253 IN UINT8 PageControl
,
257 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
260 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
264 ASSERT (SenseDataLength
!= NULL
);
265 ASSERT (HostAdapterStatus
!= NULL
);
266 ASSERT (TargetStatus
!= NULL
);
267 ASSERT (DataLength
!= NULL
);
269 if (ScsiIo
== NULL
) {
270 return EFI_INVALID_PARAMETER
;
273 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
276 CommandPacket
.Timeout
= Timeout
;
277 CommandPacket
.InDataBuffer
= DataBuffer
;
278 CommandPacket
.SenseData
= SenseData
;
279 CommandPacket
.InTransferLength
= *DataLength
;
280 CommandPacket
.Cdb
= Cdb
;
282 // Fill Cdb for Mode Sense (10) Command
284 Target
= &TargetArray
[0];
285 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
287 Cdb
[0] = EFI_SCSI_OP_MODE_SEN10
;
288 Cdb
[1] = (UINT8
) ((Lun
& 0xe0) + ((DBDField
<< 3) & 0x08));
289 Cdb
[2] = (UINT8
) ((PageControl
& 0xc0) | (PageCode
& 0x3f));
290 Cdb
[7] = (UINT8
) (*DataLength
>> 8);
291 Cdb
[8] = (UINT8
) (*DataLength
);
293 CommandPacket
.CdbLength
= 10;
294 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
295 CommandPacket
.SenseDataLength
= *SenseDataLength
;
297 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
299 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
300 *TargetStatus
= CommandPacket
.TargetStatus
;
301 *SenseDataLength
= CommandPacket
.SenseDataLength
;
302 *DataLength
= CommandPacket
.InTransferLength
;
309 Function to submit SCSI request sense command.
311 @param[in] ScsiIo A pointer to SCSI IO protocol.
312 @param[in] Timeout The length of timeout period.
313 @param[in] SenseData A pointer to output sense data.
314 @param[in out] SenseDataLength On input, the length in bytes of the SenseData buffer. On
315 output, the number of bytes written to the SenseData buffer.
316 @param[out] HostAdapterStatus The status of Host Adapter.
317 @param[out] TargetStatus The status of the target.
319 @retval EFI_SUCCESS Valid data returned
320 @retval EFI_SUCCESS The status of the unit is tested successfully.
321 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
322 but the entire DataBuffer could not be transferred.
323 The actual number of bytes transferred is returned
325 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
326 there are too many SCSI Command Packets already
328 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
329 the SCSI Request Packet.
330 @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid, or ScsiIo is NULL.
331 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
332 is not supported by the SCSI initiator(i.e., SCSI
334 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
335 Request Packet to execute.
339 ScsiRequestSenseCommand (
340 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
343 IN OUT UINT8
*SenseDataLength
,
344 OUT UINT8
*HostAdapterStatus
,
345 OUT UINT8
*TargetStatus
348 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
351 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
355 ASSERT (SenseDataLength
!= NULL
);
356 ASSERT (HostAdapterStatus
!= NULL
);
357 ASSERT (TargetStatus
!= NULL
);
359 if (ScsiIo
== NULL
) {
360 return EFI_INVALID_PARAMETER
;
363 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
366 CommandPacket
.Timeout
= Timeout
;
367 CommandPacket
.InDataBuffer
= SenseData
;
368 CommandPacket
.SenseData
= NULL
;
369 CommandPacket
.InTransferLength
= *SenseDataLength
;
370 CommandPacket
.Cdb
= Cdb
;
372 // Fill Cdb for Request Sense Command
374 Target
= &TargetArray
[0];
375 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
377 Cdb
[0] = EFI_SCSI_OP_REQUEST_SENSE
;
378 Cdb
[1] = (UINT8
) (Lun
& 0xe0);
379 Cdb
[4] = (UINT8
) (*SenseDataLength
);
381 CommandPacket
.CdbLength
= (UINT8
) 6;
382 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
383 CommandPacket
.SenseDataLength
= 0;
385 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
387 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
388 *TargetStatus
= CommandPacket
.TargetStatus
;
389 *SenseDataLength
= (UINT8
) CommandPacket
.InTransferLength
;
396 Function to submit read capacity command.
398 @param[in] ScsiIo A pointer to SCSI IO protocol.
399 @param[in] Timeout The length of timeout period.
400 @param[out] SenseData A pointer to output sense data.
401 @param[in out] SenseDataLength On input, the length in bytes of the SenseData buffer. On
402 output, the number of bytes written to the SenseData buffer.
403 @param[out] HostAdapterStatus The status of Host Adapter.
404 @param[out] TargetStatus The status of the target.
405 @param[out] DataBuffer A pointer to a data buffer.
406 @param[in,out] DataLength The length of data buffer.
407 @param[in] PMI Partial medium indicator.
409 @retval EFI_SUCCESS The status of the unit is tested successfully.
410 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
411 but the entire DataBuffer could not be transferred.
412 The actual number of bytes transferred is returned
414 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
415 there are too many SCSI Command Packets already
417 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
418 the SCSI Request Packet.
419 @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid, or ScsiIo is NULL.
420 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
421 is not supported by the SCSI initiator(i.e., SCSI
423 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
424 Request Packet to execute.
428 ScsiReadCapacityCommand (
429 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
432 IN OUT UINT8
*SenseDataLength
,
433 OUT UINT8
*HostAdapterStatus
,
434 OUT UINT8
*TargetStatus
,
435 OUT VOID
*DataBuffer
,
436 IN OUT UINT32
*DataLength
,
440 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
443 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
447 ASSERT (SenseDataLength
!= NULL
);
448 ASSERT (HostAdapterStatus
!= NULL
);
449 ASSERT (TargetStatus
!= NULL
);
450 ASSERT (DataLength
!= NULL
);
452 if (ScsiIo
== NULL
) {
453 return EFI_INVALID_PARAMETER
;
456 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
459 CommandPacket
.Timeout
= Timeout
;
460 CommandPacket
.InDataBuffer
= DataBuffer
;
461 CommandPacket
.SenseData
= SenseData
;
462 CommandPacket
.InTransferLength
= *DataLength
;
463 CommandPacket
.Cdb
= Cdb
;
465 // Fill Cdb for Read Capacity Command
467 Target
= &TargetArray
[0];
468 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
470 Cdb
[0] = EFI_SCSI_OP_READ_CAPACITY
;
471 Cdb
[1] = (UINT8
) (Lun
& 0xe0);
474 // Partial medium indicator,if PMI is FALSE, the Cdb.2 ~ Cdb.5 MUST BE ZERO.
476 ZeroMem ((Cdb
+ 2), 4);
481 CommandPacket
.CdbLength
= 10;
482 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
483 CommandPacket
.SenseDataLength
= *SenseDataLength
;
485 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
487 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
488 *TargetStatus
= CommandPacket
.TargetStatus
;
489 *SenseDataLength
= CommandPacket
.SenseDataLength
;
490 *DataLength
= CommandPacket
.InTransferLength
;
497 Function to submit read 10 command.
499 @param[in] ScsiIo A pointer to SCSI IO protocol.
500 @param[in] Timeout The length of timeout period.
501 @param[out] SenseData A pointer to output sense data.
502 @param[in out] SenseDataLength On input, the length in bytes of the SenseData buffer. On
503 output, the number of bytes written to the SenseData buffer.
504 @param[out] HostAdapterStatus The status of Host Adapter.
505 @param[out] TargetStatus The status of the target.
506 @param[out] DataBuffer Read 10 command data.
507 @param[in,out] DataLength The length of data buffer.
508 @param[in] StartLba The start address of LBA.
509 @param[in] SectorSize The sector size.
511 @retval EFI_SUCCESS The status of the unit is tested successfully.
512 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
513 but the entire DataBuffer could not be transferred.
514 The actual number of bytes transferred is returned
516 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
517 there are too many SCSI Command Packets already
519 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
520 the SCSI Request Packet.
521 @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid, or ScsiIo is NULL.
522 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
523 is not supported by the SCSI initiator(i.e., SCSI
525 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
526 Request Packet to execute.
531 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
534 IN OUT UINT8
*SenseDataLength
,
535 OUT UINT8
*HostAdapterStatus
,
536 OUT UINT8
*TargetStatus
,
537 OUT VOID
*DataBuffer
,
538 IN OUT UINT32
*DataLength
,
543 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
546 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
550 ASSERT (SenseDataLength
!= NULL
);
551 ASSERT (HostAdapterStatus
!= NULL
);
552 ASSERT (TargetStatus
!= NULL
);
553 ASSERT (DataLength
!= NULL
);
555 if (ScsiIo
== NULL
) {
556 return EFI_INVALID_PARAMETER
;
559 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
562 CommandPacket
.Timeout
= Timeout
;
563 CommandPacket
.InDataBuffer
= DataBuffer
;
564 CommandPacket
.SenseData
= SenseData
;
565 CommandPacket
.InTransferLength
= *DataLength
;
566 CommandPacket
.Cdb
= Cdb
;
568 // Fill Cdb for Read (10) Command
570 Target
= &TargetArray
[0];
571 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
573 Cdb
[0] = EFI_SCSI_OP_READ10
;
574 Cdb
[1] = (UINT8
) (Lun
& 0xe0);
575 Cdb
[2] = (UINT8
) (StartLba
>> 24);
576 Cdb
[3] = (UINT8
) (StartLba
>> 16);
577 Cdb
[4] = (UINT8
) (StartLba
>> 8);
578 Cdb
[5] = (UINT8
) (StartLba
& 0xff);
579 Cdb
[7] = (UINT8
) (SectorSize
>> 8);
580 Cdb
[8] = (UINT8
) (SectorSize
& 0xff);
582 CommandPacket
.CdbLength
= 10;
583 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
584 CommandPacket
.SenseDataLength
= *SenseDataLength
;
586 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
588 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
589 *TargetStatus
= CommandPacket
.TargetStatus
;
590 *SenseDataLength
= CommandPacket
.SenseDataLength
;
591 *DataLength
= CommandPacket
.InTransferLength
;
598 Function to submit SCSI write 10 command.
600 @param[in] ScsiIo SCSI IO Protocol to use
601 @param[in] Timeout The length of timeout period.
602 @param[out] SenseData A pointer to output sense data.
603 @param[in out] SenseDataLength On input, the length in bytes of the SenseData buffer. On
604 output, the number of bytes written to the SenseData buffer.
605 @param[out] HostAdapterStatus The status of Host Adapter.
606 @param[out] TargetStatus The status of the target.
607 @param[out] DataBuffer A pointer to a data buffer.
608 @param[in,out] DataLength The length of data buffer.
609 @param[in] StartLba The start address of LBA.
610 @param[in] SectorSize The sector size.
612 @retval EFI_SUCCESS The status of the unit is tested successfully.
613 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
614 but the entire DataBuffer could not be transferred.
615 The actual number of bytes transferred is returned
617 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
618 there are too many SCSI Command Packets already
620 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
621 the SCSI Request Packet.
622 @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid, or ScsiIo is NULL.
623 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
624 is not supported by the SCSI initiator(i.e., SCSI
626 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
627 Request Packet to execute.
632 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
635 IN OUT UINT8
*SenseDataLength
,
636 OUT UINT8
*HostAdapterStatus
,
637 OUT UINT8
*TargetStatus
,
638 OUT VOID
*DataBuffer
,
639 IN OUT UINT32
*DataLength
,
644 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
647 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
651 ASSERT (SenseDataLength
!= NULL
);
652 ASSERT (HostAdapterStatus
!= NULL
);
653 ASSERT (TargetStatus
!= NULL
);
654 ASSERT (DataLength
!= NULL
);
656 if (ScsiIo
== NULL
) {
657 return EFI_INVALID_PARAMETER
;
660 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
663 CommandPacket
.Timeout
= Timeout
;
664 CommandPacket
.OutDataBuffer
= DataBuffer
;
665 CommandPacket
.SenseData
= SenseData
;
666 CommandPacket
.OutTransferLength
= *DataLength
;
667 CommandPacket
.Cdb
= Cdb
;
669 // Fill Cdb for Write (10) Command
671 Target
= &TargetArray
[0];
672 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
674 Cdb
[0] = EFI_SCSI_OP_WRITE10
;
675 Cdb
[1] = (UINT8
) (Lun
& 0xe0);
676 Cdb
[2] = (UINT8
) (StartLba
>> 24);
677 Cdb
[3] = (UINT8
) (StartLba
>> 16);
678 Cdb
[4] = (UINT8
) (StartLba
>> 8);
679 Cdb
[5] = (UINT8
) StartLba
;
680 Cdb
[7] = (UINT8
) (SectorSize
>> 8);
681 Cdb
[8] = (UINT8
) SectorSize
;
683 CommandPacket
.CdbLength
= 10;
684 CommandPacket
.DataDirection
= EFI_SCSI_DATA_OUT
;
685 CommandPacket
.SenseDataLength
= *SenseDataLength
;
687 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
689 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
690 *TargetStatus
= CommandPacket
.TargetStatus
;
691 *SenseDataLength
= CommandPacket
.SenseDataLength
;
692 *DataLength
= CommandPacket
.OutTransferLength
;