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.
15 // The package level header files this module uses
20 // The protocols, PPI and GUID defintions for this module
23 // The Library classes this module consumes
25 #include <Library/ScsiLib.h>
26 #include <Library/BaseMemoryLib.h>
28 #include <IndustryStandard/scsi.h>
31 SubmitTestUnitReadyCommand (
32 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
35 OUT UINT8
*SenseDataLength
,
36 OUT UINT8
*HostAdapterStatus
,
37 OUT UINT8
*TargetStatus
42 Function tests the ready status of SCSI unit.
45 ScsiIo - A pointer to SCSI IO protocol.
46 Timeout - The length of timeout period.
47 SenseData - A pointer to output sense data.
48 SenseDataLength - The length of output sense data.
49 HostAdapterStatus - The status of Host Adapter.
50 TargetStatus - The status of the target.
55 EFI_SUCCESS - The status of the unit is tested successfully.
56 EFI_BAD_BUFFER_SIZE - The SCSI Request Packet was executed,
57 but the entire DataBuffer could not be transferred.
58 The actual number of bytes transferred is returned
60 EFI_NOT_READY - The SCSI Request Packet could not be sent because
61 there are too many SCSI Command Packets already
63 EFI_DEVICE_ERROR - A device error occurred while attempting to send
64 the SCSI Request Packet.
65 EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid.
66 EFI_UNSUPPORTED - The command described by the SCSI Request Packet
67 is not supported by the SCSI initiator(i.e., SCSI
69 EFI_TIMEOUT - A timeout occurred while waiting for the SCSI
70 Request Packet to execute.
74 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
77 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
82 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
85 CommandPacket
.Timeout
= Timeout
;
86 CommandPacket
.InDataBuffer
= NULL
;
87 CommandPacket
.InTransferLength
= 0;
88 CommandPacket
.OutDataBuffer
= NULL
;
89 CommandPacket
.OutTransferLength
= 0;
90 CommandPacket
.SenseData
= SenseData
;
91 CommandPacket
.Cdb
= Cdb
;
93 // Fill Cdb for Test Unit Ready Command
95 Target
= &TargetArray
[0];
96 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
98 Cdb
[0] = EFI_SCSI_OP_TEST_UNIT_READY
;
99 Cdb
[1] = (UINT8
) (Lun
& 0xe0);
100 CommandPacket
.CdbLength
= (UINT8
) 6;
101 CommandPacket
.SenseDataLength
= *SenseDataLength
;
103 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
105 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
106 *TargetStatus
= CommandPacket
.TargetStatus
;
107 *SenseDataLength
= CommandPacket
.SenseDataLength
;
113 SubmitInquiryCommand (
114 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
117 IN OUT UINT8
*SenseDataLength
,
118 OUT UINT8
*HostAdapterStatus
,
119 OUT UINT8
*TargetStatus
,
120 IN OUT VOID
*InquiryDataBuffer
,
121 IN OUT UINT32
*InquiryDataLength
,
122 IN BOOLEAN EnableVitalProductData
127 Function to submit SCSI inquiry command.
130 ScsiIo - A pointer to SCSI IO protocol.
131 Timeout - The length of timeout period.
132 SenseData - A pointer to output sense data.
133 SenseDataLength - The length of output sense data.
134 HostAdapterStatus - The status of Host Adapter.
135 TargetStatus - The status of the target.
136 InquiryDataBuffer - A pointer to inquiry data buffer.
137 InquiryDataLength - The length of inquiry data buffer.
138 EnableVitalProductData - Boolean to enable Vital Product Data.
143 EFI_SUCCESS - The status of the unit is tested successfully.
144 EFI_BAD_BUFFER_SIZE - The SCSI Request Packet was executed,
145 but the entire DataBuffer could not be transferred.
146 The actual number of bytes transferred is returned
148 EFI_NOT_READY - The SCSI Request Packet could not be sent because
149 there are too many SCSI Command Packets already
151 EFI_DEVICE_ERROR - A device error occurred while attempting to send
152 the SCSI Request Packet.
153 EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid.
154 EFI_UNSUPPORTED - The command described by the SCSI Request Packet
155 is not supported by the SCSI initiator(i.e., SCSI
157 EFI_TIMEOUT - A timeout occurred while waiting for the SCSI
158 Request Packet to execute.
162 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
165 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
169 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
172 CommandPacket
.Timeout
= Timeout
;
173 CommandPacket
.InDataBuffer
= InquiryDataBuffer
;
174 CommandPacket
.InTransferLength
= *InquiryDataLength
;
175 CommandPacket
.SenseData
= SenseData
;
176 CommandPacket
.SenseDataLength
= *SenseDataLength
;
177 CommandPacket
.Cdb
= Cdb
;
179 Target
= &TargetArray
[0];
180 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
182 Cdb
[0] = EFI_SCSI_OP_INQUIRY
;
183 Cdb
[1] = (UINT8
) (Lun
& 0xe0);
184 if (EnableVitalProductData
) {
188 if (*InquiryDataLength
> 0xff) {
189 *InquiryDataLength
= 0xff;
192 Cdb
[4] = (UINT8
) (*InquiryDataLength
);
193 CommandPacket
.CdbLength
= (UINT8
) 6;
194 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
196 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
198 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
199 *TargetStatus
= CommandPacket
.TargetStatus
;
200 *SenseDataLength
= CommandPacket
.SenseDataLength
;
201 *InquiryDataLength
= CommandPacket
.InTransferLength
;
207 SubmitModeSense10Command (
208 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
211 IN OUT UINT8
*SenseDataLength
,
212 OUT UINT8
*HostAdapterStatus
,
213 OUT UINT8
*TargetStatus
,
215 IN OUT UINT32
*DataLength
,
216 IN UINT8 DBDField
, OPTIONAL
217 IN UINT8 PageControl
,
223 Function to submit SCSI mode sense 10 command.
226 ScsiIo - A pointer to SCSI IO protocol.
227 Timeout - The length of timeout period.
228 SenseData - A pointer to output sense data.
229 SenseDataLength - The length of output sense data.
230 HostAdapterStatus - The status of Host Adapter.
231 TargetStatus - The status of the target.
232 DataBuffer - A pointer to input data buffer.
233 DataLength - The length of input data buffer.
234 DBDField - The DBD Field (Optional).
235 PageControl - Page Control.
236 PageCode - Page code.
241 EFI_SUCCESS - The status of the unit is tested successfully.
242 EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed,
243 but the entire DataBuffer could not be transferred.
244 The actual number of bytes transferred is returned
246 EFI_NOT_READY - The SCSI Request Packet could not be sent because
247 there are too many SCSI Command Packets already
249 EFI_DEVICE_ERROR - A device error occurred while attempting to send
250 the SCSI Request Packet.
251 EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid.
252 EFI_UNSUPPORTED - The command described by the SCSI Request Packet
253 is not supported by the SCSI initiator(i.e., SCSI
255 EFI_TIMEOUT - A timeout occurred while waiting for the SCSI
256 Request Packet to execute.
260 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
263 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
267 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
270 CommandPacket
.Timeout
= Timeout
;
271 CommandPacket
.InDataBuffer
= DataBuffer
;
272 CommandPacket
.SenseData
= SenseData
;
273 CommandPacket
.InTransferLength
= *DataLength
;
274 CommandPacket
.Cdb
= Cdb
;
276 // Fill Cdb for Mode Sense (10) Command
278 Target
= &TargetArray
[0];
279 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
281 Cdb
[0] = EFI_SCSI_OP_MODE_SEN10
;
282 Cdb
[1] = (UINT8
) (Lun
& 0xe0 + (DBDField
<< 3) & 0x08);
283 Cdb
[2] = (UINT8
) ((PageControl
& 0xc0) | (PageCode
& 0x3f));
284 Cdb
[7] = (UINT8
) (*DataLength
>> 8);
285 Cdb
[8] = (UINT8
) (*DataLength
);
287 CommandPacket
.CdbLength
= 10;
288 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
289 CommandPacket
.SenseDataLength
= *SenseDataLength
;
291 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
293 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
294 *TargetStatus
= CommandPacket
.TargetStatus
;
295 *SenseDataLength
= CommandPacket
.SenseDataLength
;
296 *DataLength
= CommandPacket
.InTransferLength
;
302 SubmitRequestSenseCommand (
303 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
306 IN OUT UINT8
*SenseDataLength
,
307 OUT UINT8
*HostAdapterStatus
,
308 OUT UINT8
*TargetStatus
313 Function to submit SCSI request sense command.
316 ScsiIo - A pointer to SCSI IO protocol.
317 Timeout - The length of timeout period.
318 SenseData - A pointer to output sense data.
319 SenseDataLength - The length of output sense data.
320 HostAdapterStatus - The status of Host Adapter.
321 TargetStatus - The status of the target.
326 EFI_SUCCESS - The status of the unit is tested successfully.
327 EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed,
328 but the entire DataBuffer could not be transferred.
329 The actual number of bytes transferred is returned
331 EFI_NOT_READY - The SCSI Request Packet could not be sent because
332 there are too many SCSI Command Packets already
334 EFI_DEVICE_ERROR - A device error occurred while attempting to send
335 the SCSI Request Packet.
336 EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid.
337 EFI_UNSUPPORTED - The command described by the SCSI Request Packet
338 is not supported by the SCSI initiator(i.e., SCSI
340 EFI_TIMEOUT - A timeout occurred while waiting for the SCSI
341 Request Packet to execute.
345 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
348 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
352 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
355 CommandPacket
.Timeout
= Timeout
;
356 CommandPacket
.InDataBuffer
= SenseData
;
357 CommandPacket
.SenseData
= NULL
;
358 CommandPacket
.InTransferLength
= *SenseDataLength
;
359 CommandPacket
.Cdb
= Cdb
;
361 // Fill Cdb for Request Sense Command
363 Target
= &TargetArray
[0];
364 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
366 Cdb
[0] = EFI_SCSI_OP_REQUEST_SENSE
;
367 Cdb
[1] = (UINT8
) (Lun
& 0xe0);
368 Cdb
[4] = (UINT8
) (*SenseDataLength
);
370 CommandPacket
.CdbLength
= (UINT8
) 6;
371 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
372 CommandPacket
.SenseDataLength
= 0;
374 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
376 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
377 *TargetStatus
= CommandPacket
.TargetStatus
;
378 *SenseDataLength
= (UINT8
) CommandPacket
.InTransferLength
;
384 SubmitReadCapacityCommand (
385 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
388 IN OUT UINT8
*SenseDataLength
,
389 OUT UINT8
*HostAdapterStatus
,
390 OUT UINT8
*TargetStatus
,
391 OUT VOID
*DataBuffer
,
392 IN OUT UINT32
*DataLength
,
398 Function to submit read capacity command.
401 ScsiIo - A pointer to SCSI IO protocol.
402 Timeout - The length of timeout period.
403 SenseData - A pointer to output sense data.
404 SenseDataLength - The length of output sense data.
405 HostAdapterStatus - The status of Host Adapter.
406 TargetStatus - The status of the target.
407 DataBuffer - A pointer to a data buffer.
408 DataLength - The length of data buffer.
409 PMI - Partial medium indicator.
414 EFI_SUCCESS - The status of the unit is tested successfully.
415 EFI_WARN_BUFFER_TOO_SMALL - 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 EFI_NOT_READY - The SCSI Request Packet could not be sent because
420 there are too many SCSI Command Packets already
422 EFI_DEVICE_ERROR - A device error occurred while attempting to send
423 the SCSI Request Packet.
424 EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid.
425 EFI_UNSUPPORTED - The command described by the SCSI Request Packet
426 is not supported by the SCSI initiator(i.e., SCSI
428 EFI_TIMEOUT - A timeout occurred while waiting for the SCSI
429 Request Packet to execute.
433 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
436 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
440 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
443 CommandPacket
.Timeout
= Timeout
;
444 CommandPacket
.InDataBuffer
= DataBuffer
;
445 CommandPacket
.SenseData
= SenseData
;
446 CommandPacket
.InTransferLength
= *DataLength
;
447 CommandPacket
.Cdb
= Cdb
;
449 // Fill Cdb for Read Capacity Command
451 Target
= &TargetArray
[0];
452 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
454 Cdb
[0] = EFI_SCSI_OP_READ_CAPACITY
;
455 Cdb
[1] = (UINT8
) (Lun
& 0xe0);
458 // Partial medium indicator,if PMI is FALSE, the Cdb.2 ~ Cdb.5 MUST BE ZERO.
460 ZeroMem ((Cdb
+ 2), 4);
465 CommandPacket
.CdbLength
= 10;
466 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
467 CommandPacket
.SenseDataLength
= *SenseDataLength
;
469 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
471 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
472 *TargetStatus
= CommandPacket
.TargetStatus
;
473 *SenseDataLength
= CommandPacket
.SenseDataLength
;
474 *DataLength
= CommandPacket
.InTransferLength
;
480 SubmitRead10Command (
481 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
484 IN OUT UINT8
*SenseDataLength
,
485 OUT UINT8
*HostAdapterStatus
,
486 OUT UINT8
*TargetStatus
,
487 OUT VOID
*DataBuffer
,
488 IN OUT UINT32
*DataLength
,
495 Function to submit read 10 command.
498 ScsiIo - A pointer to SCSI IO protocol.
499 Timeout - The length of timeout period.
500 SenseData - A pointer to output sense data.
501 SenseDataLength - The length of output sense data.
502 HostAdapterStatus - The status of Host Adapter.
503 TargetStatus - The status of the target.
504 DataBuffer - A pointer to a data buffer.
505 DataLength - The length of data buffer.
506 StartLba - The start address of LBA.
507 SectorSize - The sector size.
512 EFI_SUCCESS - The status of the unit is tested successfully.
513 EFI_WARN_BUFFER_TOO_SMALL - 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 EFI_NOT_READY - The SCSI Request Packet could not be sent because
518 there are too many SCSI Command Packets already
520 EFI_DEVICE_ERROR - A device error occurred while attempting to send
521 the SCSI Request Packet.
522 EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid.
523 EFI_UNSUPPORTED - The command described by the SCSI Request Packet
524 is not supported by the SCSI initiator(i.e., SCSI
526 EFI_TIMEOUT - A timeout occurred while waiting for the SCSI
527 Request Packet to execute.
531 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
534 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
538 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
541 CommandPacket
.Timeout
= Timeout
;
542 CommandPacket
.InDataBuffer
= DataBuffer
;
543 CommandPacket
.SenseData
= SenseData
;
544 CommandPacket
.InTransferLength
= *DataLength
;
545 CommandPacket
.Cdb
= Cdb
;
547 // Fill Cdb for Read (10) Command
549 Target
= &TargetArray
[0];
550 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
552 Cdb
[0] = EFI_SCSI_OP_READ10
;
553 Cdb
[1] = (UINT8
) (Lun
& 0xe0);
554 Cdb
[2] = (UINT8
) (StartLba
>> 24);
555 Cdb
[3] = (UINT8
) (StartLba
>> 16);
556 Cdb
[4] = (UINT8
) (StartLba
>> 8);
557 Cdb
[5] = (UINT8
) (StartLba
& 0xff);
558 Cdb
[7] = (UINT8
) (SectorSize
>> 8);
559 Cdb
[8] = (UINT8
) (SectorSize
& 0xff);
561 CommandPacket
.CdbLength
= 10;
562 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
563 CommandPacket
.SenseDataLength
= *SenseDataLength
;
565 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
567 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
568 *TargetStatus
= CommandPacket
.TargetStatus
;
569 *SenseDataLength
= CommandPacket
.SenseDataLength
;
570 *DataLength
= CommandPacket
.InTransferLength
;
576 SubmitWrite10Command (
577 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
580 IN OUT UINT8
*SenseDataLength
,
581 OUT UINT8
*HostAdapterStatus
,
582 OUT UINT8
*TargetStatus
,
583 OUT VOID
*DataBuffer
,
584 IN OUT UINT32
*DataLength
,
591 Function to submit SCSI write 10 command.
594 ScsiIo - A pointer to SCSI IO protocol.
595 Timeout - The length of timeout period.
596 SenseData - A pointer to output sense data.
597 SenseDataLength - The length of output sense data.
598 HostAdapterStatus - The status of Host Adapter.
599 TargetStatus - The status of the target.
600 DataBuffer - A pointer to a data buffer.
601 DataLength - The length of data buffer.
602 StartLba - The start address of LBA.
603 SectorSize - The sector size.
608 EFI_SUCCESS - The status of the unit is tested successfully.
609 EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed,
610 but the entire DataBuffer could not be transferred.
611 The actual number of bytes transferred is returned
613 EFI_NOT_READY - The SCSI Request Packet could not be sent because
614 there are too many SCSI Command Packets already
616 EFI_DEVICE_ERROR - A device error occurred while attempting to send
617 the SCSI Request Packet.
618 EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid.
619 EFI_UNSUPPORTED - The command described by the SCSI Request Packet
620 is not supported by the SCSI initiator(i.e., SCSI
622 EFI_TIMEOUT - A timeout occurred while waiting for the SCSI
623 Request Packet to execute.
627 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
630 UINT8 TargetArray
[EFI_SCSI_TARGET_MAX_BYTES
];
634 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
637 CommandPacket
.Timeout
= Timeout
;
638 CommandPacket
.OutDataBuffer
= DataBuffer
;
639 CommandPacket
.SenseData
= SenseData
;
640 CommandPacket
.OutTransferLength
= *DataLength
;
641 CommandPacket
.Cdb
= Cdb
;
643 // Fill Cdb for Write (10) Command
645 Target
= &TargetArray
[0];
646 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
648 Cdb
[0] = EFI_SCSI_OP_WRITE10
;
649 Cdb
[1] = (UINT8
) (Lun
& 0xe0);
650 Cdb
[2] = (UINT8
) (StartLba
>> 24);
651 Cdb
[3] = (UINT8
) (StartLba
>> 16);
652 Cdb
[4] = (UINT8
) (StartLba
>> 8);
653 Cdb
[5] = (UINT8
) StartLba
;
654 Cdb
[7] = (UINT8
) (SectorSize
>> 8);
655 Cdb
[8] = (UINT8
) SectorSize
;
657 CommandPacket
.CdbLength
= 10;
658 CommandPacket
.DataDirection
= EFI_SCSI_DATA_OUT
;
659 CommandPacket
.SenseDataLength
= *SenseDataLength
;
661 Status
= ScsiIo
->ExecuteScsiCommand (ScsiIo
, &CommandPacket
, NULL
);
663 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
664 *TargetStatus
= CommandPacket
.TargetStatus
;
665 *SenseDataLength
= CommandPacket
.SenseDataLength
;
666 *DataLength
= CommandPacket
.InTransferLength
;