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>
28 #include <Library/DebugLib.h>
29 #include <Library/UefiDriverEntryPoint.h>
30 #include <Library/UefiLib.h>
31 #include <Library/BaseMemoryLib.h>
32 #include <Library/ScsiLib.h>
33 #include <Library/UefiBootServicesTableLib.h>
37 EFI_DRIVER_BINDING_PROTOCOL gScsiDiskDriverBinding
= {
38 ScsiDiskDriverBindingSupported
,
39 ScsiDiskDriverBindingStart
,
40 ScsiDiskDriverBindingStop
,
47 The user Entry Point for module ScsiDisk. The user code starts with this function.
49 @param[in] ImageHandle The firmware allocated handle for the EFI image.
50 @param[in] SystemTable A pointer to the EFI System Table.
52 @retval EFI_SUCCESS The entry point is executed successfully.
53 @retval other Some error occurs when executing this entry point.
59 IN EFI_HANDLE ImageHandle
,
60 IN EFI_SYSTEM_TABLE
*SystemTable
66 // Install driver model protocol(s).
68 Status
= EfiLibInstallAllDriverProtocols (
71 &gScsiDiskDriverBinding
,
73 &gScsiDiskComponentName
,
77 ASSERT_EFI_ERROR (Status
);
85 ScsiDiskDriverBindingSupported (
86 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
87 IN EFI_HANDLE Controller
,
88 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
99 // TODO: This - add argument and description to function comment
100 // TODO: Controller - add argument and description to function comment
101 // TODO: RemainingDevicePath - add argument and description to function comment
104 EFI_SCSI_IO_PROTOCOL
*ScsiIo
;
107 Status
= gBS
->OpenProtocol (
109 &gEfiScsiIoProtocolGuid
,
111 This
->DriverBindingHandle
,
113 EFI_OPEN_PROTOCOL_BY_DRIVER
115 if (EFI_ERROR (Status
)) {
119 Status
= ScsiIo
->GetDeviceType (ScsiIo
, &DeviceType
);
120 if (!EFI_ERROR (Status
)) {
121 if ((DeviceType
== EFI_SCSI_TYPE_DISK
) || (DeviceType
== EFI_SCSI_TYPE_CDROM
)) {
122 Status
= EFI_SUCCESS
;
124 Status
= EFI_UNSUPPORTED
;
130 &gEfiScsiIoProtocolGuid
,
131 This
->DriverBindingHandle
,
139 ScsiDiskDriverBindingStart (
140 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
141 IN EFI_HANDLE Controller
,
142 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
153 // TODO: This - add argument and description to function comment
154 // TODO: Controller - add argument and description to function comment
155 // TODO: RemainingDevicePath - add argument and description to function comment
156 // TODO: EFI_DEVICE_ERROR - add return value to function comment
157 // TODO: EFI_SUCCESS - add return value to function comment
160 EFI_SCSI_IO_PROTOCOL
*ScsiIo
;
161 SCSI_DISK_DEV
*ScsiDiskDevice
;
167 Status
= gBS
->AllocatePool (
169 sizeof (SCSI_DISK_DEV
),
170 (VOID
**) &ScsiDiskDevice
172 if (EFI_ERROR (Status
)) {
176 ZeroMem (ScsiDiskDevice
, sizeof (SCSI_DISK_DEV
));
178 Status
= gBS
->OpenProtocol (
180 &gEfiScsiIoProtocolGuid
,
182 This
->DriverBindingHandle
,
184 EFI_OPEN_PROTOCOL_BY_DRIVER
186 if (EFI_ERROR (Status
)) {
187 gBS
->FreePool (ScsiDiskDevice
);
191 ScsiDiskDevice
->Signature
= SCSI_DISK_DEV_SIGNATURE
;
192 ScsiDiskDevice
->ScsiIo
= ScsiIo
;
193 ScsiDiskDevice
->BlkIo
.Media
= &ScsiDiskDevice
->BlkIoMedia
;
194 ScsiDiskDevice
->BlkIo
.Reset
= ScsiDiskReset
;
195 ScsiDiskDevice
->BlkIo
.ReadBlocks
= ScsiDiskReadBlocks
;
196 ScsiDiskDevice
->BlkIo
.WriteBlocks
= ScsiDiskWriteBlocks
;
197 ScsiDiskDevice
->BlkIo
.FlushBlocks
= ScsiDiskFlushBlocks
;
198 ScsiDiskDevice
->Handle
= Controller
;
200 ScsiIo
->GetDeviceType (ScsiIo
, &(ScsiDiskDevice
->DeviceType
));
201 switch (ScsiDiskDevice
->DeviceType
) {
202 case EFI_SCSI_TYPE_DISK
:
203 ScsiDiskDevice
->BlkIo
.Media
->BlockSize
= 0x200;
206 case EFI_SCSI_TYPE_CDROM
:
207 ScsiDiskDevice
->BlkIo
.Media
->BlockSize
= 0x800;
211 // The Sense Data Array's initial size is 6
213 ScsiDiskDevice
->SenseDataNumber
= 6;
214 Status
= gBS
->AllocatePool (
216 sizeof (EFI_SCSI_SENSE_DATA
) * ScsiDiskDevice
->SenseDataNumber
,
217 (VOID
**) &(ScsiDiskDevice
->SenseData
)
219 if (EFI_ERROR (Status
)) {
222 &gEfiScsiIoProtocolGuid
,
223 This
->DriverBindingHandle
,
226 gBS
->FreePool (ScsiDiskDevice
);
231 ScsiDiskDevice
->SenseData
,
232 sizeof (EFI_SCSI_SENSE_DATA
) * ScsiDiskDevice
->SenseDataNumber
236 // Retrive device information
239 for (Index
= 0; Index
< MaxRetry
; Index
++) {
240 Status
= ScsiDiskInquiryDevice (ScsiDiskDevice
, &NeedRetry
);
241 if (!EFI_ERROR (Status
)) {
246 gBS
->FreePool (ScsiDiskDevice
->SenseData
);
249 &gEfiScsiIoProtocolGuid
,
250 This
->DriverBindingHandle
,
253 gBS
->FreePool (ScsiDiskDevice
);
254 return EFI_DEVICE_ERROR
;
258 // The second parameter "TRUE" means must
259 // retrieve media capacity
261 Status
= ScsiDiskDetectMedia (ScsiDiskDevice
, TRUE
, &Temp
);
262 if (!EFI_ERROR (Status
)) {
263 Status
= gBS
->InstallMultipleProtocolInterfaces (
265 &gEfiBlockIoProtocolGuid
,
266 &ScsiDiskDevice
->BlkIo
,
271 if (EFI_ERROR (Status
)) {
272 gBS
->FreePool (ScsiDiskDevice
->SenseData
);
275 &gEfiScsiIoProtocolGuid
,
276 This
->DriverBindingHandle
,
279 gBS
->FreePool (ScsiDiskDevice
);
283 ScsiDiskDevice
->ControllerNameTable
= NULL
;
286 gScsiDiskComponentName
.SupportedLanguages
,
287 &ScsiDiskDevice
->ControllerNameTable
,
288 (CHAR16
*) L
"SCSI Disk Device"
297 ScsiDiskDriverBindingStop (
298 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
299 IN EFI_HANDLE Controller
,
300 IN UINTN NumberOfChildren
,
301 IN EFI_HANDLE
*ChildHandleBuffer
312 // TODO: This - add argument and description to function comment
313 // TODO: Controller - add argument and description to function comment
314 // TODO: NumberOfChildren - add argument and description to function comment
315 // TODO: ChildHandleBuffer - add argument and description to function comment
316 // TODO: EFI_SUCCESS - add return value to function comment
318 EFI_BLOCK_IO_PROTOCOL
*BlkIo
;
319 SCSI_DISK_DEV
*ScsiDiskDevice
;
322 Status
= gBS
->OpenProtocol (
324 &gEfiBlockIoProtocolGuid
,
326 This
->DriverBindingHandle
,
328 EFI_OPEN_PROTOCOL_GET_PROTOCOL
330 if (EFI_ERROR (Status
)) {
334 ScsiDiskDevice
= SCSI_DISK_DEV_FROM_THIS (BlkIo
);
335 Status
= gBS
->UninstallProtocolInterface (
337 &gEfiBlockIoProtocolGuid
,
338 &ScsiDiskDevice
->BlkIo
340 if (!EFI_ERROR (Status
)) {
343 &gEfiScsiIoProtocolGuid
,
344 This
->DriverBindingHandle
,
348 ReleaseScsiDiskDeviceResources (ScsiDiskDevice
);
359 // Block I/O Protocol Interface
365 IN EFI_BLOCK_IO_PROTOCOL
*This
,
366 IN BOOLEAN ExtendedVerification
372 TODO: Add function description
376 This - TODO: add argument description
377 ExtendedVerification - TODO: add argument description
381 TODO: add return values
385 SCSI_DISK_DEV
*ScsiDiskDevice
;
389 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
391 ScsiDiskDevice
= SCSI_DISK_DEV_FROM_THIS (This
);
393 Status
= ScsiDiskDevice
->ScsiIo
->ResetDevice (ScsiDiskDevice
->ScsiIo
);
395 if (!ExtendedVerification
) {
399 Status
= ScsiDiskDevice
->ScsiIo
->ResetBus (ScsiDiskDevice
->ScsiIo
);
402 gBS
->RestoreTPL (OldTpl
);
409 IN EFI_BLOCK_IO_PROTOCOL
*This
,
419 TODO: Add function description
423 This - TODO: add argument description
424 MediaId - TODO: add argument description
425 LBA - TODO: add argument description
426 BufferSize - TODO: add argument description
427 Buffer - TODO: add argument description
431 EFI_INVALID_PARAMETER - TODO: Add description for return value
432 EFI_SUCCESS - TODO: Add description for return value
433 EFI_DEVICE_ERROR - TODO: Add description for return value
434 EFI_NO_MEDIA - TODO: Add description for return value
435 EFI_MEDIA_CHANGED - TODO: Add description for return value
436 EFI_BAD_BUFFER_SIZE - TODO: Add description for return value
437 EFI_INVALID_PARAMETER - TODO: Add description for return value
438 EFI_INVALID_PARAMETER - TODO: Add description for return value
439 EFI_INVALID_PARAMETER - TODO: Add description for return value
443 SCSI_DISK_DEV
*ScsiDiskDevice
;
444 EFI_BLOCK_IO_MEDIA
*Media
;
447 UINTN NumberOfBlocks
;
453 return EFI_INVALID_PARAMETER
;
456 if (BufferSize
== 0) {
460 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
462 ScsiDiskDevice
= SCSI_DISK_DEV_FROM_THIS (This
);
464 if (!IsDeviceFixed (ScsiDiskDevice
)) {
466 Status
= ScsiDiskDetectMedia (ScsiDiskDevice
, FALSE
, &MediaChange
);
467 if (EFI_ERROR (Status
)) {
468 Status
= EFI_DEVICE_ERROR
;
473 gBS
->ReinstallProtocolInterface (
474 ScsiDiskDevice
->Handle
,
475 &gEfiBlockIoProtocolGuid
,
476 &ScsiDiskDevice
->BlkIo
,
477 &ScsiDiskDevice
->BlkIo
482 // Get the intrinsic block size
484 Media
= ScsiDiskDevice
->BlkIo
.Media
;
485 BlockSize
= Media
->BlockSize
;
487 NumberOfBlocks
= BufferSize
/ BlockSize
;
489 if (!(Media
->MediaPresent
)) {
490 Status
= EFI_NO_MEDIA
;
494 if (MediaId
!= Media
->MediaId
) {
495 Status
= EFI_MEDIA_CHANGED
;
499 if (BufferSize
% BlockSize
!= 0) {
500 Status
= EFI_BAD_BUFFER_SIZE
;
504 if (LBA
> Media
->LastBlock
) {
505 Status
= EFI_INVALID_PARAMETER
;
509 if ((LBA
+ NumberOfBlocks
- 1) > Media
->LastBlock
) {
510 Status
= EFI_INVALID_PARAMETER
;
514 if ((Media
->IoAlign
> 1) && (((UINTN
) Buffer
& (Media
->IoAlign
- 1)) != 0)) {
515 Status
= EFI_INVALID_PARAMETER
;
520 // if all the parameters are valid, then perform read sectors command
521 // to transfer data from device to host.
523 Status
= ScsiDiskReadSectors (ScsiDiskDevice
, Buffer
, LBA
, NumberOfBlocks
);
526 gBS
->RestoreTPL (OldTpl
);
532 ScsiDiskWriteBlocks (
533 IN EFI_BLOCK_IO_PROTOCOL
*This
,
543 TODO: Add function description
547 This - TODO: add argument description
548 MediaId - TODO: add argument description
549 LBA - TODO: add argument description
550 BufferSize - TODO: add argument description
551 Buffer - TODO: add argument description
555 EFI_INVALID_PARAMETER - TODO: Add description for return value
556 EFI_SUCCESS - TODO: Add description for return value
557 EFI_DEVICE_ERROR - TODO: Add description for return value
558 EFI_NO_MEDIA - TODO: Add description for return value
559 EFI_MEDIA_CHANGED - TODO: Add description for return value
560 EFI_BAD_BUFFER_SIZE - TODO: Add description for return value
561 EFI_INVALID_PARAMETER - TODO: Add description for return value
562 EFI_INVALID_PARAMETER - TODO: Add description for return value
563 EFI_INVALID_PARAMETER - TODO: Add description for return value
567 SCSI_DISK_DEV
*ScsiDiskDevice
;
568 EFI_BLOCK_IO_MEDIA
*Media
;
571 UINTN NumberOfBlocks
;
577 return EFI_INVALID_PARAMETER
;
580 if (BufferSize
== 0) {
584 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
586 ScsiDiskDevice
= SCSI_DISK_DEV_FROM_THIS (This
);
588 if (!IsDeviceFixed (ScsiDiskDevice
)) {
590 Status
= ScsiDiskDetectMedia (ScsiDiskDevice
, FALSE
, &MediaChange
);
591 if (EFI_ERROR (Status
)) {
592 Status
= EFI_DEVICE_ERROR
;
597 gBS
->ReinstallProtocolInterface (
598 ScsiDiskDevice
->Handle
,
599 &gEfiBlockIoProtocolGuid
,
600 &ScsiDiskDevice
->BlkIo
,
601 &ScsiDiskDevice
->BlkIo
606 // Get the intrinsic block size
608 Media
= ScsiDiskDevice
->BlkIo
.Media
;
609 BlockSize
= Media
->BlockSize
;
611 NumberOfBlocks
= BufferSize
/ BlockSize
;
613 if (!(Media
->MediaPresent
)) {
614 Status
= EFI_NO_MEDIA
;
618 if (MediaId
!= Media
->MediaId
) {
619 Status
= EFI_MEDIA_CHANGED
;
623 if (BufferSize
% BlockSize
!= 0) {
624 Status
= EFI_BAD_BUFFER_SIZE
;
628 if (LBA
> Media
->LastBlock
) {
629 Status
= EFI_INVALID_PARAMETER
;
633 if ((LBA
+ NumberOfBlocks
- 1) > Media
->LastBlock
) {
634 Status
= EFI_INVALID_PARAMETER
;
638 if ((Media
->IoAlign
> 1) && (((UINTN
) Buffer
& (Media
->IoAlign
- 1)) != 0)) {
639 Status
= EFI_INVALID_PARAMETER
;
643 // if all the parameters are valid, then perform read sectors command
644 // to transfer data from device to host.
646 Status
= ScsiDiskWriteSectors (ScsiDiskDevice
, Buffer
, LBA
, NumberOfBlocks
);
649 gBS
->RestoreTPL (OldTpl
);
656 ScsiDiskFlushBlocks (
657 IN EFI_BLOCK_IO_PROTOCOL
*This
663 TODO: Add function description
667 This - TODO: add argument description
671 EFI_SUCCESS - TODO: Add description for return value
682 ScsiDiskDetectMedia (
683 SCSI_DISK_DEV
*ScsiDiskDevice
,
684 BOOLEAN MustReadCapacity
,
691 TODO: Add function description
695 ScsiDiskDevice - TODO: add argument description
696 MustReadCapacity - TODO: add argument description
697 MediaChange - TODO: add argument description
701 EFI_DEVICE_ERROR - TODO: Add description for return value
702 EFI_DEVICE_ERROR - TODO: Add description for return value
703 EFI_DEVICE_ERROR - TODO: Add description for return value
704 EFI_SUCCESS - TODO: Add description for return value
709 EFI_STATUS ReadCapacityStatus
;
710 EFI_SCSI_SENSE_DATA
*SenseData
;
711 UINTN NumberOfSenseKeys
;
713 BOOLEAN NeedReadCapacity
;
716 EFI_BLOCK_IO_MEDIA OldMedia
;
719 Status
= EFI_SUCCESS
;
720 ReadCapacityStatus
= EFI_SUCCESS
;
722 NumberOfSenseKeys
= 0;
723 NeedReadCapacity
= FALSE
;
724 CopyMem (&OldMedia
, ScsiDiskDevice
->BlkIo
.Media
, sizeof (OldMedia
));
725 // OldMedia = *(ScsiDiskDevice->BlkIo.Media);
727 *MediaChange
= FALSE
;
730 for (Index
= 0; Index
< MaxRetry
; Index
++) {
731 Status
= ScsiDiskTestUnitReady (
737 if (!EFI_ERROR (Status
)) {
746 if ((Index
== MaxRetry
) && EFI_ERROR (Status
)) {
747 return EFI_DEVICE_ERROR
;
750 Status
= DetectMediaParsingSenseKeys (
756 if (EFI_ERROR (Status
)) {
760 // ACTION_NO_ACTION: need not read capacity
761 // other action code: need read capacity
763 if (Action
== ACTION_NO_ACTION
) {
764 NeedReadCapacity
= FALSE
;
766 NeedReadCapacity
= TRUE
;
770 // either NeedReadCapacity is TRUE, or MustReadCapacity is TRUE,
771 // retrieve capacity via Read Capacity command
773 if (NeedReadCapacity
|| MustReadCapacity
) {
776 // retrieve media information
779 for (Index
= 0; Index
< MaxRetry
; Index
++) {
781 ReadCapacityStatus
= ScsiDiskReadCapacity (
787 if (EFI_ERROR (ReadCapacityStatus
) && !NeedRetry
) {
788 return EFI_DEVICE_ERROR
;
791 // analyze sense key to action
793 Status
= DetectMediaParsingSenseKeys (
800 // if Status is error, it may indicate crisis error,
801 // so return without retry.
803 if (EFI_ERROR (Status
)) {
808 case ACTION_NO_ACTION
:
815 case ACTION_RETRY_COMMAND_LATER
:
817 // retry the ReadCapacity later and continuously, until the condition
818 // no longer emerges.
819 // stall time is 100000us, or say 0.1 second.
827 // other cases, just retry the command
833 if ((Index
== MaxRetry
) && EFI_ERROR (ReadCapacityStatus
)) {
834 return EFI_DEVICE_ERROR
;
838 if (ScsiDiskDevice
->BlkIo
.Media
->MediaId
!= OldMedia
.MediaId
) {
840 // Media change information got from the device
845 if (ScsiDiskDevice
->BlkIo
.Media
->ReadOnly
!= OldMedia
.ReadOnly
) {
847 ScsiDiskDevice
->BlkIo
.Media
->MediaId
+= 1;
850 if (ScsiDiskDevice
->BlkIo
.Media
->BlockSize
!= OldMedia
.BlockSize
) {
852 ScsiDiskDevice
->BlkIo
.Media
->MediaId
+= 1;
855 if (ScsiDiskDevice
->BlkIo
.Media
->LastBlock
!= OldMedia
.LastBlock
) {
857 ScsiDiskDevice
->BlkIo
.Media
->MediaId
+= 1;
860 if (ScsiDiskDevice
->BlkIo
.Media
->MediaPresent
!= OldMedia
.MediaPresent
) {
861 if (ScsiDiskDevice
->BlkIo
.Media
->MediaPresent
) {
863 // when change from no media to media present, reset the MediaId to 1.
865 ScsiDiskDevice
->BlkIo
.Media
->MediaId
= 1;
868 // when no media, reset the MediaId to zero.
870 ScsiDiskDevice
->BlkIo
.Media
->MediaId
= 0;
880 ScsiDiskInquiryDevice (
881 SCSI_DISK_DEV
*ScsiDiskDevice
,
888 TODO: Add function description
892 ScsiDiskDevice - TODO: add argument description
893 NeedRetry - TODO: add argument description
897 EFI_SUCCESS - TODO: Add description for return value
898 EFI_DEVICE_ERROR - TODO: Add description for return value
899 EFI_DEVICE_ERROR - TODO: Add description for return value
900 EFI_DEVICE_ERROR - TODO: Add description for return value
901 EFI_DEVICE_ERROR - TODO: Add description for return value
902 EFI_DEVICE_ERROR - TODO: Add description for return value
903 EFI_DEVICE_ERROR - 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
910 UINT32 InquiryDataLength
;
911 UINT8 SenseDataLength
;
912 UINT8 HostAdapterStatus
;
914 EFI_SCSI_SENSE_DATA
*SenseDataArray
;
915 UINTN NumberOfSenseKeys
;
920 InquiryDataLength
= sizeof (EFI_SCSI_INQUIRY_DATA
);
923 Status
= SubmitInquiryCommand (
924 ScsiDiskDevice
->ScsiIo
,
925 EfiScsiStallSeconds (1),
930 (VOID
*) &(ScsiDiskDevice
->InquiryData
),
934 if ((Status
== EFI_SUCCESS
) || (Status
== EFI_WARN_BUFFER_TOO_SMALL
)) {
936 // no need to check HostAdapterStatus and TargetStatus
938 ParseInquiryData (ScsiDiskDevice
);
940 } else if (Status
== EFI_NOT_READY
) {
942 // no need to check HostAdapterStatus and TargetStatus
945 return EFI_DEVICE_ERROR
;
946 } else if ((Status
== EFI_INVALID_PARAMETER
) || (Status
== EFI_UNSUPPORTED
)) {
948 // no need to check HostAdapterStatus and TargetStatus
951 return EFI_DEVICE_ERROR
;
954 // go ahead to check HostAdapterStatus and TargetStatus
955 // (EFI_TIMEOUT, EFI_DEVICE_ERROR)
957 Status
= CheckHostAdapterStatus (HostAdapterStatus
);
958 if ((Status
== EFI_TIMEOUT
) || (Status
== EFI_NOT_READY
)) {
960 return EFI_DEVICE_ERROR
;
961 } else if (Status
== EFI_DEVICE_ERROR
) {
963 // reset the scsi channel
965 ScsiDiskDevice
->ScsiIo
->ResetBus (ScsiDiskDevice
->ScsiIo
);
967 return EFI_DEVICE_ERROR
;
970 Status
= CheckTargetStatus (TargetStatus
);
971 if (Status
== EFI_NOT_READY
) {
973 // reset the scsi device
975 ScsiDiskDevice
->ScsiIo
->ResetDevice (ScsiDiskDevice
->ScsiIo
);
977 return EFI_DEVICE_ERROR
;
978 } else if (Status
== EFI_DEVICE_ERROR
) {
980 return EFI_DEVICE_ERROR
;
984 // if goes here, meant SubmitInquiryCommand() failed.
985 // if ScsiDiskRequestSenseKeys() succeeds at last,
986 // better retry SubmitInquiryCommand(). (by setting *NeedRetry = TRUE)
989 for (Index
= 0; Index
< MaxRetry
; Index
++) {
991 Status
= ScsiDiskRequestSenseKeys (
998 if (!EFI_ERROR (Status
)) {
1000 return EFI_DEVICE_ERROR
;
1004 return EFI_DEVICE_ERROR
;
1008 // ScsiDiskRequestSenseKeys() failed after several rounds of retry.
1009 // set *NeedRetry = FALSE to avoid the outside caller try again.
1012 return EFI_DEVICE_ERROR
;
1016 ScsiDiskTestUnitReady (
1017 SCSI_DISK_DEV
*ScsiDiskDevice
,
1019 EFI_SCSI_SENSE_DATA
**SenseDataArray
,
1020 UINTN
*NumberOfSenseKeys
1022 // TODO: function comment should start with '/*++'
1024 When Test Unit Ready command succeeds,
1025 retrieve Sense Keys via Request Sense;
1026 When Test Unit Ready command encounters any error caused by host adapter or
1027 target, return error without retrieving Sense Keys.
1029 // TODO: function comment should end with '--*/'
1030 // TODO: function comment is missing 'Routine Description:'
1031 // TODO: function comment is missing 'Arguments:'
1032 // TODO: function comment is missing 'Returns:'
1033 // TODO: ScsiDiskDevice - add argument and description to function comment
1034 // TODO: NeedRetry - add argument and description to function comment
1035 // TODO: SenseDataArray - add argument and description to function comment
1036 // TODO: NumberOfSenseKeys - add argument and description to function comment
1037 // TODO: EFI_DEVICE_ERROR - add return value to function comment
1038 // TODO: EFI_DEVICE_ERROR - add return value to function comment
1039 // TODO: EFI_DEVICE_ERROR - add return value to function comment
1040 // TODO: EFI_DEVICE_ERROR - add return value to function comment
1041 // TODO: EFI_DEVICE_ERROR - add return value to function comment
1042 // TODO: EFI_DEVICE_ERROR - add return value to function comment
1043 // TODO: EFI_SUCCESS - 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
1048 UINT8 SenseDataLength
;
1049 UINT8 HostAdapterStatus
;
1054 SenseDataLength
= 0;
1055 *NumberOfSenseKeys
= 0;
1058 // Parameter 3 and 4: do not require sense data, retrieve it when needed.
1060 Status
= SubmitTestUnitReadyCommand (
1061 ScsiDiskDevice
->ScsiIo
,
1062 EfiScsiStallSeconds (1),
1068 if (Status
== EFI_NOT_READY
) {
1070 // no need to check HostAdapterStatus and TargetStatus
1073 return EFI_DEVICE_ERROR
;
1074 } else if ((Status
== EFI_INVALID_PARAMETER
) || (Status
== EFI_UNSUPPORTED
)) {
1076 // no need to check HostAdapterStatus and TargetStatus
1079 return EFI_DEVICE_ERROR
;
1082 // go ahead to check HostAdapterStatus and TargetStatus
1084 Status
= CheckHostAdapterStatus (HostAdapterStatus
);
1085 if ((Status
== EFI_TIMEOUT
) || (Status
== EFI_NOT_READY
)) {
1087 return EFI_DEVICE_ERROR
;
1088 } else if (Status
== EFI_DEVICE_ERROR
) {
1090 // reset the scsi channel
1092 ScsiDiskDevice
->ScsiIo
->ResetBus (ScsiDiskDevice
->ScsiIo
);
1094 return EFI_DEVICE_ERROR
;
1097 Status
= CheckTargetStatus (TargetStatus
);
1098 if (Status
== EFI_NOT_READY
) {
1100 // reset the scsi device
1102 ScsiDiskDevice
->ScsiIo
->ResetDevice (ScsiDiskDevice
->ScsiIo
);
1104 return EFI_DEVICE_ERROR
;
1105 } else if (Status
== EFI_DEVICE_ERROR
) {
1107 return EFI_DEVICE_ERROR
;
1111 for (Index
= 0; Index
< MaxRetry
; Index
++) {
1113 Status
= ScsiDiskRequestSenseKeys (
1120 if (!EFI_ERROR (Status
)) {
1125 return EFI_DEVICE_ERROR
;
1129 // ScsiDiskRequestSenseKeys() failed after several rounds of retry.
1130 // set *NeedRetry = FALSE to avoid the outside caller try again.
1133 return EFI_DEVICE_ERROR
;
1137 DetectMediaParsingSenseKeys (
1138 SCSI_DISK_DEV
*ScsiDiskDevice
,
1139 EFI_SCSI_SENSE_DATA
*SenseData
,
1140 UINTN NumberOfSenseKeys
,
1145 Routine Description:
1147 TODO: Add function description
1151 ScsiDiskDevice - TODO: add argument description
1152 SenseData - TODO: add argument description
1153 NumberOfSenseKeys - TODO: add argument description
1154 Action - TODO: add argument description
1158 EFI_SUCCESS - TODO: Add description for return value
1159 EFI_SUCCESS - TODO: Add description for return value
1160 EFI_SUCCESS - TODO: Add description for return value
1161 EFI_SUCCESS - TODO: Add description for return value
1162 EFI_DEVICE_ERROR - TODO: Add description for return value
1163 EFI_DEVICE_ERROR - TODO: Add description for return value
1164 EFI_SUCCESS - TODO: Add description for return value
1165 EFI_DEVICE_ERROR - TODO: Add description for return value
1166 EFI_SUCCESS - TODO: Add description for return value
1173 // Default is to read capacity, unless..
1175 *Action
= ACTION_READ_CAPACITY
;
1177 if (NumberOfSenseKeys
== 0) {
1178 *Action
= ACTION_NO_ACTION
;
1182 if (!ScsiDiskHaveSenseKey (SenseData
, NumberOfSenseKeys
)) {
1184 // No Sense Key returned from last submitted command
1186 *Action
= ACTION_NO_ACTION
;
1190 if (ScsiDiskIsNoMedia (SenseData
, NumberOfSenseKeys
)) {
1191 ScsiDiskDevice
->BlkIo
.Media
->MediaPresent
= FALSE
;
1192 ScsiDiskDevice
->BlkIo
.Media
->LastBlock
= 0;
1193 *Action
= ACTION_NO_ACTION
;
1197 if (ScsiDiskIsMediaChange (SenseData
, NumberOfSenseKeys
)) {
1198 ScsiDiskDevice
->BlkIo
.Media
->MediaId
++;
1202 if (ScsiDiskIsMediaError (SenseData
, NumberOfSenseKeys
)) {
1203 ScsiDiskDevice
->BlkIo
.Media
->MediaPresent
= FALSE
;
1204 ScsiDiskDevice
->BlkIo
.Media
->LastBlock
= 0;
1205 return EFI_DEVICE_ERROR
;
1208 if (ScsiDiskIsHardwareError (SenseData
, NumberOfSenseKeys
)) {
1209 return EFI_DEVICE_ERROR
;
1212 if (!ScsiDiskIsDriveReady (SenseData
, NumberOfSenseKeys
, &RetryLater
)) {
1214 *Action
= ACTION_RETRY_COMMAND_LATER
;
1218 return EFI_DEVICE_ERROR
;
1225 ScsiDiskReadCapacity (
1226 SCSI_DISK_DEV
*ScsiDiskDevice
,
1228 EFI_SCSI_SENSE_DATA
**SenseDataArray
,
1229 UINTN
*NumberOfSenseKeys
1233 Routine Description:
1235 TODO: Add function description
1239 ScsiDiskDevice - TODO: add argument description
1240 NeedRetry - TODO: add argument description
1241 SenseDataArray - TODO: add argument description
1242 NumberOfSenseKeys - TODO: add argument description
1246 EFI_SUCCESS - TODO: Add description for return value
1247 EFI_DEVICE_ERROR - TODO: Add description for return value
1248 EFI_DEVICE_ERROR - TODO: Add description for return value
1249 EFI_DEVICE_ERROR - TODO: Add description for return value
1250 EFI_DEVICE_ERROR - TODO: Add description for return value
1251 EFI_DEVICE_ERROR - TODO: Add description for return value
1252 EFI_DEVICE_ERROR - 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
1259 EFI_SCSI_DISK_CAPACITY_DATA CapacityData
;
1261 UINT8 HostAdapterStatus
;
1263 EFI_STATUS CommandStatus
;
1267 UINT8 SenseDataLength
;
1269 SenseDataLength
= 0;
1270 ZeroMem (&CapacityData
, sizeof (EFI_SCSI_DISK_CAPACITY_DATA
));
1271 DataLength
= sizeof (EFI_SCSI_DISK_CAPACITY_DATA
);
1273 *NumberOfSenseKeys
= 0;
1276 // submit Read Capacity Command. in this call,not request sense data
1278 CommandStatus
= SubmitReadCapacityCommand (
1279 ScsiDiskDevice
->ScsiIo
,
1280 EfiScsiStallSeconds (1),
1285 (VOID
*) &CapacityData
,
1289 if (CommandStatus
== EFI_SUCCESS
) {
1291 // no need to check HostAdapterStatus and TargetStatus
1293 GetMediaInfo (ScsiDiskDevice
, &CapacityData
);
1295 } else if (CommandStatus
== EFI_NOT_READY
) {
1297 // no need to check HostAdapterStatus and TargetStatus
1300 return EFI_DEVICE_ERROR
;
1301 } else if ((CommandStatus
== EFI_INVALID_PARAMETER
) || (CommandStatus
== EFI_UNSUPPORTED
)) {
1303 // no need to check HostAdapterStatus and TargetStatus
1306 return EFI_DEVICE_ERROR
;
1309 // go ahead to check HostAdapterStatus and TargetStatus
1310 // (EFI_TIMEOUT, EFI_DEVICE_ERROR, EFI_WARN_BUFFER_TOO_SMALL)
1313 Status
= CheckHostAdapterStatus (HostAdapterStatus
);
1314 if ((Status
== EFI_TIMEOUT
) || (Status
== EFI_NOT_READY
)) {
1316 return EFI_DEVICE_ERROR
;
1317 } else if (Status
== EFI_DEVICE_ERROR
) {
1319 // reset the scsi channel
1321 ScsiDiskDevice
->ScsiIo
->ResetBus (ScsiDiskDevice
->ScsiIo
);
1323 return EFI_DEVICE_ERROR
;
1326 Status
= CheckTargetStatus (TargetStatus
);
1327 if (Status
== EFI_NOT_READY
) {
1329 // reset the scsi device
1331 ScsiDiskDevice
->ScsiIo
->ResetDevice (ScsiDiskDevice
->ScsiIo
);
1333 return EFI_DEVICE_ERROR
;
1334 } else if (Status
== EFI_DEVICE_ERROR
) {
1336 return EFI_DEVICE_ERROR
;
1340 // if goes here, meant SubmitReadCapacityCommand() failed.
1341 // if ScsiDiskRequestSenseKeys() succeeds at last,
1342 // better retry SubmitReadCapacityCommand(). (by setting *NeedRetry = TRUE)
1345 for (Index
= 0; Index
< MaxRetry
; Index
++) {
1347 Status
= ScsiDiskRequestSenseKeys (
1354 if (!EFI_ERROR (Status
)) {
1356 return EFI_DEVICE_ERROR
;
1360 return EFI_DEVICE_ERROR
;
1364 // ScsiDiskRequestSenseKeys() failed after several rounds of retry.
1365 // set *NeedRetry = FALSE to avoid the outside caller try again.
1368 return EFI_DEVICE_ERROR
;
1372 CheckHostAdapterStatus (
1373 UINT8 HostAdapterStatus
1377 Routine Description:
1379 TODO: Add function description
1383 HostAdapterStatus - TODO: add argument description
1387 EFI_SUCCESS - TODO: Add description for return value
1388 EFI_TIMEOUT - TODO: Add description for return value
1389 EFI_NOT_READY - TODO: Add description for return value
1390 EFI_DEVICE_ERROR - TODO: Add description for return value
1391 EFI_SUCCESS - TODO: Add description for return value
1395 switch (HostAdapterStatus
) {
1396 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_OK
:
1399 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_SELECTION_TIMEOUT
:
1400 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_TIMEOUT
:
1401 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_TIMEOUT_COMMAND
:
1404 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_MESSAGE_REJECT
:
1405 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_PARITY_ERROR
:
1406 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_REQUEST_SENSE_FAILED
:
1407 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN
:
1408 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_BUS_RESET
:
1409 return EFI_NOT_READY
;
1411 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_BUS_FREE
:
1412 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_PHASE_ERROR
:
1413 return EFI_DEVICE_ERROR
;
1426 Routine Description:
1428 TODO: Add function description
1432 TargetStatus - TODO: add argument description
1436 EFI_SUCCESS - TODO: Add description for return value
1437 EFI_NOT_READY - TODO: Add description for return value
1438 EFI_DEVICE_ERROR - TODO: Add description for return value
1439 EFI_SUCCESS - TODO: Add description for return value
1443 switch (TargetStatus
) {
1444 case EFI_SCSI_IO_STATUS_TARGET_GOOD
:
1445 case EFI_SCSI_IO_STATUS_TARGET_CHECK_CONDITION
:
1446 case EFI_SCSI_IO_STATUS_TARGET_CONDITION_MET
:
1449 case EFI_SCSI_IO_STATUS_TARGET_INTERMEDIATE
:
1450 case EFI_SCSI_IO_STATUS_TARGET_INTERMEDIATE_CONDITION_MET
:
1451 case EFI_SCSI_IO_STATUS_TARGET_BUSY
:
1452 case EFI_SCSI_IO_STATUS_TARGET_COMMOND_TERMINATED
:
1453 case EFI_SCSI_IO_STATUS_TARGET_QUEUE_FULL
:
1454 return EFI_NOT_READY
;
1456 case EFI_SCSI_IO_STATUS_TARGET_RESERVATION_CONFLICT
:
1457 return EFI_DEVICE_ERROR
;
1466 ScsiDiskRequestSenseKeys (
1467 SCSI_DISK_DEV
*ScsiDiskDevice
,
1469 EFI_SCSI_SENSE_DATA
**SenseDataArray
,
1470 UINTN
*NumberOfSenseKeys
,
1471 BOOLEAN AskResetIfError
1473 // TODO: function comment should start with '/*++'
1475 Retrieve all sense keys from the device.
1476 When encountering error during the process,
1477 if retrieve sense keys before error encounterred,
1478 return the sense keys with return status set to EFI_SUCCESS,
1479 and NeedRetry set to FALSE; otherwize, return the proper return
1482 // TODO: function comment should end with '--*/'
1483 // TODO: function comment is missing 'Routine Description:'
1484 // TODO: function comment is missing 'Arguments:'
1485 // TODO: function comment is missing 'Returns:'
1486 // TODO: ScsiDiskDevice - add argument and description to function comment
1487 // TODO: NeedRetry - add argument and description to function comment
1488 // TODO: SenseDataArray - add argument and description to function comment
1489 // TODO: NumberOfSenseKeys - add argument and description to function comment
1490 // TODO: AskResetIfError - add argument and description to function comment
1491 // TODO: EFI_SUCCESS - add return value to function comment
1492 // TODO: EFI_DEVICE_ERROR - add return value to function comment
1493 // TODO: EFI_SUCCESS - add return value to function comment
1495 EFI_SCSI_SENSE_DATA
*PtrSenseData
;
1496 UINT8 SenseDataLength
;
1499 EFI_STATUS FallStatus
;
1500 UINT8 HostAdapterStatus
;
1503 FallStatus
= EFI_SUCCESS
;
1504 SenseDataLength
= sizeof (EFI_SCSI_SENSE_DATA
);
1507 ScsiDiskDevice
->SenseData
,
1508 sizeof (EFI_SCSI_SENSE_DATA
) * (ScsiDiskDevice
->SenseDataNumber
)
1511 *NumberOfSenseKeys
= 0;
1512 *SenseDataArray
= ScsiDiskDevice
->SenseData
;
1513 PtrSenseData
= ScsiDiskDevice
->SenseData
;
1515 for (SenseReq
= TRUE
; SenseReq
;) {
1517 Status
= SubmitRequestSenseCommand (
1518 ScsiDiskDevice
->ScsiIo
,
1519 EfiScsiStallSeconds (2),
1525 if ((Status
== EFI_SUCCESS
) || (Status
== EFI_WARN_BUFFER_TOO_SMALL
)) {
1526 FallStatus
= EFI_SUCCESS
;
1527 } else if ((Status
== EFI_TIMEOUT
) || (Status
== EFI_NOT_READY
)) {
1529 FallStatus
= EFI_DEVICE_ERROR
;
1530 } else if ((Status
== EFI_INVALID_PARAMETER
) || (Status
== EFI_UNSUPPORTED
)) {
1532 FallStatus
= EFI_DEVICE_ERROR
;
1533 } else if (Status
== EFI_DEVICE_ERROR
) {
1534 if (AskResetIfError
) {
1535 ScsiDiskDevice
->ScsiIo
->ResetDevice (ScsiDiskDevice
->ScsiIo
);
1538 FallStatus
= EFI_DEVICE_ERROR
;
1541 if (EFI_ERROR (FallStatus
)) {
1542 if (*NumberOfSenseKeys
!= 0) {
1546 return EFI_DEVICE_ERROR
;
1550 (*NumberOfSenseKeys
) += 1;
1553 // no more sense key or number of sense keys exceeds predefined,
1556 if ((PtrSenseData
->Sense_Key
== EFI_SCSI_SK_NO_SENSE
) ||
1557 (*NumberOfSenseKeys
== ScsiDiskDevice
->SenseDataNumber
)) {
1570 SCSI_DISK_DEV
*ScsiDiskDevice
,
1571 EFI_SCSI_DISK_CAPACITY_DATA
*Capacity
1575 Routine Description:
1577 TODO: Add function description
1581 ScsiDiskDevice - TODO: add argument description
1582 Capacity - TODO: add argument description
1586 TODO: add return values
1590 ScsiDiskDevice
->BlkIo
.Media
->LastBlock
= (Capacity
->LastLba3
<< 24) |
1591 (Capacity
->LastLba2
<< 16) |
1592 (Capacity
->LastLba1
<< 8) |
1595 ScsiDiskDevice
->BlkIo
.Media
->MediaPresent
= TRUE
;
1596 ScsiDiskDevice
->BlkIo
.Media
->BlockSize
= (Capacity
->BlockSize3
<< 24) |
1597 (Capacity
->BlockSize2
<< 16) |
1598 (Capacity
->BlockSize1
<< 8) |
1599 Capacity
->BlockSize0
;
1600 if (ScsiDiskDevice
->DeviceType
== EFI_SCSI_TYPE_DISK
) {
1601 ScsiDiskDevice
->BlkIo
.Media
->BlockSize
= 0x200;
1604 if (ScsiDiskDevice
->DeviceType
== EFI_SCSI_TYPE_CDROM
) {
1605 ScsiDiskDevice
->BlkIo
.Media
->BlockSize
= 0x800;
1611 SCSI_DISK_DEV
*ScsiDiskDevice
1615 Routine Description:
1617 TODO: Add function description
1621 ScsiDiskDevice - TODO: add argument description
1625 TODO: add return values
1629 ScsiDiskDevice
->FixedDevice
= (BOOLEAN
) (ScsiDiskDevice
->InquiryData
.RMB
? 0 : 1);
1630 ScsiDiskDevice
->BlkIoMedia
.RemovableMedia
= (BOOLEAN
) (!ScsiDiskDevice
->FixedDevice
);
1634 ScsiDiskReadSectors (
1635 SCSI_DISK_DEV
*ScsiDiskDevice
,
1638 UINTN NumberOfBlocks
1642 Routine Description:
1644 TODO: Add function description
1648 ScsiDiskDevice - TODO: add argument description
1649 Buffer - TODO: add argument description
1650 Lba - TODO: add argument description
1651 NumberOfBlocks - TODO: add argument description
1655 EFI_DEVICE_ERROR - TODO: Add description for return value
1656 EFI_DEVICE_ERROR - TODO: Add description for return value
1657 EFI_SUCCESS - TODO: Add description for return value
1661 UINTN BlocksRemaining
;
1673 EFI_SCSI_SENSE_DATA
*SenseData
;
1674 UINTN NumberOfSenseKeys
;
1677 NumberOfSenseKeys
= 0;
1679 Status
= EFI_SUCCESS
;
1681 BlocksRemaining
= NumberOfBlocks
;
1682 BlockSize
= ScsiDiskDevice
->BlkIo
.Media
->BlockSize
;
1684 // limit the data bytes that can be transferred by one Read(10) Command
1689 Lba32
= (UINT32
) Lba
;
1691 while (BlocksRemaining
> 0) {
1693 if (BlocksRemaining
<= MaxBlock
) {
1695 SectorCount
= (UINT16
) BlocksRemaining
;
1698 SectorCount
= MaxBlock
;
1701 ByteCount
= SectorCount
* BlockSize
;
1702 Timeout
= EfiScsiStallSeconds (2);
1705 for (Index
= 0; Index
< MaxRetry
; Index
++) {
1707 Status
= ScsiDiskRead10 (
1718 if (!EFI_ERROR (Status
)) {
1723 return EFI_DEVICE_ERROR
;
1728 if ((Index
== MaxRetry
) && (Status
!= EFI_SUCCESS
)) {
1729 return EFI_DEVICE_ERROR
;
1733 // actual transferred sectors
1735 SectorCount
= ByteCount
/ BlockSize
;
1737 Lba32
+= SectorCount
;
1738 PtrBuffer
= PtrBuffer
+ SectorCount
* BlockSize
;
1739 BlocksRemaining
-= SectorCount
;
1746 ScsiDiskWriteSectors (
1747 SCSI_DISK_DEV
*ScsiDiskDevice
,
1750 UINTN NumberOfBlocks
1754 Routine Description:
1756 TODO: Add function description
1760 ScsiDiskDevice - TODO: add argument description
1761 Buffer - TODO: add argument description
1762 Lba - TODO: add argument description
1763 NumberOfBlocks - TODO: add argument description
1767 EFI_DEVICE_ERROR - TODO: Add description for return value
1768 EFI_DEVICE_ERROR - TODO: Add description for return value
1769 EFI_SUCCESS - TODO: Add description for return value
1773 UINTN BlocksRemaining
;
1785 EFI_SCSI_SENSE_DATA
*SenseData
;
1786 UINTN NumberOfSenseKeys
;
1789 NumberOfSenseKeys
= 0;
1791 Status
= EFI_SUCCESS
;
1793 BlocksRemaining
= NumberOfBlocks
;
1794 BlockSize
= ScsiDiskDevice
->BlkIo
.Media
->BlockSize
;
1796 // limit the data bytes that can be transferred by one Write(10) Command
1801 Lba32
= (UINT32
) Lba
;
1803 while (BlocksRemaining
> 0) {
1805 if (BlocksRemaining
<= MaxBlock
) {
1807 SectorCount
= (UINT16
) BlocksRemaining
;
1810 SectorCount
= MaxBlock
;
1813 ByteCount
= SectorCount
* BlockSize
;
1814 Timeout
= EfiScsiStallSeconds (2);
1816 for (Index
= 0; Index
< MaxRetry
; Index
++) {
1817 Status
= ScsiDiskWrite10 (
1828 if (!EFI_ERROR (Status
)) {
1833 return EFI_DEVICE_ERROR
;
1837 if ((Index
== MaxRetry
) && (Status
!= EFI_SUCCESS
)) {
1838 return EFI_DEVICE_ERROR
;
1841 // actual transferred sectors
1843 SectorCount
= ByteCount
/ BlockSize
;
1845 Lba32
+= SectorCount
;
1846 PtrBuffer
= PtrBuffer
+ SectorCount
* BlockSize
;
1847 BlocksRemaining
-= SectorCount
;
1855 SCSI_DISK_DEV
*ScsiDiskDevice
,
1857 EFI_SCSI_SENSE_DATA
**SenseDataArray
,
1858 UINTN
*NumberOfSenseKeys
,
1867 Routine Description:
1869 TODO: Add function description
1873 ScsiDiskDevice - TODO: add argument description
1874 NeedRetry - TODO: add argument description
1875 SenseDataArray - TODO: add argument description
1876 NumberOfSenseKeys - TODO: add argument description
1877 Timeout - TODO: add argument description
1878 DataBuffer - TODO: add argument description
1879 DataLength - TODO: add argument description
1880 StartLba - TODO: add argument description
1881 SectorSize - TODO: add argument description
1885 TODO: add return values
1889 UINT8 SenseDataLength
;
1891 UINT8 HostAdapterStatus
;
1895 *NumberOfSenseKeys
= 0;
1896 SenseDataLength
= 0;
1897 Status
= SubmitRead10Command (
1898 ScsiDiskDevice
->ScsiIo
,
1914 SCSI_DISK_DEV
*ScsiDiskDevice
,
1916 EFI_SCSI_SENSE_DATA
**SenseDataArray
,
1917 UINTN
*NumberOfSenseKeys
,
1926 Routine Description:
1928 TODO: Add function description
1932 ScsiDiskDevice - TODO: add argument description
1933 NeedRetry - TODO: add argument description
1934 SenseDataArray - TODO: add argument description
1935 NumberOfSenseKeys - TODO: add argument description
1936 Timeout - TODO: add argument description
1937 DataBuffer - TODO: add argument description
1938 DataLength - TODO: add argument description
1939 StartLba - TODO: add argument description
1940 SectorSize - TODO: add argument description
1944 TODO: add return values
1949 UINT8 SenseDataLength
;
1950 UINT8 HostAdapterStatus
;
1954 *NumberOfSenseKeys
= 0;
1955 SenseDataLength
= 0;
1956 Status
= SubmitWrite10Command (
1957 ScsiDiskDevice
->ScsiIo
,
1973 IN EFI_SCSI_SENSE_DATA
*SenseData
,
1974 IN UINTN SenseCounts
1978 Routine Description:
1980 TODO: Add function description
1984 SenseData - TODO: add argument description
1985 SenseCounts - TODO: add argument description
1989 TODO: add return values
1993 EFI_SCSI_SENSE_DATA
*SensePtr
;
1998 SensePtr
= SenseData
;
2000 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2003 // Sense Key is EFI_SCSI_SK_NOT_READY (0x2),
2004 // Additional Sense Code is ASC_NO_MEDIA (0x3A)
2006 if ((SensePtr
->Sense_Key
== EFI_SCSI_SK_NOT_READY
) &&
2007 (SensePtr
->Addnl_Sense_Code
== EFI_SCSI_ASC_NO_MEDIA
)) {
2018 ScsiDiskIsMediaError (
2019 IN EFI_SCSI_SENSE_DATA
*SenseData
,
2020 IN UINTN SenseCounts
2024 Routine Description:
2026 TODO: Add function description
2030 SenseData - TODO: add argument description
2031 SenseCounts - TODO: add argument description
2035 TODO: add return values
2039 EFI_SCSI_SENSE_DATA
*SensePtr
;
2044 SensePtr
= SenseData
;
2046 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2048 switch (SensePtr
->Sense_Key
) {
2050 case EFI_SCSI_SK_MEDIUM_ERROR
:
2052 // Sense Key is EFI_SCSI_SK_MEDIUM_ERROR (0x3)
2054 switch (SensePtr
->Addnl_Sense_Code
) {
2059 case EFI_SCSI_ASC_MEDIA_ERR1
:
2064 case EFI_SCSI_ASC_MEDIA_ERR2
:
2069 case EFI_SCSI_ASC_MEDIA_ERR3
:
2070 case EFI_SCSI_ASC_MEDIA_ERR4
:
2080 case EFI_SCSI_SK_NOT_READY
:
2082 // Sense Key is EFI_SCSI_SK_NOT_READY (0x2)
2084 switch (SensePtr
->Addnl_Sense_Code
) {
2086 // Additional Sense Code is ASC_MEDIA_UPSIDE_DOWN (0x6)
2088 case EFI_SCSI_ASC_MEDIA_UPSIDE_DOWN
:
2108 ScsiDiskIsHardwareError (
2109 IN EFI_SCSI_SENSE_DATA
*SenseData
,
2110 IN UINTN SenseCounts
2114 Routine Description:
2116 TODO: Add function description
2120 SenseData - TODO: add argument description
2121 SenseCounts - TODO: add argument description
2125 TODO: add return values
2129 EFI_SCSI_SENSE_DATA
*SensePtr
;
2134 SensePtr
= SenseData
;
2136 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2139 // Sense Key is EFI_SCSI_SK_HARDWARE_ERROR (0x4)
2141 if (SensePtr
->Sense_Key
== EFI_SCSI_SK_HARDWARE_ERROR
) {
2152 ScsiDiskIsMediaChange (
2153 IN EFI_SCSI_SENSE_DATA
*SenseData
,
2154 IN UINTN SenseCounts
2158 Routine Description:
2160 TODO: Add function description
2164 SenseData - TODO: add argument description
2165 SenseCounts - TODO: add argument description
2169 TODO: add return values
2173 EFI_SCSI_SENSE_DATA
*SensePtr
;
2175 BOOLEAN IsMediaChanged
;
2177 IsMediaChanged
= FALSE
;
2178 SensePtr
= SenseData
;
2180 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2182 // Sense Key is EFI_SCSI_SK_UNIT_ATTENTION (0x6),
2183 // Additional sense code is EFI_SCSI_ASC_MEDIA_CHANGE (0x28)
2185 if ((SensePtr
->Sense_Key
== EFI_SCSI_SK_UNIT_ATTENTION
) &&
2186 (SensePtr
->Addnl_Sense_Code
== EFI_SCSI_ASC_MEDIA_CHANGE
)) {
2187 IsMediaChanged
= TRUE
;
2193 return IsMediaChanged
;
2197 ScsiDiskIsResetBefore (
2198 IN EFI_SCSI_SENSE_DATA
*SenseData
,
2199 IN UINTN SenseCounts
2203 Routine Description:
2205 TODO: Add function description
2209 SenseData - TODO: add argument description
2210 SenseCounts - TODO: add argument description
2214 TODO: add return values
2218 EFI_SCSI_SENSE_DATA
*SensePtr
;
2220 BOOLEAN IsResetBefore
;
2222 IsResetBefore
= FALSE
;
2223 SensePtr
= SenseData
;
2225 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2228 // Sense Key is EFI_SCSI_SK_UNIT_ATTENTION (0x6)
2229 // Additional Sense Code is EFI_SCSI_ASC_RESET (0x29)
2231 if ((SensePtr
->Sense_Key
== EFI_SCSI_SK_UNIT_ATTENTION
) &&
2232 (SensePtr
->Addnl_Sense_Code
== EFI_SCSI_ASC_RESET
)) {
2233 IsResetBefore
= TRUE
;
2239 return IsResetBefore
;
2243 ScsiDiskIsDriveReady (
2244 IN EFI_SCSI_SENSE_DATA
*SenseData
,
2245 IN UINTN SenseCounts
,
2246 OUT BOOLEAN
*RetryLater
2250 Routine Description:
2252 TODO: Add function description
2256 SenseData - TODO: add argument description
2257 SenseCounts - TODO: add argument description
2258 RetryLater - TODO: add argument description
2262 TODO: add return values
2266 EFI_SCSI_SENSE_DATA
*SensePtr
;
2271 *RetryLater
= FALSE
;
2272 SensePtr
= SenseData
;
2274 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2276 switch (SensePtr
->Sense_Key
) {
2278 case EFI_SCSI_SK_NOT_READY
:
2280 // Sense Key is EFI_SCSI_SK_NOT_READY (0x2)
2282 switch (SensePtr
->Addnl_Sense_Code
) {
2283 case EFI_SCSI_ASC_NOT_READY
:
2285 // Additional Sense Code is EFI_SCSI_ASC_NOT_READY (0x4)
2287 switch (SensePtr
->Addnl_Sense_Code_Qualifier
) {
2288 case EFI_SCSI_ASCQ_IN_PROGRESS
:
2290 // Additional Sense Code Qualifier is
2291 // EFI_SCSI_ASCQ_IN_PROGRESS (0x1)
2299 *RetryLater
= FALSE
;
2320 ScsiDiskHaveSenseKey (
2321 IN EFI_SCSI_SENSE_DATA
*SenseData
,
2322 IN UINTN SenseCounts
2326 Routine Description:
2328 TODO: Add function description
2332 SenseData - TODO: add argument description
2333 SenseCounts - TODO: add argument description
2337 TODO: add return values
2341 EFI_SCSI_SENSE_DATA
*SensePtr
;
2343 BOOLEAN HaveSenseKey
;
2345 if (SenseCounts
== 0) {
2346 HaveSenseKey
= FALSE
;
2348 HaveSenseKey
= TRUE
;
2351 SensePtr
= SenseData
;
2353 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2356 // Sense Key is SK_NO_SENSE (0x0)
2358 if ((SensePtr
->Sense_Key
== EFI_SCSI_SK_NO_SENSE
) &&
2360 HaveSenseKey
= FALSE
;
2366 return HaveSenseKey
;
2370 ReleaseScsiDiskDeviceResources (
2371 IN SCSI_DISK_DEV
*ScsiDiskDevice
2375 Routine Description:
2377 TODO: Add function description
2381 ScsiDiskDevice - TODO: add argument description
2385 TODO: add return values
2389 if (ScsiDiskDevice
== NULL
) {
2393 if (ScsiDiskDevice
->SenseData
!= NULL
) {
2394 gBS
->FreePool (ScsiDiskDevice
->SenseData
);
2395 ScsiDiskDevice
->SenseData
= NULL
;
2398 if (ScsiDiskDevice
->ControllerNameTable
!= NULL
) {
2399 FreeUnicodeStringTable (ScsiDiskDevice
->ControllerNameTable
);
2400 ScsiDiskDevice
->ControllerNameTable
= NULL
;
2403 gBS
->FreePool (ScsiDiskDevice
);
2405 ScsiDiskDevice
= NULL
;