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.
20 // The package level header files this module uses
25 // The protocols, PPI and GUID defintions for this module
27 #include <Protocol/ScsiIo.h>
28 #include <Protocol/ComponentName.h>
29 #include <Protocol/BlockIo.h>
30 #include <Protocol/DriverBinding.h>
32 // The Library classes this module consumes
34 #include <Library/DebugLib.h>
35 #include <Library/UefiDriverEntryPoint.h>
36 #include <Library/UefiLib.h>
37 #include <Library/BaseMemoryLib.h>
38 #include <Library/ScsiLib.h>
39 #include <Library/UefiBootServicesTableLib.h>
43 EFI_DRIVER_BINDING_PROTOCOL gScsiDiskDriverBinding
= {
44 ScsiDiskDriverBindingSupported
,
45 ScsiDiskDriverBindingStart
,
46 ScsiDiskDriverBindingStop
,
53 The user Entry Point for module ScsiDisk. The user code starts with this function.
55 @param[in] ImageHandle The firmware allocated handle for the EFI image.
56 @param[in] SystemTable A pointer to the EFI System Table.
58 @retval EFI_SUCCESS The entry point is executed successfully.
59 @retval other Some error occurs when executing this entry point.
65 IN EFI_HANDLE ImageHandle
,
66 IN EFI_SYSTEM_TABLE
*SystemTable
72 // Install driver model protocol(s).
74 Status
= EfiLibInstallAllDriverProtocols (
77 &gScsiDiskDriverBinding
,
79 &gScsiDiskComponentName
,
83 ASSERT_EFI_ERROR (Status
);
91 ScsiDiskDriverBindingSupported (
92 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
93 IN EFI_HANDLE Controller
,
94 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
105 // TODO: This - add argument and description to function comment
106 // TODO: Controller - add argument and description to function comment
107 // TODO: RemainingDevicePath - add argument and description to function comment
110 EFI_SCSI_IO_PROTOCOL
*ScsiIo
;
113 Status
= gBS
->OpenProtocol (
115 &gEfiScsiIoProtocolGuid
,
117 This
->DriverBindingHandle
,
119 EFI_OPEN_PROTOCOL_BY_DRIVER
121 if (EFI_ERROR (Status
)) {
125 Status
= ScsiIo
->GetDeviceType (ScsiIo
, &DeviceType
);
126 if (!EFI_ERROR (Status
)) {
127 if ((DeviceType
== EFI_SCSI_TYPE_DISK
) || (DeviceType
== EFI_SCSI_TYPE_CDROM
)) {
128 Status
= EFI_SUCCESS
;
130 Status
= EFI_UNSUPPORTED
;
136 &gEfiScsiIoProtocolGuid
,
137 This
->DriverBindingHandle
,
145 ScsiDiskDriverBindingStart (
146 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
147 IN EFI_HANDLE Controller
,
148 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
159 // TODO: This - add argument and description to function comment
160 // TODO: Controller - add argument and description to function comment
161 // TODO: RemainingDevicePath - add argument and description to function comment
162 // TODO: EFI_DEVICE_ERROR - add return value to function comment
163 // TODO: EFI_SUCCESS - add return value to function comment
166 EFI_SCSI_IO_PROTOCOL
*ScsiIo
;
167 SCSI_DISK_DEV
*ScsiDiskDevice
;
173 Status
= gBS
->AllocatePool (
175 sizeof (SCSI_DISK_DEV
),
176 (VOID
**) &ScsiDiskDevice
178 if (EFI_ERROR (Status
)) {
182 ZeroMem (ScsiDiskDevice
, sizeof (SCSI_DISK_DEV
));
184 Status
= gBS
->OpenProtocol (
186 &gEfiScsiIoProtocolGuid
,
188 This
->DriverBindingHandle
,
190 EFI_OPEN_PROTOCOL_BY_DRIVER
192 if (EFI_ERROR (Status
)) {
193 gBS
->FreePool (ScsiDiskDevice
);
197 ScsiDiskDevice
->Signature
= SCSI_DISK_DEV_SIGNATURE
;
198 ScsiDiskDevice
->ScsiIo
= ScsiIo
;
199 ScsiDiskDevice
->BlkIo
.Media
= &ScsiDiskDevice
->BlkIoMedia
;
200 ScsiDiskDevice
->BlkIo
.Reset
= ScsiDiskReset
;
201 ScsiDiskDevice
->BlkIo
.ReadBlocks
= ScsiDiskReadBlocks
;
202 ScsiDiskDevice
->BlkIo
.WriteBlocks
= ScsiDiskWriteBlocks
;
203 ScsiDiskDevice
->BlkIo
.FlushBlocks
= ScsiDiskFlushBlocks
;
204 ScsiDiskDevice
->Handle
= Controller
;
206 ScsiIo
->GetDeviceType (ScsiIo
, &(ScsiDiskDevice
->DeviceType
));
207 switch (ScsiDiskDevice
->DeviceType
) {
208 case EFI_SCSI_TYPE_DISK
:
209 ScsiDiskDevice
->BlkIo
.Media
->BlockSize
= 0x200;
212 case EFI_SCSI_TYPE_CDROM
:
213 ScsiDiskDevice
->BlkIo
.Media
->BlockSize
= 0x800;
217 // The Sense Data Array's initial size is 6
219 ScsiDiskDevice
->SenseDataNumber
= 6;
220 Status
= gBS
->AllocatePool (
222 sizeof (EFI_SCSI_SENSE_DATA
) * ScsiDiskDevice
->SenseDataNumber
,
223 (VOID
**) &(ScsiDiskDevice
->SenseData
)
225 if (EFI_ERROR (Status
)) {
228 &gEfiScsiIoProtocolGuid
,
229 This
->DriverBindingHandle
,
232 gBS
->FreePool (ScsiDiskDevice
);
237 ScsiDiskDevice
->SenseData
,
238 sizeof (EFI_SCSI_SENSE_DATA
) * ScsiDiskDevice
->SenseDataNumber
242 // Retrive device information
245 for (Index
= 0; Index
< MaxRetry
; Index
++) {
246 Status
= ScsiDiskInquiryDevice (ScsiDiskDevice
, &NeedRetry
);
247 if (!EFI_ERROR (Status
)) {
252 gBS
->FreePool (ScsiDiskDevice
->SenseData
);
255 &gEfiScsiIoProtocolGuid
,
256 This
->DriverBindingHandle
,
259 gBS
->FreePool (ScsiDiskDevice
);
260 return EFI_DEVICE_ERROR
;
264 // The second parameter "TRUE" means must
265 // retrieve media capacity
267 Status
= ScsiDiskDetectMedia (ScsiDiskDevice
, TRUE
, &Temp
);
268 if (!EFI_ERROR (Status
)) {
269 Status
= gBS
->InstallMultipleProtocolInterfaces (
271 &gEfiBlockIoProtocolGuid
,
272 &ScsiDiskDevice
->BlkIo
,
277 if (EFI_ERROR (Status
)) {
278 gBS
->FreePool (ScsiDiskDevice
->SenseData
);
281 &gEfiScsiIoProtocolGuid
,
282 This
->DriverBindingHandle
,
285 gBS
->FreePool (ScsiDiskDevice
);
289 ScsiDiskDevice
->ControllerNameTable
= NULL
;
292 gScsiDiskComponentName
.SupportedLanguages
,
293 &ScsiDiskDevice
->ControllerNameTable
,
294 (CHAR16
*) L
"SCSI Disk Device"
303 ScsiDiskDriverBindingStop (
304 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
305 IN EFI_HANDLE Controller
,
306 IN UINTN NumberOfChildren
,
307 IN EFI_HANDLE
*ChildHandleBuffer
318 // TODO: This - add argument and description to function comment
319 // TODO: Controller - add argument and description to function comment
320 // TODO: NumberOfChildren - add argument and description to function comment
321 // TODO: ChildHandleBuffer - add argument and description to function comment
322 // TODO: EFI_SUCCESS - add return value to function comment
324 EFI_BLOCK_IO_PROTOCOL
*BlkIo
;
325 SCSI_DISK_DEV
*ScsiDiskDevice
;
328 Status
= gBS
->OpenProtocol (
330 &gEfiBlockIoProtocolGuid
,
332 This
->DriverBindingHandle
,
334 EFI_OPEN_PROTOCOL_GET_PROTOCOL
336 if (EFI_ERROR (Status
)) {
340 ScsiDiskDevice
= SCSI_DISK_DEV_FROM_THIS (BlkIo
);
341 Status
= gBS
->UninstallProtocolInterface (
343 &gEfiBlockIoProtocolGuid
,
344 &ScsiDiskDevice
->BlkIo
346 if (!EFI_ERROR (Status
)) {
349 &gEfiScsiIoProtocolGuid
,
350 This
->DriverBindingHandle
,
354 ReleaseScsiDiskDeviceResources (ScsiDiskDevice
);
365 // Block I/O Protocol Interface
371 IN EFI_BLOCK_IO_PROTOCOL
*This
,
372 IN BOOLEAN ExtendedVerification
378 TODO: Add function description
382 This - TODO: add argument description
383 ExtendedVerification - TODO: add argument description
387 TODO: add return values
391 SCSI_DISK_DEV
*ScsiDiskDevice
;
395 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
397 ScsiDiskDevice
= SCSI_DISK_DEV_FROM_THIS (This
);
399 Status
= ScsiDiskDevice
->ScsiIo
->ResetDevice (ScsiDiskDevice
->ScsiIo
);
401 if (!ExtendedVerification
) {
405 Status
= ScsiDiskDevice
->ScsiIo
->ResetBus (ScsiDiskDevice
->ScsiIo
);
408 gBS
->RestoreTPL (OldTpl
);
415 IN EFI_BLOCK_IO_PROTOCOL
*This
,
425 TODO: Add function description
429 This - TODO: add argument description
430 MediaId - TODO: add argument description
431 LBA - TODO: add argument description
432 BufferSize - TODO: add argument description
433 Buffer - TODO: add argument description
437 EFI_INVALID_PARAMETER - TODO: Add description for return value
438 EFI_SUCCESS - TODO: Add description for return value
439 EFI_DEVICE_ERROR - TODO: Add description for return value
440 EFI_NO_MEDIA - TODO: Add description for return value
441 EFI_MEDIA_CHANGED - TODO: Add description for return value
442 EFI_BAD_BUFFER_SIZE - TODO: Add description for return value
443 EFI_INVALID_PARAMETER - TODO: Add description for return value
444 EFI_INVALID_PARAMETER - TODO: Add description for return value
445 EFI_INVALID_PARAMETER - TODO: Add description for return value
449 SCSI_DISK_DEV
*ScsiDiskDevice
;
450 EFI_BLOCK_IO_MEDIA
*Media
;
453 UINTN NumberOfBlocks
;
459 return EFI_INVALID_PARAMETER
;
462 if (BufferSize
== 0) {
466 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
468 ScsiDiskDevice
= SCSI_DISK_DEV_FROM_THIS (This
);
470 if (!IsDeviceFixed (ScsiDiskDevice
)) {
472 Status
= ScsiDiskDetectMedia (ScsiDiskDevice
, FALSE
, &MediaChange
);
473 if (EFI_ERROR (Status
)) {
474 Status
= EFI_DEVICE_ERROR
;
479 gBS
->ReinstallProtocolInterface (
480 ScsiDiskDevice
->Handle
,
481 &gEfiBlockIoProtocolGuid
,
482 &ScsiDiskDevice
->BlkIo
,
483 &ScsiDiskDevice
->BlkIo
488 // Get the intrinsic block size
490 Media
= ScsiDiskDevice
->BlkIo
.Media
;
491 BlockSize
= Media
->BlockSize
;
493 NumberOfBlocks
= BufferSize
/ BlockSize
;
495 if (!(Media
->MediaPresent
)) {
496 Status
= EFI_NO_MEDIA
;
500 if (MediaId
!= Media
->MediaId
) {
501 Status
= EFI_MEDIA_CHANGED
;
505 if (BufferSize
% BlockSize
!= 0) {
506 Status
= EFI_BAD_BUFFER_SIZE
;
510 if (LBA
> Media
->LastBlock
) {
511 Status
= EFI_INVALID_PARAMETER
;
515 if ((LBA
+ NumberOfBlocks
- 1) > Media
->LastBlock
) {
516 Status
= EFI_INVALID_PARAMETER
;
520 if ((Media
->IoAlign
> 1) && (((UINTN
) Buffer
& (Media
->IoAlign
- 1)) != 0)) {
521 Status
= EFI_INVALID_PARAMETER
;
526 // if all the parameters are valid, then perform read sectors command
527 // to transfer data from device to host.
529 Status
= ScsiDiskReadSectors (ScsiDiskDevice
, Buffer
, LBA
, NumberOfBlocks
);
532 gBS
->RestoreTPL (OldTpl
);
538 ScsiDiskWriteBlocks (
539 IN EFI_BLOCK_IO_PROTOCOL
*This
,
549 TODO: Add function description
553 This - TODO: add argument description
554 MediaId - TODO: add argument description
555 LBA - TODO: add argument description
556 BufferSize - TODO: add argument description
557 Buffer - TODO: add argument description
561 EFI_INVALID_PARAMETER - TODO: Add description for return value
562 EFI_SUCCESS - TODO: Add description for return value
563 EFI_DEVICE_ERROR - TODO: Add description for return value
564 EFI_NO_MEDIA - TODO: Add description for return value
565 EFI_MEDIA_CHANGED - TODO: Add description for return value
566 EFI_BAD_BUFFER_SIZE - TODO: Add description for return value
567 EFI_INVALID_PARAMETER - TODO: Add description for return value
568 EFI_INVALID_PARAMETER - TODO: Add description for return value
569 EFI_INVALID_PARAMETER - TODO: Add description for return value
573 SCSI_DISK_DEV
*ScsiDiskDevice
;
574 EFI_BLOCK_IO_MEDIA
*Media
;
577 UINTN NumberOfBlocks
;
583 return EFI_INVALID_PARAMETER
;
586 if (BufferSize
== 0) {
590 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
592 ScsiDiskDevice
= SCSI_DISK_DEV_FROM_THIS (This
);
594 if (!IsDeviceFixed (ScsiDiskDevice
)) {
596 Status
= ScsiDiskDetectMedia (ScsiDiskDevice
, FALSE
, &MediaChange
);
597 if (EFI_ERROR (Status
)) {
598 Status
= EFI_DEVICE_ERROR
;
603 gBS
->ReinstallProtocolInterface (
604 ScsiDiskDevice
->Handle
,
605 &gEfiBlockIoProtocolGuid
,
606 &ScsiDiskDevice
->BlkIo
,
607 &ScsiDiskDevice
->BlkIo
612 // Get the intrinsic block size
614 Media
= ScsiDiskDevice
->BlkIo
.Media
;
615 BlockSize
= Media
->BlockSize
;
617 NumberOfBlocks
= BufferSize
/ BlockSize
;
619 if (!(Media
->MediaPresent
)) {
620 Status
= EFI_NO_MEDIA
;
624 if (MediaId
!= Media
->MediaId
) {
625 Status
= EFI_MEDIA_CHANGED
;
629 if (BufferSize
% BlockSize
!= 0) {
630 Status
= EFI_BAD_BUFFER_SIZE
;
634 if (LBA
> Media
->LastBlock
) {
635 Status
= EFI_INVALID_PARAMETER
;
639 if ((LBA
+ NumberOfBlocks
- 1) > Media
->LastBlock
) {
640 Status
= EFI_INVALID_PARAMETER
;
644 if ((Media
->IoAlign
> 1) && (((UINTN
) Buffer
& (Media
->IoAlign
- 1)) != 0)) {
645 Status
= EFI_INVALID_PARAMETER
;
649 // if all the parameters are valid, then perform read sectors command
650 // to transfer data from device to host.
652 Status
= ScsiDiskWriteSectors (ScsiDiskDevice
, Buffer
, LBA
, NumberOfBlocks
);
655 gBS
->RestoreTPL (OldTpl
);
662 ScsiDiskFlushBlocks (
663 IN EFI_BLOCK_IO_PROTOCOL
*This
669 TODO: Add function description
673 This - TODO: add argument description
677 EFI_SUCCESS - TODO: Add description for return value
688 ScsiDiskDetectMedia (
689 SCSI_DISK_DEV
*ScsiDiskDevice
,
690 BOOLEAN MustReadCapacity
,
697 TODO: Add function description
701 ScsiDiskDevice - TODO: add argument description
702 MustReadCapacity - TODO: add argument description
703 MediaChange - TODO: add argument description
707 EFI_DEVICE_ERROR - TODO: Add description for return value
708 EFI_DEVICE_ERROR - TODO: Add description for return value
709 EFI_DEVICE_ERROR - TODO: Add description for return value
710 EFI_SUCCESS - TODO: Add description for return value
715 EFI_STATUS ReadCapacityStatus
;
716 EFI_SCSI_SENSE_DATA
*SenseData
;
717 UINTN NumberOfSenseKeys
;
719 BOOLEAN NeedReadCapacity
;
722 EFI_BLOCK_IO_MEDIA OldMedia
;
725 Status
= EFI_SUCCESS
;
726 ReadCapacityStatus
= EFI_SUCCESS
;
728 NumberOfSenseKeys
= 0;
729 NeedReadCapacity
= FALSE
;
730 CopyMem (&OldMedia
, ScsiDiskDevice
->BlkIo
.Media
, sizeof (OldMedia
));
731 // OldMedia = *(ScsiDiskDevice->BlkIo.Media);
733 *MediaChange
= FALSE
;
736 for (Index
= 0; Index
< MaxRetry
; Index
++) {
737 Status
= ScsiDiskTestUnitReady (
743 if (!EFI_ERROR (Status
)) {
752 if ((Index
== MaxRetry
) && EFI_ERROR (Status
)) {
753 return EFI_DEVICE_ERROR
;
756 Status
= DetectMediaParsingSenseKeys (
762 if (EFI_ERROR (Status
)) {
766 // ACTION_NO_ACTION: need not read capacity
767 // other action code: need read capacity
769 if (Action
== ACTION_NO_ACTION
) {
770 NeedReadCapacity
= FALSE
;
772 NeedReadCapacity
= TRUE
;
776 // either NeedReadCapacity is TRUE, or MustReadCapacity is TRUE,
777 // retrieve capacity via Read Capacity command
779 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 TODO: Add function description
898 ScsiDiskDevice - TODO: add argument description
899 NeedRetry - TODO: add argument description
903 EFI_SUCCESS - TODO: Add description for return value
904 EFI_DEVICE_ERROR - TODO: Add description for return value
905 EFI_DEVICE_ERROR - TODO: Add description for return value
906 EFI_DEVICE_ERROR - TODO: Add description for return value
907 EFI_DEVICE_ERROR - TODO: Add description for return value
908 EFI_DEVICE_ERROR - TODO: Add description for return value
909 EFI_DEVICE_ERROR - TODO: Add description for return value
910 EFI_DEVICE_ERROR - TODO: Add description for return value
911 EFI_DEVICE_ERROR - TODO: Add description for return value
912 EFI_DEVICE_ERROR - TODO: Add description for return value
916 UINT32 InquiryDataLength
;
917 UINT8 SenseDataLength
;
918 UINT8 HostAdapterStatus
;
920 EFI_SCSI_SENSE_DATA
*SenseDataArray
;
921 UINTN NumberOfSenseKeys
;
926 InquiryDataLength
= sizeof (EFI_SCSI_INQUIRY_DATA
);
929 Status
= SubmitInquiryCommand (
930 ScsiDiskDevice
->ScsiIo
,
931 EfiScsiStallSeconds (1),
936 (VOID
*) &(ScsiDiskDevice
->InquiryData
),
940 if ((Status
== EFI_SUCCESS
) || (Status
== EFI_WARN_BUFFER_TOO_SMALL
)) {
942 // no need to check HostAdapterStatus and TargetStatus
944 ParseInquiryData (ScsiDiskDevice
);
946 } else if (Status
== EFI_NOT_READY
) {
948 // no need to check HostAdapterStatus and TargetStatus
951 return EFI_DEVICE_ERROR
;
952 } else if ((Status
== EFI_INVALID_PARAMETER
) || (Status
== EFI_UNSUPPORTED
)) {
954 // no need to check HostAdapterStatus and TargetStatus
957 return EFI_DEVICE_ERROR
;
960 // go ahead to check HostAdapterStatus and TargetStatus
961 // (EFI_TIMEOUT, EFI_DEVICE_ERROR)
963 Status
= CheckHostAdapterStatus (HostAdapterStatus
);
964 if ((Status
== EFI_TIMEOUT
) || (Status
== EFI_NOT_READY
)) {
966 return EFI_DEVICE_ERROR
;
967 } else if (Status
== EFI_DEVICE_ERROR
) {
969 // reset the scsi channel
971 ScsiDiskDevice
->ScsiIo
->ResetBus (ScsiDiskDevice
->ScsiIo
);
973 return EFI_DEVICE_ERROR
;
976 Status
= CheckTargetStatus (TargetStatus
);
977 if (Status
== EFI_NOT_READY
) {
979 // reset the scsi device
981 ScsiDiskDevice
->ScsiIo
->ResetDevice (ScsiDiskDevice
->ScsiIo
);
983 return EFI_DEVICE_ERROR
;
984 } else if (Status
== EFI_DEVICE_ERROR
) {
986 return EFI_DEVICE_ERROR
;
990 // if goes here, meant SubmitInquiryCommand() failed.
991 // if ScsiDiskRequestSenseKeys() succeeds at last,
992 // better retry SubmitInquiryCommand(). (by setting *NeedRetry = TRUE)
995 for (Index
= 0; Index
< MaxRetry
; Index
++) {
997 Status
= ScsiDiskRequestSenseKeys (
1004 if (!EFI_ERROR (Status
)) {
1006 return EFI_DEVICE_ERROR
;
1010 return EFI_DEVICE_ERROR
;
1014 // ScsiDiskRequestSenseKeys() failed after several rounds of retry.
1015 // set *NeedRetry = FALSE to avoid the outside caller try again.
1018 return EFI_DEVICE_ERROR
;
1022 ScsiDiskTestUnitReady (
1023 SCSI_DISK_DEV
*ScsiDiskDevice
,
1025 EFI_SCSI_SENSE_DATA
**SenseDataArray
,
1026 UINTN
*NumberOfSenseKeys
1028 // TODO: function comment should start with '/*++'
1030 When Test Unit Ready command succeeds,
1031 retrieve Sense Keys via Request Sense;
1032 When Test Unit Ready command encounters any error caused by host adapter or
1033 target, return error without retrieving Sense Keys.
1035 // TODO: function comment should end with '--*/'
1036 // TODO: function comment is missing 'Routine Description:'
1037 // TODO: function comment is missing 'Arguments:'
1038 // TODO: function comment is missing 'Returns:'
1039 // TODO: ScsiDiskDevice - add argument and description to function comment
1040 // TODO: NeedRetry - add argument and description to function comment
1041 // TODO: SenseDataArray - add argument and description to function comment
1042 // TODO: NumberOfSenseKeys - add argument and description to function comment
1043 // TODO: EFI_DEVICE_ERROR - add return value to function comment
1044 // TODO: EFI_DEVICE_ERROR - add return value to function comment
1045 // TODO: EFI_DEVICE_ERROR - add return value to function comment
1046 // TODO: EFI_DEVICE_ERROR - add return value to function comment
1047 // TODO: EFI_DEVICE_ERROR - add return value to function comment
1048 // TODO: EFI_DEVICE_ERROR - add return value to function comment
1049 // TODO: EFI_SUCCESS - add return value to function comment
1050 // TODO: EFI_DEVICE_ERROR - add return value to function comment
1051 // TODO: EFI_DEVICE_ERROR - add return value to function comment
1054 UINT8 SenseDataLength
;
1055 UINT8 HostAdapterStatus
;
1060 SenseDataLength
= 0;
1061 *NumberOfSenseKeys
= 0;
1064 // Parameter 3 and 4: do not require sense data, retrieve it when needed.
1066 Status
= SubmitTestUnitReadyCommand (
1067 ScsiDiskDevice
->ScsiIo
,
1068 EfiScsiStallSeconds (1),
1074 if (Status
== EFI_NOT_READY
) {
1076 // no need to check HostAdapterStatus and TargetStatus
1079 return EFI_DEVICE_ERROR
;
1080 } else if ((Status
== EFI_INVALID_PARAMETER
) || (Status
== EFI_UNSUPPORTED
)) {
1082 // no need to check HostAdapterStatus and TargetStatus
1085 return EFI_DEVICE_ERROR
;
1088 // go ahead to check HostAdapterStatus and TargetStatus
1090 Status
= CheckHostAdapterStatus (HostAdapterStatus
);
1091 if ((Status
== EFI_TIMEOUT
) || (Status
== EFI_NOT_READY
)) {
1093 return EFI_DEVICE_ERROR
;
1094 } else if (Status
== EFI_DEVICE_ERROR
) {
1096 // reset the scsi channel
1098 ScsiDiskDevice
->ScsiIo
->ResetBus (ScsiDiskDevice
->ScsiIo
);
1100 return EFI_DEVICE_ERROR
;
1103 Status
= CheckTargetStatus (TargetStatus
);
1104 if (Status
== EFI_NOT_READY
) {
1106 // reset the scsi device
1108 ScsiDiskDevice
->ScsiIo
->ResetDevice (ScsiDiskDevice
->ScsiIo
);
1110 return EFI_DEVICE_ERROR
;
1111 } else if (Status
== EFI_DEVICE_ERROR
) {
1113 return EFI_DEVICE_ERROR
;
1117 for (Index
= 0; Index
< MaxRetry
; Index
++) {
1119 Status
= ScsiDiskRequestSenseKeys (
1126 if (!EFI_ERROR (Status
)) {
1131 return EFI_DEVICE_ERROR
;
1135 // ScsiDiskRequestSenseKeys() failed after several rounds of retry.
1136 // set *NeedRetry = FALSE to avoid the outside caller try again.
1139 return EFI_DEVICE_ERROR
;
1143 DetectMediaParsingSenseKeys (
1144 SCSI_DISK_DEV
*ScsiDiskDevice
,
1145 EFI_SCSI_SENSE_DATA
*SenseData
,
1146 UINTN NumberOfSenseKeys
,
1151 Routine Description:
1153 TODO: Add function description
1157 ScsiDiskDevice - TODO: add argument description
1158 SenseData - TODO: add argument description
1159 NumberOfSenseKeys - TODO: add argument description
1160 Action - TODO: add argument description
1164 EFI_SUCCESS - TODO: Add description for return value
1165 EFI_SUCCESS - TODO: Add description for return value
1166 EFI_SUCCESS - TODO: Add description for return value
1167 EFI_SUCCESS - TODO: Add description for return value
1168 EFI_DEVICE_ERROR - TODO: Add description for return value
1169 EFI_DEVICE_ERROR - TODO: Add description for return value
1170 EFI_SUCCESS - TODO: Add description for return value
1171 EFI_DEVICE_ERROR - TODO: Add description for return value
1172 EFI_SUCCESS - TODO: Add description for return value
1179 // Default is to read capacity, unless..
1181 *Action
= ACTION_READ_CAPACITY
;
1183 if (NumberOfSenseKeys
== 0) {
1184 *Action
= ACTION_NO_ACTION
;
1188 if (!ScsiDiskHaveSenseKey (SenseData
, NumberOfSenseKeys
)) {
1190 // No Sense Key returned from last submitted command
1192 *Action
= ACTION_NO_ACTION
;
1196 if (ScsiDiskIsNoMedia (SenseData
, NumberOfSenseKeys
)) {
1197 ScsiDiskDevice
->BlkIo
.Media
->MediaPresent
= FALSE
;
1198 ScsiDiskDevice
->BlkIo
.Media
->LastBlock
= 0;
1199 *Action
= ACTION_NO_ACTION
;
1203 if (ScsiDiskIsMediaChange (SenseData
, NumberOfSenseKeys
)) {
1204 ScsiDiskDevice
->BlkIo
.Media
->MediaId
++;
1208 if (ScsiDiskIsMediaError (SenseData
, NumberOfSenseKeys
)) {
1209 ScsiDiskDevice
->BlkIo
.Media
->MediaPresent
= FALSE
;
1210 ScsiDiskDevice
->BlkIo
.Media
->LastBlock
= 0;
1211 return EFI_DEVICE_ERROR
;
1214 if (ScsiDiskIsHardwareError (SenseData
, NumberOfSenseKeys
)) {
1215 return EFI_DEVICE_ERROR
;
1218 if (!ScsiDiskIsDriveReady (SenseData
, NumberOfSenseKeys
, &RetryLater
)) {
1220 *Action
= ACTION_RETRY_COMMAND_LATER
;
1224 return EFI_DEVICE_ERROR
;
1231 ScsiDiskReadCapacity (
1232 SCSI_DISK_DEV
*ScsiDiskDevice
,
1234 EFI_SCSI_SENSE_DATA
**SenseDataArray
,
1235 UINTN
*NumberOfSenseKeys
1239 Routine Description:
1241 TODO: Add function description
1245 ScsiDiskDevice - TODO: add argument description
1246 NeedRetry - TODO: add argument description
1247 SenseDataArray - TODO: add argument description
1248 NumberOfSenseKeys - TODO: add argument description
1252 EFI_SUCCESS - TODO: Add description for return value
1253 EFI_DEVICE_ERROR - TODO: Add description for return value
1254 EFI_DEVICE_ERROR - TODO: Add description for return value
1255 EFI_DEVICE_ERROR - TODO: Add description for return value
1256 EFI_DEVICE_ERROR - TODO: Add description for return value
1257 EFI_DEVICE_ERROR - TODO: Add description for return value
1258 EFI_DEVICE_ERROR - TODO: Add description for return value
1259 EFI_DEVICE_ERROR - TODO: Add description for return value
1260 EFI_DEVICE_ERROR - TODO: Add description for return value
1261 EFI_DEVICE_ERROR - TODO: Add description for return value
1265 EFI_SCSI_DISK_CAPACITY_DATA CapacityData
;
1267 UINT8 HostAdapterStatus
;
1269 EFI_STATUS CommandStatus
;
1273 UINT8 SenseDataLength
;
1275 SenseDataLength
= 0;
1276 ZeroMem (&CapacityData
, sizeof (EFI_SCSI_DISK_CAPACITY_DATA
));
1277 DataLength
= sizeof (EFI_SCSI_DISK_CAPACITY_DATA
);
1279 *NumberOfSenseKeys
= 0;
1282 // submit Read Capacity Command. in this call,not request sense data
1284 CommandStatus
= SubmitReadCapacityCommand (
1285 ScsiDiskDevice
->ScsiIo
,
1286 EfiScsiStallSeconds (1),
1291 (VOID
*) &CapacityData
,
1295 if (CommandStatus
== EFI_SUCCESS
) {
1297 // no need to check HostAdapterStatus and TargetStatus
1299 GetMediaInfo (ScsiDiskDevice
, &CapacityData
);
1301 } else if (CommandStatus
== EFI_NOT_READY
) {
1303 // no need to check HostAdapterStatus and TargetStatus
1306 return EFI_DEVICE_ERROR
;
1307 } else if ((CommandStatus
== EFI_INVALID_PARAMETER
) || (CommandStatus
== EFI_UNSUPPORTED
)) {
1309 // no need to check HostAdapterStatus and TargetStatus
1312 return EFI_DEVICE_ERROR
;
1315 // go ahead to check HostAdapterStatus and TargetStatus
1316 // (EFI_TIMEOUT, EFI_DEVICE_ERROR, EFI_WARN_BUFFER_TOO_SMALL)
1319 Status
= CheckHostAdapterStatus (HostAdapterStatus
);
1320 if ((Status
== EFI_TIMEOUT
) || (Status
== EFI_NOT_READY
)) {
1322 return EFI_DEVICE_ERROR
;
1323 } else if (Status
== EFI_DEVICE_ERROR
) {
1325 // reset the scsi channel
1327 ScsiDiskDevice
->ScsiIo
->ResetBus (ScsiDiskDevice
->ScsiIo
);
1329 return EFI_DEVICE_ERROR
;
1332 Status
= CheckTargetStatus (TargetStatus
);
1333 if (Status
== EFI_NOT_READY
) {
1335 // reset the scsi device
1337 ScsiDiskDevice
->ScsiIo
->ResetDevice (ScsiDiskDevice
->ScsiIo
);
1339 return EFI_DEVICE_ERROR
;
1340 } else if (Status
== EFI_DEVICE_ERROR
) {
1342 return EFI_DEVICE_ERROR
;
1346 // if goes here, meant SubmitReadCapacityCommand() failed.
1347 // if ScsiDiskRequestSenseKeys() succeeds at last,
1348 // better retry SubmitReadCapacityCommand(). (by setting *NeedRetry = TRUE)
1351 for (Index
= 0; Index
< MaxRetry
; Index
++) {
1353 Status
= ScsiDiskRequestSenseKeys (
1360 if (!EFI_ERROR (Status
)) {
1362 return EFI_DEVICE_ERROR
;
1366 return EFI_DEVICE_ERROR
;
1370 // ScsiDiskRequestSenseKeys() failed after several rounds of retry.
1371 // set *NeedRetry = FALSE to avoid the outside caller try again.
1374 return EFI_DEVICE_ERROR
;
1378 CheckHostAdapterStatus (
1379 UINT8 HostAdapterStatus
1383 Routine Description:
1385 TODO: Add function description
1389 HostAdapterStatus - TODO: add argument description
1393 EFI_SUCCESS - TODO: Add description for return value
1394 EFI_TIMEOUT - TODO: Add description for return value
1395 EFI_NOT_READY - TODO: Add description for return value
1396 EFI_DEVICE_ERROR - TODO: Add description for return value
1397 EFI_SUCCESS - TODO: Add description for return value
1401 switch (HostAdapterStatus
) {
1402 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_OK
:
1405 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_SELECTION_TIMEOUT
:
1406 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_TIMEOUT
:
1407 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_TIMEOUT_COMMAND
:
1410 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_MESSAGE_REJECT
:
1411 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_PARITY_ERROR
:
1412 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_REQUEST_SENSE_FAILED
:
1413 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN
:
1414 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_BUS_RESET
:
1415 return EFI_NOT_READY
;
1417 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_BUS_FREE
:
1418 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_PHASE_ERROR
:
1419 return EFI_DEVICE_ERROR
;
1432 Routine Description:
1434 TODO: Add function description
1438 TargetStatus - TODO: add argument description
1442 EFI_SUCCESS - TODO: Add description for return value
1443 EFI_NOT_READY - TODO: Add description for return value
1444 EFI_DEVICE_ERROR - TODO: Add description for return value
1445 EFI_SUCCESS - TODO: Add description for return value
1449 switch (TargetStatus
) {
1450 case EFI_SCSI_IO_STATUS_TARGET_GOOD
:
1451 case EFI_SCSI_IO_STATUS_TARGET_CHECK_CONDITION
:
1452 case EFI_SCSI_IO_STATUS_TARGET_CONDITION_MET
:
1455 case EFI_SCSI_IO_STATUS_TARGET_INTERMEDIATE
:
1456 case EFI_SCSI_IO_STATUS_TARGET_INTERMEDIATE_CONDITION_MET
:
1457 case EFI_SCSI_IO_STATUS_TARGET_BUSY
:
1458 case EFI_SCSI_IO_STATUS_TARGET_COMMOND_TERMINATED
:
1459 case EFI_SCSI_IO_STATUS_TARGET_QUEUE_FULL
:
1460 return EFI_NOT_READY
;
1462 case EFI_SCSI_IO_STATUS_TARGET_RESERVATION_CONFLICT
:
1463 return EFI_DEVICE_ERROR
;
1472 ScsiDiskRequestSenseKeys (
1473 SCSI_DISK_DEV
*ScsiDiskDevice
,
1475 EFI_SCSI_SENSE_DATA
**SenseDataArray
,
1476 UINTN
*NumberOfSenseKeys
,
1477 BOOLEAN AskResetIfError
1479 // TODO: function comment should start with '/*++'
1481 Retrieve all sense keys from the device.
1482 When encountering error during the process,
1483 if retrieve sense keys before error encounterred,
1484 return the sense keys with return status set to EFI_SUCCESS,
1485 and NeedRetry set to FALSE; otherwize, return the proper return
1488 // TODO: function comment should end with '--*/'
1489 // TODO: function comment is missing 'Routine Description:'
1490 // TODO: function comment is missing 'Arguments:'
1491 // TODO: function comment is missing 'Returns:'
1492 // TODO: ScsiDiskDevice - add argument and description to function comment
1493 // TODO: NeedRetry - add argument and description to function comment
1494 // TODO: SenseDataArray - add argument and description to function comment
1495 // TODO: NumberOfSenseKeys - add argument and description to function comment
1496 // TODO: AskResetIfError - add argument and description to function comment
1497 // TODO: EFI_SUCCESS - add return value to function comment
1498 // TODO: EFI_DEVICE_ERROR - add return value to function comment
1499 // TODO: EFI_SUCCESS - add return value to function comment
1501 EFI_SCSI_SENSE_DATA
*PtrSenseData
;
1502 UINT8 SenseDataLength
;
1505 EFI_STATUS FallStatus
;
1506 UINT8 HostAdapterStatus
;
1509 FallStatus
= EFI_SUCCESS
;
1510 SenseDataLength
= sizeof (EFI_SCSI_SENSE_DATA
);
1513 ScsiDiskDevice
->SenseData
,
1514 sizeof (EFI_SCSI_SENSE_DATA
) * (ScsiDiskDevice
->SenseDataNumber
)
1517 *NumberOfSenseKeys
= 0;
1518 *SenseDataArray
= ScsiDiskDevice
->SenseData
;
1519 PtrSenseData
= ScsiDiskDevice
->SenseData
;
1521 for (SenseReq
= TRUE
; SenseReq
;) {
1523 Status
= SubmitRequestSenseCommand (
1524 ScsiDiskDevice
->ScsiIo
,
1525 EfiScsiStallSeconds (2),
1531 if ((Status
== EFI_SUCCESS
) || (Status
== EFI_WARN_BUFFER_TOO_SMALL
)) {
1532 FallStatus
= EFI_SUCCESS
;
1533 } else if ((Status
== EFI_TIMEOUT
) || (Status
== EFI_NOT_READY
)) {
1535 FallStatus
= EFI_DEVICE_ERROR
;
1536 } else if ((Status
== EFI_INVALID_PARAMETER
) || (Status
== EFI_UNSUPPORTED
)) {
1538 FallStatus
= EFI_DEVICE_ERROR
;
1539 } else if (Status
== EFI_DEVICE_ERROR
) {
1540 if (AskResetIfError
) {
1541 ScsiDiskDevice
->ScsiIo
->ResetDevice (ScsiDiskDevice
->ScsiIo
);
1544 FallStatus
= EFI_DEVICE_ERROR
;
1547 if (EFI_ERROR (FallStatus
)) {
1548 if (*NumberOfSenseKeys
!= 0) {
1552 return EFI_DEVICE_ERROR
;
1556 (*NumberOfSenseKeys
) += 1;
1559 // no more sense key or number of sense keys exceeds predefined,
1562 if ((PtrSenseData
->Sense_Key
== EFI_SCSI_SK_NO_SENSE
) ||
1563 (*NumberOfSenseKeys
== ScsiDiskDevice
->SenseDataNumber
)) {
1576 SCSI_DISK_DEV
*ScsiDiskDevice
,
1577 EFI_SCSI_DISK_CAPACITY_DATA
*Capacity
1581 Routine Description:
1583 TODO: Add function description
1587 ScsiDiskDevice - TODO: add argument description
1588 Capacity - TODO: add argument description
1592 TODO: add return values
1596 ScsiDiskDevice
->BlkIo
.Media
->LastBlock
= (Capacity
->LastLba3
<< 24) |
1597 (Capacity
->LastLba2
<< 16) |
1598 (Capacity
->LastLba1
<< 8) |
1601 ScsiDiskDevice
->BlkIo
.Media
->MediaPresent
= TRUE
;
1602 ScsiDiskDevice
->BlkIo
.Media
->BlockSize
= (Capacity
->BlockSize3
<< 24) |
1603 (Capacity
->BlockSize2
<< 16) |
1604 (Capacity
->BlockSize1
<< 8) |
1605 Capacity
->BlockSize0
;
1606 if (ScsiDiskDevice
->DeviceType
== EFI_SCSI_TYPE_DISK
) {
1607 ScsiDiskDevice
->BlkIo
.Media
->BlockSize
= 0x200;
1610 if (ScsiDiskDevice
->DeviceType
== EFI_SCSI_TYPE_CDROM
) {
1611 ScsiDiskDevice
->BlkIo
.Media
->BlockSize
= 0x800;
1617 SCSI_DISK_DEV
*ScsiDiskDevice
1621 Routine Description:
1623 TODO: Add function description
1627 ScsiDiskDevice - TODO: add argument description
1631 TODO: add return values
1635 ScsiDiskDevice
->FixedDevice
= (BOOLEAN
) (ScsiDiskDevice
->InquiryData
.RMB
? 0 : 1);
1636 ScsiDiskDevice
->BlkIoMedia
.RemovableMedia
= (BOOLEAN
) (!ScsiDiskDevice
->FixedDevice
);
1640 ScsiDiskReadSectors (
1641 SCSI_DISK_DEV
*ScsiDiskDevice
,
1644 UINTN NumberOfBlocks
1648 Routine Description:
1650 TODO: Add function description
1654 ScsiDiskDevice - TODO: add argument description
1655 Buffer - TODO: add argument description
1656 Lba - TODO: add argument description
1657 NumberOfBlocks - TODO: add argument description
1661 EFI_DEVICE_ERROR - TODO: Add description for return value
1662 EFI_DEVICE_ERROR - TODO: Add description for return value
1663 EFI_SUCCESS - TODO: Add description for return value
1667 UINTN BlocksRemaining
;
1679 EFI_SCSI_SENSE_DATA
*SenseData
;
1680 UINTN NumberOfSenseKeys
;
1683 NumberOfSenseKeys
= 0;
1685 Status
= EFI_SUCCESS
;
1687 BlocksRemaining
= NumberOfBlocks
;
1688 BlockSize
= ScsiDiskDevice
->BlkIo
.Media
->BlockSize
;
1690 // limit the data bytes that can be transferred by one Read(10) Command
1695 Lba32
= (UINT32
) Lba
;
1697 while (BlocksRemaining
> 0) {
1699 if (BlocksRemaining
<= MaxBlock
) {
1701 SectorCount
= (UINT16
) BlocksRemaining
;
1704 SectorCount
= MaxBlock
;
1707 ByteCount
= SectorCount
* BlockSize
;
1708 Timeout
= EfiScsiStallSeconds (2);
1711 for (Index
= 0; Index
< MaxRetry
; Index
++) {
1713 Status
= ScsiDiskRead10 (
1724 if (!EFI_ERROR (Status
)) {
1729 return EFI_DEVICE_ERROR
;
1734 if ((Index
== MaxRetry
) && (Status
!= EFI_SUCCESS
)) {
1735 return EFI_DEVICE_ERROR
;
1739 // actual transferred sectors
1741 SectorCount
= ByteCount
/ BlockSize
;
1743 Lba32
+= SectorCount
;
1744 PtrBuffer
= PtrBuffer
+ SectorCount
* BlockSize
;
1745 BlocksRemaining
-= SectorCount
;
1752 ScsiDiskWriteSectors (
1753 SCSI_DISK_DEV
*ScsiDiskDevice
,
1756 UINTN NumberOfBlocks
1760 Routine Description:
1762 TODO: Add function description
1766 ScsiDiskDevice - TODO: add argument description
1767 Buffer - TODO: add argument description
1768 Lba - TODO: add argument description
1769 NumberOfBlocks - TODO: add argument description
1773 EFI_DEVICE_ERROR - TODO: Add description for return value
1774 EFI_DEVICE_ERROR - TODO: Add description for return value
1775 EFI_SUCCESS - TODO: Add description for return value
1779 UINTN BlocksRemaining
;
1791 EFI_SCSI_SENSE_DATA
*SenseData
;
1792 UINTN NumberOfSenseKeys
;
1795 NumberOfSenseKeys
= 0;
1797 Status
= EFI_SUCCESS
;
1799 BlocksRemaining
= NumberOfBlocks
;
1800 BlockSize
= ScsiDiskDevice
->BlkIo
.Media
->BlockSize
;
1802 // limit the data bytes that can be transferred by one Write(10) Command
1807 Lba32
= (UINT32
) Lba
;
1809 while (BlocksRemaining
> 0) {
1811 if (BlocksRemaining
<= MaxBlock
) {
1813 SectorCount
= (UINT16
) BlocksRemaining
;
1816 SectorCount
= MaxBlock
;
1819 ByteCount
= SectorCount
* BlockSize
;
1820 Timeout
= EfiScsiStallSeconds (2);
1822 for (Index
= 0; Index
< MaxRetry
; Index
++) {
1823 Status
= ScsiDiskWrite10 (
1834 if (!EFI_ERROR (Status
)) {
1839 return EFI_DEVICE_ERROR
;
1843 if ((Index
== MaxRetry
) && (Status
!= EFI_SUCCESS
)) {
1844 return EFI_DEVICE_ERROR
;
1847 // actual transferred sectors
1849 SectorCount
= ByteCount
/ BlockSize
;
1851 Lba32
+= SectorCount
;
1852 PtrBuffer
= PtrBuffer
+ SectorCount
* BlockSize
;
1853 BlocksRemaining
-= SectorCount
;
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
1895 UINT8 SenseDataLength
;
1897 UINT8 HostAdapterStatus
;
1901 *NumberOfSenseKeys
= 0;
1902 SenseDataLength
= 0;
1903 Status
= SubmitRead10Command (
1904 ScsiDiskDevice
->ScsiIo
,
1920 SCSI_DISK_DEV
*ScsiDiskDevice
,
1922 EFI_SCSI_SENSE_DATA
**SenseDataArray
,
1923 UINTN
*NumberOfSenseKeys
,
1932 Routine Description:
1934 TODO: Add function description
1938 ScsiDiskDevice - TODO: add argument description
1939 NeedRetry - TODO: add argument description
1940 SenseDataArray - TODO: add argument description
1941 NumberOfSenseKeys - TODO: add argument description
1942 Timeout - TODO: add argument description
1943 DataBuffer - TODO: add argument description
1944 DataLength - TODO: add argument description
1945 StartLba - TODO: add argument description
1946 SectorSize - TODO: add argument description
1950 TODO: add return values
1955 UINT8 SenseDataLength
;
1956 UINT8 HostAdapterStatus
;
1960 *NumberOfSenseKeys
= 0;
1961 SenseDataLength
= 0;
1962 Status
= SubmitWrite10Command (
1963 ScsiDiskDevice
->ScsiIo
,
1979 IN EFI_SCSI_SENSE_DATA
*SenseData
,
1980 IN UINTN SenseCounts
1984 Routine Description:
1986 TODO: Add function description
1990 SenseData - TODO: add argument description
1991 SenseCounts - TODO: add argument description
1995 TODO: add return values
1999 EFI_SCSI_SENSE_DATA
*SensePtr
;
2004 SensePtr
= SenseData
;
2006 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2009 // Sense Key is EFI_SCSI_SK_NOT_READY (0x2),
2010 // Additional Sense Code is ASC_NO_MEDIA (0x3A)
2012 if ((SensePtr
->Sense_Key
== EFI_SCSI_SK_NOT_READY
) &&
2013 (SensePtr
->Addnl_Sense_Code
== EFI_SCSI_ASC_NO_MEDIA
)) {
2024 ScsiDiskIsMediaError (
2025 IN EFI_SCSI_SENSE_DATA
*SenseData
,
2026 IN UINTN SenseCounts
2030 Routine Description:
2032 TODO: Add function description
2036 SenseData - TODO: add argument description
2037 SenseCounts - TODO: add argument description
2041 TODO: add return values
2045 EFI_SCSI_SENSE_DATA
*SensePtr
;
2050 SensePtr
= SenseData
;
2052 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2054 switch (SensePtr
->Sense_Key
) {
2056 case EFI_SCSI_SK_MEDIUM_ERROR
:
2058 // Sense Key is EFI_SCSI_SK_MEDIUM_ERROR (0x3)
2060 switch (SensePtr
->Addnl_Sense_Code
) {
2065 case EFI_SCSI_ASC_MEDIA_ERR1
:
2070 case EFI_SCSI_ASC_MEDIA_ERR2
:
2075 case EFI_SCSI_ASC_MEDIA_ERR3
:
2076 case EFI_SCSI_ASC_MEDIA_ERR4
:
2086 case EFI_SCSI_SK_NOT_READY
:
2088 // Sense Key is EFI_SCSI_SK_NOT_READY (0x2)
2090 switch (SensePtr
->Addnl_Sense_Code
) {
2092 // Additional Sense Code is ASC_MEDIA_UPSIDE_DOWN (0x6)
2094 case EFI_SCSI_ASC_MEDIA_UPSIDE_DOWN
:
2114 ScsiDiskIsHardwareError (
2115 IN EFI_SCSI_SENSE_DATA
*SenseData
,
2116 IN UINTN SenseCounts
2120 Routine Description:
2122 TODO: Add function description
2126 SenseData - TODO: add argument description
2127 SenseCounts - TODO: add argument description
2131 TODO: add return values
2135 EFI_SCSI_SENSE_DATA
*SensePtr
;
2140 SensePtr
= SenseData
;
2142 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2145 // Sense Key is EFI_SCSI_SK_HARDWARE_ERROR (0x4)
2147 if (SensePtr
->Sense_Key
== EFI_SCSI_SK_HARDWARE_ERROR
) {
2158 ScsiDiskIsMediaChange (
2159 IN EFI_SCSI_SENSE_DATA
*SenseData
,
2160 IN UINTN SenseCounts
2164 Routine Description:
2166 TODO: Add function description
2170 SenseData - TODO: add argument description
2171 SenseCounts - TODO: add argument description
2175 TODO: add return values
2179 EFI_SCSI_SENSE_DATA
*SensePtr
;
2181 BOOLEAN IsMediaChanged
;
2183 IsMediaChanged
= FALSE
;
2184 SensePtr
= SenseData
;
2186 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2188 // Sense Key is EFI_SCSI_SK_UNIT_ATTENTION (0x6),
2189 // Additional sense code is EFI_SCSI_ASC_MEDIA_CHANGE (0x28)
2191 if ((SensePtr
->Sense_Key
== EFI_SCSI_SK_UNIT_ATTENTION
) &&
2192 (SensePtr
->Addnl_Sense_Code
== EFI_SCSI_ASC_MEDIA_CHANGE
)) {
2193 IsMediaChanged
= TRUE
;
2199 return IsMediaChanged
;
2203 ScsiDiskIsResetBefore (
2204 IN EFI_SCSI_SENSE_DATA
*SenseData
,
2205 IN UINTN SenseCounts
2209 Routine Description:
2211 TODO: Add function description
2215 SenseData - TODO: add argument description
2216 SenseCounts - TODO: add argument description
2220 TODO: add return values
2224 EFI_SCSI_SENSE_DATA
*SensePtr
;
2226 BOOLEAN IsResetBefore
;
2228 IsResetBefore
= FALSE
;
2229 SensePtr
= SenseData
;
2231 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2234 // Sense Key is EFI_SCSI_SK_UNIT_ATTENTION (0x6)
2235 // Additional Sense Code is EFI_SCSI_ASC_RESET (0x29)
2237 if ((SensePtr
->Sense_Key
== EFI_SCSI_SK_UNIT_ATTENTION
) &&
2238 (SensePtr
->Addnl_Sense_Code
== EFI_SCSI_ASC_RESET
)) {
2239 IsResetBefore
= TRUE
;
2245 return IsResetBefore
;
2249 ScsiDiskIsDriveReady (
2250 IN EFI_SCSI_SENSE_DATA
*SenseData
,
2251 IN UINTN SenseCounts
,
2252 OUT BOOLEAN
*RetryLater
2256 Routine Description:
2258 TODO: Add function description
2262 SenseData - TODO: add argument description
2263 SenseCounts - TODO: add argument description
2264 RetryLater - TODO: add argument description
2268 TODO: add return values
2272 EFI_SCSI_SENSE_DATA
*SensePtr
;
2277 *RetryLater
= FALSE
;
2278 SensePtr
= SenseData
;
2280 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2282 switch (SensePtr
->Sense_Key
) {
2284 case EFI_SCSI_SK_NOT_READY
:
2286 // Sense Key is EFI_SCSI_SK_NOT_READY (0x2)
2288 switch (SensePtr
->Addnl_Sense_Code
) {
2289 case EFI_SCSI_ASC_NOT_READY
:
2291 // Additional Sense Code is EFI_SCSI_ASC_NOT_READY (0x4)
2293 switch (SensePtr
->Addnl_Sense_Code_Qualifier
) {
2294 case EFI_SCSI_ASCQ_IN_PROGRESS
:
2296 // Additional Sense Code Qualifier is
2297 // EFI_SCSI_ASCQ_IN_PROGRESS (0x1)
2305 *RetryLater
= FALSE
;
2326 ScsiDiskHaveSenseKey (
2327 IN EFI_SCSI_SENSE_DATA
*SenseData
,
2328 IN UINTN SenseCounts
2332 Routine Description:
2334 TODO: Add function description
2338 SenseData - TODO: add argument description
2339 SenseCounts - TODO: add argument description
2343 TODO: add return values
2347 EFI_SCSI_SENSE_DATA
*SensePtr
;
2349 BOOLEAN HaveSenseKey
;
2351 if (SenseCounts
== 0) {
2352 HaveSenseKey
= FALSE
;
2354 HaveSenseKey
= TRUE
;
2357 SensePtr
= SenseData
;
2359 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2362 // Sense Key is SK_NO_SENSE (0x0)
2364 if ((SensePtr
->Sense_Key
== EFI_SCSI_SK_NO_SENSE
) &&
2366 HaveSenseKey
= FALSE
;
2372 return HaveSenseKey
;
2376 ReleaseScsiDiskDeviceResources (
2377 IN SCSI_DISK_DEV
*ScsiDiskDevice
2381 Routine Description:
2383 TODO: Add function description
2387 ScsiDiskDevice - TODO: add argument description
2391 TODO: add return values
2395 if (ScsiDiskDevice
== NULL
) {
2399 if (ScsiDiskDevice
->SenseData
!= NULL
) {
2400 gBS
->FreePool (ScsiDiskDevice
->SenseData
);
2401 ScsiDiskDevice
->SenseData
= NULL
;
2404 if (ScsiDiskDevice
->ControllerNameTable
!= NULL
) {
2405 FreeUnicodeStringTable (ScsiDiskDevice
->ControllerNameTable
);
2406 ScsiDiskDevice
->ControllerNameTable
= NULL
;
2409 gBS
->FreePool (ScsiDiskDevice
);
2411 ScsiDiskDevice
= NULL
;