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 #include <IndustryStandard/scsi.h>
26 SubmitTestUnitReadyCommand (
27 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
30 OUT UINT8
*SenseDataLength
,
31 OUT UINT8
*HostAdapterStatus
,
32 OUT UINT8
*TargetStatus
37 Function tests the ready status of SCSI unit.
40 ScsiIo - A pointer to SCSI IO protocol.
41 Timeout - The length of timeout period.
42 SenseData - A pointer to output sense data.
43 SenseDataLength - The length of output sense data.
44 HostAdapterStatus - The status of Host Adapter.
45 TargetStatus - The status of the target.
50 EFI_SUCCESS - The status of the unit is tested successfully.
51 EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed,
52 but the entire DataBuffer could not be transferred.
53 The actual number of bytes transferred is returned
55 EFI_NOT_READY - The SCSI Request Packet could not be sent because
56 there are too many SCSI Command Packets already
58 EFI_DEVICE_ERROR - A device error occurred while attempting to send
59 the SCSI Request Packet.
60 EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid.
61 EFI_UNSUPPORTED - The command described by the SCSI Request Packet
62 is not supported by the SCSI initiator(i.e., SCSI
64 EFI_TIMEOUT - A timeout occurred while waiting for the SCSI
65 Request Packet to execute.
69 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
75 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
78 CommandPacket
.Timeout
= Timeout
;
79 CommandPacket
.InDataBuffer
= NULL
;
80 CommandPacket
.SenseData
= SenseData
;
81 CommandPacket
.InTransferLength
= 0;
82 CommandPacket
.Cdb
= Cdb
;
84 // Fill Cdb for Test Unit Ready Command
86 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
88 Cdb
[0] = EFI_SCSI_OP_TEST_UNIT_READY
;
89 Cdb
[1] = (UINT8
) (Lun
& 0xe0);
90 CommandPacket
.CdbLength
= (UINT8
) 6;
91 CommandPacket
.SenseDataLength
= *SenseDataLength
;
93 Status
= ScsiIo
->ExecuteSCSICommand (ScsiIo
, &CommandPacket
, NULL
);
95 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
96 *TargetStatus
= CommandPacket
.TargetStatus
;
97 *SenseDataLength
= CommandPacket
.SenseDataLength
;
103 SubmitInquiryCommand (
104 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
107 IN OUT UINT8
*SenseDataLength
,
108 OUT UINT8
*HostAdapterStatus
,
109 OUT UINT8
*TargetStatus
,
110 IN OUT VOID
*InquiryDataBuffer
,
111 IN OUT UINT32
*InquiryDataLength
,
112 IN BOOLEAN EnableVitalProductData
117 Function to submit SCSI inquiry command.
120 ScsiIo - A pointer to SCSI IO protocol.
121 Timeout - The length of timeout period.
122 SenseData - A pointer to output sense data.
123 SenseDataLength - The length of output sense data.
124 HostAdapterStatus - The status of Host Adapter.
125 TargetStatus - The status of the target.
126 InquiryDataBuffer - A pointer to inquiry data buffer.
127 InquiryDataLength - The length of inquiry data buffer.
128 EnableVitalProductData - Boolean to enable Vital Product Data.
133 EFI_SUCCESS - The status of the unit is tested successfully.
134 EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed,
135 but the entire DataBuffer could not be transferred.
136 The actual number of bytes transferred is returned
138 EFI_NOT_READY - The SCSI Request Packet could not be sent because
139 there are too many SCSI Command Packets already
141 EFI_DEVICE_ERROR - A device error occurred while attempting to send
142 the SCSI Request Packet.
143 EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid.
144 EFI_UNSUPPORTED - The command described by the SCSI Request Packet
145 is not supported by the SCSI initiator(i.e., SCSI
147 EFI_TIMEOUT - A timeout occurred while waiting for the SCSI
148 Request Packet to execute.
152 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
158 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
161 CommandPacket
.Timeout
= Timeout
;
162 CommandPacket
.InDataBuffer
= InquiryDataBuffer
;
163 CommandPacket
.InTransferLength
= *InquiryDataLength
;
164 CommandPacket
.SenseData
= SenseData
;
165 CommandPacket
.SenseDataLength
= *SenseDataLength
;
166 CommandPacket
.Cdb
= Cdb
;
168 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
170 Cdb
[0] = EFI_SCSI_OP_INQUIRY
;
171 Cdb
[1] = (UINT8
) (Lun
& 0xe0);
172 if (EnableVitalProductData
) {
176 if (*InquiryDataLength
> 0xff) {
177 *InquiryDataLength
= 0xff;
180 Cdb
[4] = (UINT8
) (*InquiryDataLength
);
181 CommandPacket
.CdbLength
= (UINT8
) 6;
182 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
184 Status
= ScsiIo
->ExecuteSCSICommand (ScsiIo
, &CommandPacket
, NULL
);
186 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
187 *TargetStatus
= CommandPacket
.TargetStatus
;
188 *SenseDataLength
= CommandPacket
.SenseDataLength
;
189 *InquiryDataLength
= CommandPacket
.InTransferLength
;
195 SubmitModeSense10Command (
196 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
199 IN OUT UINT8
*SenseDataLength
,
200 OUT UINT8
*HostAdapterStatus
,
201 OUT UINT8
*TargetStatus
,
203 IN OUT UINT32
*DataLength
,
204 IN UINT8 DBDField
, OPTIONAL
205 IN UINT8 PageControl
,
211 Function to submit SCSI mode sense 10 command.
214 ScsiIo - A pointer to SCSI IO protocol.
215 Timeout - The length of timeout period.
216 SenseData - A pointer to output sense data.
217 SenseDataLength - The length of output sense data.
218 HostAdapterStatus - The status of Host Adapter.
219 TargetStatus - The status of the target.
220 DataBuffer - A pointer to input data buffer.
221 DataLength - The length of input data buffer.
222 DBDField - The DBD Field (Optional).
223 PageControl - Page Control.
224 PageCode - Page code.
229 EFI_SUCCESS - The status of the unit is tested successfully.
230 EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed,
231 but the entire DataBuffer could not be transferred.
232 The actual number of bytes transferred is returned
234 EFI_NOT_READY - The SCSI Request Packet could not be sent because
235 there are too many SCSI Command Packets already
237 EFI_DEVICE_ERROR - A device error occurred while attempting to send
238 the SCSI Request Packet.
239 EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid.
240 EFI_UNSUPPORTED - The command described by the SCSI Request Packet
241 is not supported by the SCSI initiator(i.e., SCSI
243 EFI_TIMEOUT - A timeout occurred while waiting for the SCSI
244 Request Packet to execute.
248 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
254 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
257 CommandPacket
.Timeout
= Timeout
;
258 CommandPacket
.InDataBuffer
= DataBuffer
;
259 CommandPacket
.SenseData
= SenseData
;
260 CommandPacket
.InTransferLength
= *DataLength
;
261 CommandPacket
.Cdb
= Cdb
;
263 // Fill Cdb for Mode Sense (10) Command
265 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
267 Cdb
[0] = EFI_SCSI_OP_MODE_SEN10
;
268 Cdb
[1] = (UINT8
) ((Lun
& 0xe0) + ((DBDField
<< 3) & 0x08));
269 Cdb
[2] = (UINT8
) ((PageControl
& 0xc0) | (PageCode
& 0x3f));
270 Cdb
[7] = (UINT8
) (*DataLength
>> 8);
271 Cdb
[8] = (UINT8
) (*DataLength
);
273 CommandPacket
.CdbLength
= 10;
274 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
275 CommandPacket
.SenseDataLength
= *SenseDataLength
;
277 Status
= ScsiIo
->ExecuteSCSICommand (ScsiIo
, &CommandPacket
, NULL
);
279 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
280 *TargetStatus
= CommandPacket
.TargetStatus
;
281 *SenseDataLength
= CommandPacket
.SenseDataLength
;
282 *DataLength
= CommandPacket
.InTransferLength
;
288 SubmitRequestSenseCommand (
289 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
292 IN OUT UINT8
*SenseDataLength
,
293 OUT UINT8
*HostAdapterStatus
,
294 OUT UINT8
*TargetStatus
299 Function to submit SCSI request sense command.
302 ScsiIo - A pointer to SCSI IO protocol.
303 Timeout - The length of timeout period.
304 SenseData - A pointer to output sense data.
305 SenseDataLength - The length of output sense data.
306 HostAdapterStatus - The status of Host Adapter.
307 TargetStatus - The status of the target.
312 EFI_SUCCESS - The status of the unit is tested successfully.
313 EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed,
314 but the entire DataBuffer could not be transferred.
315 The actual number of bytes transferred is returned
317 EFI_NOT_READY - The SCSI Request Packet could not be sent because
318 there are too many SCSI Command Packets already
320 EFI_DEVICE_ERROR - A device error occurred while attempting to send
321 the SCSI Request Packet.
322 EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid.
323 EFI_UNSUPPORTED - The command described by the SCSI Request Packet
324 is not supported by the SCSI initiator(i.e., SCSI
326 EFI_TIMEOUT - A timeout occurred while waiting for the SCSI
327 Request Packet to execute.
331 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
337 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
340 if (*SenseDataLength > 0xff) {
341 *SenseDataLength = 0xff;
344 CommandPacket
.Timeout
= Timeout
;
345 CommandPacket
.InDataBuffer
= SenseData
;
346 CommandPacket
.SenseData
= NULL
;
347 CommandPacket
.InTransferLength
= *SenseDataLength
;
348 CommandPacket
.Cdb
= Cdb
;
350 // Fill Cdb for Request Sense Command
352 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
354 Cdb
[0] = EFI_SCSI_OP_REQUEST_SENSE
;
355 Cdb
[1] = (UINT8
) (Lun
& 0xe0);
356 Cdb
[4] = (UINT8
) (*SenseDataLength
);
358 CommandPacket
.CdbLength
= (UINT8
) 6;
359 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
360 CommandPacket
.SenseDataLength
= 0;
362 Status
= ScsiIo
->ExecuteSCSICommand (ScsiIo
, &CommandPacket
, NULL
);
364 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
365 *TargetStatus
= CommandPacket
.TargetStatus
;
366 *SenseDataLength
= (UINT8
) CommandPacket
.InTransferLength
;
372 SubmitReadCapacityCommand (
373 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
376 IN OUT UINT8
*SenseDataLength
,
377 OUT UINT8
*HostAdapterStatus
,
378 OUT UINT8
*TargetStatus
,
379 OUT VOID
*DataBuffer
,
380 IN OUT UINT32
*DataLength
,
386 Function to submit read capacity command.
389 ScsiIo - A pointer to SCSI IO protocol.
390 Timeout - The length of timeout period.
391 SenseData - A pointer to output sense data.
392 SenseDataLength - The length of output sense data.
393 HostAdapterStatus - The status of Host Adapter.
394 TargetStatus - The status of the target.
395 DataBuffer - A pointer to a data buffer.
396 DataLength - The length of data buffer.
397 PMI - Partial medium indicator.
402 EFI_SUCCESS - The status of the unit is tested successfully.
403 EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed,
404 but the entire DataBuffer could not be transferred.
405 The actual number of bytes transferred is returned
407 EFI_NOT_READY - The SCSI Request Packet could not be sent because
408 there are too many SCSI Command Packets already
410 EFI_DEVICE_ERROR - A device error occurred while attempting to send
411 the SCSI Request Packet.
412 EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid.
413 EFI_UNSUPPORTED - The command described by the SCSI Request Packet
414 is not supported by the SCSI initiator(i.e., SCSI
416 EFI_TIMEOUT - A timeout occurred while waiting for the SCSI
417 Request Packet to execute.
421 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
427 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
430 CommandPacket
.Timeout
= Timeout
;
431 CommandPacket
.InDataBuffer
= DataBuffer
;
432 CommandPacket
.SenseData
= SenseData
;
433 CommandPacket
.InTransferLength
= *DataLength
;
434 CommandPacket
.Cdb
= Cdb
;
436 // Fill Cdb for Read Capacity Command
438 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
440 Cdb
[0] = EFI_SCSI_OP_READ_CAPACITY
;
441 Cdb
[1] = (UINT8
) (Lun
& 0xe0);
444 // Partial medium indicator,if PMI is FALSE, the Cdb.2 ~ Cdb.5 MUST BE ZERO.
446 ZeroMem ((Cdb
+ 2), 4);
451 CommandPacket
.CdbLength
= 10;
452 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
453 CommandPacket
.SenseDataLength
= *SenseDataLength
;
455 Status
= ScsiIo
->ExecuteSCSICommand (ScsiIo
, &CommandPacket
, NULL
);
457 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
458 *TargetStatus
= CommandPacket
.TargetStatus
;
459 *SenseDataLength
= CommandPacket
.SenseDataLength
;
460 *DataLength
= CommandPacket
.InTransferLength
;
466 SubmitRead10Command (
467 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
470 IN OUT UINT8
*SenseDataLength
,
471 OUT UINT8
*HostAdapterStatus
,
472 OUT UINT8
*TargetStatus
,
473 OUT VOID
*DataBuffer
,
474 IN OUT UINT32
*DataLength
,
481 Function to submit read 10 command.
484 ScsiIo - A pointer to SCSI IO protocol.
485 Timeout - The length of timeout period.
486 SenseData - A pointer to output sense data.
487 SenseDataLength - The length of output sense data.
488 HostAdapterStatus - The status of Host Adapter.
489 TargetStatus - The status of the target.
490 DataBuffer - A pointer to a data buffer.
491 DataLength - The length of data buffer.
492 StartLba - The start address of LBA.
493 SectorSize - The sector size.
498 EFI_SUCCESS - The status of the unit is tested successfully.
499 EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed,
500 but the entire DataBuffer could not be transferred.
501 The actual number of bytes transferred is returned
503 EFI_NOT_READY - The SCSI Request Packet could not be sent because
504 there are too many SCSI Command Packets already
506 EFI_DEVICE_ERROR - A device error occurred while attempting to send
507 the SCSI Request Packet.
508 EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid.
509 EFI_UNSUPPORTED - The command described by the SCSI Request Packet
510 is not supported by the SCSI initiator(i.e., SCSI
512 EFI_TIMEOUT - A timeout occurred while waiting for the SCSI
513 Request Packet to execute.
517 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
523 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
526 CommandPacket
.Timeout
= Timeout
;
527 CommandPacket
.InDataBuffer
= DataBuffer
;
528 CommandPacket
.SenseData
= SenseData
;
529 CommandPacket
.InTransferLength
= *DataLength
;
530 CommandPacket
.Cdb
= Cdb
;
532 // Fill Cdb for Read (10) Command
534 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
536 Cdb
[0] = EFI_SCSI_OP_READ10
;
537 Cdb
[1] = (UINT8
) (Lun
& 0xe0);
538 Cdb
[2] = (UINT8
) (StartLba
>> 24);
539 Cdb
[3] = (UINT8
) (StartLba
>> 16);
540 Cdb
[4] = (UINT8
) (StartLba
>> 8);
541 Cdb
[5] = (UINT8
) StartLba
;
542 Cdb
[7] = (UINT8
) (SectorSize
>> 8);
543 Cdb
[8] = (UINT8
) SectorSize
;
545 CommandPacket
.CdbLength
= 10;
546 CommandPacket
.DataDirection
= EFI_SCSI_DATA_IN
;
547 CommandPacket
.SenseDataLength
= *SenseDataLength
;
549 Status
= ScsiIo
->ExecuteSCSICommand (ScsiIo
, &CommandPacket
, NULL
);
551 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
552 *TargetStatus
= CommandPacket
.TargetStatus
;
553 *SenseDataLength
= CommandPacket
.SenseDataLength
;
554 *DataLength
= CommandPacket
.InTransferLength
;
560 SubmitWrite10Command (
561 IN EFI_SCSI_IO_PROTOCOL
*ScsiIo
,
564 IN OUT UINT8
*SenseDataLength
,
565 OUT UINT8
*HostAdapterStatus
,
566 OUT UINT8
*TargetStatus
,
567 OUT VOID
*DataBuffer
,
568 IN OUT UINT32
*DataLength
,
575 Function to submit SCSI write 10 command.
578 ScsiIo - A pointer to SCSI IO protocol.
579 Timeout - The length of timeout period.
580 SenseData - A pointer to output sense data.
581 SenseDataLength - The length of output sense data.
582 HostAdapterStatus - The status of Host Adapter.
583 TargetStatus - The status of the target.
584 DataBuffer - A pointer to a data buffer.
585 DataLength - The length of data buffer.
586 StartLba - The start address of LBA.
587 SectorSize - The sector size.
592 EFI_SUCCESS - The status of the unit is tested successfully.
593 EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed,
594 but the entire DataBuffer could not be transferred.
595 The actual number of bytes transferred is returned
597 EFI_NOT_READY - The SCSI Request Packet could not be sent because
598 there are too many SCSI Command Packets already
600 EFI_DEVICE_ERROR - A device error occurred while attempting to send
601 the SCSI Request Packet.
602 EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid.
603 EFI_UNSUPPORTED - The command described by the SCSI Request Packet
604 is not supported by the SCSI initiator(i.e., SCSI
606 EFI_TIMEOUT - A timeout occurred while waiting for the SCSI
607 Request Packet to execute.
611 EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket
;
617 ZeroMem (&CommandPacket
, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET
));
620 CommandPacket
.Timeout
= Timeout
;
621 CommandPacket
.InDataBuffer
= DataBuffer
;
622 CommandPacket
.SenseData
= SenseData
;
623 CommandPacket
.InTransferLength
= *DataLength
;
624 CommandPacket
.Cdb
= Cdb
;
626 // Fill Cdb for Write (10) Command
628 ScsiIo
->GetDeviceLocation (ScsiIo
, &Target
, &Lun
);
630 Cdb
[0] = EFI_SCSI_OP_WRITE10
;
631 Cdb
[1] = (UINT8
) (Lun
& 0xe0);
632 Cdb
[2] = (UINT8
) (StartLba
>> 24);
633 Cdb
[3] = (UINT8
) (StartLba
>> 16);
634 Cdb
[4] = (UINT8
) (StartLba
>> 8);
635 Cdb
[5] = (UINT8
) StartLba
;
636 Cdb
[7] = (UINT8
) (SectorSize
>> 8);
637 Cdb
[8] = (UINT8
) SectorSize
;
639 CommandPacket
.CdbLength
= 10;
640 CommandPacket
.DataDirection
= EFI_SCSI_DATA_OUT
;
641 CommandPacket
.SenseDataLength
= *SenseDataLength
;
643 Status
= ScsiIo
->ExecuteSCSICommand (ScsiIo
, &CommandPacket
, NULL
);
645 *HostAdapterStatus
= CommandPacket
.HostAdapterStatus
;
646 *TargetStatus
= CommandPacket
.TargetStatus
;
647 *SenseDataLength
= CommandPacket
.SenseDataLength
;
648 *DataLength
= CommandPacket
.InTransferLength
;