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.
24 ScsiDiskDriverBindingSupported (
25 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
26 IN EFI_HANDLE Controller
,
27 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
32 ScsiDiskDriverBindingStart (
33 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
34 IN EFI_HANDLE Controller
,
35 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
40 ScsiDiskDriverBindingStop (
41 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
42 IN EFI_HANDLE Controller
,
43 IN UINTN NumberOfChildren
,
44 IN EFI_HANDLE
*ChildHandleBuffer
47 EFI_DRIVER_BINDING_PROTOCOL gScsiDiskDriverBinding
= {
48 ScsiDiskDriverBindingSupported
,
49 ScsiDiskDriverBindingStart
,
50 ScsiDiskDriverBindingStop
,
58 ScsiDiskDriverBindingSupported (
59 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
60 IN EFI_HANDLE Controller
,
61 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
72 // TODO: This - add argument and description to function comment
73 // TODO: Controller - add argument and description to function comment
74 // TODO: RemainingDevicePath - add argument and description to function comment
77 EFI_SCSI_IO_PROTOCOL
*ScsiIo
;
80 Status
= gBS
->OpenProtocol (
82 &gEfiScsiIoProtocolGuid
,
84 This
->DriverBindingHandle
,
86 EFI_OPEN_PROTOCOL_BY_DRIVER
88 if (EFI_ERROR (Status
)) {
92 Status
= ScsiIo
->GetDeviceType (ScsiIo
, &DeviceType
);
93 if (!EFI_ERROR (Status
)) {
94 if ((DeviceType
== EFI_SCSI_TYPE_DISK
) || (DeviceType
== EFI_SCSI_TYPE_CDROM
)) {
97 Status
= EFI_UNSUPPORTED
;
103 &gEfiScsiIoProtocolGuid
,
104 This
->DriverBindingHandle
,
112 ScsiDiskDriverBindingStart (
113 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
114 IN EFI_HANDLE Controller
,
115 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
126 // TODO: This - add argument and description to function comment
127 // TODO: Controller - add argument and description to function comment
128 // TODO: RemainingDevicePath - add argument and description to function comment
129 // TODO: EFI_DEVICE_ERROR - add return value to function comment
130 // TODO: EFI_SUCCESS - add return value to function comment
133 EFI_SCSI_IO_PROTOCOL
*ScsiIo
;
134 SCSI_DISK_DEV
*ScsiDiskDevice
;
140 Status
= gBS
->AllocatePool (
142 sizeof (SCSI_DISK_DEV
),
143 (VOID
**) &ScsiDiskDevice
145 if (EFI_ERROR (Status
)) {
149 ZeroMem (ScsiDiskDevice
, sizeof (SCSI_DISK_DEV
));
151 Status
= gBS
->OpenProtocol (
153 &gEfiScsiIoProtocolGuid
,
155 This
->DriverBindingHandle
,
157 EFI_OPEN_PROTOCOL_BY_DRIVER
159 if (EFI_ERROR (Status
)) {
160 gBS
->FreePool (ScsiDiskDevice
);
164 ScsiDiskDevice
->Signature
= SCSI_DISK_DEV_SIGNATURE
;
165 ScsiDiskDevice
->ScsiIo
= ScsiIo
;
166 ScsiDiskDevice
->BlkIo
.Media
= &ScsiDiskDevice
->BlkIoMedia
;
167 ScsiDiskDevice
->BlkIo
.Reset
= ScsiDiskReset
;
168 ScsiDiskDevice
->BlkIo
.ReadBlocks
= ScsiDiskReadBlocks
;
169 ScsiDiskDevice
->BlkIo
.WriteBlocks
= ScsiDiskWriteBlocks
;
170 ScsiDiskDevice
->BlkIo
.FlushBlocks
= ScsiDiskFlushBlocks
;
171 ScsiDiskDevice
->Handle
= Controller
;
173 ScsiIo
->GetDeviceType (ScsiIo
, &(ScsiDiskDevice
->DeviceType
));
174 switch (ScsiDiskDevice
->DeviceType
) {
175 case EFI_SCSI_TYPE_DISK
:
176 ScsiDiskDevice
->BlkIo
.Media
->BlockSize
= 0x200;
179 case EFI_SCSI_TYPE_CDROM
:
180 ScsiDiskDevice
->BlkIo
.Media
->BlockSize
= 0x800;
184 // The Sense Data Array's initial size is 6
186 ScsiDiskDevice
->SenseDataNumber
= 6;
187 Status
= gBS
->AllocatePool (
189 sizeof (EFI_SCSI_SENSE_DATA
) * ScsiDiskDevice
->SenseDataNumber
,
190 (VOID
**) &(ScsiDiskDevice
->SenseData
)
192 if (EFI_ERROR (Status
)) {
195 &gEfiScsiIoProtocolGuid
,
196 This
->DriverBindingHandle
,
199 gBS
->FreePool (ScsiDiskDevice
);
204 ScsiDiskDevice
->SenseData
,
205 sizeof (EFI_SCSI_SENSE_DATA
) * ScsiDiskDevice
->SenseDataNumber
209 // Retrive device information
212 for (Index
= 0; Index
< MaxRetry
; Index
++) {
213 Status
= ScsiDiskInquiryDevice (ScsiDiskDevice
, &NeedRetry
);
214 if (!EFI_ERROR (Status
)) {
219 gBS
->FreePool (ScsiDiskDevice
->SenseData
);
222 &gEfiScsiIoProtocolGuid
,
223 This
->DriverBindingHandle
,
226 gBS
->FreePool (ScsiDiskDevice
);
227 return EFI_DEVICE_ERROR
;
231 // The second parameter "TRUE" means must
232 // retrieve media capacity
234 Status
= ScsiDiskDetectMedia (ScsiDiskDevice
, TRUE
, &Temp
);
235 if (!EFI_ERROR (Status
)) {
236 Status
= gBS
->InstallMultipleProtocolInterfaces (
238 &gEfiBlockIoProtocolGuid
,
239 &ScsiDiskDevice
->BlkIo
,
244 if (EFI_ERROR (Status
)) {
245 gBS
->FreePool (ScsiDiskDevice
->SenseData
);
248 &gEfiScsiIoProtocolGuid
,
249 This
->DriverBindingHandle
,
252 gBS
->FreePool (ScsiDiskDevice
);
256 ScsiDiskDevice
->ControllerNameTable
= NULL
;
259 gScsiDiskComponentName
.SupportedLanguages
,
260 &ScsiDiskDevice
->ControllerNameTable
,
261 (CHAR16
*) L
"SCSI Disk Device"
270 ScsiDiskDriverBindingStop (
271 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
272 IN EFI_HANDLE Controller
,
273 IN UINTN NumberOfChildren
,
274 IN EFI_HANDLE
*ChildHandleBuffer
285 // TODO: This - add argument and description to function comment
286 // TODO: Controller - add argument and description to function comment
287 // TODO: NumberOfChildren - add argument and description to function comment
288 // TODO: ChildHandleBuffer - add argument and description to function comment
289 // TODO: EFI_SUCCESS - add return value to function comment
291 EFI_BLOCK_IO_PROTOCOL
*BlkIo
;
292 SCSI_DISK_DEV
*ScsiDiskDevice
;
295 Status
= gBS
->OpenProtocol (
297 &gEfiBlockIoProtocolGuid
,
299 This
->DriverBindingHandle
,
301 EFI_OPEN_PROTOCOL_GET_PROTOCOL
303 if (EFI_ERROR (Status
)) {
307 ScsiDiskDevice
= SCSI_DISK_DEV_FROM_THIS (BlkIo
);
308 Status
= gBS
->UninstallProtocolInterface (
310 &gEfiBlockIoProtocolGuid
,
311 &ScsiDiskDevice
->BlkIo
313 if (!EFI_ERROR (Status
)) {
316 &gEfiScsiIoProtocolGuid
,
317 This
->DriverBindingHandle
,
321 ReleaseScsiDiskDeviceResources (ScsiDiskDevice
);
332 // Block I/O Protocol Interface
338 IN EFI_BLOCK_IO_PROTOCOL
*This
,
339 IN BOOLEAN ExtendedVerification
345 TODO: Add function description
349 This - TODO: add argument description
350 ExtendedVerification - TODO: add argument description
354 TODO: add return values
358 SCSI_DISK_DEV
*ScsiDiskDevice
;
361 ScsiDiskDevice
= SCSI_DISK_DEV_FROM_THIS (This
);
363 Status
= ScsiDiskDevice
->ScsiIo
->ResetDevice (ScsiDiskDevice
->ScsiIo
);
365 if (!ExtendedVerification
) {
369 Status
= ScsiDiskDevice
->ScsiIo
->ResetBus (ScsiDiskDevice
->ScsiIo
);
377 IN EFI_BLOCK_IO_PROTOCOL
*This
,
387 TODO: Add function description
391 This - TODO: add argument description
392 MediaId - TODO: add argument description
393 LBA - TODO: add argument description
394 BufferSize - TODO: add argument description
395 Buffer - TODO: add argument description
399 EFI_INVALID_PARAMETER - TODO: Add description for return value
400 EFI_SUCCESS - TODO: Add description for return value
401 EFI_DEVICE_ERROR - TODO: Add description for return value
402 EFI_NO_MEDIA - TODO: Add description for return value
403 EFI_MEDIA_CHANGED - TODO: Add description for return value
404 EFI_BAD_BUFFER_SIZE - TODO: Add description for return value
405 EFI_INVALID_PARAMETER - TODO: Add description for return value
406 EFI_INVALID_PARAMETER - TODO: Add description for return value
407 EFI_INVALID_PARAMETER - TODO: Add description for return value
411 SCSI_DISK_DEV
*ScsiDiskDevice
;
412 EFI_BLOCK_IO_MEDIA
*Media
;
415 UINTN NumberOfBlocks
;
420 return EFI_INVALID_PARAMETER
;
423 if (BufferSize
== 0) {
427 ScsiDiskDevice
= SCSI_DISK_DEV_FROM_THIS (This
);
429 if (!IsDeviceFixed (ScsiDiskDevice
)) {
431 Status
= ScsiDiskDetectMedia (ScsiDiskDevice
, FALSE
, &MediaChange
);
432 if (EFI_ERROR (Status
)) {
433 return EFI_DEVICE_ERROR
;
437 gBS
->ReinstallProtocolInterface (
438 ScsiDiskDevice
->Handle
,
439 &gEfiBlockIoProtocolGuid
,
440 &ScsiDiskDevice
->BlkIo
,
441 &ScsiDiskDevice
->BlkIo
446 // Get the intrinsic block size
448 Media
= ScsiDiskDevice
->BlkIo
.Media
;
449 BlockSize
= Media
->BlockSize
;
451 NumberOfBlocks
= BufferSize
/ BlockSize
;
453 if (!(Media
->MediaPresent
)) {
457 if (MediaId
!= Media
->MediaId
) {
458 return EFI_MEDIA_CHANGED
;
461 if (BufferSize
% BlockSize
!= 0) {
462 return EFI_BAD_BUFFER_SIZE
;
465 if (LBA
> Media
->LastBlock
) {
466 return EFI_INVALID_PARAMETER
;
469 if ((LBA
+ NumberOfBlocks
- 1) > Media
->LastBlock
) {
470 return EFI_INVALID_PARAMETER
;
473 if ((Media
->IoAlign
> 1) && (((UINTN
) Buffer
& (Media
->IoAlign
- 1)) != 0)) {
474 return EFI_INVALID_PARAMETER
;
478 // if all the parameters are valid, then perform read sectors command
479 // to transfer data from device to host.
481 Status
= ScsiDiskReadSectors (ScsiDiskDevice
, Buffer
, LBA
, NumberOfBlocks
);
488 ScsiDiskWriteBlocks (
489 IN EFI_BLOCK_IO_PROTOCOL
*This
,
499 TODO: Add function description
503 This - TODO: add argument description
504 MediaId - TODO: add argument description
505 LBA - TODO: add argument description
506 BufferSize - TODO: add argument description
507 Buffer - TODO: add argument description
511 EFI_INVALID_PARAMETER - TODO: Add description for return value
512 EFI_SUCCESS - TODO: Add description for return value
513 EFI_DEVICE_ERROR - TODO: Add description for return value
514 EFI_NO_MEDIA - TODO: Add description for return value
515 EFI_MEDIA_CHANGED - TODO: Add description for return value
516 EFI_BAD_BUFFER_SIZE - TODO: Add description for return value
517 EFI_INVALID_PARAMETER - TODO: Add description for return value
518 EFI_INVALID_PARAMETER - TODO: Add description for return value
519 EFI_INVALID_PARAMETER - TODO: Add description for return value
523 SCSI_DISK_DEV
*ScsiDiskDevice
;
524 EFI_BLOCK_IO_MEDIA
*Media
;
527 UINTN NumberOfBlocks
;
532 return EFI_INVALID_PARAMETER
;
535 if (BufferSize
== 0) {
539 ScsiDiskDevice
= SCSI_DISK_DEV_FROM_THIS (This
);
541 if (!IsDeviceFixed (ScsiDiskDevice
)) {
543 Status
= ScsiDiskDetectMedia (ScsiDiskDevice
, FALSE
, &MediaChange
);
544 if (EFI_ERROR (Status
)) {
545 return EFI_DEVICE_ERROR
;
549 gBS
->ReinstallProtocolInterface (
550 ScsiDiskDevice
->Handle
,
551 &gEfiBlockIoProtocolGuid
,
552 &ScsiDiskDevice
->BlkIo
,
553 &ScsiDiskDevice
->BlkIo
558 // Get the intrinsic block size
560 Media
= ScsiDiskDevice
->BlkIo
.Media
;
561 BlockSize
= Media
->BlockSize
;
563 NumberOfBlocks
= BufferSize
/ BlockSize
;
565 if (!(Media
->MediaPresent
)) {
569 if (MediaId
!= Media
->MediaId
) {
570 return EFI_MEDIA_CHANGED
;
573 if (BufferSize
% BlockSize
!= 0) {
574 return EFI_BAD_BUFFER_SIZE
;
577 if (LBA
> Media
->LastBlock
) {
578 return EFI_INVALID_PARAMETER
;
581 if ((LBA
+ NumberOfBlocks
- 1) > Media
->LastBlock
) {
582 return EFI_INVALID_PARAMETER
;
585 if ((Media
->IoAlign
> 1) && (((UINTN
) Buffer
& (Media
->IoAlign
- 1)) != 0)) {
586 return EFI_INVALID_PARAMETER
;
589 // if all the parameters are valid, then perform read sectors command
590 // to transfer data from device to host.
592 Status
= ScsiDiskWriteSectors (ScsiDiskDevice
, Buffer
, LBA
, NumberOfBlocks
);
599 ScsiDiskFlushBlocks (
600 IN EFI_BLOCK_IO_PROTOCOL
*This
606 TODO: Add function description
610 This - TODO: add argument description
614 EFI_SUCCESS - TODO: Add description for return value
625 ScsiDiskDetectMedia (
626 SCSI_DISK_DEV
*ScsiDiskDevice
,
627 BOOLEAN MustReadCapacity
,
634 TODO: Add function description
638 ScsiDiskDevice - TODO: add argument description
639 MustReadCapacity - TODO: add argument description
640 MediaChange - TODO: add argument description
644 EFI_DEVICE_ERROR - TODO: Add description for return value
645 EFI_DEVICE_ERROR - TODO: Add description for return value
646 EFI_DEVICE_ERROR - TODO: Add description for return value
647 EFI_SUCCESS - TODO: Add description for return value
652 EFI_STATUS ReadCapacityStatus
;
653 EFI_SCSI_SENSE_DATA
*SenseData
;
654 UINTN NumberOfSenseKeys
;
656 BOOLEAN NeedReadCapacity
;
659 EFI_BLOCK_IO_MEDIA OldMedia
;
662 Status
= EFI_SUCCESS
;
663 ReadCapacityStatus
= EFI_SUCCESS
;
665 NumberOfSenseKeys
= 0;
666 NeedReadCapacity
= FALSE
;
667 CopyMem (&OldMedia
, ScsiDiskDevice
->BlkIo
.Media
, sizeof (OldMedia
));
668 // OldMedia = *(ScsiDiskDevice->BlkIo.Media);
670 *MediaChange
= FALSE
;
673 for (Index
= 0; Index
< MaxRetry
; Index
++) {
674 Status
= ScsiDiskTestUnitReady (
680 if (!EFI_ERROR (Status
)) {
689 if ((Index
== MaxRetry
) && EFI_ERROR (Status
)) {
690 return EFI_DEVICE_ERROR
;
693 Status
= DetectMediaParsingSenseKeys (
699 if (EFI_ERROR (Status
)) {
703 // ACTION_NO_ACTION: need not read capacity
704 // other action code: need read capacity
706 if (Action
== ACTION_NO_ACTION
) {
707 NeedReadCapacity
= FALSE
;
709 NeedReadCapacity
= TRUE
;
713 // either NeedReadCapacity is TRUE, or MustReadCapacity is TRUE,
714 // retrieve capacity via Read Capacity command
716 if (NeedReadCapacity
|| MustReadCapacity
) {
719 // retrieve media information
722 for (Index
= 0; Index
< MaxRetry
; Index
++) {
724 ReadCapacityStatus
= ScsiDiskReadCapacity (
730 if (EFI_ERROR (ReadCapacityStatus
) && !NeedRetry
) {
731 return EFI_DEVICE_ERROR
;
734 // analyze sense key to action
736 Status
= DetectMediaParsingSenseKeys (
743 // if Status is error, it may indicate crisis error,
744 // so return without retry.
746 if (EFI_ERROR (Status
)) {
751 case ACTION_NO_ACTION
:
758 case ACTION_RETRY_COMMAND_LATER
:
760 // retry the ReadCapacity later and continuously, until the condition
761 // no longer emerges.
762 // stall time is 100000us, or say 0.1 second.
770 // other cases, just retry the command
776 if ((Index
== MaxRetry
) && EFI_ERROR (ReadCapacityStatus
)) {
777 return EFI_DEVICE_ERROR
;
781 if (ScsiDiskDevice
->BlkIo
.Media
->MediaId
!= OldMedia
.MediaId
) {
783 // Media change information got from the device
788 if (ScsiDiskDevice
->BlkIo
.Media
->ReadOnly
!= OldMedia
.ReadOnly
) {
790 ScsiDiskDevice
->BlkIo
.Media
->MediaId
+= 1;
793 if (ScsiDiskDevice
->BlkIo
.Media
->BlockSize
!= OldMedia
.BlockSize
) {
795 ScsiDiskDevice
->BlkIo
.Media
->MediaId
+= 1;
798 if (ScsiDiskDevice
->BlkIo
.Media
->LastBlock
!= OldMedia
.LastBlock
) {
800 ScsiDiskDevice
->BlkIo
.Media
->MediaId
+= 1;
803 if (ScsiDiskDevice
->BlkIo
.Media
->MediaPresent
!= OldMedia
.MediaPresent
) {
804 if (ScsiDiskDevice
->BlkIo
.Media
->MediaPresent
) {
806 // when change from no media to media present, reset the MediaId to 1.
808 ScsiDiskDevice
->BlkIo
.Media
->MediaId
= 1;
811 // when no media, reset the MediaId to zero.
813 ScsiDiskDevice
->BlkIo
.Media
->MediaId
= 0;
823 ScsiDiskInquiryDevice (
824 SCSI_DISK_DEV
*ScsiDiskDevice
,
831 TODO: Add function description
835 ScsiDiskDevice - TODO: add argument description
836 NeedRetry - TODO: add argument description
840 EFI_SUCCESS - TODO: Add description for return value
841 EFI_DEVICE_ERROR - TODO: Add description for return value
842 EFI_DEVICE_ERROR - TODO: Add description for return value
843 EFI_DEVICE_ERROR - TODO: Add description for return value
844 EFI_DEVICE_ERROR - TODO: Add description for return value
845 EFI_DEVICE_ERROR - TODO: Add description for return value
846 EFI_DEVICE_ERROR - TODO: Add description for return value
847 EFI_DEVICE_ERROR - TODO: Add description for return value
848 EFI_DEVICE_ERROR - TODO: Add description for return value
849 EFI_DEVICE_ERROR - TODO: Add description for return value
853 UINT32 InquiryDataLength
;
854 UINT8 SenseDataLength
;
855 UINT8 HostAdapterStatus
;
857 EFI_SCSI_SENSE_DATA
*SenseDataArray
;
858 UINTN NumberOfSenseKeys
;
863 InquiryDataLength
= sizeof (EFI_SCSI_INQUIRY_DATA
);
866 Status
= SubmitInquiryCommand (
867 ScsiDiskDevice
->ScsiIo
,
868 EfiScsiStallSeconds (1),
873 (VOID
*) &(ScsiDiskDevice
->InquiryData
),
877 if ((Status
== EFI_SUCCESS
) || (Status
== EFI_WARN_BUFFER_TOO_SMALL
)) {
879 // no need to check HostAdapterStatus and TargetStatus
881 ParseInquiryData (ScsiDiskDevice
);
883 } else if (Status
== EFI_NOT_READY
) {
885 // no need to check HostAdapterStatus and TargetStatus
888 return EFI_DEVICE_ERROR
;
889 } else if ((Status
== EFI_INVALID_PARAMETER
) || (Status
== EFI_UNSUPPORTED
)) {
891 // no need to check HostAdapterStatus and TargetStatus
894 return EFI_DEVICE_ERROR
;
897 // go ahead to check HostAdapterStatus and TargetStatus
898 // (EFI_TIMEOUT, EFI_DEVICE_ERROR)
900 Status
= CheckHostAdapterStatus (HostAdapterStatus
);
901 if ((Status
== EFI_TIMEOUT
) || (Status
== EFI_NOT_READY
)) {
903 return EFI_DEVICE_ERROR
;
904 } else if (Status
== EFI_DEVICE_ERROR
) {
906 // reset the scsi channel
908 ScsiDiskDevice
->ScsiIo
->ResetBus (ScsiDiskDevice
->ScsiIo
);
910 return EFI_DEVICE_ERROR
;
913 Status
= CheckTargetStatus (TargetStatus
);
914 if (Status
== EFI_NOT_READY
) {
916 // reset the scsi device
918 ScsiDiskDevice
->ScsiIo
->ResetDevice (ScsiDiskDevice
->ScsiIo
);
920 return EFI_DEVICE_ERROR
;
921 } else if (Status
== EFI_DEVICE_ERROR
) {
923 return EFI_DEVICE_ERROR
;
927 // if goes here, meant SubmitInquiryCommand() failed.
928 // if ScsiDiskRequestSenseKeys() succeeds at last,
929 // better retry SubmitInquiryCommand(). (by setting *NeedRetry = TRUE)
932 for (Index
= 0; Index
< MaxRetry
; Index
++) {
934 Status
= ScsiDiskRequestSenseKeys (
941 if (!EFI_ERROR (Status
)) {
943 return EFI_DEVICE_ERROR
;
947 return EFI_DEVICE_ERROR
;
951 // ScsiDiskRequestSenseKeys() failed after several rounds of retry.
952 // set *NeedRetry = FALSE to avoid the outside caller try again.
955 return EFI_DEVICE_ERROR
;
959 ScsiDiskTestUnitReady (
960 SCSI_DISK_DEV
*ScsiDiskDevice
,
962 EFI_SCSI_SENSE_DATA
**SenseDataArray
,
963 UINTN
*NumberOfSenseKeys
965 // TODO: function comment should start with '/*++'
967 When Test Unit Ready command succeeds,
968 retrieve Sense Keys via Request Sense;
969 When Test Unit Ready command encounters any error caused by host adapter or
970 target, return error without retrieving Sense Keys.
972 // TODO: function comment should end with '--*/'
973 // TODO: function comment is missing 'Routine Description:'
974 // TODO: function comment is missing 'Arguments:'
975 // TODO: function comment is missing 'Returns:'
976 // TODO: ScsiDiskDevice - add argument and description to function comment
977 // TODO: NeedRetry - add argument and description to function comment
978 // TODO: SenseDataArray - add argument and description to function comment
979 // TODO: NumberOfSenseKeys - add argument and description to function comment
980 // TODO: EFI_DEVICE_ERROR - add return value to function comment
981 // TODO: EFI_DEVICE_ERROR - add return value to function comment
982 // TODO: EFI_DEVICE_ERROR - add return value to function comment
983 // TODO: EFI_DEVICE_ERROR - add return value to function comment
984 // TODO: EFI_DEVICE_ERROR - add return value to function comment
985 // TODO: EFI_DEVICE_ERROR - add return value to function comment
986 // TODO: EFI_SUCCESS - add return value to function comment
987 // TODO: EFI_DEVICE_ERROR - add return value to function comment
988 // TODO: EFI_DEVICE_ERROR - add return value to function comment
991 UINT8 SenseDataLength
;
992 UINT8 HostAdapterStatus
;
998 *NumberOfSenseKeys
= 0;
1001 // Parameter 3 and 4: do not require sense data, retrieve it when needed.
1003 Status
= SubmitTestUnitReadyCommand (
1004 ScsiDiskDevice
->ScsiIo
,
1005 EfiScsiStallSeconds (1),
1011 if (Status
== EFI_NOT_READY
) {
1013 // no need to check HostAdapterStatus and TargetStatus
1016 return EFI_DEVICE_ERROR
;
1017 } else if ((Status
== EFI_INVALID_PARAMETER
) || (Status
== EFI_UNSUPPORTED
)) {
1019 // no need to check HostAdapterStatus and TargetStatus
1022 return EFI_DEVICE_ERROR
;
1025 // go ahead to check HostAdapterStatus and TargetStatus
1027 Status
= CheckHostAdapterStatus (HostAdapterStatus
);
1028 if ((Status
== EFI_TIMEOUT
) || (Status
== EFI_NOT_READY
)) {
1030 return EFI_DEVICE_ERROR
;
1031 } else if (Status
== EFI_DEVICE_ERROR
) {
1033 // reset the scsi channel
1035 ScsiDiskDevice
->ScsiIo
->ResetBus (ScsiDiskDevice
->ScsiIo
);
1037 return EFI_DEVICE_ERROR
;
1040 Status
= CheckTargetStatus (TargetStatus
);
1041 if (Status
== EFI_NOT_READY
) {
1043 // reset the scsi device
1045 ScsiDiskDevice
->ScsiIo
->ResetDevice (ScsiDiskDevice
->ScsiIo
);
1047 return EFI_DEVICE_ERROR
;
1048 } else if (Status
== EFI_DEVICE_ERROR
) {
1050 return EFI_DEVICE_ERROR
;
1054 for (Index
= 0; Index
< MaxRetry
; Index
++) {
1056 Status
= ScsiDiskRequestSenseKeys (
1063 if (!EFI_ERROR (Status
)) {
1068 return EFI_DEVICE_ERROR
;
1072 // ScsiDiskRequestSenseKeys() failed after several rounds of retry.
1073 // set *NeedRetry = FALSE to avoid the outside caller try again.
1076 return EFI_DEVICE_ERROR
;
1080 DetectMediaParsingSenseKeys (
1081 SCSI_DISK_DEV
*ScsiDiskDevice
,
1082 EFI_SCSI_SENSE_DATA
*SenseData
,
1083 UINTN NumberOfSenseKeys
,
1088 Routine Description:
1090 TODO: Add function description
1094 ScsiDiskDevice - TODO: add argument description
1095 SenseData - TODO: add argument description
1096 NumberOfSenseKeys - TODO: add argument description
1097 Action - TODO: add argument description
1101 EFI_SUCCESS - TODO: Add description for return value
1102 EFI_SUCCESS - TODO: Add description for return value
1103 EFI_SUCCESS - TODO: Add description for return value
1104 EFI_SUCCESS - TODO: Add description for return value
1105 EFI_DEVICE_ERROR - TODO: Add description for return value
1106 EFI_DEVICE_ERROR - TODO: Add description for return value
1107 EFI_SUCCESS - TODO: Add description for return value
1108 EFI_DEVICE_ERROR - TODO: Add description for return value
1109 EFI_SUCCESS - TODO: Add description for return value
1116 // Default is to read capacity, unless..
1118 *Action
= ACTION_READ_CAPACITY
;
1120 if (NumberOfSenseKeys
== 0) {
1121 *Action
= ACTION_NO_ACTION
;
1125 if (!ScsiDiskHaveSenseKey (SenseData
, NumberOfSenseKeys
)) {
1127 // No Sense Key returned from last submitted command
1129 *Action
= ACTION_NO_ACTION
;
1133 if (ScsiDiskIsNoMedia (SenseData
, NumberOfSenseKeys
)) {
1134 ScsiDiskDevice
->BlkIo
.Media
->MediaPresent
= FALSE
;
1135 ScsiDiskDevice
->BlkIo
.Media
->LastBlock
= 0;
1136 *Action
= ACTION_NO_ACTION
;
1140 if (ScsiDiskIsMediaChange (SenseData
, NumberOfSenseKeys
)) {
1141 ScsiDiskDevice
->BlkIo
.Media
->MediaId
++;
1145 if (ScsiDiskIsMediaError (SenseData
, NumberOfSenseKeys
)) {
1146 ScsiDiskDevice
->BlkIo
.Media
->MediaPresent
= FALSE
;
1147 ScsiDiskDevice
->BlkIo
.Media
->LastBlock
= 0;
1148 return EFI_DEVICE_ERROR
;
1151 if (ScsiDiskIsHardwareError (SenseData
, NumberOfSenseKeys
)) {
1152 return EFI_DEVICE_ERROR
;
1155 if (!ScsiDiskIsDriveReady (SenseData
, NumberOfSenseKeys
, &RetryLater
)) {
1157 *Action
= ACTION_RETRY_COMMAND_LATER
;
1161 return EFI_DEVICE_ERROR
;
1168 ScsiDiskReadCapacity (
1169 SCSI_DISK_DEV
*ScsiDiskDevice
,
1171 EFI_SCSI_SENSE_DATA
**SenseDataArray
,
1172 UINTN
*NumberOfSenseKeys
1176 Routine Description:
1178 TODO: Add function description
1182 ScsiDiskDevice - TODO: add argument description
1183 NeedRetry - TODO: add argument description
1184 SenseDataArray - TODO: add argument description
1185 NumberOfSenseKeys - TODO: add argument description
1189 EFI_SUCCESS - TODO: Add description for return value
1190 EFI_DEVICE_ERROR - TODO: Add description for return value
1191 EFI_DEVICE_ERROR - TODO: Add description for return value
1192 EFI_DEVICE_ERROR - TODO: Add description for return value
1193 EFI_DEVICE_ERROR - TODO: Add description for return value
1194 EFI_DEVICE_ERROR - TODO: Add description for return value
1195 EFI_DEVICE_ERROR - TODO: Add description for return value
1196 EFI_DEVICE_ERROR - TODO: Add description for return value
1197 EFI_DEVICE_ERROR - TODO: Add description for return value
1198 EFI_DEVICE_ERROR - TODO: Add description for return value
1202 EFI_SCSI_DISK_CAPACITY_DATA CapacityData
;
1204 UINT8 HostAdapterStatus
;
1206 EFI_STATUS CommandStatus
;
1210 UINT8 SenseDataLength
;
1212 SenseDataLength
= 0;
1213 ZeroMem (&CapacityData
, sizeof (EFI_SCSI_DISK_CAPACITY_DATA
));
1214 DataLength
= sizeof (EFI_SCSI_DISK_CAPACITY_DATA
);
1216 *NumberOfSenseKeys
= 0;
1219 // submit Read Capacity Command. in this call,not request sense data
1221 CommandStatus
= SubmitReadCapacityCommand (
1222 ScsiDiskDevice
->ScsiIo
,
1223 EfiScsiStallSeconds (1),
1228 (VOID
*) &CapacityData
,
1232 if (CommandStatus
== EFI_SUCCESS
) {
1234 // no need to check HostAdapterStatus and TargetStatus
1236 GetMediaInfo (ScsiDiskDevice
, &CapacityData
);
1238 } else if (CommandStatus
== EFI_NOT_READY
) {
1240 // no need to check HostAdapterStatus and TargetStatus
1243 return EFI_DEVICE_ERROR
;
1244 } else if ((CommandStatus
== EFI_INVALID_PARAMETER
) || (CommandStatus
== EFI_UNSUPPORTED
)) {
1246 // no need to check HostAdapterStatus and TargetStatus
1249 return EFI_DEVICE_ERROR
;
1252 // go ahead to check HostAdapterStatus and TargetStatus
1253 // (EFI_TIMEOUT, EFI_DEVICE_ERROR, EFI_WARN_BUFFER_TOO_SMALL)
1256 Status
= CheckHostAdapterStatus (HostAdapterStatus
);
1257 if ((Status
== EFI_TIMEOUT
) || (Status
== EFI_NOT_READY
)) {
1259 return EFI_DEVICE_ERROR
;
1260 } else if (Status
== EFI_DEVICE_ERROR
) {
1262 // reset the scsi channel
1264 ScsiDiskDevice
->ScsiIo
->ResetBus (ScsiDiskDevice
->ScsiIo
);
1266 return EFI_DEVICE_ERROR
;
1269 Status
= CheckTargetStatus (TargetStatus
);
1270 if (Status
== EFI_NOT_READY
) {
1272 // reset the scsi device
1274 ScsiDiskDevice
->ScsiIo
->ResetDevice (ScsiDiskDevice
->ScsiIo
);
1276 return EFI_DEVICE_ERROR
;
1277 } else if (Status
== EFI_DEVICE_ERROR
) {
1279 return EFI_DEVICE_ERROR
;
1283 // if goes here, meant SubmitReadCapacityCommand() failed.
1284 // if ScsiDiskRequestSenseKeys() succeeds at last,
1285 // better retry SubmitReadCapacityCommand(). (by setting *NeedRetry = TRUE)
1288 for (Index
= 0; Index
< MaxRetry
; Index
++) {
1290 Status
= ScsiDiskRequestSenseKeys (
1297 if (!EFI_ERROR (Status
)) {
1299 return EFI_DEVICE_ERROR
;
1303 return EFI_DEVICE_ERROR
;
1307 // ScsiDiskRequestSenseKeys() failed after several rounds of retry.
1308 // set *NeedRetry = FALSE to avoid the outside caller try again.
1311 return EFI_DEVICE_ERROR
;
1315 CheckHostAdapterStatus (
1316 UINT8 HostAdapterStatus
1320 Routine Description:
1322 TODO: Add function description
1326 HostAdapterStatus - TODO: add argument description
1330 EFI_SUCCESS - TODO: Add description for return value
1331 EFI_TIMEOUT - TODO: Add description for return value
1332 EFI_NOT_READY - TODO: Add description for return value
1333 EFI_DEVICE_ERROR - TODO: Add description for return value
1334 EFI_SUCCESS - TODO: Add description for return value
1338 switch (HostAdapterStatus
) {
1339 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_OK
:
1342 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_SELECTION_TIMEOUT
:
1343 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_TIMEOUT
:
1344 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_TIMEOUT_COMMAND
:
1347 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_MESSAGE_REJECT
:
1348 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_PARITY_ERROR
:
1349 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_REQUEST_SENSE_FAILED
:
1350 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN
:
1351 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_BUS_RESET
:
1352 return EFI_NOT_READY
;
1354 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_BUS_FREE
:
1355 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_PHASE_ERROR
:
1356 return EFI_DEVICE_ERROR
;
1369 Routine Description:
1371 TODO: Add function description
1375 TargetStatus - TODO: add argument description
1379 EFI_SUCCESS - TODO: Add description for return value
1380 EFI_NOT_READY - TODO: Add description for return value
1381 EFI_DEVICE_ERROR - TODO: Add description for return value
1382 EFI_SUCCESS - TODO: Add description for return value
1386 switch (TargetStatus
) {
1387 case EFI_SCSI_IO_STATUS_TARGET_GOOD
:
1388 case EFI_SCSI_IO_STATUS_TARGET_CHECK_CONDITION
:
1389 case EFI_SCSI_IO_STATUS_TARGET_CONDITION_MET
:
1392 case EFI_SCSI_IO_STATUS_TARGET_INTERMEDIATE
:
1393 case EFI_SCSI_IO_STATUS_TARGET_INTERMEDIATE_CONDITION_MET
:
1394 case EFI_SCSI_IO_STATUS_TARGET_BUSY
:
1395 case EFI_SCSI_IO_STATUS_TARGET_COMMOND_TERMINATED
:
1396 case EFI_SCSI_IO_STATUS_TARGET_QUEUE_FULL
:
1397 return EFI_NOT_READY
;
1399 case EFI_SCSI_IO_STATUS_TARGET_RESERVATION_CONFLICT
:
1400 return EFI_DEVICE_ERROR
;
1409 ScsiDiskRequestSenseKeys (
1410 SCSI_DISK_DEV
*ScsiDiskDevice
,
1412 EFI_SCSI_SENSE_DATA
**SenseDataArray
,
1413 UINTN
*NumberOfSenseKeys
,
1414 BOOLEAN AskResetIfError
1416 // TODO: function comment should start with '/*++'
1418 Retrieve all sense keys from the device.
1419 When encountering error during the process,
1420 if retrieve sense keys before error encounterred,
1421 return the sense keys with return status set to EFI_SUCCESS,
1422 and NeedRetry set to FALSE; otherwize, return the proper return
1425 // TODO: function comment should end with '--*/'
1426 // TODO: function comment is missing 'Routine Description:'
1427 // TODO: function comment is missing 'Arguments:'
1428 // TODO: function comment is missing 'Returns:'
1429 // TODO: ScsiDiskDevice - add argument and description to function comment
1430 // TODO: NeedRetry - add argument and description to function comment
1431 // TODO: SenseDataArray - add argument and description to function comment
1432 // TODO: NumberOfSenseKeys - add argument and description to function comment
1433 // TODO: AskResetIfError - add argument and description to function comment
1434 // TODO: EFI_SUCCESS - add return value to function comment
1435 // TODO: EFI_DEVICE_ERROR - add return value to function comment
1436 // TODO: EFI_SUCCESS - add return value to function comment
1438 EFI_SCSI_SENSE_DATA
*PtrSenseData
;
1439 UINT8 SenseDataLength
;
1442 EFI_STATUS FallStatus
;
1443 UINT8 HostAdapterStatus
;
1446 FallStatus
= EFI_SUCCESS
;
1447 SenseDataLength
= sizeof (EFI_SCSI_SENSE_DATA
);
1450 ScsiDiskDevice
->SenseData
,
1451 sizeof (EFI_SCSI_SENSE_DATA
) * (ScsiDiskDevice
->SenseDataNumber
)
1454 *NumberOfSenseKeys
= 0;
1455 *SenseDataArray
= ScsiDiskDevice
->SenseData
;
1456 PtrSenseData
= ScsiDiskDevice
->SenseData
;
1458 for (SenseReq
= TRUE
; SenseReq
;) {
1460 Status
= SubmitRequestSenseCommand (
1461 ScsiDiskDevice
->ScsiIo
,
1462 EfiScsiStallSeconds (2),
1468 if ((Status
== EFI_SUCCESS
) || (Status
== EFI_WARN_BUFFER_TOO_SMALL
)) {
1469 FallStatus
= EFI_SUCCESS
;
1470 } else if ((Status
== EFI_TIMEOUT
) || (Status
== EFI_NOT_READY
)) {
1472 FallStatus
= EFI_DEVICE_ERROR
;
1473 } else if ((Status
== EFI_INVALID_PARAMETER
) || (Status
== EFI_UNSUPPORTED
)) {
1475 FallStatus
= EFI_DEVICE_ERROR
;
1476 } else if (Status
== EFI_DEVICE_ERROR
) {
1477 if (AskResetIfError
) {
1478 ScsiDiskDevice
->ScsiIo
->ResetDevice (ScsiDiskDevice
->ScsiIo
);
1481 FallStatus
= EFI_DEVICE_ERROR
;
1484 if (EFI_ERROR (FallStatus
)) {
1485 if (*NumberOfSenseKeys
!= 0) {
1489 return EFI_DEVICE_ERROR
;
1493 (*NumberOfSenseKeys
) += 1;
1496 // no more sense key or number of sense keys exceeds predefined,
1499 if ((PtrSenseData
->Sense_Key
== EFI_SCSI_SK_NO_SENSE
) ||
1500 (*NumberOfSenseKeys
== ScsiDiskDevice
->SenseDataNumber
)) {
1513 SCSI_DISK_DEV
*ScsiDiskDevice
,
1514 EFI_SCSI_DISK_CAPACITY_DATA
*Capacity
1518 Routine Description:
1520 TODO: Add function description
1524 ScsiDiskDevice - TODO: add argument description
1525 Capacity - TODO: add argument description
1529 TODO: add return values
1533 ScsiDiskDevice
->BlkIo
.Media
->LastBlock
= (Capacity
->LastLba3
<< 24) |
1534 (Capacity
->LastLba2
<< 16) |
1535 (Capacity
->LastLba1
<< 8) |
1538 ScsiDiskDevice
->BlkIo
.Media
->MediaPresent
= TRUE
;
1539 ScsiDiskDevice
->BlkIo
.Media
->BlockSize
= (Capacity
->BlockSize3
<< 24) |
1540 (Capacity
->BlockSize2
<< 16) |
1541 (Capacity
->BlockSize1
<< 8) |
1542 Capacity
->BlockSize0
;
1543 if (ScsiDiskDevice
->DeviceType
== EFI_SCSI_TYPE_DISK
) {
1544 ScsiDiskDevice
->BlkIo
.Media
->BlockSize
= 0x200;
1547 if (ScsiDiskDevice
->DeviceType
== EFI_SCSI_TYPE_CDROM
) {
1548 ScsiDiskDevice
->BlkIo
.Media
->BlockSize
= 0x800;
1554 SCSI_DISK_DEV
*ScsiDiskDevice
1558 Routine Description:
1560 TODO: Add function description
1564 ScsiDiskDevice - TODO: add argument description
1568 TODO: add return values
1572 ScsiDiskDevice
->FixedDevice
= (BOOLEAN
) (ScsiDiskDevice
->InquiryData
.RMB
? 0 : 1);
1573 ScsiDiskDevice
->BlkIoMedia
.RemovableMedia
= (BOOLEAN
) (!ScsiDiskDevice
->FixedDevice
);
1577 ScsiDiskReadSectors (
1578 SCSI_DISK_DEV
*ScsiDiskDevice
,
1581 UINTN NumberOfBlocks
1585 Routine Description:
1587 TODO: Add function description
1591 ScsiDiskDevice - TODO: add argument description
1592 Buffer - TODO: add argument description
1593 Lba - TODO: add argument description
1594 NumberOfBlocks - TODO: add argument description
1598 EFI_DEVICE_ERROR - TODO: Add description for return value
1599 EFI_DEVICE_ERROR - TODO: Add description for return value
1600 EFI_SUCCESS - TODO: Add description for return value
1604 UINTN BlocksRemaining
;
1616 EFI_SCSI_SENSE_DATA
*SenseData
;
1617 UINT8 SenseDataLength
;
1618 UINTN NumberOfSenseKeys
;
1621 SenseDataLength
= 0;
1622 NumberOfSenseKeys
= 0;
1624 Status
= EFI_SUCCESS
;
1626 BlocksRemaining
= NumberOfBlocks
;
1627 BlockSize
= ScsiDiskDevice
->BlkIo
.Media
->BlockSize
;
1629 // limit the data bytes that can be transferred by one Read(10) Command
1634 Lba32
= (UINT32
) Lba
;
1636 while (BlocksRemaining
> 0) {
1638 if (BlocksRemaining
<= MaxBlock
) {
1640 SectorCount
= (UINT16
) BlocksRemaining
;
1643 SectorCount
= MaxBlock
;
1646 ByteCount
= SectorCount
* BlockSize
;
1647 Timeout
= EfiScsiStallSeconds (2);
1650 for (Index
= 0; Index
< MaxRetry
; Index
++) {
1652 Status
= ScsiDiskRead10 (
1663 if (!EFI_ERROR (Status
)) {
1668 return EFI_DEVICE_ERROR
;
1673 if ((Index
== MaxRetry
) && (Status
!= EFI_SUCCESS
)) {
1674 return EFI_DEVICE_ERROR
;
1678 // actual transferred sectors
1680 SectorCount
= ByteCount
/ BlockSize
;
1682 Lba32
+= SectorCount
;
1683 PtrBuffer
= PtrBuffer
+ SectorCount
* BlockSize
;
1684 BlocksRemaining
-= SectorCount
;
1691 ScsiDiskWriteSectors (
1692 SCSI_DISK_DEV
*ScsiDiskDevice
,
1695 UINTN NumberOfBlocks
1699 Routine Description:
1701 TODO: Add function description
1705 ScsiDiskDevice - TODO: add argument description
1706 Buffer - TODO: add argument description
1707 Lba - TODO: add argument description
1708 NumberOfBlocks - TODO: add argument description
1712 EFI_DEVICE_ERROR - TODO: Add description for return value
1713 EFI_DEVICE_ERROR - TODO: Add description for return value
1714 EFI_SUCCESS - TODO: Add description for return value
1718 UINTN BlocksRemaining
;
1730 EFI_SCSI_SENSE_DATA
*SenseData
;
1731 UINT8 SenseDataLength
;
1732 UINTN NumberOfSenseKeys
;
1735 SenseDataLength
= 0;
1736 NumberOfSenseKeys
= 0;
1738 Status
= EFI_SUCCESS
;
1740 BlocksRemaining
= NumberOfBlocks
;
1741 BlockSize
= ScsiDiskDevice
->BlkIo
.Media
->BlockSize
;
1743 // limit the data bytes that can be transferred by one Write(10) Command
1748 Lba32
= (UINT32
) Lba
;
1750 while (BlocksRemaining
> 0) {
1752 if (BlocksRemaining
<= MaxBlock
) {
1754 SectorCount
= (UINT16
) BlocksRemaining
;
1757 SectorCount
= MaxBlock
;
1760 ByteCount
= SectorCount
* BlockSize
;
1761 Timeout
= EfiScsiStallSeconds (2);
1763 for (Index
= 0; Index
< MaxRetry
; Index
++) {
1764 Status
= ScsiDiskWrite10 (
1775 if (!EFI_ERROR (Status
)) {
1780 return EFI_DEVICE_ERROR
;
1784 if ((Index
== MaxRetry
) && (Status
!= EFI_SUCCESS
)) {
1785 return EFI_DEVICE_ERROR
;
1788 // actual transferred sectors
1790 SectorCount
= ByteCount
/ BlockSize
;
1792 Lba32
+= SectorCount
;
1793 PtrBuffer
= PtrBuffer
+ SectorCount
* BlockSize
;
1794 BlocksRemaining
-= SectorCount
;
1802 SCSI_DISK_DEV
*ScsiDiskDevice
,
1804 EFI_SCSI_SENSE_DATA
**SenseDataArray
,
1805 UINTN
*NumberOfSenseKeys
,
1814 Routine Description:
1816 TODO: Add function description
1820 ScsiDiskDevice - TODO: add argument description
1821 NeedRetry - TODO: add argument description
1822 SenseDataArray - TODO: add argument description
1823 NumberOfSenseKeys - TODO: add argument description
1824 Timeout - TODO: add argument description
1825 DataBuffer - TODO: add argument description
1826 DataLength - TODO: add argument description
1827 StartLba - TODO: add argument description
1828 SectorSize - TODO: add argument description
1832 TODO: add return values
1836 UINT8 SenseDataLength
;
1838 UINT8 HostAdapterStatus
;
1842 *NumberOfSenseKeys
= 0;
1843 SenseDataLength
= 0;
1844 Status
= SubmitRead10Command (
1845 ScsiDiskDevice
->ScsiIo
,
1861 SCSI_DISK_DEV
*ScsiDiskDevice
,
1863 EFI_SCSI_SENSE_DATA
**SenseDataArray
,
1864 UINTN
*NumberOfSenseKeys
,
1873 Routine Description:
1875 TODO: Add function description
1879 ScsiDiskDevice - TODO: add argument description
1880 NeedRetry - TODO: add argument description
1881 SenseDataArray - TODO: add argument description
1882 NumberOfSenseKeys - TODO: add argument description
1883 Timeout - TODO: add argument description
1884 DataBuffer - TODO: add argument description
1885 DataLength - TODO: add argument description
1886 StartLba - TODO: add argument description
1887 SectorSize - TODO: add argument description
1891 TODO: add return values
1896 UINT8 SenseDataLength
;
1897 UINT8 HostAdapterStatus
;
1901 *NumberOfSenseKeys
= 0;
1902 SenseDataLength
= 0;
1903 Status
= SubmitWrite10Command (
1904 ScsiDiskDevice
->ScsiIo
,
1920 IN EFI_SCSI_SENSE_DATA
*SenseData
,
1921 IN UINTN SenseCounts
1925 Routine Description:
1927 TODO: Add function description
1931 SenseData - TODO: add argument description
1932 SenseCounts - TODO: add argument description
1936 TODO: add return values
1940 EFI_SCSI_SENSE_DATA
*SensePtr
;
1945 SensePtr
= SenseData
;
1947 for (Index
= 0; Index
< SenseCounts
; Index
++) {
1950 // Sense Key is EFI_SCSI_SK_NOT_READY (0x2),
1951 // Additional Sense Code is ASC_NO_MEDIA (0x3A)
1953 if ((SensePtr
->Sense_Key
== EFI_SCSI_SK_NOT_READY
) &&
1954 (SensePtr
->Addnl_Sense_Code
== EFI_SCSI_ASC_NO_MEDIA
)) {
1965 ScsiDiskIsMediaError (
1966 IN EFI_SCSI_SENSE_DATA
*SenseData
,
1967 IN UINTN SenseCounts
1971 Routine Description:
1973 TODO: Add function description
1977 SenseData - TODO: add argument description
1978 SenseCounts - TODO: add argument description
1982 TODO: add return values
1986 EFI_SCSI_SENSE_DATA
*SensePtr
;
1991 SensePtr
= SenseData
;
1993 for (Index
= 0; Index
< SenseCounts
; Index
++) {
1995 switch (SensePtr
->Sense_Key
) {
1997 case EFI_SCSI_SK_MEDIUM_ERROR
:
1999 // Sense Key is EFI_SCSI_SK_MEDIUM_ERROR (0x3)
2001 switch (SensePtr
->Addnl_Sense_Code
) {
2006 case EFI_SCSI_ASC_MEDIA_ERR1
:
2011 case EFI_SCSI_ASC_MEDIA_ERR2
:
2016 case EFI_SCSI_ASC_MEDIA_ERR3
:
2017 case EFI_SCSI_ASC_MEDIA_ERR4
:
2027 case EFI_SCSI_SK_NOT_READY
:
2029 // Sense Key is EFI_SCSI_SK_NOT_READY (0x2)
2031 switch (SensePtr
->Addnl_Sense_Code
) {
2033 // Additional Sense Code is ASC_MEDIA_UPSIDE_DOWN (0x6)
2035 case EFI_SCSI_ASC_MEDIA_UPSIDE_DOWN
:
2055 ScsiDiskIsHardwareError (
2056 IN EFI_SCSI_SENSE_DATA
*SenseData
,
2057 IN UINTN SenseCounts
2061 Routine Description:
2063 TODO: Add function description
2067 SenseData - TODO: add argument description
2068 SenseCounts - TODO: add argument description
2072 TODO: add return values
2076 EFI_SCSI_SENSE_DATA
*SensePtr
;
2081 SensePtr
= SenseData
;
2083 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2086 // Sense Key is EFI_SCSI_SK_HARDWARE_ERROR (0x4)
2088 if (SensePtr
->Sense_Key
== EFI_SCSI_SK_HARDWARE_ERROR
) {
2099 ScsiDiskIsMediaChange (
2100 IN EFI_SCSI_SENSE_DATA
*SenseData
,
2101 IN UINTN SenseCounts
2105 Routine Description:
2107 TODO: Add function description
2111 SenseData - TODO: add argument description
2112 SenseCounts - TODO: add argument description
2116 TODO: add return values
2120 EFI_SCSI_SENSE_DATA
*SensePtr
;
2122 BOOLEAN IsMediaChanged
;
2124 IsMediaChanged
= FALSE
;
2125 SensePtr
= SenseData
;
2127 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2129 // Sense Key is EFI_SCSI_SK_UNIT_ATTENTION (0x6),
2130 // Additional sense code is EFI_SCSI_ASC_MEDIA_CHANGE (0x28)
2132 if ((SensePtr
->Sense_Key
== EFI_SCSI_SK_UNIT_ATTENTION
) &&
2133 (SensePtr
->Addnl_Sense_Code
== EFI_SCSI_ASC_MEDIA_CHANGE
)) {
2134 IsMediaChanged
= TRUE
;
2140 return IsMediaChanged
;
2144 ScsiDiskIsResetBefore (
2145 IN EFI_SCSI_SENSE_DATA
*SenseData
,
2146 IN UINTN SenseCounts
2150 Routine Description:
2152 TODO: Add function description
2156 SenseData - TODO: add argument description
2157 SenseCounts - TODO: add argument description
2161 TODO: add return values
2165 EFI_SCSI_SENSE_DATA
*SensePtr
;
2167 BOOLEAN IsResetBefore
;
2169 IsResetBefore
= FALSE
;
2170 SensePtr
= SenseData
;
2172 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2175 // Sense Key is EFI_SCSI_SK_UNIT_ATTENTION (0x6)
2176 // Additional Sense Code is EFI_SCSI_ASC_RESET (0x29)
2178 if ((SensePtr
->Sense_Key
== EFI_SCSI_SK_UNIT_ATTENTION
) &&
2179 (SensePtr
->Addnl_Sense_Code
== EFI_SCSI_ASC_RESET
)) {
2180 IsResetBefore
= TRUE
;
2186 return IsResetBefore
;
2190 ScsiDiskIsDriveReady (
2191 IN EFI_SCSI_SENSE_DATA
*SenseData
,
2192 IN UINTN SenseCounts
,
2193 OUT BOOLEAN
*RetryLater
2197 Routine Description:
2199 TODO: Add function description
2203 SenseData - TODO: add argument description
2204 SenseCounts - TODO: add argument description
2205 RetryLater - TODO: add argument description
2209 TODO: add return values
2213 EFI_SCSI_SENSE_DATA
*SensePtr
;
2218 *RetryLater
= FALSE
;
2219 SensePtr
= SenseData
;
2221 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2223 switch (SensePtr
->Sense_Key
) {
2225 case EFI_SCSI_SK_NOT_READY
:
2227 // Sense Key is EFI_SCSI_SK_NOT_READY (0x2)
2229 switch (SensePtr
->Addnl_Sense_Code
) {
2230 case EFI_SCSI_ASC_NOT_READY
:
2232 // Additional Sense Code is EFI_SCSI_ASC_NOT_READY (0x4)
2234 switch (SensePtr
->Addnl_Sense_Code_Qualifier
) {
2235 case EFI_SCSI_ASCQ_IN_PROGRESS
:
2237 // Additional Sense Code Qualifier is
2238 // EFI_SCSI_ASCQ_IN_PROGRESS (0x1)
2246 *RetryLater
= FALSE
;
2267 ScsiDiskHaveSenseKey (
2268 IN EFI_SCSI_SENSE_DATA
*SenseData
,
2269 IN UINTN SenseCounts
2273 Routine Description:
2275 TODO: Add function description
2279 SenseData - TODO: add argument description
2280 SenseCounts - TODO: add argument description
2284 TODO: add return values
2288 EFI_SCSI_SENSE_DATA
*SensePtr
;
2290 BOOLEAN HaveSenseKey
;
2292 if (SenseCounts
== 0) {
2293 HaveSenseKey
= FALSE
;
2295 HaveSenseKey
= TRUE
;
2298 SensePtr
= SenseData
;
2300 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2303 // Sense Key is SK_NO_SENSE (0x0)
2305 if ((SensePtr
->Sense_Key
== EFI_SCSI_SK_NO_SENSE
) &&
2307 HaveSenseKey
= FALSE
;
2313 return HaveSenseKey
;
2317 ReleaseScsiDiskDeviceResources (
2318 IN SCSI_DISK_DEV
*ScsiDiskDevice
2322 Routine Description:
2324 TODO: Add function description
2328 ScsiDiskDevice - TODO: add argument description
2332 TODO: add return values
2336 if (ScsiDiskDevice
== NULL
) {
2340 if (ScsiDiskDevice
->SenseData
!= NULL
) {
2341 gBS
->FreePool (ScsiDiskDevice
->SenseData
);
2342 ScsiDiskDevice
->SenseData
= NULL
;
2345 if (ScsiDiskDevice
->ControllerNameTable
!= NULL
) {
2346 FreeUnicodeStringTable (ScsiDiskDevice
->ControllerNameTable
);
2347 ScsiDiskDevice
->ControllerNameTable
= NULL
;
2350 gBS
->FreePool (ScsiDiskDevice
);
2352 ScsiDiskDevice
= NULL
;