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.
55 ScsiTestUnitReadyCommand (
56 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
58 IN OUT VOID
*SenseData
,
59 IN OUT UINT8
*SenseDataLength
,
60 OUT UINT8
*HostAdapterStatus
,
61 OUT UINT8
*TargetStatus
64 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
67 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
71 ASSERT (SenseDataLength
!= NULL
);
72 ASSERT (HostAdapterStatus
!= NULL
);
73 ASSERT (TargetStatus
!= NULL
);
76 return EFI_INVALID_PARAMETER
;
79 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
82 CommandPacket
.Timeout
= Timeout
;
83 CommandPacket
.InDataBuffer
= NULL
;
84 CommandPacket
.InTransferLength
= 0;
85 CommandPacket
.OutDataBuffer
= NULL
;
86 CommandPacket
.OutTransferLength
= 0;
87 CommandPacket
.SenseData
= SenseData
;
88 CommandPacket
.Cdb
= Cdb
;
90 // Fill Cdb for Test Unit Ready Command
92 Target
= &TargetArray
[0];
93 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
95 Cdb
[0] = EFI_SCSI_OP_TEST_UNIT_READY
;
96 Cdb
[1] = (UINT8
) (Lun
& 0xe0);
97 CommandPacket
.CdbLength
= (UINT8
) 6;
98 CommandPacket
.SenseDataLength
= *SenseDataLength
;
100 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
102 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
103 *TargetStatus
= CommandPacket
.TargetStatus
;
104 *SenseDataLength
= CommandPacket
.SenseDataLength
;
111 Function to submit SCSI inquiry command.
113 @param[in] ScsiIo SCSI IO Protocol to use
114 @param[in] Timeout The length of timeout period.
115 @param[out] SenseData A pointer to output sense data.
116 @param[in out] SenseDataLength On input, the length in bytes of the SenseData buffer. On
117 output, the number of bytes written to the SenseData buffer.
118 @param[out] HostAdapterStatus The status of Host Adapter.
119 @param[out] TargetStatus The status of the target.
120 @param[in] InquirydataBuffer A pointer to inquiry data buffer.
121 @param[in,out] InquiryDataLength The length of inquiry data buffer.
122 @param[in] EnableVitalProductData Boolean to enable Vital Product Data.
124 @retval EFI_SUCCESS The status of the unit is tested successfully.
125 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
126 but the entire DataBuffer could not be transferred.
127 The actual number of bytes transferred is returned
129 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
130 there are too many SCSI Command Packets already
132 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
133 the SCSI Request Packet.
134 @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid, or ScsiIo is NULL.
135 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
136 is not supported by the SCSI initiator(i.e., SCSI
138 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
139 Request Packet to execute.
144 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
147 IN OUT UINT8
*SenseDataLength
,
148 OUT UINT8
*HostAdapterStatus
,
149 OUT UINT8
*TargetStatus
,
150 IN VOID
*InquiryDataBuffer
,
151 IN OUT UINT32
*InquiryDataLength
,
152 IN BOOLEAN EnableVitalProductData
155 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
158 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
162 ASSERT (SenseDataLength
!= NULL
);
163 ASSERT (HostAdapterStatus
!= NULL
);
164 ASSERT (TargetStatus
!= NULL
);
165 ASSERT (InquiryDataLength
!= NULL
);
167 if (ScsiIo
== NULL
) {
168 return EFI_INVALID_PARAMETER
;
171 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
174 CommandPacket
.Timeout
= Timeout
;
175 CommandPacket
.InDataBuffer
= InquiryDataBuffer
;
176 CommandPacket
.InTransferLength
= *InquiryDataLength
;
177 CommandPacket
.SenseData
= SenseData
;
178 CommandPacket
.SenseDataLength
= *SenseDataLength
;
179 CommandPacket
.Cdb
= Cdb
;
181 Target
= &TargetArray
[0];
182 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
184 Cdb
[0] = EFI_SCSI_OP_INQUIRY
;
185 Cdb
[1] = (UINT8
) (Lun
& 0xe0);
186 if (EnableVitalProductData
) {
190 if (*InquiryDataLength
> 0xff) {
191 *InquiryDataLength
= 0xff;
194 Cdb
[4] = (UINT8
) (*InquiryDataLength
);
195 CommandPacket
.CdbLength
= (UINT8
) 6;
196 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
198 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
200 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
201 *TargetStatus
= CommandPacket
.TargetStatus
;
202 *SenseDataLength
= CommandPacket
.SenseDataLength
;
203 *InquiryDataLength
= CommandPacket
.InTransferLength
;
210 Function to submit SCSI mode sense 10 command.
212 @param[in] ScsiIo A pointer to SCSI IO protocol.
213 @param[in] Timeout The length of timeout period.
214 @param[out] SenseData A pointer to output sense data.
215 @param[in out] SenseDataLength On input, the length in bytes of the SenseData buffer. On
216 output, the number of bytes written to the SenseData buffer.
217 @param[out] HostAdapterStatus The status of Host Adapter.
218 @param[out] TargetStatus The status of the target.
219 @param[in] DataBuffer A pointer to input data buffer.
220 @param[in,out] DataLength The length of input data buffer.
221 @param[in] DBDField The DBD Field (Optional).
222 @param[in] PageControl Page Control.
223 @param[in] PageCode Page code.
225 @retval EFI_SUCCESS The status of the unit is tested successfully.
226 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
227 but the entire DataBuffer could not be transferred.
228 The actual number of bytes transferred is returned
230 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
231 there are too many SCSI Command Packets already
233 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
234 the SCSI Request Packet.
235 @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid, or ScsiIo is NULL.
236 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
237 is not supported by the SCSI initiator(i.e., SCSI
239 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
240 Request Packet to execute.
244 ScsiModeSense10Command (
245 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
248 IN OUT UINT8
*SenseDataLength
,
249 OUT UINT8
*HostAdapterStatus
,
250 OUT UINT8
*TargetStatus
,
252 IN OUT UINT32
*DataLength
,
253 IN UINT8 DBDField
, OPTIONAL
254 IN UINT8 PageControl
,
258 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
261 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
265 ASSERT (SenseDataLength
!= NULL
);
266 ASSERT (HostAdapterStatus
!= NULL
);
267 ASSERT (TargetStatus
!= NULL
);
268 ASSERT (DataLength
!= NULL
);
270 if (ScsiIo
== NULL
) {
271 return EFI_INVALID_PARAMETER
;
274 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
277 CommandPacket
.Timeout
= Timeout
;
278 CommandPacket
.InDataBuffer
= DataBuffer
;
279 CommandPacket
.SenseData
= SenseData
;
280 CommandPacket
.InTransferLength
= *DataLength
;
281 CommandPacket
.Cdb
= Cdb
;
283 // Fill Cdb for Mode Sense (10) Command
285 Target
= &TargetArray
[0];
286 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
288 Cdb
[0] = EFI_SCSI_OP_MODE_SEN10
;
289 Cdb
[1] = (UINT8
) ((Lun
& 0xe0) + ((DBDField
<< 3) & 0x08));
290 Cdb
[2] = (UINT8
) ((PageControl
& 0xc0) | (PageCode
& 0x3f));
291 Cdb
[7] = (UINT8
) (*DataLength
>> 8);
292 Cdb
[8] = (UINT8
) (*DataLength
);
294 CommandPacket
.CdbLength
= 10;
295 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
296 CommandPacket
.SenseDataLength
= *SenseDataLength
;
298 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
300 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
301 *TargetStatus
= CommandPacket
.TargetStatus
;
302 *SenseDataLength
= CommandPacket
.SenseDataLength
;
303 *DataLength
= CommandPacket
.InTransferLength
;
310 Function to submit SCSI request sense command.
312 @param[in] ScsiIo A pointer to SCSI IO protocol.
313 @param[in] Timeout The length of timeout period.
314 @param[in] SenseData A pointer to output sense data.
315 @param[in out] SenseDataLength On input, the length in bytes of the SenseData buffer. On
316 output, the number of bytes written to the SenseData buffer.
317 @param[out] HostAdapterStatus The status of Host Adapter.
318 @param[out] TargetStatus The status of the target.
320 @retval EFI_SUCCESS Valid data returned
321 @retval EFI_SUCCESS The status of the unit is tested successfully.
322 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
323 but the entire DataBuffer could not be transferred.
324 The actual number of bytes transferred is returned
326 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
327 there are too many SCSI Command Packets already
329 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
330 the SCSI Request Packet.
331 @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid, or ScsiIo is NULL.
332 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
333 is not supported by the SCSI initiator(i.e., SCSI
335 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
336 Request Packet to execute.
340 ScsiRequestSenseCommand (
341 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
344 IN OUT UINT8
*SenseDataLength
,
345 OUT UINT8
*HostAdapterStatus
,
346 OUT UINT8
*TargetStatus
349 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
352 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
356 ASSERT (SenseDataLength
!= NULL
);
357 ASSERT (HostAdapterStatus
!= NULL
);
358 ASSERT (TargetStatus
!= NULL
);
360 if (ScsiIo
== NULL
) {
361 return EFI_INVALID_PARAMETER
;
364 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
367 CommandPacket
.Timeout
= Timeout
;
368 CommandPacket
.InDataBuffer
= SenseData
;
369 CommandPacket
.SenseData
= NULL
;
370 CommandPacket
.InTransferLength
= *SenseDataLength
;
371 CommandPacket
.Cdb
= Cdb
;
373 // Fill Cdb for Request Sense Command
375 Target
= &TargetArray
[0];
376 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
378 Cdb
[0] = EFI_SCSI_OP_REQUEST_SENSE
;
379 Cdb
[1] = (UINT8
) (Lun
& 0xe0);
380 Cdb
[4] = (UINT8
) (*SenseDataLength
);
382 CommandPacket
.CdbLength
= (UINT8
) 6;
383 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
384 CommandPacket
.SenseDataLength
= 0;
386 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
388 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
389 *TargetStatus
= CommandPacket
.TargetStatus
;
390 *SenseDataLength
= (UINT8
) CommandPacket
.InTransferLength
;
397 Function to submit read capacity command.
399 @param[in] ScsiIo A pointer to SCSI IO protocol.
400 @param[in] Timeout The length of timeout period.
401 @param[out] SenseData A pointer to output sense data.
402 @param[in out] SenseDataLength On input, the length in bytes of the SenseData buffer. On
403 output, the number of bytes written to the SenseData buffer.
404 @param[out] HostAdapterStatus The status of Host Adapter.
405 @param[out] TargetStatus The status of the target.
406 @param[out] DataBuffer A pointer to a data buffer.
407 @param[in,out] DataLength The length of data buffer.
408 @param[in] PMI Partial medium indicator.
410 @retval EFI_SUCCESS The status of the unit is tested successfully.
411 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
412 but the entire DataBuffer could not be transferred.
413 The actual number of bytes transferred is returned
415 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
416 there are too many SCSI Command Packets already
418 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
419 the SCSI Request Packet.
420 @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid, or ScsiIo is NULL.
421 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
422 is not supported by the SCSI initiator(i.e., SCSI
424 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
425 Request Packet to execute.
429 ScsiReadCapacityCommand (
430 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
433 IN OUT UINT8
*SenseDataLength
,
434 OUT UINT8
*HostAdapterStatus
,
435 OUT UINT8
*TargetStatus
,
436 OUT VOID
*DataBuffer
,
437 IN OUT UINT32
*DataLength
,
441 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
444 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
448 ASSERT (SenseDataLength
!= NULL
);
449 ASSERT (HostAdapterStatus
!= NULL
);
450 ASSERT (TargetStatus
!= NULL
);
451 ASSERT (DataLength
!= NULL
);
453 if (ScsiIo
== NULL
) {
454 return EFI_INVALID_PARAMETER
;
457 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
460 CommandPacket
.Timeout
= Timeout
;
461 CommandPacket
.InDataBuffer
= DataBuffer
;
462 CommandPacket
.SenseData
= SenseData
;
463 CommandPacket
.InTransferLength
= *DataLength
;
464 CommandPacket
.Cdb
= Cdb
;
466 // Fill Cdb for Read Capacity Command
468 Target
= &TargetArray
[0];
469 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
471 Cdb
[0] = EFI_SCSI_OP_READ_CAPACITY
;
472 Cdb
[1] = (UINT8
) (Lun
& 0xe0);
475 // Partial medium indicator,if PMI is FALSE, the Cdb.2 ~ Cdb.5 MUST BE ZERO.
477 ZeroMem ((Cdb
+ 2), 4);
482 CommandPacket
.CdbLength
= 10;
483 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
484 CommandPacket
.SenseDataLength
= *SenseDataLength
;
486 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
488 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
489 *TargetStatus
= CommandPacket
.TargetStatus
;
490 *SenseDataLength
= CommandPacket
.SenseDataLength
;
491 *DataLength
= CommandPacket
.InTransferLength
;
498 Function to submit read 10 command.
500 @param[in] ScsiIo A pointer to SCSI IO protocol.
501 @param[in] Timeout The length of timeout period.
502 @param[out] SenseData A pointer to output sense data.
503 @param[in out] SenseDataLength On input, the length in bytes of the SenseData buffer. On
504 output, the number of bytes written to the SenseData buffer.
505 @param[out] HostAdapterStatus The status of Host Adapter.
506 @param[out] TargetStatus The status of the target.
507 @param[out] DataBuffer Read 10 command data.
508 @param[in,out] DataLength The length of data buffer.
509 @param[in] StartLba The start address of LBA.
510 @param[in] SectorSize The sector size.
512 @retval EFI_SUCCESS The status of the unit is tested successfully.
513 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
514 but the entire DataBuffer could not be transferred.
515 The actual number of bytes transferred is returned
517 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
518 there are too many SCSI Command Packets already
520 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
521 the SCSI Request Packet.
522 @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid, or ScsiIo is NULL.
523 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
524 is not supported by the SCSI initiator(i.e., SCSI
526 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
527 Request Packet to execute.
532 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
535 IN OUT UINT8
*SenseDataLength
,
536 OUT UINT8
*HostAdapterStatus
,
537 OUT UINT8
*TargetStatus
,
538 OUT VOID
*DataBuffer
,
539 IN OUT UINT32
*DataLength
,
544 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
547 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
551 ASSERT (SenseDataLength
!= NULL
);
552 ASSERT (HostAdapterStatus
!= NULL
);
553 ASSERT (TargetStatus
!= NULL
);
554 ASSERT (DataLength
!= NULL
);
556 if (ScsiIo
== NULL
) {
557 return EFI_INVALID_PARAMETER
;
560 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
563 CommandPacket
.Timeout
= Timeout
;
564 CommandPacket
.InDataBuffer
= DataBuffer
;
565 CommandPacket
.SenseData
= SenseData
;
566 CommandPacket
.InTransferLength
= *DataLength
;
567 CommandPacket
.Cdb
= Cdb
;
569 // Fill Cdb for Read (10) Command
571 Target
= &TargetArray
[0];
572 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
574 Cdb
[0] = EFI_SCSI_OP_READ10
;
575 Cdb
[1] = (UINT8
) (Lun
& 0xe0);
576 Cdb
[2] = (UINT8
) (StartLba
>> 24);
577 Cdb
[3] = (UINT8
) (StartLba
>> 16);
578 Cdb
[4] = (UINT8
) (StartLba
>> 8);
579 Cdb
[5] = (UINT8
) (StartLba
& 0xff);
580 Cdb
[7] = (UINT8
) (SectorSize
>> 8);
581 Cdb
[8] = (UINT8
) (SectorSize
& 0xff);
583 CommandPacket
.CdbLength
= 10;
584 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
585 CommandPacket
.SenseDataLength
= *SenseDataLength
;
587 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
589 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
590 *TargetStatus
= CommandPacket
.TargetStatus
;
591 *SenseDataLength
= CommandPacket
.SenseDataLength
;
592 *DataLength
= CommandPacket
.InTransferLength
;
599 Function to submit SCSI write 10 command.
601 @param[in] ScsiIo SCSI IO Protocol to use
602 @param[in] Timeout The length of timeout period.
603 @param[out] SenseData A pointer to output sense data.
604 @param[in out] SenseDataLength On input, the length in bytes of the SenseData buffer. On
605 output, the number of bytes written to the SenseData buffer.
606 @param[out] HostAdapterStatus The status of Host Adapter.
607 @param[out] TargetStatus The status of the target.
608 @param[out] DataBuffer A pointer to a data buffer.
609 @param[in,out] DataLength The length of data buffer.
610 @param[in] StartLba The start address of LBA.
611 @param[in] SectorSize The sector size.
613 @retval EFI_SUCCESS The status of the unit is tested successfully.
614 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
615 but the entire DataBuffer could not be transferred.
616 The actual number of bytes transferred is returned
618 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
619 there are too many SCSI Command Packets already
621 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
622 the SCSI Request Packet.
623 @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid, or ScsiIo is NULL.
624 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
625 is not supported by the SCSI initiator(i.e., SCSI
627 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
628 Request Packet to execute.
633 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
636 IN OUT UINT8
*SenseDataLength
,
637 OUT UINT8
*HostAdapterStatus
,
638 OUT UINT8
*TargetStatus
,
639 OUT VOID
*DataBuffer
,
640 IN OUT UINT32
*DataLength
,
645 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
648 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
652 ASSERT (SenseDataLength
!= NULL
);
653 ASSERT (HostAdapterStatus
!= NULL
);
654 ASSERT (TargetStatus
!= NULL
);
655 ASSERT (DataLength
!= NULL
);
657 if (ScsiIo
== NULL
) {
658 return EFI_INVALID_PARAMETER
;
661 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
664 CommandPacket
.Timeout
= Timeout
;
665 CommandPacket
.OutDataBuffer
= DataBuffer
;
666 CommandPacket
.SenseData
= SenseData
;
667 CommandPacket
.OutTransferLength
= *DataLength
;
668 CommandPacket
.Cdb
= Cdb
;
670 // Fill Cdb for Write (10) Command
672 Target
= &TargetArray
[0];
673 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
675 Cdb
[0] = EFI_SCSI_OP_WRITE10
;
676 Cdb
[1] = (UINT8
) (Lun
& 0xe0);
677 Cdb
[2] = (UINT8
) (StartLba
>> 24);
678 Cdb
[3] = (UINT8
) (StartLba
>> 16);
679 Cdb
[4] = (UINT8
) (StartLba
>> 8);
680 Cdb
[5] = (UINT8
) StartLba
;
681 Cdb
[7] = (UINT8
) (SectorSize
>> 8);
682 Cdb
[8] = (UINT8
) SectorSize
;
684 CommandPacket
.CdbLength
= 10;
685 CommandPacket
.DataDirection
= EFI_SCSI_DATA_OUT
;
686 CommandPacket
.SenseDataLength
= *SenseDataLength
;
688 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
690 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
691 *TargetStatus
= CommandPacket
.TargetStatus
;
692 *SenseDataLength
= CommandPacket
.SenseDataLength
;
693 *DataLength
= CommandPacket
.OutTransferLength
;