2 SCSI disk driver that layers on every SCSI IO protocol in the system.
4 Copyright (c) 2006 - 2008, Intel Corporation. <BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #include <Protocol/ScsiIo.h>
19 #include <Protocol/ComponentName.h>
20 #include <Protocol/BlockIo.h>
21 #include <Protocol/DriverBinding.h>
22 #include <Protocol/ScsiPassThruExt.h>
24 #include <Library/DebugLib.h>
25 #include <Library/UefiDriverEntryPoint.h>
26 #include <Library/UefiLib.h>
27 #include <Library/BaseMemoryLib.h>
28 #include <Library/ScsiLib.h>
29 #include <Library/UefiBootServicesTableLib.h>
33 EFI_DRIVER_BINDING_PROTOCOL gScsiDiskDriverBinding
= {
34 ScsiDiskDriverBindingSupported
,
35 ScsiDiskDriverBindingStart
,
36 ScsiDiskDriverBindingStop
,
43 The user Entry Point for module ScsiDisk. The user code starts with this function.
45 @param[in] ImageHandle The firmware allocated handle for the EFI image.
46 @param[in] SystemTable A pointer to the EFI System Table.
48 @retval EFI_SUCCESS The entry point is executed successfully.
49 @retval other Some error occurs when executing this entry point.
55 IN EFI_HANDLE ImageHandle
,
56 IN EFI_SYSTEM_TABLE
*SystemTable
62 // Install driver model protocol(s).
64 Status
= EfiLibInstallDriverBindingComponentName2 (
67 &gScsiDiskDriverBinding
,
69 &gScsiDiskComponentName
,
70 &gScsiDiskComponentName2
72 ASSERT_EFI_ERROR (Status
);
80 ScsiDiskDriverBindingSupported (
81 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
82 IN EFI_HANDLE Controller
,
83 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
89 Test to see if this driver supports ControllerHandle. Any ControllerHandle
90 that has ScsiIoProtocol installed will be supported.
94 This - Protocol instance pointer.
95 Controller - Handle of device to test
96 RemainingDevicePath - Not used
100 EFI_SUCCESS - This driver supports this device.
101 EFI_UNSUPPORTED - This driver does not support this device.
107 EFI_SCSI_IO_PROTOCOL
*ScsiIo
;
110 Status
= gBS
->OpenProtocol (
112 &gEfiScsiIoProtocolGuid
,
114 This
->DriverBindingHandle
,
116 EFI_OPEN_PROTOCOL_BY_DRIVER
118 if (EFI_ERROR (Status
)) {
122 Status
= ScsiIo
->GetDeviceType (ScsiIo
, &DeviceType
);
123 if (!EFI_ERROR (Status
)) {
124 if ((DeviceType
== EFI_SCSI_TYPE_DISK
) || (DeviceType
== EFI_SCSI_TYPE_CDROM
)) {
125 Status
= EFI_SUCCESS
;
127 Status
= EFI_UNSUPPORTED
;
133 &gEfiScsiIoProtocolGuid
,
134 This
->DriverBindingHandle
,
142 ScsiDiskDriverBindingStart (
143 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
144 IN EFI_HANDLE Controller
,
145 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
151 Start SCSI Disk Driver, and attach BlockIoProtocol to it.
155 This - Protocol instance pointer.
156 Controller - Handle of device to test
157 RemainingDevicePath - Not used
161 EFI_SUCCESS - This driver supports this device.
162 EFI_UNSUPPORTED - This driver does not support this device.
168 EFI_SCSI_IO_PROTOCOL
*ScsiIo
;
169 SCSI_DISK_DEV
*ScsiDiskDevice
;
175 Status
= gBS
->AllocatePool (
177 sizeof (SCSI_DISK_DEV
),
178 (VOID
**) &ScsiDiskDevice
180 if (EFI_ERROR (Status
)) {
184 ZeroMem (ScsiDiskDevice
, sizeof (SCSI_DISK_DEV
));
186 Status
= gBS
->OpenProtocol (
188 &gEfiScsiIoProtocolGuid
,
190 This
->DriverBindingHandle
,
192 EFI_OPEN_PROTOCOL_BY_DRIVER
194 if (EFI_ERROR (Status
)) {
195 gBS
->FreePool (ScsiDiskDevice
);
199 ScsiDiskDevice
->Signature
= SCSI_DISK_DEV_SIGNATURE
;
200 ScsiDiskDevice
->ScsiIo
= ScsiIo
;
201 ScsiDiskDevice
->BlkIo
.Media
= &ScsiDiskDevice
->BlkIoMedia
;
202 ScsiDiskDevice
->BlkIo
.Reset
= ScsiDiskReset
;
203 ScsiDiskDevice
->BlkIo
.ReadBlocks
= ScsiDiskReadBlocks
;
204 ScsiDiskDevice
->BlkIo
.WriteBlocks
= ScsiDiskWriteBlocks
;
205 ScsiDiskDevice
->BlkIo
.FlushBlocks
= ScsiDiskFlushBlocks
;
206 ScsiDiskDevice
->Handle
= Controller
;
208 ScsiIo
->GetDeviceType (ScsiIo
, &(ScsiDiskDevice
->DeviceType
));
209 switch (ScsiDiskDevice
->DeviceType
) {
210 case EFI_SCSI_TYPE_DISK
:
211 ScsiDiskDevice
->BlkIo
.Media
->BlockSize
= 0x200;
214 case EFI_SCSI_TYPE_CDROM
:
215 ScsiDiskDevice
->BlkIo
.Media
->BlockSize
= 0x800;
219 // The Sense Data Array's initial size is 6
221 ScsiDiskDevice
->SenseDataNumber
= 6;
222 Status
= gBS
->AllocatePool (
224 sizeof (EFI_SCSI_SENSE_DATA
) * ScsiDiskDevice
->SenseDataNumber
,
225 (VOID
**) &(ScsiDiskDevice
->SenseData
)
227 if (EFI_ERROR (Status
)) {
230 &gEfiScsiIoProtocolGuid
,
231 This
->DriverBindingHandle
,
234 gBS
->FreePool (ScsiDiskDevice
);
239 ScsiDiskDevice
->SenseData
,
240 sizeof (EFI_SCSI_SENSE_DATA
) * ScsiDiskDevice
->SenseDataNumber
244 // Retrive device information
247 for (Index
= 0; Index
< MaxRetry
; Index
++) {
248 Status
= ScsiDiskInquiryDevice (ScsiDiskDevice
, &NeedRetry
);
249 if (!EFI_ERROR (Status
)) {
254 gBS
->FreePool (ScsiDiskDevice
->SenseData
);
257 &gEfiScsiIoProtocolGuid
,
258 This
->DriverBindingHandle
,
261 gBS
->FreePool (ScsiDiskDevice
);
262 return EFI_DEVICE_ERROR
;
266 // The second parameter "TRUE" means must
267 // retrieve media capacity
269 Status
= ScsiDiskDetectMedia (ScsiDiskDevice
, TRUE
, &Temp
);
270 if (!EFI_ERROR (Status
)) {
271 Status
= gBS
->InstallMultipleProtocolInterfaces (
273 &gEfiBlockIoProtocolGuid
,
274 &ScsiDiskDevice
->BlkIo
,
279 if (EFI_ERROR (Status
)) {
280 gBS
->FreePool (ScsiDiskDevice
->SenseData
);
283 &gEfiScsiIoProtocolGuid
,
284 This
->DriverBindingHandle
,
287 gBS
->FreePool (ScsiDiskDevice
);
291 ScsiDiskDevice
->ControllerNameTable
= NULL
;
294 gScsiDiskComponentName
.SupportedLanguages
,
295 &ScsiDiskDevice
->ControllerNameTable
,
301 gScsiDiskComponentName2
.SupportedLanguages
,
302 &ScsiDiskDevice
->ControllerNameTable
,
314 ScsiDiskDriverBindingStop (
315 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
316 IN EFI_HANDLE Controller
,
317 IN UINTN NumberOfChildren
,
318 IN EFI_HANDLE
*ChildHandleBuffer
324 Stop this driver on ControllerHandle. Support stoping any child handles
325 created by this driver.
329 This - Protocol instance pointer.
330 Controller - Handle of device to stop driver on
331 NumberOfChildren - Number of Children in the ChildHandleBuffer
332 ChildHandleBuffer - List of handles for the children we need to stop.
342 EFI_BLOCK_IO_PROTOCOL
*BlkIo
;
343 SCSI_DISK_DEV
*ScsiDiskDevice
;
346 Status
= gBS
->OpenProtocol (
348 &gEfiBlockIoProtocolGuid
,
350 This
->DriverBindingHandle
,
352 EFI_OPEN_PROTOCOL_GET_PROTOCOL
354 if (EFI_ERROR (Status
)) {
358 ScsiDiskDevice
= SCSI_DISK_DEV_FROM_THIS (BlkIo
);
359 Status
= gBS
->UninstallProtocolInterface (
361 &gEfiBlockIoProtocolGuid
,
362 &ScsiDiskDevice
->BlkIo
364 if (!EFI_ERROR (Status
)) {
367 &gEfiScsiIoProtocolGuid
,
368 This
->DriverBindingHandle
,
372 ReleaseScsiDiskDeviceResources (ScsiDiskDevice
);
386 IN EFI_BLOCK_IO_PROTOCOL
*This
,
387 IN BOOLEAN ExtendedVerification
397 This - The pointer of EFI_BLOCK_IO_PROTOCOL
398 ExtendedVerification - The flag about if extend verificate
407 SCSI_DISK_DEV
*ScsiDiskDevice
;
410 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
412 ScsiDiskDevice
= SCSI_DISK_DEV_FROM_THIS (This
);
414 Status
= ScsiDiskDevice
->ScsiIo
->ResetDevice (ScsiDiskDevice
->ScsiIo
);
416 if (!ExtendedVerification
) {
420 Status
= ScsiDiskDevice
->ScsiIo
->ResetBus (ScsiDiskDevice
->ScsiIo
);
423 gBS
->RestoreTPL (OldTpl
);
430 IN EFI_BLOCK_IO_PROTOCOL
*This
,
440 The function is to Read Block from SCSI Disk
444 This - The pointer of EFI_BLOCK_IO_PROTOCOL
445 MediaId - The Id of Media detected
446 LBA - The logic block address
447 BufferSize - The size of Buffer
448 Buffer - The buffer to fill the read out data
452 EFI_INVALID_PARAMETER - Invalid parameter passed in.
453 EFI_SUCCESS - Successfully to read out block.
454 EFI_DEVICE_ERROR - Fail to detect media.
455 EFI_NO_MEDIA - Media is not present.
456 EFI_MEDIA_CHANGED - Media has changed.
457 EFI_BAD_BUFFER_SIZE - The buffer size is not multiple of BlockSize.
461 SCSI_DISK_DEV
*ScsiDiskDevice
;
462 EFI_BLOCK_IO_MEDIA
*Media
;
465 UINTN NumberOfBlocks
;
471 return EFI_INVALID_PARAMETER
;
474 if (BufferSize
== 0) {
478 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
480 ScsiDiskDevice
= SCSI_DISK_DEV_FROM_THIS (This
);
482 if (!IsDeviceFixed (ScsiDiskDevice
)) {
484 Status
= ScsiDiskDetectMedia (ScsiDiskDevice
, FALSE
, &MediaChange
);
485 if (EFI_ERROR (Status
)) {
486 Status
= EFI_DEVICE_ERROR
;
491 gBS
->ReinstallProtocolInterface (
492 ScsiDiskDevice
->Handle
,
493 &gEfiBlockIoProtocolGuid
,
494 &ScsiDiskDevice
->BlkIo
,
495 &ScsiDiskDevice
->BlkIo
500 // Get the intrinsic block size
502 Media
= ScsiDiskDevice
->BlkIo
.Media
;
503 BlockSize
= Media
->BlockSize
;
505 NumberOfBlocks
= BufferSize
/ BlockSize
;
507 if (!(Media
->MediaPresent
)) {
508 Status
= EFI_NO_MEDIA
;
512 if (MediaId
!= Media
->MediaId
) {
513 Status
= EFI_MEDIA_CHANGED
;
517 if (BufferSize
% BlockSize
!= 0) {
518 Status
= EFI_BAD_BUFFER_SIZE
;
522 if (LBA
> Media
->LastBlock
) {
523 Status
= EFI_INVALID_PARAMETER
;
527 if ((LBA
+ NumberOfBlocks
- 1) > Media
->LastBlock
) {
528 Status
= EFI_INVALID_PARAMETER
;
532 if ((Media
->IoAlign
> 1) && (((UINTN
) Buffer
& (Media
->IoAlign
- 1)) != 0)) {
533 Status
= EFI_INVALID_PARAMETER
;
538 // If all the parameters are valid, then perform read sectors command
539 // to transfer data from device to host.
541 Status
= ScsiDiskReadSectors (ScsiDiskDevice
, Buffer
, LBA
, NumberOfBlocks
);
544 gBS
->RestoreTPL (OldTpl
);
550 ScsiDiskWriteBlocks (
551 IN EFI_BLOCK_IO_PROTOCOL
*This
,
561 The function is to Write Block to SCSI Disk
565 This - The pointer of EFI_BLOCK_IO_PROTOCOL
566 MediaId - The Id of Media detected
567 LBA - The logic block address
568 BufferSize - The size of Buffer
569 Buffer - The buffer to fill the read out data
573 EFI_INVALID_PARAMETER - Invalid parameter passed in.
574 EFI_SUCCESS - Successfully to read out block.
575 EFI_DEVICE_ERROR - Fail to detect media.
576 EFI_NO_MEDIA - Media is not present.
577 EFI_MEDIA_CHANGED - Media has changed.
578 EFI_BAD_BUFFER_SIZE - The buffer size is not multiple of BlockSize.
582 SCSI_DISK_DEV
*ScsiDiskDevice
;
583 EFI_BLOCK_IO_MEDIA
*Media
;
586 UINTN NumberOfBlocks
;
592 return EFI_INVALID_PARAMETER
;
595 if (BufferSize
== 0) {
599 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
601 ScsiDiskDevice
= SCSI_DISK_DEV_FROM_THIS (This
);
603 if (!IsDeviceFixed (ScsiDiskDevice
)) {
605 Status
= ScsiDiskDetectMedia (ScsiDiskDevice
, FALSE
, &MediaChange
);
606 if (EFI_ERROR (Status
)) {
607 Status
= EFI_DEVICE_ERROR
;
612 gBS
->ReinstallProtocolInterface (
613 ScsiDiskDevice
->Handle
,
614 &gEfiBlockIoProtocolGuid
,
615 &ScsiDiskDevice
->BlkIo
,
616 &ScsiDiskDevice
->BlkIo
621 // Get the intrinsic block size
623 Media
= ScsiDiskDevice
->BlkIo
.Media
;
624 BlockSize
= Media
->BlockSize
;
626 NumberOfBlocks
= BufferSize
/ BlockSize
;
628 if (!(Media
->MediaPresent
)) {
629 Status
= EFI_NO_MEDIA
;
633 if (MediaId
!= Media
->MediaId
) {
634 Status
= EFI_MEDIA_CHANGED
;
638 if (BufferSize
% BlockSize
!= 0) {
639 Status
= EFI_BAD_BUFFER_SIZE
;
643 if (LBA
> Media
->LastBlock
) {
644 Status
= EFI_INVALID_PARAMETER
;
648 if ((LBA
+ NumberOfBlocks
- 1) > Media
->LastBlock
) {
649 Status
= EFI_INVALID_PARAMETER
;
653 if ((Media
->IoAlign
> 1) && (((UINTN
) Buffer
& (Media
->IoAlign
- 1)) != 0)) {
654 Status
= EFI_INVALID_PARAMETER
;
658 // if all the parameters are valid, then perform read sectors command
659 // to transfer data from device to host.
661 Status
= ScsiDiskWriteSectors (ScsiDiskDevice
, Buffer
, LBA
, NumberOfBlocks
);
664 gBS
->RestoreTPL (OldTpl
);
670 ScsiDiskFlushBlocks (
671 IN EFI_BLOCK_IO_PROTOCOL
*This
681 This - The pointer of EFI_BLOCK_IO_PROTOCOL
696 ScsiDiskDetectMedia (
697 SCSI_DISK_DEV
*ScsiDiskDevice
,
698 BOOLEAN MustReadCapacity
,
705 Dectect Device and read out capacity ,if error occurs, parse the sense key.
709 ScsiDiskDevice - The pointer of SCSI_DISK_DEV
710 MustReadCapacity - The flag about reading device capacity
711 MediaChange - The pointer of flag indicates if media has changed
715 EFI_DEVICE_ERROR - Indicates that error occurs
716 EFI_SUCCESS - Successfully to detect media
721 EFI_STATUS ReadCapacityStatus
;
722 EFI_SCSI_SENSE_DATA
*SenseData
;
723 UINTN NumberOfSenseKeys
;
725 BOOLEAN NeedReadCapacity
;
728 EFI_BLOCK_IO_MEDIA OldMedia
;
731 Status
= EFI_SUCCESS
;
732 ReadCapacityStatus
= EFI_SUCCESS
;
734 NumberOfSenseKeys
= 0;
735 NeedReadCapacity
= FALSE
;
736 CopyMem (&OldMedia
, ScsiDiskDevice
->BlkIo
.Media
, sizeof (OldMedia
));
737 *MediaChange
= FALSE
;
740 for (Index
= 0; Index
< MaxRetry
; Index
++) {
741 Status
= ScsiDiskTestUnitReady (
747 if (!EFI_ERROR (Status
)) {
756 if ((Index
== MaxRetry
) && EFI_ERROR (Status
)) {
757 return EFI_DEVICE_ERROR
;
760 Status
= DetectMediaParsingSenseKeys (
766 if (EFI_ERROR (Status
)) {
770 // ACTION_NO_ACTION: need not read capacity
771 // other action code: need read capacity
773 if (Action
== ACTION_NO_ACTION
) {
774 NeedReadCapacity
= FALSE
;
776 NeedReadCapacity
= TRUE
;
780 // either NeedReadCapacity is TRUE, or MustReadCapacity is TRUE,
781 // retrieve capacity via Read Capacity command
783 if (NeedReadCapacity
|| MustReadCapacity
) {
785 // retrieve media information
788 for (Index
= 0; Index
< MaxRetry
; Index
++) {
790 ReadCapacityStatus
= ScsiDiskReadCapacity (
796 if (EFI_ERROR (ReadCapacityStatus
) && !NeedRetry
) {
797 return EFI_DEVICE_ERROR
;
800 // analyze sense key to action
802 Status
= DetectMediaParsingSenseKeys (
809 // if Status is error, it may indicate crisis error,
810 // so return without retry.
812 if (EFI_ERROR (Status
)) {
817 case ACTION_NO_ACTION
:
824 case ACTION_RETRY_COMMAND_LATER
:
826 // retry the ReadCapacity later and continuously, until the condition
827 // no longer emerges.
828 // stall time is 100000us, or say 0.1 second.
836 // other cases, just retry the command
842 if ((Index
== MaxRetry
) && EFI_ERROR (ReadCapacityStatus
)) {
843 return EFI_DEVICE_ERROR
;
847 if (ScsiDiskDevice
->BlkIo
.Media
->MediaId
!= OldMedia
.MediaId
) {
849 // Media change information got from the device
854 if (ScsiDiskDevice
->BlkIo
.Media
->ReadOnly
!= OldMedia
.ReadOnly
) {
856 ScsiDiskDevice
->BlkIo
.Media
->MediaId
+= 1;
859 if (ScsiDiskDevice
->BlkIo
.Media
->BlockSize
!= OldMedia
.BlockSize
) {
861 ScsiDiskDevice
->BlkIo
.Media
->MediaId
+= 1;
864 if (ScsiDiskDevice
->BlkIo
.Media
->LastBlock
!= OldMedia
.LastBlock
) {
866 ScsiDiskDevice
->BlkIo
.Media
->MediaId
+= 1;
869 if (ScsiDiskDevice
->BlkIo
.Media
->MediaPresent
!= OldMedia
.MediaPresent
) {
870 if (ScsiDiskDevice
->BlkIo
.Media
->MediaPresent
) {
872 // when change from no media to media present, reset the MediaId to 1.
874 ScsiDiskDevice
->BlkIo
.Media
->MediaId
= 1;
877 // when no media, reset the MediaId to zero.
879 ScsiDiskDevice
->BlkIo
.Media
->MediaId
= 0;
889 ScsiDiskInquiryDevice (
890 SCSI_DISK_DEV
*ScsiDiskDevice
,
897 Send out Inquiry command to Device
901 ScsiDiskDevice - The pointer of SCSI_DISK_DEV
902 NeedRetry - Indicates if needs try again when error happens
906 EFI_DEVICE_ERROR - Indicates that error occurs
907 EFI_SUCCESS - Successfully to detect media
911 UINT32 InquiryDataLength
;
912 UINT8 SenseDataLength
;
913 UINT8 HostAdapterStatus
;
915 EFI_SCSI_SENSE_DATA
*SenseDataArray
;
916 UINTN NumberOfSenseKeys
;
921 InquiryDataLength
= sizeof (EFI_SCSI_INQUIRY_DATA
);
924 Status
= ScsiInquiryCommand (
925 ScsiDiskDevice
->ScsiIo
,
926 EFI_SCSI_STALL_SECONDS (1),
931 (VOID
*) &(ScsiDiskDevice
->InquiryData
),
936 // no need to check HostAdapterStatus and TargetStatus
938 if ((Status
== EFI_SUCCESS
) || (Status
== EFI_WARN_BUFFER_TOO_SMALL
)) {
939 ParseInquiryData (ScsiDiskDevice
);
942 } else if (Status
== EFI_NOT_READY
) {
944 return EFI_DEVICE_ERROR
;
946 } else if ((Status
== EFI_INVALID_PARAMETER
) || (Status
== EFI_UNSUPPORTED
)) {
948 return EFI_DEVICE_ERROR
;
951 // go ahead to check HostAdapterStatus and TargetStatus
952 // (EFI_TIMEOUT, EFI_DEVICE_ERROR)
955 Status
= CheckHostAdapterStatus (HostAdapterStatus
);
956 if ((Status
== EFI_TIMEOUT
) || (Status
== EFI_NOT_READY
)) {
958 return EFI_DEVICE_ERROR
;
959 } else if (Status
== EFI_DEVICE_ERROR
) {
961 // reset the scsi channel
963 ScsiDiskDevice
->ScsiIo
->ResetBus (ScsiDiskDevice
->ScsiIo
);
965 return EFI_DEVICE_ERROR
;
968 Status
= CheckTargetStatus (TargetStatus
);
969 if (Status
== EFI_NOT_READY
) {
971 // reset the scsi device
973 ScsiDiskDevice
->ScsiIo
->ResetDevice (ScsiDiskDevice
->ScsiIo
);
975 return EFI_DEVICE_ERROR
;
977 } else if (Status
== EFI_DEVICE_ERROR
) {
979 return EFI_DEVICE_ERROR
;
983 // if goes here, meant SubmitInquiryCommand() failed.
984 // if ScsiDiskRequestSenseKeys() succeeds at last,
985 // better retry SubmitInquiryCommand(). (by setting *NeedRetry = TRUE)
988 for (Index
= 0; Index
< MaxRetry
; Index
++) {
989 Status
= ScsiDiskRequestSenseKeys (
996 if (!EFI_ERROR (Status
)) {
998 return EFI_DEVICE_ERROR
;
1002 return EFI_DEVICE_ERROR
;
1006 // ScsiDiskRequestSenseKeys() failed after several rounds of retry.
1007 // set *NeedRetry = FALSE to avoid the outside caller try again.
1010 return EFI_DEVICE_ERROR
;
1014 ScsiDiskTestUnitReady (
1015 SCSI_DISK_DEV
*ScsiDiskDevice
,
1017 EFI_SCSI_SENSE_DATA
**SenseDataArray
,
1018 UINTN
*NumberOfSenseKeys
1022 Routine Description:
1024 When Test Unit Ready command succeeds, retrieve Sense Keys via Request Sense;
1025 When Test Unit Ready command encounters any error caused by host adapter or
1026 target, return error without retrieving Sense Keys.
1030 ScsiDiskDevice - The pointer of SCSI_DISK_DEV
1031 NeedRetry - The pointer of flag indicates try again
1032 SenseDataArray - The pointer of an array of sense data
1033 NumberOfSenseKeys - The pointer of the number of sense data array
1037 EFI_DEVICE_ERROR - Indicates that error occurs
1038 EFI_SUCCESS - Successfully to test unit
1043 UINT8 SenseDataLength
;
1044 UINT8 HostAdapterStatus
;
1049 SenseDataLength
= 0;
1050 *NumberOfSenseKeys
= 0;
1053 // Parameter 3 and 4: do not require sense data, retrieve it when needed.
1055 Status
= ScsiTestUnitReadyCommand (
1056 ScsiDiskDevice
->ScsiIo
,
1057 EFI_SCSI_STALL_SECONDS (1),
1064 // no need to check HostAdapterStatus and TargetStatus
1066 if (Status
== EFI_NOT_READY
) {
1068 return EFI_DEVICE_ERROR
;
1070 } else if ((Status
== EFI_INVALID_PARAMETER
) || (Status
== EFI_UNSUPPORTED
)) {
1072 return EFI_DEVICE_ERROR
;
1075 // go ahead to check HostAdapterStatus and TargetStatus(in case of EFI_DEVICE_ERROR)
1078 Status
= CheckHostAdapterStatus (HostAdapterStatus
);
1079 if ((Status
== EFI_TIMEOUT
) || (Status
== EFI_NOT_READY
)) {
1081 return EFI_DEVICE_ERROR
;
1083 } else if (Status
== EFI_DEVICE_ERROR
) {
1085 // reset the scsi channel
1087 ScsiDiskDevice
->ScsiIo
->ResetBus (ScsiDiskDevice
->ScsiIo
);
1089 return EFI_DEVICE_ERROR
;
1092 Status
= CheckTargetStatus (TargetStatus
);
1093 if (Status
== EFI_NOT_READY
) {
1095 // reset the scsi device
1097 ScsiDiskDevice
->ScsiIo
->ResetDevice (ScsiDiskDevice
->ScsiIo
);
1099 return EFI_DEVICE_ERROR
;
1101 } else if (Status
== EFI_DEVICE_ERROR
) {
1103 return EFI_DEVICE_ERROR
;
1107 for (Index
= 0; Index
< MaxRetry
; Index
++) {
1108 Status
= ScsiDiskRequestSenseKeys (
1115 if (!EFI_ERROR (Status
)) {
1120 return EFI_DEVICE_ERROR
;
1124 // ScsiDiskRequestSenseKeys() failed after several rounds of retry.
1125 // set *NeedRetry = FALSE to avoid the outside caller try again.
1128 return EFI_DEVICE_ERROR
;
1132 DetectMediaParsingSenseKeys (
1133 SCSI_DISK_DEV
*ScsiDiskDevice
,
1134 EFI_SCSI_SENSE_DATA
*SenseData
,
1135 UINTN NumberOfSenseKeys
,
1140 Routine Description:
1142 Parsing Sense Keys which got from request sense command.
1146 ScsiDiskDevice - The pointer of SCSI_DISK_DEV
1147 SenseData - The pointer of EFI_SCSI_SENSE_DATA
1148 NumberOfSenseKeys - The number of sense key
1149 Action - The pointer of action which indicates what is need to do next
1153 EFI_DEVICE_ERROR - Indicates that error occurs
1154 EFI_SUCCESS - Successfully to complete the parsing
1161 // Default is to read capacity, unless..
1163 *Action
= ACTION_READ_CAPACITY
;
1165 if (NumberOfSenseKeys
== 0) {
1166 *Action
= ACTION_NO_ACTION
;
1170 if (!ScsiDiskHaveSenseKey (SenseData
, NumberOfSenseKeys
)) {
1172 // No Sense Key returned from last submitted command
1174 *Action
= ACTION_NO_ACTION
;
1178 if (ScsiDiskIsNoMedia (SenseData
, NumberOfSenseKeys
)) {
1179 ScsiDiskDevice
->BlkIo
.Media
->MediaPresent
= FALSE
;
1180 ScsiDiskDevice
->BlkIo
.Media
->LastBlock
= 0;
1181 *Action
= ACTION_NO_ACTION
;
1185 if (ScsiDiskIsMediaChange (SenseData
, NumberOfSenseKeys
)) {
1186 ScsiDiskDevice
->BlkIo
.Media
->MediaId
++;
1190 if (ScsiDiskIsMediaError (SenseData
, NumberOfSenseKeys
)) {
1191 ScsiDiskDevice
->BlkIo
.Media
->MediaPresent
= FALSE
;
1192 ScsiDiskDevice
->BlkIo
.Media
->LastBlock
= 0;
1193 return EFI_DEVICE_ERROR
;
1196 if (ScsiDiskIsHardwareError (SenseData
, NumberOfSenseKeys
)) {
1197 return EFI_DEVICE_ERROR
;
1200 if (!ScsiDiskIsDriveReady (SenseData
, NumberOfSenseKeys
, &RetryLater
)) {
1202 *Action
= ACTION_RETRY_COMMAND_LATER
;
1206 return EFI_DEVICE_ERROR
;
1213 ScsiDiskReadCapacity (
1214 SCSI_DISK_DEV
*ScsiDiskDevice
,
1216 EFI_SCSI_SENSE_DATA
**SenseDataArray
,
1217 UINTN
*NumberOfSenseKeys
1221 Routine Description:
1223 Send read capacity command to device and get the device parameter
1227 ScsiDiskDevice - The pointer of SCSI_DISK_DEV
1228 NeedRetry - The pointer of flag indicates if need a retry
1229 SenseDataArray - The pointer of an array of sense data
1230 NumberOfSenseKeys - The number of sense key
1234 EFI_DEVICE_ERROR - Indicates that error occurs
1235 EFI_SUCCESS - Successfully to read capacity
1239 EFI_SCSI_DISK_CAPACITY_DATA CapacityData
;
1241 UINT8 HostAdapterStatus
;
1243 EFI_STATUS CommandStatus
;
1247 UINT8 SenseDataLength
;
1249 SenseDataLength
= 0;
1250 ZeroMem (&CapacityData
, sizeof (EFI_SCSI_DISK_CAPACITY_DATA
));
1251 DataLength
= sizeof (EFI_SCSI_DISK_CAPACITY_DATA
);
1253 *NumberOfSenseKeys
= 0;
1256 // submit Read Capacity Command. in this call,not request sense data
1258 CommandStatus
= ScsiReadCapacityCommand (
1259 ScsiDiskDevice
->ScsiIo
,
1260 EFI_SCSI_STALL_SECONDS (1),
1265 (VOID
*) &CapacityData
,
1270 // no need to check HostAdapterStatus and TargetStatus
1272 if (CommandStatus
== EFI_SUCCESS
) {
1273 GetMediaInfo (ScsiDiskDevice
, &CapacityData
);
1276 } else if (CommandStatus
== EFI_NOT_READY
) {
1278 return EFI_DEVICE_ERROR
;
1280 } else if ((CommandStatus
== EFI_INVALID_PARAMETER
) || (CommandStatus
== EFI_UNSUPPORTED
)) {
1282 return EFI_DEVICE_ERROR
;
1285 // go ahead to check HostAdapterStatus and TargetStatus
1286 // (EFI_TIMEOUT, EFI_DEVICE_ERROR, EFI_WARN_BUFFER_TOO_SMALL)
1289 Status
= CheckHostAdapterStatus (HostAdapterStatus
);
1290 if ((Status
== EFI_TIMEOUT
) || (Status
== EFI_NOT_READY
)) {
1292 return EFI_DEVICE_ERROR
;
1294 } else if (Status
== EFI_DEVICE_ERROR
) {
1296 // reset the scsi channel
1298 ScsiDiskDevice
->ScsiIo
->ResetBus (ScsiDiskDevice
->ScsiIo
);
1300 return EFI_DEVICE_ERROR
;
1303 Status
= CheckTargetStatus (TargetStatus
);
1304 if (Status
== EFI_NOT_READY
) {
1306 // reset the scsi device
1308 ScsiDiskDevice
->ScsiIo
->ResetDevice (ScsiDiskDevice
->ScsiIo
);
1310 return EFI_DEVICE_ERROR
;
1312 } else if (Status
== EFI_DEVICE_ERROR
) {
1314 return EFI_DEVICE_ERROR
;
1318 // if goes here, meant SubmitReadCapacityCommand() failed.
1319 // if ScsiDiskRequestSenseKeys() succeeds at last,
1320 // better retry SubmitReadCapacityCommand(). (by setting *NeedRetry = TRUE)
1323 for (Index
= 0; Index
< MaxRetry
; Index
++) {
1325 Status
= ScsiDiskRequestSenseKeys (
1332 if (!EFI_ERROR (Status
)) {
1334 return EFI_DEVICE_ERROR
;
1338 return EFI_DEVICE_ERROR
;
1342 // ScsiDiskRequestSenseKeys() failed after several rounds of retry.
1343 // set *NeedRetry = FALSE to avoid the outside caller try again.
1346 return EFI_DEVICE_ERROR
;
1350 CheckHostAdapterStatus (
1351 UINT8 HostAdapterStatus
1355 Routine Description:
1357 Check the HostAdapter status
1361 HostAdapterStatus - Host Adapter status
1372 switch (HostAdapterStatus
) {
1373 case EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK
:
1376 case EFI_EXT_SCSI_STATUS_HOST_ADAPTER_SELECTION_TIMEOUT
:
1377 case EFI_EXT_SCSI_STATUS_HOST_ADAPTER_TIMEOUT
:
1378 case EFI_EXT_SCSI_STATUS_HOST_ADAPTER_TIMEOUT_COMMAND
:
1381 case EFI_EXT_SCSI_STATUS_HOST_ADAPTER_MESSAGE_REJECT
:
1382 case EFI_EXT_SCSI_STATUS_HOST_ADAPTER_PARITY_ERROR
:
1383 case EFI_EXT_SCSI_STATUS_HOST_ADAPTER_REQUEST_SENSE_FAILED
:
1384 case EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN
:
1385 case EFI_EXT_SCSI_STATUS_HOST_ADAPTER_BUS_RESET
:
1386 return EFI_NOT_READY
;
1388 case EFI_EXT_SCSI_STATUS_HOST_ADAPTER_BUS_FREE
:
1389 case EFI_EXT_SCSI_STATUS_HOST_ADAPTER_PHASE_ERROR
:
1390 return EFI_DEVICE_ERROR
;
1403 Routine Description:
1405 Check the target status
1409 TargetStatus - Target status
1419 switch (TargetStatus
) {
1420 case EFI_EXT_SCSI_STATUS_TARGET_GOOD
:
1421 case EFI_EXT_SCSI_STATUS_TARGET_CHECK_CONDITION
:
1422 case EFI_EXT_SCSI_STATUS_TARGET_CONDITION_MET
:
1425 case EFI_EXT_SCSI_STATUS_TARGET_INTERMEDIATE
:
1426 case EFI_EXT_SCSI_STATUS_TARGET_INTERMEDIATE_CONDITION_MET
:
1427 case EFI_EXT_SCSI_STATUS_TARGET_BUSY
:
1428 case EFI_EXT_SCSI_STATUS_TARGET_TASK_SET_FULL
:
1429 return EFI_NOT_READY
;
1431 case EFI_EXT_SCSI_STATUS_TARGET_RESERVATION_CONFLICT
:
1432 return EFI_DEVICE_ERROR
;
1441 ScsiDiskRequestSenseKeys (
1442 SCSI_DISK_DEV
*ScsiDiskDevice
,
1444 EFI_SCSI_SENSE_DATA
**SenseDataArray
,
1445 UINTN
*NumberOfSenseKeys
,
1446 BOOLEAN AskResetIfError
1450 Routine Description:
1452 Retrieve all sense keys from the device.
1453 When encountering error during the process,
1454 if retrieve sense keys before error encounterred,
1455 return the sense keys with return status set to EFI_SUCCESS,
1456 and NeedRetry set to FALSE; otherwize, return the proper return
1461 ScsiDiskDevice - The pointer of SCSI_DISK_DEV
1462 NeedRetry - The pointer of flag indicates if need a retry
1463 SenseDataArray - The pointer of an array of sense data
1464 NumberOfSenseKeys - The number of sense key
1465 AskResetIfError - The flag indicates if need reset when error occurs
1469 EFI_DEVICE_ERROR - Indicates that error occurs
1470 EFI_SUCCESS - Successfully to request sense key
1474 EFI_SCSI_SENSE_DATA
*PtrSenseData
;
1475 UINT8 SenseDataLength
;
1478 EFI_STATUS FallStatus
;
1479 UINT8 HostAdapterStatus
;
1482 FallStatus
= EFI_SUCCESS
;
1483 SenseDataLength
= sizeof (EFI_SCSI_SENSE_DATA
);
1486 ScsiDiskDevice
->SenseData
,
1487 sizeof (EFI_SCSI_SENSE_DATA
) * (ScsiDiskDevice
->SenseDataNumber
)
1490 *NumberOfSenseKeys
= 0;
1491 *SenseDataArray
= ScsiDiskDevice
->SenseData
;
1492 PtrSenseData
= ScsiDiskDevice
->SenseData
;
1494 for (SenseReq
= TRUE
; SenseReq
;) {
1495 Status
= ScsiRequestSenseCommand (
1496 ScsiDiskDevice
->ScsiIo
,
1497 EFI_SCSI_STALL_SECONDS (2),
1503 if ((Status
== EFI_SUCCESS
) || (Status
== EFI_WARN_BUFFER_TOO_SMALL
)) {
1504 FallStatus
= EFI_SUCCESS
;
1506 } else if ((Status
== EFI_TIMEOUT
) || (Status
== EFI_NOT_READY
)) {
1508 FallStatus
= EFI_DEVICE_ERROR
;
1510 } else if ((Status
== EFI_INVALID_PARAMETER
) || (Status
== EFI_UNSUPPORTED
)) {
1512 FallStatus
= EFI_DEVICE_ERROR
;
1514 } else if (Status
== EFI_DEVICE_ERROR
) {
1515 if (AskResetIfError
) {
1516 ScsiDiskDevice
->ScsiIo
->ResetDevice (ScsiDiskDevice
->ScsiIo
);
1519 FallStatus
= EFI_DEVICE_ERROR
;
1522 if (EFI_ERROR (FallStatus
)) {
1523 if (*NumberOfSenseKeys
!= 0) {
1527 return EFI_DEVICE_ERROR
;
1531 (*NumberOfSenseKeys
) += 1;
1534 // no more sense key or number of sense keys exceeds predefined,
1537 if ((PtrSenseData
->Sense_Key
== EFI_SCSI_SK_NO_SENSE
) ||
1538 (*NumberOfSenseKeys
== ScsiDiskDevice
->SenseDataNumber
)) {
1548 SCSI_DISK_DEV
*ScsiDiskDevice
,
1549 EFI_SCSI_DISK_CAPACITY_DATA
*Capacity
1553 Routine Description:
1555 Get information from media read capacity command
1559 ScsiDiskDevice - The pointer of SCSI_DISK_DEV
1560 Capacity - The pointer of EFI_SCSI_DISK_CAPACITY_DATA
1568 ScsiDiskDevice
->BlkIo
.Media
->LastBlock
= (Capacity
->LastLba3
<< 24) |
1569 (Capacity
->LastLba2
<< 16) |
1570 (Capacity
->LastLba1
<< 8) |
1573 ScsiDiskDevice
->BlkIo
.Media
->MediaPresent
= TRUE
;
1574 ScsiDiskDevice
->BlkIo
.Media
->BlockSize
= (Capacity
->BlockSize3
<< 24) |
1575 (Capacity
->BlockSize2
<< 16) |
1576 (Capacity
->BlockSize1
<< 8) |
1577 Capacity
->BlockSize0
;
1578 if (ScsiDiskDevice
->DeviceType
== EFI_SCSI_TYPE_DISK
) {
1579 ScsiDiskDevice
->BlkIo
.Media
->BlockSize
= 0x200;
1582 if (ScsiDiskDevice
->DeviceType
== EFI_SCSI_TYPE_CDROM
) {
1583 ScsiDiskDevice
->BlkIo
.Media
->BlockSize
= 0x800;
1589 SCSI_DISK_DEV
*ScsiDiskDevice
1593 Routine Description:
1599 ScsiDiskDevice - The pointer of SCSI_DISK_DEV
1607 ScsiDiskDevice
->FixedDevice
= (BOOLEAN
) (ScsiDiskDevice
->InquiryData
.RMB
? 0 : 1);
1608 ScsiDiskDevice
->BlkIoMedia
.RemovableMedia
= (BOOLEAN
) (!ScsiDiskDevice
->FixedDevice
);
1613 ScsiDiskReadSectors (
1614 SCSI_DISK_DEV
*ScsiDiskDevice
,
1617 UINTN NumberOfBlocks
1621 Routine Description:
1623 Read sector from SCSI Disk
1627 ScsiDiskDevice - The poiniter of SCSI_DISK_DEV
1628 Buffer - The buffer to fill in the read out data
1629 Lba - Logic block address
1630 NumberOfBlocks - The number of blocks to read
1639 UINTN BlocksRemaining
;
1651 EFI_SCSI_SENSE_DATA
*SenseData
;
1652 UINTN NumberOfSenseKeys
;
1655 NumberOfSenseKeys
= 0;
1657 Status
= EFI_SUCCESS
;
1659 BlocksRemaining
= NumberOfBlocks
;
1660 BlockSize
= ScsiDiskDevice
->BlkIo
.Media
->BlockSize
;
1662 // limit the data bytes that can be transferred by one Read(10) Command
1667 Lba32
= (UINT32
) Lba
;
1669 while (BlocksRemaining
> 0) {
1671 if (BlocksRemaining
<= MaxBlock
) {
1673 SectorCount
= (UINT16
) BlocksRemaining
;
1676 SectorCount
= MaxBlock
;
1679 ByteCount
= SectorCount
* BlockSize
;
1680 Timeout
= EFI_SCSI_STALL_SECONDS (2);
1683 for (Index
= 0; Index
< MaxRetry
; Index
++) {
1685 Status
= ScsiDiskRead10 (
1696 if (!EFI_ERROR (Status
)) {
1701 return EFI_DEVICE_ERROR
;
1706 if ((Index
== MaxRetry
) && (Status
!= EFI_SUCCESS
)) {
1707 return EFI_DEVICE_ERROR
;
1711 // actual transferred sectors
1713 SectorCount
= ByteCount
/ BlockSize
;
1715 Lba32
+= SectorCount
;
1716 PtrBuffer
= PtrBuffer
+ SectorCount
* BlockSize
;
1717 BlocksRemaining
-= SectorCount
;
1724 ScsiDiskWriteSectors (
1725 SCSI_DISK_DEV
*ScsiDiskDevice
,
1728 UINTN NumberOfBlocks
1732 Routine Description:
1734 Write SCSI Disk sectors
1738 ScsiDiskDevice - The pointer of SCSI_DISK_DEV
1739 Buffer - The data buffer to write sector
1740 Lba - Logic block address
1741 NumberOfBlocks - The number of blocks to write
1750 UINTN BlocksRemaining
;
1762 EFI_SCSI_SENSE_DATA
*SenseData
;
1763 UINTN NumberOfSenseKeys
;
1766 NumberOfSenseKeys
= 0;
1768 Status
= EFI_SUCCESS
;
1770 BlocksRemaining
= NumberOfBlocks
;
1771 BlockSize
= ScsiDiskDevice
->BlkIo
.Media
->BlockSize
;
1773 // limit the data bytes that can be transferred by one Write(10) Command
1778 Lba32
= (UINT32
) Lba
;
1780 while (BlocksRemaining
> 0) {
1782 if (BlocksRemaining
<= MaxBlock
) {
1784 SectorCount
= (UINT16
) BlocksRemaining
;
1787 SectorCount
= MaxBlock
;
1790 ByteCount
= SectorCount
* BlockSize
;
1791 Timeout
= EFI_SCSI_STALL_SECONDS (2);
1793 for (Index
= 0; Index
< MaxRetry
; Index
++) {
1794 Status
= ScsiDiskWrite10 (
1805 if (!EFI_ERROR (Status
)) {
1810 return EFI_DEVICE_ERROR
;
1814 if ((Index
== MaxRetry
) && (Status
!= EFI_SUCCESS
)) {
1815 return EFI_DEVICE_ERROR
;
1818 // actual transferred sectors
1820 SectorCount
= ByteCount
/ BlockSize
;
1822 Lba32
+= SectorCount
;
1823 PtrBuffer
= PtrBuffer
+ SectorCount
* BlockSize
;
1824 BlocksRemaining
-= SectorCount
;
1832 SCSI_DISK_DEV
*ScsiDiskDevice
,
1834 EFI_SCSI_SENSE_DATA
**SenseDataArray
,
1835 UINTN
*NumberOfSenseKeys
,
1844 Routine Description:
1846 Sumbmit Read command
1850 ScsiDiskDevice - The pointer of ScsiDiskDevice
1851 NeedRetry - The pointer of flag indicates if needs retry if error happens
1852 SenseDataArray - The pointer of an array of sense data
1853 NumberOfSenseKeys - The number of sense key
1854 Timeout - The time to complete the command
1855 DataBuffer - The buffer to fill with the read out data
1856 DataLength - The length of buffer
1857 StartLba - The start logic block address
1858 SectorSize - The size of sector
1866 UINT8 SenseDataLength
;
1868 UINT8 HostAdapterStatus
;
1872 *NumberOfSenseKeys
= 0;
1873 SenseDataLength
= 0;
1874 Status
= ScsiRead10Command (
1875 ScsiDiskDevice
->ScsiIo
,
1891 SCSI_DISK_DEV
*ScsiDiskDevice
,
1893 EFI_SCSI_SENSE_DATA
**SenseDataArray
,
1894 UINTN
*NumberOfSenseKeys
,
1903 Routine Description:
1905 Submit Write Command
1909 ScsiDiskDevice - The pointer of ScsiDiskDevice
1910 NeedRetry - The pointer of flag indicates if needs retry if error happens
1911 SenseDataArray - The pointer of an array of sense data
1912 NumberOfSenseKeys - The number of sense key
1913 Timeout - The time to complete the command
1914 DataBuffer - The buffer to fill with the read out data
1915 DataLength - The length of buffer
1916 StartLba - The start logic block address
1917 SectorSize - The size of sector
1926 UINT8 SenseDataLength
;
1927 UINT8 HostAdapterStatus
;
1931 *NumberOfSenseKeys
= 0;
1932 SenseDataLength
= 0;
1933 Status
= ScsiWrite10Command (
1934 ScsiDiskDevice
->ScsiIo
,
1950 IN EFI_SCSI_SENSE_DATA
*SenseData
,
1951 IN UINTN SenseCounts
1955 Routine Description:
1957 Check sense key to find if media presents
1961 SenseData - The pointer of EFI_SCSI_SENSE_DATA
1962 SenseCounts - The number of sense key
1970 EFI_SCSI_SENSE_DATA
*SensePtr
;
1975 SensePtr
= SenseData
;
1977 for (Index
= 0; Index
< SenseCounts
; Index
++) {
1979 // Sense Key is EFI_SCSI_SK_NOT_READY (0x2),
1980 // Additional Sense Code is ASC_NO_MEDIA (0x3A)
1982 if ((SensePtr
->Sense_Key
== EFI_SCSI_SK_NOT_READY
) &&
1983 (SensePtr
->Addnl_Sense_Code
== EFI_SCSI_ASC_NO_MEDIA
)) {
1993 ScsiDiskIsMediaError (
1994 IN EFI_SCSI_SENSE_DATA
*SenseData
,
1995 IN UINTN SenseCounts
1999 Routine Description:
2005 SenseData - The pointer of EFI_SCSI_SENSE_DATA
2006 SenseCounts - The number of sense key
2014 EFI_SCSI_SENSE_DATA
*SensePtr
;
2019 SensePtr
= SenseData
;
2021 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2023 switch (SensePtr
->Sense_Key
) {
2025 case EFI_SCSI_SK_MEDIUM_ERROR
:
2027 // Sense Key is EFI_SCSI_SK_MEDIUM_ERROR (0x3)
2029 switch (SensePtr
->Addnl_Sense_Code
) {
2034 case EFI_SCSI_ASC_MEDIA_ERR1
:
2039 case EFI_SCSI_ASC_MEDIA_ERR2
:
2044 case EFI_SCSI_ASC_MEDIA_ERR3
:
2045 case EFI_SCSI_ASC_MEDIA_ERR4
:
2055 case EFI_SCSI_SK_NOT_READY
:
2057 // Sense Key is EFI_SCSI_SK_NOT_READY (0x2)
2059 switch (SensePtr
->Addnl_Sense_Code
) {
2061 // Additional Sense Code is ASC_MEDIA_UPSIDE_DOWN (0x6)
2063 case EFI_SCSI_ASC_MEDIA_UPSIDE_DOWN
:
2083 ScsiDiskIsHardwareError (
2084 IN EFI_SCSI_SENSE_DATA
*SenseData
,
2085 IN UINTN SenseCounts
2089 Routine Description:
2091 Check sense key to find if hardware error happens
2095 SenseData - The pointer of EFI_SCSI_SENSE_DATA
2096 SenseCounts - The number of sense key
2104 EFI_SCSI_SENSE_DATA
*SensePtr
;
2109 SensePtr
= SenseData
;
2111 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2114 // Sense Key is EFI_SCSI_SK_HARDWARE_ERROR (0x4)
2116 if (SensePtr
->Sense_Key
== EFI_SCSI_SK_HARDWARE_ERROR
) {
2127 ScsiDiskIsMediaChange (
2128 IN EFI_SCSI_SENSE_DATA
*SenseData
,
2129 IN UINTN SenseCounts
2133 Routine Description:
2135 Check sense key to find if media has changed
2139 SenseData - The pointer of EFI_SCSI_SENSE_DATA
2140 SenseCounts - The number of sense key
2148 EFI_SCSI_SENSE_DATA
*SensePtr
;
2150 BOOLEAN IsMediaChanged
;
2152 IsMediaChanged
= FALSE
;
2153 SensePtr
= SenseData
;
2155 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2157 // Sense Key is EFI_SCSI_SK_UNIT_ATTENTION (0x6),
2158 // Additional sense code is EFI_SCSI_ASC_MEDIA_CHANGE (0x28)
2160 if ((SensePtr
->Sense_Key
== EFI_SCSI_SK_UNIT_ATTENTION
) &&
2161 (SensePtr
->Addnl_Sense_Code
== EFI_SCSI_ASC_MEDIA_CHANGE
)) {
2162 IsMediaChanged
= TRUE
;
2168 return IsMediaChanged
;
2172 ScsiDiskIsResetBefore (
2173 IN EFI_SCSI_SENSE_DATA
*SenseData
,
2174 IN UINTN SenseCounts
2178 Routine Description:
2180 Check sense key to find if reset happens
2184 SenseData - The pointer of EFI_SCSI_SENSE_DATA
2185 SenseCounts - The number of sense key
2193 EFI_SCSI_SENSE_DATA
*SensePtr
;
2195 BOOLEAN IsResetBefore
;
2197 IsResetBefore
= FALSE
;
2198 SensePtr
= SenseData
;
2200 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2203 // Sense Key is EFI_SCSI_SK_UNIT_ATTENTION (0x6)
2204 // Additional Sense Code is EFI_SCSI_ASC_RESET (0x29)
2206 if ((SensePtr
->Sense_Key
== EFI_SCSI_SK_UNIT_ATTENTION
) &&
2207 (SensePtr
->Addnl_Sense_Code
== EFI_SCSI_ASC_RESET
)) {
2208 IsResetBefore
= TRUE
;
2214 return IsResetBefore
;
2218 ScsiDiskIsDriveReady (
2219 IN EFI_SCSI_SENSE_DATA
*SenseData
,
2220 IN UINTN SenseCounts
,
2221 OUT BOOLEAN
*RetryLater
2225 Routine Description:
2227 Check sense key to find if the drive is ready
2231 SenseData - The pointer of EFI_SCSI_SENSE_DATA
2232 SenseCounts - The number of sense key
2233 RetryLater - The flag means if need a retry
2241 EFI_SCSI_SENSE_DATA
*SensePtr
;
2246 *RetryLater
= FALSE
;
2247 SensePtr
= SenseData
;
2249 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2251 switch (SensePtr
->Sense_Key
) {
2253 case EFI_SCSI_SK_NOT_READY
:
2255 // Sense Key is EFI_SCSI_SK_NOT_READY (0x2)
2257 switch (SensePtr
->Addnl_Sense_Code
) {
2258 case EFI_SCSI_ASC_NOT_READY
:
2260 // Additional Sense Code is EFI_SCSI_ASC_NOT_READY (0x4)
2262 switch (SensePtr
->Addnl_Sense_Code_Qualifier
) {
2263 case EFI_SCSI_ASCQ_IN_PROGRESS
:
2265 // Additional Sense Code Qualifier is
2266 // EFI_SCSI_ASCQ_IN_PROGRESS (0x1)
2274 *RetryLater
= FALSE
;
2295 ScsiDiskHaveSenseKey (
2296 IN EFI_SCSI_SENSE_DATA
*SenseData
,
2297 IN UINTN SenseCounts
2301 Routine Description:
2303 Check sense key to find if it has sense key
2307 SenseData - The pointer of EFI_SCSI_SENSE_DATA
2308 SenseCounts - The number of sense key
2316 EFI_SCSI_SENSE_DATA
*SensePtr
;
2318 BOOLEAN HaveSenseKey
;
2320 if (SenseCounts
== 0) {
2321 HaveSenseKey
= FALSE
;
2323 HaveSenseKey
= TRUE
;
2326 SensePtr
= SenseData
;
2328 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2331 // Sense Key is SK_NO_SENSE (0x0)
2333 if ((SensePtr
->Sense_Key
== EFI_SCSI_SK_NO_SENSE
) &&
2335 HaveSenseKey
= FALSE
;
2341 return HaveSenseKey
;
2345 ReleaseScsiDiskDeviceResources (
2346 IN SCSI_DISK_DEV
*ScsiDiskDevice
2350 Routine Description:
2352 Release resource about disk device
2356 ScsiDiskDevice - The pointer of SCSI_DISK_DEV
2364 if (ScsiDiskDevice
== NULL
) {
2368 if (ScsiDiskDevice
->SenseData
!= NULL
) {
2369 gBS
->FreePool (ScsiDiskDevice
->SenseData
);
2370 ScsiDiskDevice
->SenseData
= NULL
;
2373 if (ScsiDiskDevice
->ControllerNameTable
!= NULL
) {
2374 FreeUnicodeStringTable (ScsiDiskDevice
->ControllerNameTable
);
2375 ScsiDiskDevice
->ControllerNameTable
= NULL
;
2378 gBS
->FreePool (ScsiDiskDevice
);
2380 ScsiDiskDevice
= NULL
;