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>
25 Function test the ready status of the SCSI unit.
27 @param[in] ScsiIo A pointer to SCSI IO protocol.
28 @param[in] Timeout The length of timeout period.
29 @param[in out] SenseData A pointer to the sense data that
30 was generated by the execution of the SCSI Request Packet.
31 @param[in out] SenseDataLength On input, the length in bytes of the SenseData buffer. On
32 output, the number of bytes written to the SenseData buffer.
33 @param[out] HostAdapterStatus The status of Host Adapter.
34 @param[out] TargetStatus The status of the target.
36 @retval EFI_SUCCESS The status of the unit is tested successfully.
37 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
38 but the entire DataBuffer could not be transferred.
39 The actual number of bytes transferred is returned
41 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
42 there are too many SCSI Command Packets already
44 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
45 the SCSI Request Packet.
46 @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid, or ScsiIo is NULL.
47 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
48 is not supported by the SCSI initiator(i.e., SCSI
50 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
51 Request Packet to execute.
56 ScsiTestUnitReadyCommand (
57 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
59 IN OUT VOID
*SenseData
,
60 IN OUT UINT8
*SenseDataLength
,
61 OUT UINT8
*HostAdapterStatus
,
62 OUT UINT8
*TargetStatus
65 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
68 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
72 ASSERT (SenseDataLength
!= NULL
);
73 ASSERT (HostAdapterStatus
!= NULL
);
74 ASSERT (TargetStatus
!= NULL
);
77 return EFI_INVALID_PARAMETER
;
80 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
83 CommandPacket
.Timeout
= Timeout
;
84 CommandPacket
.InDataBuffer
= NULL
;
85 CommandPacket
.InTransferLength
= 0;
86 CommandPacket
.OutDataBuffer
= NULL
;
87 CommandPacket
.OutTransferLength
= 0;
88 CommandPacket
.SenseData
= SenseData
;
89 CommandPacket
.Cdb
= Cdb
;
91 // Fill Cdb for Test Unit Ready Command
93 Target
= &TargetArray
[0];
94 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
96 Cdb
[0] = EFI_SCSI_OP_TEST_UNIT_READY
;
97 Cdb
[1] = (UINT8
) (Lun
& 0xe0);
98 CommandPacket
.CdbLength
= (UINT8
) 6;
99 CommandPacket
.SenseDataLength
= *SenseDataLength
;
101 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
103 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
104 *TargetStatus
= CommandPacket
.TargetStatus
;
105 *SenseDataLength
= CommandPacket
.SenseDataLength
;
112 Function to submit SCSI inquiry command.
114 @param[in] ScsiIo SCSI IO Protocol to use
115 @param[in] Timeout The length of timeout period.
116 @param[out] SenseData A pointer to output sense data.
117 @param[in out] SenseDataLength On input, the length in bytes of the SenseData buffer. On
118 output, the number of bytes written to the SenseData buffer.
119 @param[out] HostAdapterStatus The status of Host Adapter.
120 @param[out] TargetStatus The status of the target.
121 @param[in] InquirydataBuffer A pointer to inquiry data buffer.
122 @param[in,out] InquiryDataLength The length of inquiry data buffer.
123 @param[in] EnableVitalProductData Boolean to enable Vital Product Data.
125 @retval EFI_SUCCESS The status of the unit is tested successfully.
126 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
127 but the entire DataBuffer could not be transferred.
128 The actual number of bytes transferred is returned
130 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
131 there are too many SCSI Command Packets already
133 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
134 the SCSI Request Packet.
135 @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid, or ScsiIo is NULL.
136 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
137 is not supported by the SCSI initiator(i.e., SCSI
139 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
140 Request Packet to execute.
146 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
149 IN OUT UINT8
*SenseDataLength
,
150 OUT UINT8
*HostAdapterStatus
,
151 OUT UINT8
*TargetStatus
,
152 IN VOID
*InquiryDataBuffer
,
153 IN OUT UINT32
*InquiryDataLength
,
154 IN BOOLEAN EnableVitalProductData
157 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
160 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
164 ASSERT (SenseDataLength
!= NULL
);
165 ASSERT (HostAdapterStatus
!= NULL
);
166 ASSERT (TargetStatus
!= NULL
);
167 ASSERT (InquiryDataLength
!= NULL
);
169 if (ScsiIo
== NULL
) {
170 return EFI_INVALID_PARAMETER
;
173 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
176 CommandPacket
.Timeout
= Timeout
;
177 CommandPacket
.InDataBuffer
= InquiryDataBuffer
;
178 CommandPacket
.InTransferLength
= *InquiryDataLength
;
179 CommandPacket
.SenseData
= SenseData
;
180 CommandPacket
.SenseDataLength
= *SenseDataLength
;
181 CommandPacket
.Cdb
= Cdb
;
183 Target
= &TargetArray
[0];
184 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
186 Cdb
[0] = EFI_SCSI_OP_INQUIRY
;
187 Cdb
[1] = (UINT8
) (Lun
& 0xe0);
188 if (EnableVitalProductData
) {
192 if (*InquiryDataLength
> 0xff) {
193 *InquiryDataLength
= 0xff;
196 Cdb
[4] = (UINT8
) (*InquiryDataLength
);
197 CommandPacket
.CdbLength
= (UINT8
) 6;
198 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
200 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
202 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
203 *TargetStatus
= CommandPacket
.TargetStatus
;
204 *SenseDataLength
= CommandPacket
.SenseDataLength
;
205 *InquiryDataLength
= CommandPacket
.InTransferLength
;
212 Function to submit SCSI mode sense 10 command.
214 @param[in] ScsiIo A pointer to SCSI IO protocol.
215 @param[in] Timeout The length of timeout period.
216 @param[out] SenseData A pointer to output sense data.
217 @param[in out] SenseDataLength On input, the length in bytes of the SenseData buffer. On
218 output, the number of bytes written to the SenseData buffer.
219 @param[out] HostAdapterStatus The status of Host Adapter.
220 @param[out] TargetStatus The status of the target.
221 @param[in] DataBuffer A pointer to input data buffer.
222 @param[in,out] DataLength The length of input data buffer.
223 @param[in] DBDField The DBD Field (Optional).
224 @param[in] PageControl Page Control.
225 @param[in] PageCode Page code.
227 @retval EFI_SUCCESS The status of the unit is tested successfully.
228 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
229 but the entire DataBuffer could not be transferred.
230 The actual number of bytes transferred is returned
232 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
233 there are too many SCSI Command Packets already
235 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
236 the SCSI Request Packet.
237 @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid, or ScsiIo is NULL.
238 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
239 is not supported by the SCSI initiator(i.e., SCSI
241 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
242 Request Packet to execute.
247 ScsiModeSense10Command (
248 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
251 IN OUT UINT8
*SenseDataLength
,
252 OUT UINT8
*HostAdapterStatus
,
253 OUT UINT8
*TargetStatus
,
255 IN OUT UINT32
*DataLength
,
256 IN UINT8 DBDField
, OPTIONAL
257 IN UINT8 PageControl
,
261 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
264 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
268 ASSERT (SenseDataLength
!= NULL
);
269 ASSERT (HostAdapterStatus
!= NULL
);
270 ASSERT (TargetStatus
!= NULL
);
271 ASSERT (DataLength
!= NULL
);
273 if (ScsiIo
== NULL
) {
274 return EFI_INVALID_PARAMETER
;
277 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
280 CommandPacket
.Timeout
= Timeout
;
281 CommandPacket
.InDataBuffer
= DataBuffer
;
282 CommandPacket
.SenseData
= SenseData
;
283 CommandPacket
.InTransferLength
= *DataLength
;
284 CommandPacket
.Cdb
= Cdb
;
286 // Fill Cdb for Mode Sense (10) Command
288 Target
= &TargetArray
[0];
289 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
291 Cdb
[0] = EFI_SCSI_OP_MODE_SEN10
;
292 Cdb
[1] = (UINT8
) ((Lun
& 0xe0) + ((DBDField
<< 3) & 0x08));
293 Cdb
[2] = (UINT8
) ((PageControl
& 0xc0) | (PageCode
& 0x3f));
294 Cdb
[7] = (UINT8
) (*DataLength
>> 8);
295 Cdb
[8] = (UINT8
) (*DataLength
);
297 CommandPacket
.CdbLength
= 10;
298 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
299 CommandPacket
.SenseDataLength
= *SenseDataLength
;
301 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
303 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
304 *TargetStatus
= CommandPacket
.TargetStatus
;
305 *SenseDataLength
= CommandPacket
.SenseDataLength
;
306 *DataLength
= CommandPacket
.InTransferLength
;
313 Function to submit SCSI request sense command.
315 @param[in] ScsiIo A pointer to SCSI IO protocol.
316 @param[in] Timeout The length of timeout period.
317 @param[in] SenseData A pointer to output sense data.
318 @param[in out] SenseDataLength On input, the length in bytes of the SenseData buffer. On
319 output, the number of bytes written to the SenseData buffer.
320 @param[out] HostAdapterStatus The status of Host Adapter.
321 @param[out] TargetStatus The status of the target.
323 @retval EFI_SUCCESS Valid data returned
324 @retval EFI_SUCCESS The status of the unit is tested successfully.
325 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
326 but the entire DataBuffer could not be transferred.
327 The actual number of bytes transferred is returned
329 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
330 there are too many SCSI Command Packets already
332 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
333 the SCSI Request Packet.
334 @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid, or ScsiIo is NULL.
335 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
336 is not supported by the SCSI initiator(i.e., SCSI
338 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
339 Request Packet to execute.
344 ScsiRequestSenseCommand (
345 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
348 IN OUT UINT8
*SenseDataLength
,
349 OUT UINT8
*HostAdapterStatus
,
350 OUT UINT8
*TargetStatus
353 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
356 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
360 ASSERT (SenseDataLength
!= NULL
);
361 ASSERT (HostAdapterStatus
!= NULL
);
362 ASSERT (TargetStatus
!= NULL
);
364 if (ScsiIo
== NULL
) {
365 return EFI_INVALID_PARAMETER
;
368 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
371 CommandPacket
.Timeout
= Timeout
;
372 CommandPacket
.InDataBuffer
= SenseData
;
373 CommandPacket
.SenseData
= NULL
;
374 CommandPacket
.InTransferLength
= *SenseDataLength
;
375 CommandPacket
.Cdb
= Cdb
;
377 // Fill Cdb for Request Sense Command
379 Target
= &TargetArray
[0];
380 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
382 Cdb
[0] = EFI_SCSI_OP_REQUEST_SENSE
;
383 Cdb
[1] = (UINT8
) (Lun
& 0xe0);
384 Cdb
[4] = (UINT8
) (*SenseDataLength
);
386 CommandPacket
.CdbLength
= (UINT8
) 6;
387 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
388 CommandPacket
.SenseDataLength
= 0;
390 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
392 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
393 *TargetStatus
= CommandPacket
.TargetStatus
;
394 *SenseDataLength
= (UINT8
) CommandPacket
.InTransferLength
;
401 Function to submit read capacity command.
403 @param[in] ScsiIo A pointer to SCSI IO protocol.
404 @param[in] Timeout The length of timeout period.
405 @param[out] SenseData A pointer to output sense data.
406 @param[in out] SenseDataLength On input, the length in bytes of the SenseData buffer. On
407 output, the number of bytes written to the SenseData buffer.
408 @param[out] HostAdapterStatus The status of Host Adapter.
409 @param[out] TargetStatus The status of the target.
410 @param[out] DataBuffer A pointer to a data buffer.
411 @param[in,out] DataLength The length of data buffer.
412 @param[in] PMI Partial medium indicator.
414 @retval EFI_SUCCESS The status of the unit is tested successfully.
415 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
416 but the entire DataBuffer could not be transferred.
417 The actual number of bytes transferred is returned
419 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
420 there are too many SCSI Command Packets already
422 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
423 the SCSI Request Packet.
424 @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid, or ScsiIo is NULL.
425 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
426 is not supported by the SCSI initiator(i.e., SCSI
428 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
429 Request Packet to execute.
434 ScsiReadCapacityCommand (
435 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
438 IN OUT UINT8
*SenseDataLength
,
439 OUT UINT8
*HostAdapterStatus
,
440 OUT UINT8
*TargetStatus
,
441 OUT VOID
*DataBuffer
,
442 IN OUT UINT32
*DataLength
,
446 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
449 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
453 ASSERT (SenseDataLength
!= NULL
);
454 ASSERT (HostAdapterStatus
!= NULL
);
455 ASSERT (TargetStatus
!= NULL
);
456 ASSERT (DataLength
!= NULL
);
458 if (ScsiIo
== NULL
) {
459 return EFI_INVALID_PARAMETER
;
462 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
465 CommandPacket
.Timeout
= Timeout
;
466 CommandPacket
.InDataBuffer
= DataBuffer
;
467 CommandPacket
.SenseData
= SenseData
;
468 CommandPacket
.InTransferLength
= *DataLength
;
469 CommandPacket
.Cdb
= Cdb
;
471 // Fill Cdb for Read Capacity Command
473 Target
= &TargetArray
[0];
474 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
476 Cdb
[0] = EFI_SCSI_OP_READ_CAPACITY
;
477 Cdb
[1] = (UINT8
) (Lun
& 0xe0);
480 // Partial medium indicator,if PMI is FALSE, the Cdb.2 ~ Cdb.5 MUST BE ZERO.
482 ZeroMem ((Cdb
+ 2), 4);
487 CommandPacket
.CdbLength
= 10;
488 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
489 CommandPacket
.SenseDataLength
= *SenseDataLength
;
491 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
493 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
494 *TargetStatus
= CommandPacket
.TargetStatus
;
495 *SenseDataLength
= CommandPacket
.SenseDataLength
;
496 *DataLength
= CommandPacket
.InTransferLength
;
503 Function to submit read 10 command.
505 @param[in] ScsiIo A pointer to SCSI IO protocol.
506 @param[in] Timeout The length of timeout period.
507 @param[out] SenseData A pointer to output sense data.
508 @param[in out] SenseDataLength On input, the length in bytes of the SenseData buffer. On
509 output, the number of bytes written to the SenseData buffer.
510 @param[out] HostAdapterStatus The status of Host Adapter.
511 @param[out] TargetStatus The status of the target.
512 @param[out] DataBuffer Read 10 command data.
513 @param[in,out] DataLength The length of data buffer.
514 @param[in] StartLba The start address of LBA.
515 @param[in] SectorSize The sector size.
517 @retval EFI_SUCCESS The status of the unit is tested successfully.
518 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
519 but the entire DataBuffer could not be transferred.
520 The actual number of bytes transferred is returned
522 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
523 there are too many SCSI Command Packets already
525 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
526 the SCSI Request Packet.
527 @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid, or ScsiIo is NULL.
528 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
529 is not supported by the SCSI initiator(i.e., SCSI
531 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
532 Request Packet to execute.
538 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
541 IN OUT UINT8
*SenseDataLength
,
542 OUT UINT8
*HostAdapterStatus
,
543 OUT UINT8
*TargetStatus
,
544 OUT VOID
*DataBuffer
,
545 IN OUT UINT32
*DataLength
,
550 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
553 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
557 ASSERT (SenseDataLength
!= NULL
);
558 ASSERT (HostAdapterStatus
!= NULL
);
559 ASSERT (TargetStatus
!= NULL
);
560 ASSERT (DataLength
!= NULL
);
562 if (ScsiIo
== NULL
) {
563 return EFI_INVALID_PARAMETER
;
566 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
569 CommandPacket
.Timeout
= Timeout
;
570 CommandPacket
.InDataBuffer
= DataBuffer
;
571 CommandPacket
.SenseData
= SenseData
;
572 CommandPacket
.InTransferLength
= *DataLength
;
573 CommandPacket
.Cdb
= Cdb
;
575 // Fill Cdb for Read (10) Command
577 Target
= &TargetArray
[0];
578 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
580 Cdb
[0] = EFI_SCSI_OP_READ10
;
581 Cdb
[1] = (UINT8
) (Lun
& 0xe0);
582 Cdb
[2] = (UINT8
) (StartLba
>> 24);
583 Cdb
[3] = (UINT8
) (StartLba
>> 16);
584 Cdb
[4] = (UINT8
) (StartLba
>> 8);
585 Cdb
[5] = (UINT8
) (StartLba
& 0xff);
586 Cdb
[7] = (UINT8
) (SectorSize
>> 8);
587 Cdb
[8] = (UINT8
) (SectorSize
& 0xff);
589 CommandPacket
.CdbLength
= 10;
590 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
591 CommandPacket
.SenseDataLength
= *SenseDataLength
;
593 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
595 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
596 *TargetStatus
= CommandPacket
.TargetStatus
;
597 *SenseDataLength
= CommandPacket
.SenseDataLength
;
598 *DataLength
= CommandPacket
.InTransferLength
;
605 Function to submit SCSI write 10 command.
607 @param[in] ScsiIo SCSI IO Protocol to use
608 @param[in] Timeout The length of timeout period.
609 @param[out] SenseData A pointer to output sense data.
610 @param[in out] SenseDataLength On input, the length in bytes of the SenseData buffer. On
611 output, the number of bytes written to the SenseData buffer.
612 @param[out] HostAdapterStatus The status of Host Adapter.
613 @param[out] TargetStatus The status of the target.
614 @param[out] DataBuffer A pointer to a data buffer.
615 @param[in,out] DataLength The length of data buffer.
616 @param[in] StartLba The start address of LBA.
617 @param[in] SectorSize The sector size.
619 @retval EFI_SUCCESS The status of the unit is tested successfully.
620 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
621 but the entire DataBuffer could not be transferred.
622 The actual number of bytes transferred is returned
624 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
625 there are too many SCSI Command Packets already
627 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
628 the SCSI Request Packet.
629 @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid, or ScsiIo is NULL.
630 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
631 is not supported by the SCSI initiator(i.e., SCSI
633 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
634 Request Packet to execute.
640 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
643 IN OUT UINT8
*SenseDataLength
,
644 OUT UINT8
*HostAdapterStatus
,
645 OUT UINT8
*TargetStatus
,
646 OUT VOID
*DataBuffer
,
647 IN OUT UINT32
*DataLength
,
652 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
655 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
659 ASSERT (SenseDataLength
!= NULL
);
660 ASSERT (HostAdapterStatus
!= NULL
);
661 ASSERT (TargetStatus
!= NULL
);
662 ASSERT (DataLength
!= NULL
);
664 if (ScsiIo
== NULL
) {
665 return EFI_INVALID_PARAMETER
;
668 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
671 CommandPacket
.Timeout
= Timeout
;
672 CommandPacket
.OutDataBuffer
= DataBuffer
;
673 CommandPacket
.SenseData
= SenseData
;
674 CommandPacket
.OutTransferLength
= *DataLength
;
675 CommandPacket
.Cdb
= Cdb
;
677 // Fill Cdb for Write (10) Command
679 Target
= &TargetArray
[0];
680 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
682 Cdb
[0] = EFI_SCSI_OP_WRITE10
;
683 Cdb
[1] = (UINT8
) (Lun
& 0xe0);
684 Cdb
[2] = (UINT8
) (StartLba
>> 24);
685 Cdb
[3] = (UINT8
) (StartLba
>> 16);
686 Cdb
[4] = (UINT8
) (StartLba
>> 8);
687 Cdb
[5] = (UINT8
) StartLba
;
688 Cdb
[7] = (UINT8
) (SectorSize
>> 8);
689 Cdb
[8] = (UINT8
) SectorSize
;
691 CommandPacket
.CdbLength
= 10;
692 CommandPacket
.DataDirection
= EFI_SCSI_DATA_OUT
;
693 CommandPacket
.SenseDataLength
= *SenseDataLength
;
695 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
697 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
698 *TargetStatus
= CommandPacket
.TargetStatus
;
699 *SenseDataLength
= CommandPacket
.SenseDataLength
;
700 *DataLength
= CommandPacket
.OutTransferLength
;