3 Copyright (c) 2006 - 2007, 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 <Protocol/ScsiIo.h>
24 #include <Protocol/ComponentName.h>
25 #include <Protocol/BlockIo.h>
26 #include <Protocol/DriverBinding.h>
27 #include <Protocol/ScsiPassThruExt.h>
29 #include <Library/DebugLib.h>
30 #include <Library/UefiDriverEntryPoint.h>
31 #include <Library/UefiLib.h>
32 #include <Library/BaseMemoryLib.h>
33 #include <Library/ScsiLib.h>
34 #include <Library/UefiBootServicesTableLib.h>
38 EFI_DRIVER_BINDING_PROTOCOL gScsiDiskDriverBinding
= {
39 ScsiDiskDriverBindingSupported
,
40 ScsiDiskDriverBindingStart
,
41 ScsiDiskDriverBindingStop
,
48 The user Entry Point for module ScsiDisk. The user code starts with this function.
50 @param[in] ImageHandle The firmware allocated handle for the EFI image.
51 @param[in] SystemTable A pointer to the EFI System Table.
53 @retval EFI_SUCCESS The entry point is executed successfully.
54 @retval other Some error occurs when executing this entry point.
60 IN EFI_HANDLE ImageHandle
,
61 IN EFI_SYSTEM_TABLE
*SystemTable
67 // Install driver model protocol(s).
69 Status
= EfiLibInstallAllDriverProtocols (
72 &gScsiDiskDriverBinding
,
74 &gScsiDiskComponentName
,
78 ASSERT_EFI_ERROR (Status
);
86 ScsiDiskDriverBindingSupported (
87 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
88 IN EFI_HANDLE Controller
,
89 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
95 Test to see if this driver supports ControllerHandle. Any ControllerHandle
96 that has ScsiIoProtocol installed will be supported.
100 This - Protocol instance pointer.
101 Controller - Handle of device to test
102 RemainingDevicePath - Not used
106 EFI_SUCCESS - This driver supports this device.
107 EFI_UNSUPPORTED - This driver does not support this device.
113 EFI_SCSI_IO_PROTOCOL
*ScsiIo
;
116 Status
= gBS
->OpenProtocol (
118 &gEfiScsiIoProtocolGuid
,
120 This
->DriverBindingHandle
,
122 EFI_OPEN_PROTOCOL_BY_DRIVER
124 if (EFI_ERROR (Status
)) {
128 Status
= ScsiIo
->GetDeviceType (ScsiIo
, &DeviceType
);
129 if (!EFI_ERROR (Status
)) {
130 if ((DeviceType
== EFI_SCSI_TYPE_DISK
) || (DeviceType
== EFI_SCSI_TYPE_CDROM
)) {
131 Status
= EFI_SUCCESS
;
133 Status
= EFI_UNSUPPORTED
;
139 &gEfiScsiIoProtocolGuid
,
140 This
->DriverBindingHandle
,
148 ScsiDiskDriverBindingStart (
149 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
150 IN EFI_HANDLE Controller
,
151 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
157 Start SCSI Disk Driver, and attach BlockIoProtocol to it.
161 This - Protocol instance pointer.
162 Controller - Handle of device to test
163 RemainingDevicePath - Not used
167 EFI_SUCCESS - This driver supports this device.
168 EFI_UNSUPPORTED - This driver does not support this device.
174 EFI_SCSI_IO_PROTOCOL
*ScsiIo
;
175 SCSI_DISK_DEV
*ScsiDiskDevice
;
181 Status
= gBS
->AllocatePool (
183 sizeof (SCSI_DISK_DEV
),
184 (VOID
**) &ScsiDiskDevice
186 if (EFI_ERROR (Status
)) {
190 ZeroMem (ScsiDiskDevice
, sizeof (SCSI_DISK_DEV
));
192 Status
= gBS
->OpenProtocol (
194 &gEfiScsiIoProtocolGuid
,
196 This
->DriverBindingHandle
,
198 EFI_OPEN_PROTOCOL_BY_DRIVER
200 if (EFI_ERROR (Status
)) {
201 gBS
->FreePool (ScsiDiskDevice
);
205 ScsiDiskDevice
->Signature
= SCSI_DISK_DEV_SIGNATURE
;
206 ScsiDiskDevice
->ScsiIo
= ScsiIo
;
207 ScsiDiskDevice
->BlkIo
.Media
= &ScsiDiskDevice
->BlkIoMedia
;
208 ScsiDiskDevice
->BlkIo
.Reset
= ScsiDiskReset
;
209 ScsiDiskDevice
->BlkIo
.ReadBlocks
= ScsiDiskReadBlocks
;
210 ScsiDiskDevice
->BlkIo
.WriteBlocks
= ScsiDiskWriteBlocks
;
211 ScsiDiskDevice
->BlkIo
.FlushBlocks
= ScsiDiskFlushBlocks
;
212 ScsiDiskDevice
->Handle
= Controller
;
214 ScsiIo
->GetDeviceType (ScsiIo
, &(ScsiDiskDevice
->DeviceType
));
215 switch (ScsiDiskDevice
->DeviceType
) {
216 case EFI_SCSI_TYPE_DISK
:
217 ScsiDiskDevice
->BlkIo
.Media
->BlockSize
= 0x200;
220 case EFI_SCSI_TYPE_CDROM
:
221 ScsiDiskDevice
->BlkIo
.Media
->BlockSize
= 0x800;
225 // The Sense Data Array's initial size is 6
227 ScsiDiskDevice
->SenseDataNumber
= 6;
228 Status
= gBS
->AllocatePool (
230 sizeof (EFI_SCSI_SENSE_DATA
) * ScsiDiskDevice
->SenseDataNumber
,
231 (VOID
**) &(ScsiDiskDevice
->SenseData
)
233 if (EFI_ERROR (Status
)) {
236 &gEfiScsiIoProtocolGuid
,
237 This
->DriverBindingHandle
,
240 gBS
->FreePool (ScsiDiskDevice
);
245 ScsiDiskDevice
->SenseData
,
246 sizeof (EFI_SCSI_SENSE_DATA
) * ScsiDiskDevice
->SenseDataNumber
250 // Retrive device information
253 for (Index
= 0; Index
< MaxRetry
; Index
++) {
254 Status
= ScsiDiskInquiryDevice (ScsiDiskDevice
, &NeedRetry
);
255 if (!EFI_ERROR (Status
)) {
260 gBS
->FreePool (ScsiDiskDevice
->SenseData
);
263 &gEfiScsiIoProtocolGuid
,
264 This
->DriverBindingHandle
,
267 gBS
->FreePool (ScsiDiskDevice
);
268 return EFI_DEVICE_ERROR
;
272 // The second parameter "TRUE" means must
273 // retrieve media capacity
275 Status
= ScsiDiskDetectMedia (ScsiDiskDevice
, TRUE
, &Temp
);
276 if (!EFI_ERROR (Status
)) {
277 Status
= gBS
->InstallMultipleProtocolInterfaces (
279 &gEfiBlockIoProtocolGuid
,
280 &ScsiDiskDevice
->BlkIo
,
285 if (EFI_ERROR (Status
)) {
286 gBS
->FreePool (ScsiDiskDevice
->SenseData
);
289 &gEfiScsiIoProtocolGuid
,
290 This
->DriverBindingHandle
,
293 gBS
->FreePool (ScsiDiskDevice
);
297 ScsiDiskDevice
->ControllerNameTable
= NULL
;
300 gScsiDiskComponentName
.SupportedLanguages
,
301 &ScsiDiskDevice
->ControllerNameTable
,
311 ScsiDiskDriverBindingStop (
312 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
313 IN EFI_HANDLE Controller
,
314 IN UINTN NumberOfChildren
,
315 IN EFI_HANDLE
*ChildHandleBuffer
321 Stop this driver on ControllerHandle. Support stoping any child handles
322 created by this driver.
326 This - Protocol instance pointer.
327 Controller - Handle of device to stop driver on
328 NumberOfChildren - Number of Children in the ChildHandleBuffer
329 ChildHandleBuffer - List of handles for the children we need to stop.
339 EFI_BLOCK_IO_PROTOCOL
*BlkIo
;
340 SCSI_DISK_DEV
*ScsiDiskDevice
;
343 Status
= gBS
->OpenProtocol (
345 &gEfiBlockIoProtocolGuid
,
347 This
->DriverBindingHandle
,
349 EFI_OPEN_PROTOCOL_GET_PROTOCOL
351 if (EFI_ERROR (Status
)) {
355 ScsiDiskDevice
= SCSI_DISK_DEV_FROM_THIS (BlkIo
);
356 Status
= gBS
->UninstallProtocolInterface (
358 &gEfiBlockIoProtocolGuid
,
359 &ScsiDiskDevice
->BlkIo
361 if (!EFI_ERROR (Status
)) {
364 &gEfiScsiIoProtocolGuid
,
365 This
->DriverBindingHandle
,
369 ReleaseScsiDiskDeviceResources (ScsiDiskDevice
);
383 IN EFI_BLOCK_IO_PROTOCOL
*This
,
384 IN BOOLEAN ExtendedVerification
394 This - The pointer of EFI_BLOCK_IO_PROTOCOL
395 ExtendedVerification - The flag about if extend verificate
404 SCSI_DISK_DEV
*ScsiDiskDevice
;
407 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
409 ScsiDiskDevice
= SCSI_DISK_DEV_FROM_THIS (This
);
411 Status
= ScsiDiskDevice
->ScsiIo
->ResetDevice (ScsiDiskDevice
->ScsiIo
);
413 if (!ExtendedVerification
) {
417 Status
= ScsiDiskDevice
->ScsiIo
->ResetBus (ScsiDiskDevice
->ScsiIo
);
420 gBS
->RestoreTPL (OldTpl
);
427 IN EFI_BLOCK_IO_PROTOCOL
*This
,
437 The function is to Read Block from SCSI Disk
441 This - The pointer of EFI_BLOCK_IO_PROTOCOL
442 MediaId - The Id of Media detected
443 LBA - The logic block address
444 BufferSize - The size of Buffer
445 Buffer - The buffer to fill the read out data
449 EFI_INVALID_PARAMETER - Invalid parameter passed in.
450 EFI_SUCCESS - Successfully to read out block.
451 EFI_DEVICE_ERROR - Fail to detect media.
452 EFI_NO_MEDIA - Media is not present.
453 EFI_MEDIA_CHANGED - Media has changed.
454 EFI_BAD_BUFFER_SIZE - The buffer size is not multiple of BlockSize.
458 SCSI_DISK_DEV
*ScsiDiskDevice
;
459 EFI_BLOCK_IO_MEDIA
*Media
;
462 UINTN NumberOfBlocks
;
468 return EFI_INVALID_PARAMETER
;
471 if (BufferSize
== 0) {
475 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
477 ScsiDiskDevice
= SCSI_DISK_DEV_FROM_THIS (This
);
479 if (!IsDeviceFixed (ScsiDiskDevice
)) {
481 Status
= ScsiDiskDetectMedia (ScsiDiskDevice
, FALSE
, &MediaChange
);
482 if (EFI_ERROR (Status
)) {
483 Status
= EFI_DEVICE_ERROR
;
488 gBS
->ReinstallProtocolInterface (
489 ScsiDiskDevice
->Handle
,
490 &gEfiBlockIoProtocolGuid
,
491 &ScsiDiskDevice
->BlkIo
,
492 &ScsiDiskDevice
->BlkIo
497 // Get the intrinsic block size
499 Media
= ScsiDiskDevice
->BlkIo
.Media
;
500 BlockSize
= Media
->BlockSize
;
502 NumberOfBlocks
= BufferSize
/ BlockSize
;
504 if (!(Media
->MediaPresent
)) {
505 Status
= EFI_NO_MEDIA
;
509 if (MediaId
!= Media
->MediaId
) {
510 Status
= EFI_MEDIA_CHANGED
;
514 if (BufferSize
% BlockSize
!= 0) {
515 Status
= EFI_BAD_BUFFER_SIZE
;
519 if (LBA
> Media
->LastBlock
) {
520 Status
= EFI_INVALID_PARAMETER
;
524 if ((LBA
+ NumberOfBlocks
- 1) > Media
->LastBlock
) {
525 Status
= EFI_INVALID_PARAMETER
;
529 if ((Media
->IoAlign
> 1) && (((UINTN
) Buffer
& (Media
->IoAlign
- 1)) != 0)) {
530 Status
= EFI_INVALID_PARAMETER
;
535 // If all the parameters are valid, then perform read sectors command
536 // to transfer data from device to host.
538 Status
= ScsiDiskReadSectors (ScsiDiskDevice
, Buffer
, LBA
, NumberOfBlocks
);
541 gBS
->RestoreTPL (OldTpl
);
547 ScsiDiskWriteBlocks (
548 IN EFI_BLOCK_IO_PROTOCOL
*This
,
558 The function is to Write Block to SCSI Disk
562 This - The pointer of EFI_BLOCK_IO_PROTOCOL
563 MediaId - The Id of Media detected
564 LBA - The logic block address
565 BufferSize - The size of Buffer
566 Buffer - The buffer to fill the read out data
570 EFI_INVALID_PARAMETER - Invalid parameter passed in.
571 EFI_SUCCESS - Successfully to read out block.
572 EFI_DEVICE_ERROR - Fail to detect media.
573 EFI_NO_MEDIA - Media is not present.
574 EFI_MEDIA_CHANGED - Media has changed.
575 EFI_BAD_BUFFER_SIZE - The buffer size is not multiple of BlockSize.
579 SCSI_DISK_DEV
*ScsiDiskDevice
;
580 EFI_BLOCK_IO_MEDIA
*Media
;
583 UINTN NumberOfBlocks
;
589 return EFI_INVALID_PARAMETER
;
592 if (BufferSize
== 0) {
596 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
598 ScsiDiskDevice
= SCSI_DISK_DEV_FROM_THIS (This
);
600 if (!IsDeviceFixed (ScsiDiskDevice
)) {
602 Status
= ScsiDiskDetectMedia (ScsiDiskDevice
, FALSE
, &MediaChange
);
603 if (EFI_ERROR (Status
)) {
604 Status
= EFI_DEVICE_ERROR
;
609 gBS
->ReinstallProtocolInterface (
610 ScsiDiskDevice
->Handle
,
611 &gEfiBlockIoProtocolGuid
,
612 &ScsiDiskDevice
->BlkIo
,
613 &ScsiDiskDevice
->BlkIo
618 // Get the intrinsic block size
620 Media
= ScsiDiskDevice
->BlkIo
.Media
;
621 BlockSize
= Media
->BlockSize
;
623 NumberOfBlocks
= BufferSize
/ BlockSize
;
625 if (!(Media
->MediaPresent
)) {
626 Status
= EFI_NO_MEDIA
;
630 if (MediaId
!= Media
->MediaId
) {
631 Status
= EFI_MEDIA_CHANGED
;
635 if (BufferSize
% BlockSize
!= 0) {
636 Status
= EFI_BAD_BUFFER_SIZE
;
640 if (LBA
> Media
->LastBlock
) {
641 Status
= EFI_INVALID_PARAMETER
;
645 if ((LBA
+ NumberOfBlocks
- 1) > Media
->LastBlock
) {
646 Status
= EFI_INVALID_PARAMETER
;
650 if ((Media
->IoAlign
> 1) && (((UINTN
) Buffer
& (Media
->IoAlign
- 1)) != 0)) {
651 Status
= EFI_INVALID_PARAMETER
;
655 // if all the parameters are valid, then perform read sectors command
656 // to transfer data from device to host.
658 Status
= ScsiDiskWriteSectors (ScsiDiskDevice
, Buffer
, LBA
, NumberOfBlocks
);
661 gBS
->RestoreTPL (OldTpl
);
667 ScsiDiskFlushBlocks (
668 IN EFI_BLOCK_IO_PROTOCOL
*This
678 This - The pointer of EFI_BLOCK_IO_PROTOCOL
693 ScsiDiskDetectMedia (
694 SCSI_DISK_DEV
*ScsiDiskDevice
,
695 BOOLEAN MustReadCapacity
,
702 Dectect Device and read out capacity ,if error occurs, parse the sense key.
706 ScsiDiskDevice - The pointer of SCSI_DISK_DEV
707 MustReadCapacity - The flag about reading device capacity
708 MediaChange - The pointer of flag indicates if media has changed
712 EFI_DEVICE_ERROR - Indicates that error occurs
713 EFI_SUCCESS - Successfully to detect media
718 EFI_STATUS ReadCapacityStatus
;
719 EFI_SCSI_SENSE_DATA
*SenseData
;
720 UINTN NumberOfSenseKeys
;
722 BOOLEAN NeedReadCapacity
;
725 EFI_BLOCK_IO_MEDIA OldMedia
;
728 Status
= EFI_SUCCESS
;
729 ReadCapacityStatus
= EFI_SUCCESS
;
731 NumberOfSenseKeys
= 0;
732 NeedReadCapacity
= FALSE
;
733 CopyMem (&OldMedia
, ScsiDiskDevice
->BlkIo
.Media
, sizeof (OldMedia
));
734 *MediaChange
= FALSE
;
737 for (Index
= 0; Index
< MaxRetry
; Index
++) {
738 Status
= ScsiDiskTestUnitReady (
744 if (!EFI_ERROR (Status
)) {
753 if ((Index
== MaxRetry
) && EFI_ERROR (Status
)) {
754 return EFI_DEVICE_ERROR
;
757 Status
= DetectMediaParsingSenseKeys (
763 if (EFI_ERROR (Status
)) {
767 // ACTION_NO_ACTION: need not read capacity
768 // other action code: need read capacity
770 if (Action
== ACTION_NO_ACTION
) {
771 NeedReadCapacity
= FALSE
;
773 NeedReadCapacity
= TRUE
;
777 // either NeedReadCapacity is TRUE, or MustReadCapacity is TRUE,
778 // retrieve capacity via Read Capacity command
780 if (NeedReadCapacity
|| MustReadCapacity
) {
782 // retrieve media information
785 for (Index
= 0; Index
< MaxRetry
; Index
++) {
787 ReadCapacityStatus
= ScsiDiskReadCapacity (
793 if (EFI_ERROR (ReadCapacityStatus
) && !NeedRetry
) {
794 return EFI_DEVICE_ERROR
;
797 // analyze sense key to action
799 Status
= DetectMediaParsingSenseKeys (
806 // if Status is error, it may indicate crisis error,
807 // so return without retry.
809 if (EFI_ERROR (Status
)) {
814 case ACTION_NO_ACTION
:
821 case ACTION_RETRY_COMMAND_LATER
:
823 // retry the ReadCapacity later and continuously, until the condition
824 // no longer emerges.
825 // stall time is 100000us, or say 0.1 second.
833 // other cases, just retry the command
839 if ((Index
== MaxRetry
) && EFI_ERROR (ReadCapacityStatus
)) {
840 return EFI_DEVICE_ERROR
;
844 if (ScsiDiskDevice
->BlkIo
.Media
->MediaId
!= OldMedia
.MediaId
) {
846 // Media change information got from the device
851 if (ScsiDiskDevice
->BlkIo
.Media
->ReadOnly
!= OldMedia
.ReadOnly
) {
853 ScsiDiskDevice
->BlkIo
.Media
->MediaId
+= 1;
856 if (ScsiDiskDevice
->BlkIo
.Media
->BlockSize
!= OldMedia
.BlockSize
) {
858 ScsiDiskDevice
->BlkIo
.Media
->MediaId
+= 1;
861 if (ScsiDiskDevice
->BlkIo
.Media
->LastBlock
!= OldMedia
.LastBlock
) {
863 ScsiDiskDevice
->BlkIo
.Media
->MediaId
+= 1;
866 if (ScsiDiskDevice
->BlkIo
.Media
->MediaPresent
!= OldMedia
.MediaPresent
) {
867 if (ScsiDiskDevice
->BlkIo
.Media
->MediaPresent
) {
869 // when change from no media to media present, reset the MediaId to 1.
871 ScsiDiskDevice
->BlkIo
.Media
->MediaId
= 1;
874 // when no media, reset the MediaId to zero.
876 ScsiDiskDevice
->BlkIo
.Media
->MediaId
= 0;
886 ScsiDiskInquiryDevice (
887 SCSI_DISK_DEV
*ScsiDiskDevice
,
894 Send out Inquiry command to Device
898 ScsiDiskDevice - The pointer of SCSI_DISK_DEV
899 NeedRetry - Indicates if needs try again when error happens
903 EFI_DEVICE_ERROR - Indicates that error occurs
904 EFI_SUCCESS - Successfully to detect media
908 UINT32 InquiryDataLength
;
909 UINT8 SenseDataLength
;
910 UINT8 HostAdapterStatus
;
912 EFI_SCSI_SENSE_DATA
*SenseDataArray
;
913 UINTN NumberOfSenseKeys
;
918 InquiryDataLength
= sizeof (EFI_SCSI_INQUIRY_DATA
);
921 Status
= ScsiInquiryCommand (
922 ScsiDiskDevice
->ScsiIo
,
923 EfiScsiStallSeconds (1),
928 (VOID
*) &(ScsiDiskDevice
->InquiryData
),
933 // no need to check HostAdapterStatus and TargetStatus
935 if ((Status
== EFI_SUCCESS
) || (Status
== EFI_WARN_BUFFER_TOO_SMALL
)) {
936 ParseInquiryData (ScsiDiskDevice
);
939 } else if (Status
== EFI_NOT_READY
) {
941 return EFI_DEVICE_ERROR
;
943 } else if ((Status
== EFI_INVALID_PARAMETER
) || (Status
== EFI_UNSUPPORTED
)) {
945 return EFI_DEVICE_ERROR
;
948 // go ahead to check HostAdapterStatus and TargetStatus
949 // (EFI_TIMEOUT, EFI_DEVICE_ERROR)
952 Status
= CheckHostAdapterStatus (HostAdapterStatus
);
953 if ((Status
== EFI_TIMEOUT
) || (Status
== EFI_NOT_READY
)) {
955 return EFI_DEVICE_ERROR
;
956 } else if (Status
== EFI_DEVICE_ERROR
) {
958 // reset the scsi channel
960 ScsiDiskDevice
->ScsiIo
->ResetBus (ScsiDiskDevice
->ScsiIo
);
962 return EFI_DEVICE_ERROR
;
965 Status
= CheckTargetStatus (TargetStatus
);
966 if (Status
== EFI_NOT_READY
) {
968 // reset the scsi device
970 ScsiDiskDevice
->ScsiIo
->ResetDevice (ScsiDiskDevice
->ScsiIo
);
972 return EFI_DEVICE_ERROR
;
974 } else if (Status
== EFI_DEVICE_ERROR
) {
976 return EFI_DEVICE_ERROR
;
980 // if goes here, meant SubmitInquiryCommand() failed.
981 // if ScsiDiskRequestSenseKeys() succeeds at last,
982 // better retry SubmitInquiryCommand(). (by setting *NeedRetry = TRUE)
985 for (Index
= 0; Index
< MaxRetry
; Index
++) {
986 Status
= ScsiDiskRequestSenseKeys (
993 if (!EFI_ERROR (Status
)) {
995 return EFI_DEVICE_ERROR
;
999 return EFI_DEVICE_ERROR
;
1003 // ScsiDiskRequestSenseKeys() failed after several rounds of retry.
1004 // set *NeedRetry = FALSE to avoid the outside caller try again.
1007 return EFI_DEVICE_ERROR
;
1011 ScsiDiskTestUnitReady (
1012 SCSI_DISK_DEV
*ScsiDiskDevice
,
1014 EFI_SCSI_SENSE_DATA
**SenseDataArray
,
1015 UINTN
*NumberOfSenseKeys
1019 Routine Description:
1021 When Test Unit Ready command succeeds, retrieve Sense Keys via Request Sense;
1022 When Test Unit Ready command encounters any error caused by host adapter or
1023 target, return error without retrieving Sense Keys.
1027 ScsiDiskDevice - The pointer of SCSI_DISK_DEV
1028 NeedRetry - The pointer of flag indicates try again
1029 SenseDataArray - The pointer of an array of sense data
1030 NumberOfSenseKeys - The pointer of the number of sense data array
1034 EFI_DEVICE_ERROR - Indicates that error occurs
1035 EFI_SUCCESS - Successfully to test unit
1040 UINT8 SenseDataLength
;
1041 UINT8 HostAdapterStatus
;
1046 SenseDataLength
= 0;
1047 *NumberOfSenseKeys
= 0;
1050 // Parameter 3 and 4: do not require sense data, retrieve it when needed.
1052 Status
= ScsiTestUnitReadyCommand (
1053 ScsiDiskDevice
->ScsiIo
,
1054 EfiScsiStallSeconds (1),
1061 // no need to check HostAdapterStatus and TargetStatus
1063 if (Status
== EFI_NOT_READY
) {
1065 return EFI_DEVICE_ERROR
;
1067 } else if ((Status
== EFI_INVALID_PARAMETER
) || (Status
== EFI_UNSUPPORTED
)) {
1069 return EFI_DEVICE_ERROR
;
1072 // go ahead to check HostAdapterStatus and TargetStatus(in case of EFI_DEVICE_ERROR)
1075 Status
= CheckHostAdapterStatus (HostAdapterStatus
);
1076 if ((Status
== EFI_TIMEOUT
) || (Status
== EFI_NOT_READY
)) {
1078 return EFI_DEVICE_ERROR
;
1080 } else if (Status
== EFI_DEVICE_ERROR
) {
1082 // reset the scsi channel
1084 ScsiDiskDevice
->ScsiIo
->ResetBus (ScsiDiskDevice
->ScsiIo
);
1086 return EFI_DEVICE_ERROR
;
1089 Status
= CheckTargetStatus (TargetStatus
);
1090 if (Status
== EFI_NOT_READY
) {
1092 // reset the scsi device
1094 ScsiDiskDevice
->ScsiIo
->ResetDevice (ScsiDiskDevice
->ScsiIo
);
1096 return EFI_DEVICE_ERROR
;
1098 } else if (Status
== EFI_DEVICE_ERROR
) {
1100 return EFI_DEVICE_ERROR
;
1104 for (Index
= 0; Index
< MaxRetry
; Index
++) {
1105 Status
= ScsiDiskRequestSenseKeys (
1112 if (!EFI_ERROR (Status
)) {
1117 return EFI_DEVICE_ERROR
;
1121 // ScsiDiskRequestSenseKeys() failed after several rounds of retry.
1122 // set *NeedRetry = FALSE to avoid the outside caller try again.
1125 return EFI_DEVICE_ERROR
;
1129 DetectMediaParsingSenseKeys (
1130 SCSI_DISK_DEV
*ScsiDiskDevice
,
1131 EFI_SCSI_SENSE_DATA
*SenseData
,
1132 UINTN NumberOfSenseKeys
,
1137 Routine Description:
1139 Parsing Sense Keys which got from request sense command.
1143 ScsiDiskDevice - The pointer of SCSI_DISK_DEV
1144 SenseData - The pointer of EFI_SCSI_SENSE_DATA
1145 NumberOfSenseKeys - The number of sense key
1146 Action - The pointer of action which indicates what is need to do next
1150 EFI_DEVICE_ERROR - Indicates that error occurs
1151 EFI_SUCCESS - Successfully to complete the parsing
1158 // Default is to read capacity, unless..
1160 *Action
= ACTION_READ_CAPACITY
;
1162 if (NumberOfSenseKeys
== 0) {
1163 *Action
= ACTION_NO_ACTION
;
1167 if (!ScsiDiskHaveSenseKey (SenseData
, NumberOfSenseKeys
)) {
1169 // No Sense Key returned from last submitted command
1171 *Action
= ACTION_NO_ACTION
;
1175 if (ScsiDiskIsNoMedia (SenseData
, NumberOfSenseKeys
)) {
1176 ScsiDiskDevice
->BlkIo
.Media
->MediaPresent
= FALSE
;
1177 ScsiDiskDevice
->BlkIo
.Media
->LastBlock
= 0;
1178 *Action
= ACTION_NO_ACTION
;
1182 if (ScsiDiskIsMediaChange (SenseData
, NumberOfSenseKeys
)) {
1183 ScsiDiskDevice
->BlkIo
.Media
->MediaId
++;
1187 if (ScsiDiskIsMediaError (SenseData
, NumberOfSenseKeys
)) {
1188 ScsiDiskDevice
->BlkIo
.Media
->MediaPresent
= FALSE
;
1189 ScsiDiskDevice
->BlkIo
.Media
->LastBlock
= 0;
1190 return EFI_DEVICE_ERROR
;
1193 if (ScsiDiskIsHardwareError (SenseData
, NumberOfSenseKeys
)) {
1194 return EFI_DEVICE_ERROR
;
1197 if (!ScsiDiskIsDriveReady (SenseData
, NumberOfSenseKeys
, &RetryLater
)) {
1199 *Action
= ACTION_RETRY_COMMAND_LATER
;
1203 return EFI_DEVICE_ERROR
;
1210 ScsiDiskReadCapacity (
1211 SCSI_DISK_DEV
*ScsiDiskDevice
,
1213 EFI_SCSI_SENSE_DATA
**SenseDataArray
,
1214 UINTN
*NumberOfSenseKeys
1218 Routine Description:
1220 Send read capacity command to device and get the device parameter
1224 ScsiDiskDevice - The pointer of SCSI_DISK_DEV
1225 NeedRetry - The pointer of flag indicates if need a retry
1226 SenseDataArray - The pointer of an array of sense data
1227 NumberOfSenseKeys - The number of sense key
1231 EFI_DEVICE_ERROR - Indicates that error occurs
1232 EFI_SUCCESS - Successfully to read capacity
1236 EFI_SCSI_DISK_CAPACITY_DATA CapacityData
;
1238 UINT8 HostAdapterStatus
;
1240 EFI_STATUS CommandStatus
;
1244 UINT8 SenseDataLength
;
1246 SenseDataLength
= 0;
1247 ZeroMem (&CapacityData
, sizeof (EFI_SCSI_DISK_CAPACITY_DATA
));
1248 DataLength
= sizeof (EFI_SCSI_DISK_CAPACITY_DATA
);
1250 *NumberOfSenseKeys
= 0;
1253 // submit Read Capacity Command. in this call,not request sense data
1255 CommandStatus
= ScsiReadCapacityCommand (
1256 ScsiDiskDevice
->ScsiIo
,
1257 EfiScsiStallSeconds (1),
1262 (VOID
*) &CapacityData
,
1267 // no need to check HostAdapterStatus and TargetStatus
1269 if (CommandStatus
== EFI_SUCCESS
) {
1270 GetMediaInfo (ScsiDiskDevice
, &CapacityData
);
1273 } else if (CommandStatus
== EFI_NOT_READY
) {
1275 return EFI_DEVICE_ERROR
;
1277 } else if ((CommandStatus
== EFI_INVALID_PARAMETER
) || (CommandStatus
== EFI_UNSUPPORTED
)) {
1279 return EFI_DEVICE_ERROR
;
1282 // go ahead to check HostAdapterStatus and TargetStatus
1283 // (EFI_TIMEOUT, EFI_DEVICE_ERROR, EFI_WARN_BUFFER_TOO_SMALL)
1286 Status
= CheckHostAdapterStatus (HostAdapterStatus
);
1287 if ((Status
== EFI_TIMEOUT
) || (Status
== EFI_NOT_READY
)) {
1289 return EFI_DEVICE_ERROR
;
1291 } else if (Status
== EFI_DEVICE_ERROR
) {
1293 // reset the scsi channel
1295 ScsiDiskDevice
->ScsiIo
->ResetBus (ScsiDiskDevice
->ScsiIo
);
1297 return EFI_DEVICE_ERROR
;
1300 Status
= CheckTargetStatus (TargetStatus
);
1301 if (Status
== EFI_NOT_READY
) {
1303 // reset the scsi device
1305 ScsiDiskDevice
->ScsiIo
->ResetDevice (ScsiDiskDevice
->ScsiIo
);
1307 return EFI_DEVICE_ERROR
;
1309 } else if (Status
== EFI_DEVICE_ERROR
) {
1311 return EFI_DEVICE_ERROR
;
1315 // if goes here, meant SubmitReadCapacityCommand() failed.
1316 // if ScsiDiskRequestSenseKeys() succeeds at last,
1317 // better retry SubmitReadCapacityCommand(). (by setting *NeedRetry = TRUE)
1320 for (Index
= 0; Index
< MaxRetry
; Index
++) {
1322 Status
= ScsiDiskRequestSenseKeys (
1329 if (!EFI_ERROR (Status
)) {
1331 return EFI_DEVICE_ERROR
;
1335 return EFI_DEVICE_ERROR
;
1339 // ScsiDiskRequestSenseKeys() failed after several rounds of retry.
1340 // set *NeedRetry = FALSE to avoid the outside caller try again.
1343 return EFI_DEVICE_ERROR
;
1347 CheckHostAdapterStatus (
1348 UINT8 HostAdapterStatus
1352 Routine Description:
1354 Check the HostAdapter status
1358 HostAdapterStatus - Host Adapter status
1369 switch (HostAdapterStatus
) {
1370 case EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK
:
1373 case EFI_EXT_SCSI_STATUS_HOST_ADAPTER_SELECTION_TIMEOUT
:
1374 case EFI_EXT_SCSI_STATUS_HOST_ADAPTER_TIMEOUT
:
1375 case EFI_EXT_SCSI_STATUS_HOST_ADAPTER_TIMEOUT_COMMAND
:
1378 case EFI_EXT_SCSI_STATUS_HOST_ADAPTER_MESSAGE_REJECT
:
1379 case EFI_EXT_SCSI_STATUS_HOST_ADAPTER_PARITY_ERROR
:
1380 case EFI_EXT_SCSI_STATUS_HOST_ADAPTER_REQUEST_SENSE_FAILED
:
1381 case EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN
:
1382 case EFI_EXT_SCSI_STATUS_HOST_ADAPTER_BUS_RESET
:
1383 return EFI_NOT_READY
;
1385 case EFI_EXT_SCSI_STATUS_HOST_ADAPTER_BUS_FREE
:
1386 case EFI_EXT_SCSI_STATUS_HOST_ADAPTER_PHASE_ERROR
:
1387 return EFI_DEVICE_ERROR
;
1400 Routine Description:
1402 Check the target status
1406 TargetStatus - Target status
1416 switch (TargetStatus
) {
1417 case EFI_EXT_SCSI_STATUS_TARGET_GOOD
:
1418 case EFI_EXT_SCSI_STATUS_TARGET_CHECK_CONDITION
:
1419 case EFI_EXT_SCSI_STATUS_TARGET_CONDITION_MET
:
1422 case EFI_EXT_SCSI_STATUS_TARGET_INTERMEDIATE
:
1423 case EFI_EXT_SCSI_STATUS_TARGET_INTERMEDIATE_CONDITION_MET
:
1424 case EFI_EXT_SCSI_STATUS_TARGET_BUSY
:
1425 case EFI_EXT_SCSI_STATUS_TARGET_TASK_SET_FULL
:
1426 return EFI_NOT_READY
;
1428 case EFI_EXT_SCSI_STATUS_TARGET_RESERVATION_CONFLICT
:
1429 return EFI_DEVICE_ERROR
;
1438 ScsiDiskRequestSenseKeys (
1439 SCSI_DISK_DEV
*ScsiDiskDevice
,
1441 EFI_SCSI_SENSE_DATA
**SenseDataArray
,
1442 UINTN
*NumberOfSenseKeys
,
1443 BOOLEAN AskResetIfError
1447 Routine Description:
1449 Retrieve all sense keys from the device.
1450 When encountering error during the process,
1451 if retrieve sense keys before error encounterred,
1452 return the sense keys with return status set to EFI_SUCCESS,
1453 and NeedRetry set to FALSE; otherwize, return the proper return
1458 ScsiDiskDevice - The pointer of SCSI_DISK_DEV
1459 NeedRetry - The pointer of flag indicates if need a retry
1460 SenseDataArray - The pointer of an array of sense data
1461 NumberOfSenseKeys - The number of sense key
1462 AskResetIfError - The flag indicates if need reset when error occurs
1466 EFI_DEVICE_ERROR - Indicates that error occurs
1467 EFI_SUCCESS - Successfully to request sense key
1471 EFI_SCSI_SENSE_DATA
*PtrSenseData
;
1472 UINT8 SenseDataLength
;
1475 EFI_STATUS FallStatus
;
1476 UINT8 HostAdapterStatus
;
1479 FallStatus
= EFI_SUCCESS
;
1480 SenseDataLength
= sizeof (EFI_SCSI_SENSE_DATA
);
1483 ScsiDiskDevice
->SenseData
,
1484 sizeof (EFI_SCSI_SENSE_DATA
) * (ScsiDiskDevice
->SenseDataNumber
)
1487 *NumberOfSenseKeys
= 0;
1488 *SenseDataArray
= ScsiDiskDevice
->SenseData
;
1489 PtrSenseData
= ScsiDiskDevice
->SenseData
;
1491 for (SenseReq
= TRUE
; SenseReq
;) {
1492 Status
= ScsiRequestSenseCommand (
1493 ScsiDiskDevice
->ScsiIo
,
1494 EfiScsiStallSeconds (2),
1500 if ((Status
== EFI_SUCCESS
) || (Status
== EFI_WARN_BUFFER_TOO_SMALL
)) {
1501 FallStatus
= EFI_SUCCESS
;
1503 } else if ((Status
== EFI_TIMEOUT
) || (Status
== EFI_NOT_READY
)) {
1505 FallStatus
= EFI_DEVICE_ERROR
;
1507 } else if ((Status
== EFI_INVALID_PARAMETER
) || (Status
== EFI_UNSUPPORTED
)) {
1509 FallStatus
= EFI_DEVICE_ERROR
;
1511 } else if (Status
== EFI_DEVICE_ERROR
) {
1512 if (AskResetIfError
) {
1513 ScsiDiskDevice
->ScsiIo
->ResetDevice (ScsiDiskDevice
->ScsiIo
);
1516 FallStatus
= EFI_DEVICE_ERROR
;
1519 if (EFI_ERROR (FallStatus
)) {
1520 if (*NumberOfSenseKeys
!= 0) {
1524 return EFI_DEVICE_ERROR
;
1528 (*NumberOfSenseKeys
) += 1;
1531 // no more sense key or number of sense keys exceeds predefined,
1534 if ((PtrSenseData
->Sense_Key
== EFI_SCSI_SK_NO_SENSE
) ||
1535 (*NumberOfSenseKeys
== ScsiDiskDevice
->SenseDataNumber
)) {
1545 SCSI_DISK_DEV
*ScsiDiskDevice
,
1546 EFI_SCSI_DISK_CAPACITY_DATA
*Capacity
1550 Routine Description:
1552 Get information from media read capacity command
1556 ScsiDiskDevice - The pointer of SCSI_DISK_DEV
1557 Capacity - The pointer of EFI_SCSI_DISK_CAPACITY_DATA
1565 ScsiDiskDevice
->BlkIo
.Media
->LastBlock
= (Capacity
->LastLba3
<< 24) |
1566 (Capacity
->LastLba2
<< 16) |
1567 (Capacity
->LastLba1
<< 8) |
1570 ScsiDiskDevice
->BlkIo
.Media
->MediaPresent
= TRUE
;
1571 ScsiDiskDevice
->BlkIo
.Media
->BlockSize
= (Capacity
->BlockSize3
<< 24) |
1572 (Capacity
->BlockSize2
<< 16) |
1573 (Capacity
->BlockSize1
<< 8) |
1574 Capacity
->BlockSize0
;
1575 if (ScsiDiskDevice
->DeviceType
== EFI_SCSI_TYPE_DISK
) {
1576 ScsiDiskDevice
->BlkIo
.Media
->BlockSize
= 0x200;
1579 if (ScsiDiskDevice
->DeviceType
== EFI_SCSI_TYPE_CDROM
) {
1580 ScsiDiskDevice
->BlkIo
.Media
->BlockSize
= 0x800;
1586 SCSI_DISK_DEV
*ScsiDiskDevice
1590 Routine Description:
1596 ScsiDiskDevice - The pointer of SCSI_DISK_DEV
1604 ScsiDiskDevice
->FixedDevice
= (BOOLEAN
) (ScsiDiskDevice
->InquiryData
.RMB
? 0 : 1);
1605 ScsiDiskDevice
->BlkIoMedia
.RemovableMedia
= (BOOLEAN
) (!ScsiDiskDevice
->FixedDevice
);
1610 ScsiDiskReadSectors (
1611 SCSI_DISK_DEV
*ScsiDiskDevice
,
1614 UINTN NumberOfBlocks
1618 Routine Description:
1620 Read sector from SCSI Disk
1624 ScsiDiskDevice - The poiniter of SCSI_DISK_DEV
1625 Buffer - The buffer to fill in the read out data
1626 Lba - Logic block address
1627 NumberOfBlocks - The number of blocks to read
1636 UINTN BlocksRemaining
;
1648 EFI_SCSI_SENSE_DATA
*SenseData
;
1649 UINTN NumberOfSenseKeys
;
1652 NumberOfSenseKeys
= 0;
1654 Status
= EFI_SUCCESS
;
1656 BlocksRemaining
= NumberOfBlocks
;
1657 BlockSize
= ScsiDiskDevice
->BlkIo
.Media
->BlockSize
;
1659 // limit the data bytes that can be transferred by one Read(10) Command
1664 Lba32
= (UINT32
) Lba
;
1666 while (BlocksRemaining
> 0) {
1668 if (BlocksRemaining
<= MaxBlock
) {
1670 SectorCount
= (UINT16
) BlocksRemaining
;
1673 SectorCount
= MaxBlock
;
1676 ByteCount
= SectorCount
* BlockSize
;
1677 Timeout
= EfiScsiStallSeconds (2);
1680 for (Index
= 0; Index
< MaxRetry
; Index
++) {
1682 Status
= ScsiDiskRead10 (
1693 if (!EFI_ERROR (Status
)) {
1698 return EFI_DEVICE_ERROR
;
1703 if ((Index
== MaxRetry
) && (Status
!= EFI_SUCCESS
)) {
1704 return EFI_DEVICE_ERROR
;
1708 // actual transferred sectors
1710 SectorCount
= ByteCount
/ BlockSize
;
1712 Lba32
+= SectorCount
;
1713 PtrBuffer
= PtrBuffer
+ SectorCount
* BlockSize
;
1714 BlocksRemaining
-= SectorCount
;
1721 ScsiDiskWriteSectors (
1722 SCSI_DISK_DEV
*ScsiDiskDevice
,
1725 UINTN NumberOfBlocks
1729 Routine Description:
1731 Write SCSI Disk sectors
1735 ScsiDiskDevice - The pointer of SCSI_DISK_DEV
1736 Buffer - The data buffer to write sector
1737 Lba - Logic block address
1738 NumberOfBlocks - The number of blocks to write
1747 UINTN BlocksRemaining
;
1759 EFI_SCSI_SENSE_DATA
*SenseData
;
1760 UINTN NumberOfSenseKeys
;
1763 NumberOfSenseKeys
= 0;
1765 Status
= EFI_SUCCESS
;
1767 BlocksRemaining
= NumberOfBlocks
;
1768 BlockSize
= ScsiDiskDevice
->BlkIo
.Media
->BlockSize
;
1770 // limit the data bytes that can be transferred by one Write(10) Command
1775 Lba32
= (UINT32
) Lba
;
1777 while (BlocksRemaining
> 0) {
1779 if (BlocksRemaining
<= MaxBlock
) {
1781 SectorCount
= (UINT16
) BlocksRemaining
;
1784 SectorCount
= MaxBlock
;
1787 ByteCount
= SectorCount
* BlockSize
;
1788 Timeout
= EfiScsiStallSeconds (2);
1790 for (Index
= 0; Index
< MaxRetry
; Index
++) {
1791 Status
= ScsiDiskWrite10 (
1802 if (!EFI_ERROR (Status
)) {
1807 return EFI_DEVICE_ERROR
;
1811 if ((Index
== MaxRetry
) && (Status
!= EFI_SUCCESS
)) {
1812 return EFI_DEVICE_ERROR
;
1815 // actual transferred sectors
1817 SectorCount
= ByteCount
/ BlockSize
;
1819 Lba32
+= SectorCount
;
1820 PtrBuffer
= PtrBuffer
+ SectorCount
* BlockSize
;
1821 BlocksRemaining
-= SectorCount
;
1829 SCSI_DISK_DEV
*ScsiDiskDevice
,
1831 EFI_SCSI_SENSE_DATA
**SenseDataArray
,
1832 UINTN
*NumberOfSenseKeys
,
1841 Routine Description:
1843 Sumbmit Read command
1847 ScsiDiskDevice - The pointer of ScsiDiskDevice
1848 NeedRetry - The pointer of flag indicates if needs retry if error happens
1849 SenseDataArray - The pointer of an array of sense data
1850 NumberOfSenseKeys - The number of sense key
1851 Timeout - The time to complete the command
1852 DataBuffer - The buffer to fill with the read out data
1853 DataLength - The length of buffer
1854 StartLba - The start logic block address
1855 SectorSize - The size of sector
1863 UINT8 SenseDataLength
;
1865 UINT8 HostAdapterStatus
;
1869 *NumberOfSenseKeys
= 0;
1870 SenseDataLength
= 0;
1871 Status
= ScsiRead10Command (
1872 ScsiDiskDevice
->ScsiIo
,
1888 SCSI_DISK_DEV
*ScsiDiskDevice
,
1890 EFI_SCSI_SENSE_DATA
**SenseDataArray
,
1891 UINTN
*NumberOfSenseKeys
,
1900 Routine Description:
1902 Submit Write Command
1906 ScsiDiskDevice - The pointer of ScsiDiskDevice
1907 NeedRetry - The pointer of flag indicates if needs retry if error happens
1908 SenseDataArray - The pointer of an array of sense data
1909 NumberOfSenseKeys - The number of sense key
1910 Timeout - The time to complete the command
1911 DataBuffer - The buffer to fill with the read out data
1912 DataLength - The length of buffer
1913 StartLba - The start logic block address
1914 SectorSize - The size of sector
1923 UINT8 SenseDataLength
;
1924 UINT8 HostAdapterStatus
;
1928 *NumberOfSenseKeys
= 0;
1929 SenseDataLength
= 0;
1930 Status
= ScsiWrite10Command (
1931 ScsiDiskDevice
->ScsiIo
,
1947 IN EFI_SCSI_SENSE_DATA
*SenseData
,
1948 IN UINTN SenseCounts
1952 Routine Description:
1954 Check sense key to find if media presents
1958 SenseData - The pointer of EFI_SCSI_SENSE_DATA
1959 SenseCounts - The number of sense key
1967 EFI_SCSI_SENSE_DATA
*SensePtr
;
1972 SensePtr
= SenseData
;
1974 for (Index
= 0; Index
< SenseCounts
; Index
++) {
1976 // Sense Key is EFI_SCSI_SK_NOT_READY (0x2),
1977 // Additional Sense Code is ASC_NO_MEDIA (0x3A)
1979 if ((SensePtr
->Sense_Key
== EFI_SCSI_SK_NOT_READY
) &&
1980 (SensePtr
->Addnl_Sense_Code
== EFI_SCSI_ASC_NO_MEDIA
)) {
1990 ScsiDiskIsMediaError (
1991 IN EFI_SCSI_SENSE_DATA
*SenseData
,
1992 IN UINTN SenseCounts
1996 Routine Description:
2002 SenseData - The pointer of EFI_SCSI_SENSE_DATA
2003 SenseCounts - The number of sense key
2011 EFI_SCSI_SENSE_DATA
*SensePtr
;
2016 SensePtr
= SenseData
;
2018 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2020 switch (SensePtr
->Sense_Key
) {
2022 case EFI_SCSI_SK_MEDIUM_ERROR
:
2024 // Sense Key is EFI_SCSI_SK_MEDIUM_ERROR (0x3)
2026 switch (SensePtr
->Addnl_Sense_Code
) {
2031 case EFI_SCSI_ASC_MEDIA_ERR1
:
2036 case EFI_SCSI_ASC_MEDIA_ERR2
:
2041 case EFI_SCSI_ASC_MEDIA_ERR3
:
2042 case EFI_SCSI_ASC_MEDIA_ERR4
:
2052 case EFI_SCSI_SK_NOT_READY
:
2054 // Sense Key is EFI_SCSI_SK_NOT_READY (0x2)
2056 switch (SensePtr
->Addnl_Sense_Code
) {
2058 // Additional Sense Code is ASC_MEDIA_UPSIDE_DOWN (0x6)
2060 case EFI_SCSI_ASC_MEDIA_UPSIDE_DOWN
:
2080 ScsiDiskIsHardwareError (
2081 IN EFI_SCSI_SENSE_DATA
*SenseData
,
2082 IN UINTN SenseCounts
2086 Routine Description:
2088 Check sense key to find if hardware error happens
2092 SenseData - The pointer of EFI_SCSI_SENSE_DATA
2093 SenseCounts - The number of sense key
2101 EFI_SCSI_SENSE_DATA
*SensePtr
;
2106 SensePtr
= SenseData
;
2108 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2111 // Sense Key is EFI_SCSI_SK_HARDWARE_ERROR (0x4)
2113 if (SensePtr
->Sense_Key
== EFI_SCSI_SK_HARDWARE_ERROR
) {
2124 ScsiDiskIsMediaChange (
2125 IN EFI_SCSI_SENSE_DATA
*SenseData
,
2126 IN UINTN SenseCounts
2130 Routine Description:
2132 Check sense key to find if media has changed
2136 SenseData - The pointer of EFI_SCSI_SENSE_DATA
2137 SenseCounts - The number of sense key
2145 EFI_SCSI_SENSE_DATA
*SensePtr
;
2147 BOOLEAN IsMediaChanged
;
2149 IsMediaChanged
= FALSE
;
2150 SensePtr
= SenseData
;
2152 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2154 // Sense Key is EFI_SCSI_SK_UNIT_ATTENTION (0x6),
2155 // Additional sense code is EFI_SCSI_ASC_MEDIA_CHANGE (0x28)
2157 if ((SensePtr
->Sense_Key
== EFI_SCSI_SK_UNIT_ATTENTION
) &&
2158 (SensePtr
->Addnl_Sense_Code
== EFI_SCSI_ASC_MEDIA_CHANGE
)) {
2159 IsMediaChanged
= TRUE
;
2165 return IsMediaChanged
;
2169 ScsiDiskIsResetBefore (
2170 IN EFI_SCSI_SENSE_DATA
*SenseData
,
2171 IN UINTN SenseCounts
2175 Routine Description:
2177 Check sense key to find if reset happens
2181 SenseData - The pointer of EFI_SCSI_SENSE_DATA
2182 SenseCounts - The number of sense key
2190 EFI_SCSI_SENSE_DATA
*SensePtr
;
2192 BOOLEAN IsResetBefore
;
2194 IsResetBefore
= FALSE
;
2195 SensePtr
= SenseData
;
2197 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2200 // Sense Key is EFI_SCSI_SK_UNIT_ATTENTION (0x6)
2201 // Additional Sense Code is EFI_SCSI_ASC_RESET (0x29)
2203 if ((SensePtr
->Sense_Key
== EFI_SCSI_SK_UNIT_ATTENTION
) &&
2204 (SensePtr
->Addnl_Sense_Code
== EFI_SCSI_ASC_RESET
)) {
2205 IsResetBefore
= TRUE
;
2211 return IsResetBefore
;
2215 ScsiDiskIsDriveReady (
2216 IN EFI_SCSI_SENSE_DATA
*SenseData
,
2217 IN UINTN SenseCounts
,
2218 OUT BOOLEAN
*RetryLater
2222 Routine Description:
2224 Check sense key to find if the drive is ready
2228 SenseData - The pointer of EFI_SCSI_SENSE_DATA
2229 SenseCounts - The number of sense key
2230 RetryLater - The flag means if need a retry
2238 EFI_SCSI_SENSE_DATA
*SensePtr
;
2243 *RetryLater
= FALSE
;
2244 SensePtr
= SenseData
;
2246 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2248 switch (SensePtr
->Sense_Key
) {
2250 case EFI_SCSI_SK_NOT_READY
:
2252 // Sense Key is EFI_SCSI_SK_NOT_READY (0x2)
2254 switch (SensePtr
->Addnl_Sense_Code
) {
2255 case EFI_SCSI_ASC_NOT_READY
:
2257 // Additional Sense Code is EFI_SCSI_ASC_NOT_READY (0x4)
2259 switch (SensePtr
->Addnl_Sense_Code_Qualifier
) {
2260 case EFI_SCSI_ASCQ_IN_PROGRESS
:
2262 // Additional Sense Code Qualifier is
2263 // EFI_SCSI_ASCQ_IN_PROGRESS (0x1)
2271 *RetryLater
= FALSE
;
2292 ScsiDiskHaveSenseKey (
2293 IN EFI_SCSI_SENSE_DATA
*SenseData
,
2294 IN UINTN SenseCounts
2298 Routine Description:
2300 Check sense key to find if it has sense key
2304 SenseData - The pointer of EFI_SCSI_SENSE_DATA
2305 SenseCounts - The number of sense key
2313 EFI_SCSI_SENSE_DATA
*SensePtr
;
2315 BOOLEAN HaveSenseKey
;
2317 if (SenseCounts
== 0) {
2318 HaveSenseKey
= FALSE
;
2320 HaveSenseKey
= TRUE
;
2323 SensePtr
= SenseData
;
2325 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2328 // Sense Key is SK_NO_SENSE (0x0)
2330 if ((SensePtr
->Sense_Key
== EFI_SCSI_SK_NO_SENSE
) &&
2332 HaveSenseKey
= FALSE
;
2338 return HaveSenseKey
;
2342 ReleaseScsiDiskDeviceResources (
2343 IN SCSI_DISK_DEV
*ScsiDiskDevice
2347 Routine Description:
2349 Release resource about disk device
2353 ScsiDiskDevice - The pointer of SCSI_DISK_DEV
2361 if (ScsiDiskDevice
== NULL
) {
2365 if (ScsiDiskDevice
->SenseData
!= NULL
) {
2366 gBS
->FreePool (ScsiDiskDevice
->SenseData
);
2367 ScsiDiskDevice
->SenseData
= NULL
;
2370 if (ScsiDiskDevice
->ControllerNameTable
!= NULL
) {
2371 FreeUnicodeStringTable (ScsiDiskDevice
->ControllerNameTable
);
2372 ScsiDiskDevice
->ControllerNameTable
= NULL
;
2375 gBS
->FreePool (ScsiDiskDevice
);
2377 ScsiDiskDevice
= NULL
;