3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
23 // The package level header files this module uses
28 // The protocols, PPI and GUID defintions for this module
31 // The Library classes this module consumes
33 #include <Library/ScsiLib.h>
34 #include <Library/BaseMemoryLib.h>
36 #include <IndustryStandard/scsi.h>
39 SubmitTestUnitReadyCommand (
40 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
43 OUT UINT8
*SenseDataLength
,
44 OUT UINT8
*HostAdapterStatus
,
45 OUT UINT8
*TargetStatus
50 Function tests the ready status of SCSI unit.
53 ScsiIo - A pointer to SCSI IO protocol.
54 Timeout - The length of timeout period.
55 SenseData - A pointer to output sense data.
56 SenseDataLength - The length of output sense data.
57 HostAdapterStatus - The status of Host Adapter.
58 TargetStatus - The status of the target.
63 EFI_SUCCESS - The status of the unit is tested successfully.
64 EFI_BAD_BUFFER_SIZE - The SCSI Request Packet was executed,
65 but the entire DataBuffer could not be transferred.
66 The actual number of bytes transferred is returned
68 EFI_NOT_READY - The SCSI Request Packet could not be sent because
69 there are too many SCSI Command Packets already
71 EFI_DEVICE_ERROR - A device error occurred while attempting to send
72 the SCSI Request Packet.
73 EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid.
74 EFI_UNSUPPORTED - The command described by the SCSI Request Packet
75 is not supported by the SCSI initiator(i.e., SCSI
77 EFI_TIMEOUT - A timeout occurred while waiting for the SCSI
78 Request Packet to execute.
82 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
85 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
90 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
93 CommandPacket
.Timeout
= Timeout
;
94 CommandPacket
.InDataBuffer
= NULL
;
95 CommandPacket
.InTransferLength
= 0;
96 CommandPacket
.OutDataBuffer
= NULL
;
97 CommandPacket
.OutTransferLength
= 0;
98 CommandPacket
.SenseData
= SenseData
;
99 CommandPacket
.Cdb
= Cdb
;
101 // Fill Cdb for Test Unit Ready Command
103 Target
= &TargetArray
[0];
104 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
106 Cdb
[0] = EFI_SCSI_OP_TEST_UNIT_READY
;
107 Cdb
[1] = (UINT8
) (Lun
& 0xe0);
108 CommandPacket
.CdbLength
= (UINT8
) 6;
109 CommandPacket
.SenseDataLength
= *SenseDataLength
;
111 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
113 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
114 *TargetStatus
= CommandPacket
.TargetStatus
;
115 *SenseDataLength
= CommandPacket
.SenseDataLength
;
121 SubmitInquiryCommand (
122 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
125 IN OUT UINT8
*SenseDataLength
,
126 OUT UINT8
*HostAdapterStatus
,
127 OUT UINT8
*TargetStatus
,
128 IN OUT VOID
*InquiryDataBuffer
,
129 IN OUT UINT32
*InquiryDataLength
,
130 IN BOOLEAN EnableVitalProductData
135 Function to submit SCSI inquiry command.
138 ScsiIo - A pointer to SCSI IO protocol.
139 Timeout - The length of timeout period.
140 SenseData - A pointer to output sense data.
141 SenseDataLength - The length of output sense data.
142 HostAdapterStatus - The status of Host Adapter.
143 TargetStatus - The status of the target.
144 InquiryDataBuffer - A pointer to inquiry data buffer.
145 InquiryDataLength - The length of inquiry data buffer.
146 EnableVitalProductData - Boolean to enable Vital Product Data.
151 EFI_SUCCESS - The status of the unit is tested successfully.
152 EFI_BAD_BUFFER_SIZE - The SCSI Request Packet was executed,
153 but the entire DataBuffer could not be transferred.
154 The actual number of bytes transferred is returned
156 EFI_NOT_READY - The SCSI Request Packet could not be sent because
157 there are too many SCSI Command Packets already
159 EFI_DEVICE_ERROR - A device error occurred while attempting to send
160 the SCSI Request Packet.
161 EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid.
162 EFI_UNSUPPORTED - The command described by the SCSI Request Packet
163 is not supported by the SCSI initiator(i.e., SCSI
165 EFI_TIMEOUT - A timeout occurred while waiting for the SCSI
166 Request Packet to execute.
170 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
173 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
177 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
180 CommandPacket
.Timeout
= Timeout
;
181 CommandPacket
.InDataBuffer
= InquiryDataBuffer
;
182 CommandPacket
.InTransferLength
= *InquiryDataLength
;
183 CommandPacket
.SenseData
= SenseData
;
184 CommandPacket
.SenseDataLength
= *SenseDataLength
;
185 CommandPacket
.Cdb
= Cdb
;
187 Target
= &TargetArray
[0];
188 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
190 Cdb
[0] = EFI_SCSI_OP_INQUIRY
;
191 Cdb
[1] = (UINT8
) (Lun
& 0xe0);
192 if (EnableVitalProductData
) {
196 if (*InquiryDataLength
> 0xff) {
197 *InquiryDataLength
= 0xff;
200 Cdb
[4] = (UINT8
) (*InquiryDataLength
);
201 CommandPacket
.CdbLength
= (UINT8
) 6;
202 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
204 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
206 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
207 *TargetStatus
= CommandPacket
.TargetStatus
;
208 *SenseDataLength
= CommandPacket
.SenseDataLength
;
209 *InquiryDataLength
= CommandPacket
.InTransferLength
;
215 SubmitModeSense10Command (
216 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
219 IN OUT UINT8
*SenseDataLength
,
220 OUT UINT8
*HostAdapterStatus
,
221 OUT UINT8
*TargetStatus
,
223 IN OUT UINT32
*DataLength
,
224 IN UINT8 DBDField
, OPTIONAL
225 IN UINT8 PageControl
,
231 Function to submit SCSI mode sense 10 command.
234 ScsiIo - A pointer to SCSI IO protocol.
235 Timeout - The length of timeout period.
236 SenseData - A pointer to output sense data.
237 SenseDataLength - The length of output sense data.
238 HostAdapterStatus - The status of Host Adapter.
239 TargetStatus - The status of the target.
240 DataBuffer - A pointer to input data buffer.
241 DataLength - The length of input data buffer.
242 DBDField - The DBD Field (Optional).
243 PageControl - Page Control.
244 PageCode - Page code.
249 EFI_SUCCESS - The status of the unit is tested successfully.
250 EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed,
251 but the entire DataBuffer could not be transferred.
252 The actual number of bytes transferred is returned
254 EFI_NOT_READY - The SCSI Request Packet could not be sent because
255 there are too many SCSI Command Packets already
257 EFI_DEVICE_ERROR - A device error occurred while attempting to send
258 the SCSI Request Packet.
259 EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid.
260 EFI_UNSUPPORTED - The command described by the SCSI Request Packet
261 is not supported by the SCSI initiator(i.e., SCSI
263 EFI_TIMEOUT - A timeout occurred while waiting for the SCSI
264 Request Packet to execute.
268 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
271 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
275 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
278 CommandPacket
.Timeout
= Timeout
;
279 CommandPacket
.InDataBuffer
= DataBuffer
;
280 CommandPacket
.SenseData
= SenseData
;
281 CommandPacket
.InTransferLength
= *DataLength
;
282 CommandPacket
.Cdb
= Cdb
;
284 // Fill Cdb for Mode Sense (10) Command
286 Target
= &TargetArray
[0];
287 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
289 Cdb
[0] = EFI_SCSI_OP_MODE_SEN10
;
290 Cdb
[1] = (UINT8
) (Lun
& 0xe0 + (DBDField
<< 3) & 0x08);
291 Cdb
[2] = (UINT8
) ((PageControl
& 0xc0) | (PageCode
& 0x3f));
292 Cdb
[7] = (UINT8
) (*DataLength
>> 8);
293 Cdb
[8] = (UINT8
) (*DataLength
);
295 CommandPacket
.CdbLength
= 10;
296 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
297 CommandPacket
.SenseDataLength
= *SenseDataLength
;
299 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
301 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
302 *TargetStatus
= CommandPacket
.TargetStatus
;
303 *SenseDataLength
= CommandPacket
.SenseDataLength
;
304 *DataLength
= CommandPacket
.InTransferLength
;
310 SubmitRequestSenseCommand (
311 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
314 IN OUT UINT8
*SenseDataLength
,
315 OUT UINT8
*HostAdapterStatus
,
316 OUT UINT8
*TargetStatus
321 Function to submit SCSI request sense command.
324 ScsiIo - A pointer to SCSI IO protocol.
325 Timeout - The length of timeout period.
326 SenseData - A pointer to output sense data.
327 SenseDataLength - The length of output sense data.
328 HostAdapterStatus - The status of Host Adapter.
329 TargetStatus - The status of the target.
334 EFI_SUCCESS - The status of the unit is tested successfully.
335 EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed,
336 but the entire DataBuffer could not be transferred.
337 The actual number of bytes transferred is returned
339 EFI_NOT_READY - The SCSI Request Packet could not be sent because
340 there are too many SCSI Command Packets already
342 EFI_DEVICE_ERROR - A device error occurred while attempting to send
343 the SCSI Request Packet.
344 EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid.
345 EFI_UNSUPPORTED - The command described by the SCSI Request Packet
346 is not supported by the SCSI initiator(i.e., SCSI
348 EFI_TIMEOUT - A timeout occurred while waiting for the SCSI
349 Request Packet to execute.
353 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
356 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
360 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
363 CommandPacket
.Timeout
= Timeout
;
364 CommandPacket
.InDataBuffer
= SenseData
;
365 CommandPacket
.SenseData
= NULL
;
366 CommandPacket
.InTransferLength
= *SenseDataLength
;
367 CommandPacket
.Cdb
= Cdb
;
369 // Fill Cdb for Request Sense Command
371 Target
= &TargetArray
[0];
372 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
374 Cdb
[0] = EFI_SCSI_OP_REQUEST_SENSE
;
375 Cdb
[1] = (UINT8
) (Lun
& 0xe0);
376 Cdb
[4] = (UINT8
) (*SenseDataLength
);
378 CommandPacket
.CdbLength
= (UINT8
) 6;
379 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
380 CommandPacket
.SenseDataLength
= 0;
382 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
384 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
385 *TargetStatus
= CommandPacket
.TargetStatus
;
386 *SenseDataLength
= (UINT8
) CommandPacket
.InTransferLength
;
392 SubmitReadCapacityCommand (
393 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
396 IN OUT UINT8
*SenseDataLength
,
397 OUT UINT8
*HostAdapterStatus
,
398 OUT UINT8
*TargetStatus
,
399 OUT VOID
*DataBuffer
,
400 IN OUT UINT32
*DataLength
,
406 Function to submit read capacity command.
409 ScsiIo - A pointer to SCSI IO protocol.
410 Timeout - The length of timeout period.
411 SenseData - A pointer to output sense data.
412 SenseDataLength - The length of output sense data.
413 HostAdapterStatus - The status of Host Adapter.
414 TargetStatus - The status of the target.
415 DataBuffer - A pointer to a data buffer.
416 DataLength - The length of data buffer.
417 PMI - Partial medium indicator.
422 EFI_SUCCESS - The status of the unit is tested successfully.
423 EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed,
424 but the entire DataBuffer could not be transferred.
425 The actual number of bytes transferred is returned
427 EFI_NOT_READY - The SCSI Request Packet could not be sent because
428 there are too many SCSI Command Packets already
430 EFI_DEVICE_ERROR - A device error occurred while attempting to send
431 the SCSI Request Packet.
432 EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid.
433 EFI_UNSUPPORTED - The command described by the SCSI Request Packet
434 is not supported by the SCSI initiator(i.e., SCSI
436 EFI_TIMEOUT - A timeout occurred while waiting for the SCSI
437 Request Packet to execute.
441 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
444 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
448 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
451 CommandPacket
.Timeout
= Timeout
;
452 CommandPacket
.InDataBuffer
= DataBuffer
;
453 CommandPacket
.SenseData
= SenseData
;
454 CommandPacket
.InTransferLength
= *DataLength
;
455 CommandPacket
.Cdb
= Cdb
;
457 // Fill Cdb for Read Capacity Command
459 Target
= &TargetArray
[0];
460 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
462 Cdb
[0] = EFI_SCSI_OP_READ_CAPACITY
;
463 Cdb
[1] = (UINT8
) (Lun
& 0xe0);
466 // Partial medium indicator,if PMI is FALSE, the Cdb.2 ~ Cdb.5 MUST BE ZERO.
468 ZeroMem ((Cdb
+ 2), 4);
473 CommandPacket
.CdbLength
= 10;
474 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
475 CommandPacket
.SenseDataLength
= *SenseDataLength
;
477 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
479 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
480 *TargetStatus
= CommandPacket
.TargetStatus
;
481 *SenseDataLength
= CommandPacket
.SenseDataLength
;
482 *DataLength
= CommandPacket
.InTransferLength
;
488 SubmitRead10Command (
489 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
492 IN OUT UINT8
*SenseDataLength
,
493 OUT UINT8
*HostAdapterStatus
,
494 OUT UINT8
*TargetStatus
,
495 OUT VOID
*DataBuffer
,
496 IN OUT UINT32
*DataLength
,
503 Function to submit read 10 command.
506 ScsiIo - A pointer to SCSI IO protocol.
507 Timeout - The length of timeout period.
508 SenseData - A pointer to output sense data.
509 SenseDataLength - The length of output sense data.
510 HostAdapterStatus - The status of Host Adapter.
511 TargetStatus - The status of the target.
512 DataBuffer - A pointer to a data buffer.
513 DataLength - The length of data buffer.
514 StartLba - The start address of LBA.
515 SectorSize - The sector size.
520 EFI_SUCCESS - The status of the unit is tested successfully.
521 EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed,
522 but the entire DataBuffer could not be transferred.
523 The actual number of bytes transferred is returned
525 EFI_NOT_READY - The SCSI Request Packet could not be sent because
526 there are too many SCSI Command Packets already
528 EFI_DEVICE_ERROR - A device error occurred while attempting to send
529 the SCSI Request Packet.
530 EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid.
531 EFI_UNSUPPORTED - The command described by the SCSI Request Packet
532 is not supported by the SCSI initiator(i.e., SCSI
534 EFI_TIMEOUT - A timeout occurred while waiting for the SCSI
535 Request Packet to execute.
539 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
542 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
546 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
549 CommandPacket
.Timeout
= Timeout
;
550 CommandPacket
.InDataBuffer
= DataBuffer
;
551 CommandPacket
.SenseData
= SenseData
;
552 CommandPacket
.InTransferLength
= *DataLength
;
553 CommandPacket
.Cdb
= Cdb
;
555 // Fill Cdb for Read (10) Command
557 Target
= &TargetArray
[0];
558 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
560 Cdb
[0] = EFI_SCSI_OP_READ10
;
561 Cdb
[1] = (UINT8
) (Lun
& 0xe0);
562 Cdb
[2] = (UINT8
) (StartLba
>> 24);
563 Cdb
[3] = (UINT8
) (StartLba
>> 16);
564 Cdb
[4] = (UINT8
) (StartLba
>> 8);
565 Cdb
[5] = (UINT8
) (StartLba
& 0xff);
566 Cdb
[7] = (UINT8
) (SectorSize
>> 8);
567 Cdb
[8] = (UINT8
) (SectorSize
& 0xff);
569 CommandPacket
.CdbLength
= 10;
570 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
571 CommandPacket
.SenseDataLength
= *SenseDataLength
;
573 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
575 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
576 *TargetStatus
= CommandPacket
.TargetStatus
;
577 *SenseDataLength
= CommandPacket
.SenseDataLength
;
578 *DataLength
= CommandPacket
.InTransferLength
;
584 SubmitWrite10Command (
585 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
588 IN OUT UINT8
*SenseDataLength
,
589 OUT UINT8
*HostAdapterStatus
,
590 OUT UINT8
*TargetStatus
,
591 OUT VOID
*DataBuffer
,
592 IN OUT UINT32
*DataLength
,
599 Function to submit SCSI write 10 command.
602 ScsiIo - A pointer to SCSI IO protocol.
603 Timeout - The length of timeout period.
604 SenseData - A pointer to output sense data.
605 SenseDataLength - The length of output sense data.
606 HostAdapterStatus - The status of Host Adapter.
607 TargetStatus - The status of the target.
608 DataBuffer - A pointer to a data buffer.
609 DataLength - The length of data buffer.
610 StartLba - The start address of LBA.
611 SectorSize - The sector size.
616 EFI_SUCCESS - The status of the unit is tested successfully.
617 EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed,
618 but the entire DataBuffer could not be transferred.
619 The actual number of bytes transferred is returned
621 EFI_NOT_READY - The SCSI Request Packet could not be sent because
622 there are too many SCSI Command Packets already
624 EFI_DEVICE_ERROR - A device error occurred while attempting to send
625 the SCSI Request Packet.
626 EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid.
627 EFI_UNSUPPORTED - The command described by the SCSI Request Packet
628 is not supported by the SCSI initiator(i.e., SCSI
630 EFI_TIMEOUT - A timeout occurred while waiting for the SCSI
631 Request Packet to execute.
635 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
638 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
642 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
645 CommandPacket
.Timeout
= Timeout
;
646 CommandPacket
.OutDataBuffer
= DataBuffer
;
647 CommandPacket
.SenseData
= SenseData
;
648 CommandPacket
.OutTransferLength
= *DataLength
;
649 CommandPacket
.Cdb
= Cdb
;
651 // Fill Cdb for Write (10) Command
653 Target
= &TargetArray
[0];
654 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
656 Cdb
[0] = EFI_SCSI_OP_WRITE10
;
657 Cdb
[1] = (UINT8
) (Lun
& 0xe0);
658 Cdb
[2] = (UINT8
) (StartLba
>> 24);
659 Cdb
[3] = (UINT8
) (StartLba
>> 16);
660 Cdb
[4] = (UINT8
) (StartLba
>> 8);
661 Cdb
[5] = (UINT8
) StartLba
;
662 Cdb
[7] = (UINT8
) (SectorSize
>> 8);
663 Cdb
[8] = (UINT8
) SectorSize
;
665 CommandPacket
.CdbLength
= 10;
666 CommandPacket
.DataDirection
= EFI_SCSI_DATA_OUT
;
667 CommandPacket
.SenseDataLength
= *SenseDataLength
;
669 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
671 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
672 *TargetStatus
= CommandPacket
.TargetStatus
;
673 *SenseDataLength
= CommandPacket
.SenseDataLength
;
674 *DataLength
= CommandPacket
.InTransferLength
;