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.
22 EFI_DRIVER_BINDING_PROTOCOL gScsiDiskDriverBinding
= {
23 ScsiDiskDriverBindingSupported
,
24 ScsiDiskDriverBindingStart
,
25 ScsiDiskDriverBindingStop
,
33 ScsiDiskDriverBindingSupported (
34 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
35 IN EFI_HANDLE Controller
,
36 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
47 // TODO: This - add argument and description to function comment
48 // TODO: Controller - add argument and description to function comment
49 // TODO: RemainingDevicePath - add argument and description to function comment
52 EFI_SCSI_IO_PROTOCOL
*ScsiIo
;
55 Status
= gBS
->OpenProtocol (
57 &gEfiScsiIoProtocolGuid
,
59 This
->DriverBindingHandle
,
61 EFI_OPEN_PROTOCOL_BY_DRIVER
63 if (EFI_ERROR (Status
)) {
67 Status
= ScsiIo
->GetDeviceType (ScsiIo
, &DeviceType
);
68 if (!EFI_ERROR (Status
)) {
69 if ((DeviceType
== EFI_SCSI_TYPE_DISK
) || (DeviceType
== EFI_SCSI_TYPE_CDROM
)) {
72 Status
= EFI_UNSUPPORTED
;
78 &gEfiScsiIoProtocolGuid
,
79 This
->DriverBindingHandle
,
87 ScsiDiskDriverBindingStart (
88 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
89 IN EFI_HANDLE Controller
,
90 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
101 // TODO: This - add argument and description to function comment
102 // TODO: Controller - add argument and description to function comment
103 // TODO: RemainingDevicePath - add argument and description to function comment
104 // TODO: EFI_DEVICE_ERROR - add return value to function comment
105 // TODO: EFI_SUCCESS - add return value to function comment
108 EFI_SCSI_IO_PROTOCOL
*ScsiIo
;
109 SCSI_DISK_DEV
*ScsiDiskDevice
;
115 Status
= gBS
->AllocatePool (
117 sizeof (SCSI_DISK_DEV
),
118 (VOID
**) &ScsiDiskDevice
120 if (EFI_ERROR (Status
)) {
124 ZeroMem (ScsiDiskDevice
, sizeof (SCSI_DISK_DEV
));
126 Status
= gBS
->OpenProtocol (
128 &gEfiScsiIoProtocolGuid
,
130 This
->DriverBindingHandle
,
132 EFI_OPEN_PROTOCOL_BY_DRIVER
134 if (EFI_ERROR (Status
)) {
135 gBS
->FreePool (ScsiDiskDevice
);
139 ScsiDiskDevice
->Signature
= SCSI_DISK_DEV_SIGNATURE
;
140 ScsiDiskDevice
->ScsiIo
= ScsiIo
;
141 ScsiDiskDevice
->BlkIo
.Media
= &ScsiDiskDevice
->BlkIoMedia
;
142 ScsiDiskDevice
->BlkIo
.Reset
= ScsiDiskReset
;
143 ScsiDiskDevice
->BlkIo
.ReadBlocks
= ScsiDiskReadBlocks
;
144 ScsiDiskDevice
->BlkIo
.WriteBlocks
= ScsiDiskWriteBlocks
;
145 ScsiDiskDevice
->BlkIo
.FlushBlocks
= ScsiDiskFlushBlocks
;
146 ScsiDiskDevice
->Handle
= Controller
;
148 ScsiIo
->GetDeviceType (ScsiIo
, &(ScsiDiskDevice
->DeviceType
));
149 switch (ScsiDiskDevice
->DeviceType
) {
150 case EFI_SCSI_TYPE_DISK
:
151 ScsiDiskDevice
->BlkIo
.Media
->BlockSize
= 0x200;
154 case EFI_SCSI_TYPE_CDROM
:
155 ScsiDiskDevice
->BlkIo
.Media
->BlockSize
= 0x800;
159 // The Sense Data Array's initial size is 6
161 ScsiDiskDevice
->SenseDataNumber
= 6;
162 Status
= gBS
->AllocatePool (
164 sizeof (EFI_SCSI_SENSE_DATA
) * ScsiDiskDevice
->SenseDataNumber
,
165 (VOID
**) &(ScsiDiskDevice
->SenseData
)
167 if (EFI_ERROR (Status
)) {
170 &gEfiScsiIoProtocolGuid
,
171 This
->DriverBindingHandle
,
174 gBS
->FreePool (ScsiDiskDevice
);
179 ScsiDiskDevice
->SenseData
,
180 sizeof (EFI_SCSI_SENSE_DATA
) * ScsiDiskDevice
->SenseDataNumber
184 // Retrive device information
187 for (Index
= 0; Index
< MaxRetry
; Index
++) {
188 Status
= ScsiDiskInquiryDevice (ScsiDiskDevice
, &NeedRetry
);
189 if (!EFI_ERROR (Status
)) {
194 gBS
->FreePool (ScsiDiskDevice
->SenseData
);
197 &gEfiScsiIoProtocolGuid
,
198 This
->DriverBindingHandle
,
201 gBS
->FreePool (ScsiDiskDevice
);
202 return EFI_DEVICE_ERROR
;
206 // The second parameter "TRUE" means must
207 // retrieve media capacity
209 Status
= ScsiDiskDetectMedia (ScsiDiskDevice
, TRUE
, &Temp
);
210 if (!EFI_ERROR (Status
)) {
211 Status
= gBS
->InstallMultipleProtocolInterfaces (
213 &gEfiBlockIoProtocolGuid
,
214 &ScsiDiskDevice
->BlkIo
,
219 if (EFI_ERROR (Status
)) {
220 gBS
->FreePool (ScsiDiskDevice
->SenseData
);
223 &gEfiScsiIoProtocolGuid
,
224 This
->DriverBindingHandle
,
227 gBS
->FreePool (ScsiDiskDevice
);
231 ScsiDiskDevice
->ControllerNameTable
= NULL
;
234 gScsiDiskComponentName
.SupportedLanguages
,
235 &ScsiDiskDevice
->ControllerNameTable
,
236 (CHAR16
*) L
"SCSI Disk Device"
245 ScsiDiskDriverBindingStop (
246 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
247 IN EFI_HANDLE Controller
,
248 IN UINTN NumberOfChildren
,
249 IN EFI_HANDLE
*ChildHandleBuffer
260 // TODO: This - add argument and description to function comment
261 // TODO: Controller - add argument and description to function comment
262 // TODO: NumberOfChildren - add argument and description to function comment
263 // TODO: ChildHandleBuffer - add argument and description to function comment
264 // TODO: EFI_SUCCESS - add return value to function comment
266 EFI_BLOCK_IO_PROTOCOL
*BlkIo
;
267 SCSI_DISK_DEV
*ScsiDiskDevice
;
270 Status
= gBS
->OpenProtocol (
272 &gEfiBlockIoProtocolGuid
,
274 This
->DriverBindingHandle
,
276 EFI_OPEN_PROTOCOL_GET_PROTOCOL
278 if (EFI_ERROR (Status
)) {
282 ScsiDiskDevice
= SCSI_DISK_DEV_FROM_THIS (BlkIo
);
283 Status
= gBS
->UninstallProtocolInterface (
285 &gEfiBlockIoProtocolGuid
,
286 &ScsiDiskDevice
->BlkIo
288 if (!EFI_ERROR (Status
)) {
291 &gEfiScsiIoProtocolGuid
,
292 This
->DriverBindingHandle
,
296 ReleaseScsiDiskDeviceResources (ScsiDiskDevice
);
307 // Block I/O Protocol Interface
313 IN EFI_BLOCK_IO_PROTOCOL
*This
,
314 IN BOOLEAN ExtendedVerification
320 TODO: Add function description
324 This - TODO: add argument description
325 ExtendedVerification - TODO: add argument description
329 TODO: add return values
333 SCSI_DISK_DEV
*ScsiDiskDevice
;
337 OldTpl
= gBS
->RaiseTPL (EFI_TPL_CALLBACK
);
339 ScsiDiskDevice
= SCSI_DISK_DEV_FROM_THIS (This
);
341 Status
= ScsiDiskDevice
->ScsiIo
->ResetDevice (ScsiDiskDevice
->ScsiIo
);
343 if (!ExtendedVerification
) {
347 Status
= ScsiDiskDevice
->ScsiIo
->ResetBus (ScsiDiskDevice
->ScsiIo
);
350 gBS
->RestoreTPL (OldTpl
);
357 IN EFI_BLOCK_IO_PROTOCOL
*This
,
367 TODO: Add function description
371 This - TODO: add argument description
372 MediaId - TODO: add argument description
373 LBA - TODO: add argument description
374 BufferSize - TODO: add argument description
375 Buffer - TODO: add argument description
379 EFI_INVALID_PARAMETER - TODO: Add description for return value
380 EFI_SUCCESS - TODO: Add description for return value
381 EFI_DEVICE_ERROR - TODO: Add description for return value
382 EFI_NO_MEDIA - TODO: Add description for return value
383 EFI_MEDIA_CHANGED - TODO: Add description for return value
384 EFI_BAD_BUFFER_SIZE - TODO: Add description for return value
385 EFI_INVALID_PARAMETER - TODO: Add description for return value
386 EFI_INVALID_PARAMETER - TODO: Add description for return value
387 EFI_INVALID_PARAMETER - TODO: Add description for return value
391 SCSI_DISK_DEV
*ScsiDiskDevice
;
392 EFI_BLOCK_IO_MEDIA
*Media
;
395 UINTN NumberOfBlocks
;
401 return EFI_INVALID_PARAMETER
;
404 if (BufferSize
== 0) {
408 OldTpl
= gBS
->RaiseTPL (EFI_TPL_CALLBACK
);
410 ScsiDiskDevice
= SCSI_DISK_DEV_FROM_THIS (This
);
412 if (!IsDeviceFixed (ScsiDiskDevice
)) {
414 Status
= ScsiDiskDetectMedia (ScsiDiskDevice
, FALSE
, &MediaChange
);
415 if (EFI_ERROR (Status
)) {
416 Status
= EFI_DEVICE_ERROR
;
421 gBS
->ReinstallProtocolInterface (
422 ScsiDiskDevice
->Handle
,
423 &gEfiBlockIoProtocolGuid
,
424 &ScsiDiskDevice
->BlkIo
,
425 &ScsiDiskDevice
->BlkIo
430 // Get the intrinsic block size
432 Media
= ScsiDiskDevice
->BlkIo
.Media
;
433 BlockSize
= Media
->BlockSize
;
435 NumberOfBlocks
= BufferSize
/ BlockSize
;
437 if (!(Media
->MediaPresent
)) {
438 Status
= EFI_NO_MEDIA
;
442 if (MediaId
!= Media
->MediaId
) {
443 Status
= EFI_MEDIA_CHANGED
;
447 if (BufferSize
% BlockSize
!= 0) {
448 Status
= EFI_BAD_BUFFER_SIZE
;
452 if (LBA
> Media
->LastBlock
) {
453 Status
= EFI_INVALID_PARAMETER
;
457 if ((LBA
+ NumberOfBlocks
- 1) > Media
->LastBlock
) {
458 Status
= EFI_INVALID_PARAMETER
;
462 if ((Media
->IoAlign
> 1) && (((UINTN
) Buffer
& (Media
->IoAlign
- 1)) != 0)) {
463 Status
= EFI_INVALID_PARAMETER
;
468 // if all the parameters are valid, then perform read sectors command
469 // to transfer data from device to host.
471 Status
= ScsiDiskReadSectors (ScsiDiskDevice
, Buffer
, LBA
, NumberOfBlocks
);
474 gBS
->RestoreTPL (OldTpl
);
480 ScsiDiskWriteBlocks (
481 IN EFI_BLOCK_IO_PROTOCOL
*This
,
491 TODO: Add function description
495 This - TODO: add argument description
496 MediaId - TODO: add argument description
497 LBA - TODO: add argument description
498 BufferSize - TODO: add argument description
499 Buffer - TODO: add argument description
503 EFI_INVALID_PARAMETER - TODO: Add description for return value
504 EFI_SUCCESS - TODO: Add description for return value
505 EFI_DEVICE_ERROR - TODO: Add description for return value
506 EFI_NO_MEDIA - TODO: Add description for return value
507 EFI_MEDIA_CHANGED - TODO: Add description for return value
508 EFI_BAD_BUFFER_SIZE - TODO: Add description for return value
509 EFI_INVALID_PARAMETER - TODO: Add description for return value
510 EFI_INVALID_PARAMETER - TODO: Add description for return value
511 EFI_INVALID_PARAMETER - TODO: Add description for return value
515 SCSI_DISK_DEV
*ScsiDiskDevice
;
516 EFI_BLOCK_IO_MEDIA
*Media
;
519 UINTN NumberOfBlocks
;
525 return EFI_INVALID_PARAMETER
;
528 if (BufferSize
== 0) {
532 OldTpl
= gBS
->RaiseTPL (EFI_TPL_CALLBACK
);
534 ScsiDiskDevice
= SCSI_DISK_DEV_FROM_THIS (This
);
536 if (!IsDeviceFixed (ScsiDiskDevice
)) {
538 Status
= ScsiDiskDetectMedia (ScsiDiskDevice
, FALSE
, &MediaChange
);
539 if (EFI_ERROR (Status
)) {
540 Status
= EFI_DEVICE_ERROR
;
545 gBS
->ReinstallProtocolInterface (
546 ScsiDiskDevice
->Handle
,
547 &gEfiBlockIoProtocolGuid
,
548 &ScsiDiskDevice
->BlkIo
,
549 &ScsiDiskDevice
->BlkIo
554 // Get the intrinsic block size
556 Media
= ScsiDiskDevice
->BlkIo
.Media
;
557 BlockSize
= Media
->BlockSize
;
559 NumberOfBlocks
= BufferSize
/ BlockSize
;
561 if (!(Media
->MediaPresent
)) {
562 Status
= EFI_NO_MEDIA
;
566 if (MediaId
!= Media
->MediaId
) {
567 Status
= EFI_MEDIA_CHANGED
;
571 if (BufferSize
% BlockSize
!= 0) {
572 Status
= EFI_BAD_BUFFER_SIZE
;
576 if (LBA
> Media
->LastBlock
) {
577 Status
= EFI_INVALID_PARAMETER
;
581 if ((LBA
+ NumberOfBlocks
- 1) > Media
->LastBlock
) {
582 Status
= EFI_INVALID_PARAMETER
;
586 if ((Media
->IoAlign
> 1) && (((UINTN
) Buffer
& (Media
->IoAlign
- 1)) != 0)) {
587 Status
= EFI_INVALID_PARAMETER
;
591 // if all the parameters are valid, then perform read sectors command
592 // to transfer data from device to host.
594 Status
= ScsiDiskWriteSectors (ScsiDiskDevice
, Buffer
, LBA
, NumberOfBlocks
);
597 gBS
->RestoreTPL (OldTpl
);
604 ScsiDiskFlushBlocks (
605 IN EFI_BLOCK_IO_PROTOCOL
*This
611 TODO: Add function description
615 This - TODO: add argument description
619 EFI_SUCCESS - TODO: Add description for return value
630 ScsiDiskDetectMedia (
631 SCSI_DISK_DEV
*ScsiDiskDevice
,
632 BOOLEAN MustReadCapacity
,
639 TODO: Add function description
643 ScsiDiskDevice - TODO: add argument description
644 MustReadCapacity - TODO: add argument description
645 MediaChange - TODO: add argument description
649 EFI_DEVICE_ERROR - TODO: Add description for return value
650 EFI_DEVICE_ERROR - TODO: Add description for return value
651 EFI_DEVICE_ERROR - TODO: Add description for return value
652 EFI_SUCCESS - TODO: Add description for return value
657 EFI_STATUS ReadCapacityStatus
;
658 EFI_SCSI_SENSE_DATA
*SenseData
;
659 UINTN NumberOfSenseKeys
;
661 BOOLEAN NeedReadCapacity
;
664 EFI_BLOCK_IO_MEDIA OldMedia
;
667 Status
= EFI_SUCCESS
;
668 ReadCapacityStatus
= EFI_SUCCESS
;
670 NumberOfSenseKeys
= 0;
671 NeedReadCapacity
= FALSE
;
672 CopyMem (&OldMedia
, ScsiDiskDevice
->BlkIo
.Media
, sizeof (OldMedia
));
673 // OldMedia = *(ScsiDiskDevice->BlkIo.Media);
675 *MediaChange
= FALSE
;
678 for (Index
= 0; Index
< MaxRetry
; Index
++) {
679 Status
= ScsiDiskTestUnitReady (
685 if (!EFI_ERROR (Status
)) {
694 if ((Index
== MaxRetry
) && EFI_ERROR (Status
)) {
695 return EFI_DEVICE_ERROR
;
698 Status
= DetectMediaParsingSenseKeys (
704 if (EFI_ERROR (Status
)) {
708 // ACTION_NO_ACTION: need not read capacity
709 // other action code: need read capacity
711 if (Action
== ACTION_NO_ACTION
) {
712 NeedReadCapacity
= FALSE
;
714 NeedReadCapacity
= TRUE
;
718 // either NeedReadCapacity is TRUE, or MustReadCapacity is TRUE,
719 // retrieve capacity via Read Capacity command
721 if (NeedReadCapacity
|| MustReadCapacity
) {
724 // retrieve media information
727 for (Index
= 0; Index
< MaxRetry
; Index
++) {
729 ReadCapacityStatus
= ScsiDiskReadCapacity (
735 if (EFI_ERROR (ReadCapacityStatus
) && !NeedRetry
) {
736 return EFI_DEVICE_ERROR
;
739 // analyze sense key to action
741 Status
= DetectMediaParsingSenseKeys (
748 // if Status is error, it may indicate crisis error,
749 // so return without retry.
751 if (EFI_ERROR (Status
)) {
756 case ACTION_NO_ACTION
:
763 case ACTION_RETRY_COMMAND_LATER
:
765 // retry the ReadCapacity later and continuously, until the condition
766 // no longer emerges.
767 // stall time is 100000us, or say 0.1 second.
775 // other cases, just retry the command
781 if ((Index
== MaxRetry
) && EFI_ERROR (ReadCapacityStatus
)) {
782 return EFI_DEVICE_ERROR
;
786 if (ScsiDiskDevice
->BlkIo
.Media
->MediaId
!= OldMedia
.MediaId
) {
788 // Media change information got from the device
793 if (ScsiDiskDevice
->BlkIo
.Media
->ReadOnly
!= OldMedia
.ReadOnly
) {
795 ScsiDiskDevice
->BlkIo
.Media
->MediaId
+= 1;
798 if (ScsiDiskDevice
->BlkIo
.Media
->BlockSize
!= OldMedia
.BlockSize
) {
800 ScsiDiskDevice
->BlkIo
.Media
->MediaId
+= 1;
803 if (ScsiDiskDevice
->BlkIo
.Media
->LastBlock
!= OldMedia
.LastBlock
) {
805 ScsiDiskDevice
->BlkIo
.Media
->MediaId
+= 1;
808 if (ScsiDiskDevice
->BlkIo
.Media
->MediaPresent
!= OldMedia
.MediaPresent
) {
809 if (ScsiDiskDevice
->BlkIo
.Media
->MediaPresent
) {
811 // when change from no media to media present, reset the MediaId to 1.
813 ScsiDiskDevice
->BlkIo
.Media
->MediaId
= 1;
816 // when no media, reset the MediaId to zero.
818 ScsiDiskDevice
->BlkIo
.Media
->MediaId
= 0;
828 ScsiDiskInquiryDevice (
829 SCSI_DISK_DEV
*ScsiDiskDevice
,
836 TODO: Add function description
840 ScsiDiskDevice - TODO: add argument description
841 NeedRetry - TODO: add argument description
845 EFI_SUCCESS - TODO: Add description for return value
846 EFI_DEVICE_ERROR - TODO: Add description for return value
847 EFI_DEVICE_ERROR - TODO: Add description for return value
848 EFI_DEVICE_ERROR - TODO: Add description for return value
849 EFI_DEVICE_ERROR - TODO: Add description for return value
850 EFI_DEVICE_ERROR - TODO: Add description for return value
851 EFI_DEVICE_ERROR - TODO: Add description for return value
852 EFI_DEVICE_ERROR - TODO: Add description for return value
853 EFI_DEVICE_ERROR - TODO: Add description for return value
854 EFI_DEVICE_ERROR - TODO: Add description for return value
858 UINT32 InquiryDataLength
;
859 UINT8 SenseDataLength
;
860 UINT8 HostAdapterStatus
;
862 EFI_SCSI_SENSE_DATA
*SenseDataArray
;
863 UINTN NumberOfSenseKeys
;
868 InquiryDataLength
= sizeof (EFI_SCSI_INQUIRY_DATA
);
871 Status
= SubmitInquiryCommand (
872 ScsiDiskDevice
->ScsiIo
,
873 EfiScsiStallSeconds (1),
878 (VOID
*) &(ScsiDiskDevice
->InquiryData
),
882 if ((Status
== EFI_SUCCESS
) || (Status
== EFI_WARN_BUFFER_TOO_SMALL
)) {
884 // no need to check HostAdapterStatus and TargetStatus
886 ParseInquiryData (ScsiDiskDevice
);
888 } else if (Status
== EFI_NOT_READY
) {
890 // no need to check HostAdapterStatus and TargetStatus
893 return EFI_DEVICE_ERROR
;
894 } else if ((Status
== EFI_INVALID_PARAMETER
) || (Status
== EFI_UNSUPPORTED
)) {
896 // no need to check HostAdapterStatus and TargetStatus
899 return EFI_DEVICE_ERROR
;
902 // go ahead to check HostAdapterStatus and TargetStatus
903 // (EFI_TIMEOUT, EFI_DEVICE_ERROR)
905 Status
= CheckHostAdapterStatus (HostAdapterStatus
);
906 if ((Status
== EFI_TIMEOUT
) || (Status
== EFI_NOT_READY
)) {
908 return EFI_DEVICE_ERROR
;
909 } else if (Status
== EFI_DEVICE_ERROR
) {
911 // reset the scsi channel
913 ScsiDiskDevice
->ScsiIo
->ResetBus (ScsiDiskDevice
->ScsiIo
);
915 return EFI_DEVICE_ERROR
;
918 Status
= CheckTargetStatus (TargetStatus
);
919 if (Status
== EFI_NOT_READY
) {
921 // reset the scsi device
923 ScsiDiskDevice
->ScsiIo
->ResetDevice (ScsiDiskDevice
->ScsiIo
);
925 return EFI_DEVICE_ERROR
;
926 } else if (Status
== EFI_DEVICE_ERROR
) {
928 return EFI_DEVICE_ERROR
;
932 // if goes here, meant SubmitInquiryCommand() failed.
933 // if ScsiDiskRequestSenseKeys() succeeds at last,
934 // better retry SubmitInquiryCommand(). (by setting *NeedRetry = TRUE)
937 for (Index
= 0; Index
< MaxRetry
; Index
++) {
939 Status
= ScsiDiskRequestSenseKeys (
946 if (!EFI_ERROR (Status
)) {
948 return EFI_DEVICE_ERROR
;
952 return EFI_DEVICE_ERROR
;
956 // ScsiDiskRequestSenseKeys() failed after several rounds of retry.
957 // set *NeedRetry = FALSE to avoid the outside caller try again.
960 return EFI_DEVICE_ERROR
;
964 ScsiDiskTestUnitReady (
965 SCSI_DISK_DEV
*ScsiDiskDevice
,
967 EFI_SCSI_SENSE_DATA
**SenseDataArray
,
968 UINTN
*NumberOfSenseKeys
970 // TODO: function comment should start with '/*++'
972 When Test Unit Ready command succeeds,
973 retrieve Sense Keys via Request Sense;
974 When Test Unit Ready command encounters any error caused by host adapter or
975 target, return error without retrieving Sense Keys.
977 // TODO: function comment should end with '--*/'
978 // TODO: function comment is missing 'Routine Description:'
979 // TODO: function comment is missing 'Arguments:'
980 // TODO: function comment is missing 'Returns:'
981 // TODO: ScsiDiskDevice - add argument and description to function comment
982 // TODO: NeedRetry - add argument and description to function comment
983 // TODO: SenseDataArray - add argument and description to function comment
984 // TODO: NumberOfSenseKeys - add argument and description to function comment
985 // TODO: EFI_DEVICE_ERROR - add return value to function comment
986 // TODO: EFI_DEVICE_ERROR - add return value to function comment
987 // TODO: EFI_DEVICE_ERROR - add return value to function comment
988 // TODO: EFI_DEVICE_ERROR - add return value to function comment
989 // TODO: EFI_DEVICE_ERROR - add return value to function comment
990 // TODO: EFI_DEVICE_ERROR - add return value to function comment
991 // TODO: EFI_SUCCESS - add return value to function comment
992 // TODO: EFI_DEVICE_ERROR - add return value to function comment
993 // TODO: EFI_DEVICE_ERROR - add return value to function comment
996 UINT8 SenseDataLength
;
997 UINT8 HostAdapterStatus
;
1002 SenseDataLength
= 0;
1003 *NumberOfSenseKeys
= 0;
1006 // Parameter 3 and 4: do not require sense data, retrieve it when needed.
1008 Status
= SubmitTestUnitReadyCommand (
1009 ScsiDiskDevice
->ScsiIo
,
1010 EfiScsiStallSeconds (1),
1016 if (Status
== EFI_NOT_READY
) {
1018 // no need to check HostAdapterStatus and TargetStatus
1021 return EFI_DEVICE_ERROR
;
1022 } else if ((Status
== EFI_INVALID_PARAMETER
) || (Status
== EFI_UNSUPPORTED
)) {
1024 // no need to check HostAdapterStatus and TargetStatus
1027 return EFI_DEVICE_ERROR
;
1030 // go ahead to check HostAdapterStatus and TargetStatus
1032 Status
= CheckHostAdapterStatus (HostAdapterStatus
);
1033 if ((Status
== EFI_TIMEOUT
) || (Status
== EFI_NOT_READY
)) {
1035 return EFI_DEVICE_ERROR
;
1036 } else if (Status
== EFI_DEVICE_ERROR
) {
1038 // reset the scsi channel
1040 ScsiDiskDevice
->ScsiIo
->ResetBus (ScsiDiskDevice
->ScsiIo
);
1042 return EFI_DEVICE_ERROR
;
1045 Status
= CheckTargetStatus (TargetStatus
);
1046 if (Status
== EFI_NOT_READY
) {
1048 // reset the scsi device
1050 ScsiDiskDevice
->ScsiIo
->ResetDevice (ScsiDiskDevice
->ScsiIo
);
1052 return EFI_DEVICE_ERROR
;
1053 } else if (Status
== EFI_DEVICE_ERROR
) {
1055 return EFI_DEVICE_ERROR
;
1059 for (Index
= 0; Index
< MaxRetry
; Index
++) {
1061 Status
= ScsiDiskRequestSenseKeys (
1068 if (!EFI_ERROR (Status
)) {
1073 return EFI_DEVICE_ERROR
;
1077 // ScsiDiskRequestSenseKeys() failed after several rounds of retry.
1078 // set *NeedRetry = FALSE to avoid the outside caller try again.
1081 return EFI_DEVICE_ERROR
;
1085 DetectMediaParsingSenseKeys (
1086 SCSI_DISK_DEV
*ScsiDiskDevice
,
1087 EFI_SCSI_SENSE_DATA
*SenseData
,
1088 UINTN NumberOfSenseKeys
,
1093 Routine Description:
1095 TODO: Add function description
1099 ScsiDiskDevice - TODO: add argument description
1100 SenseData - TODO: add argument description
1101 NumberOfSenseKeys - TODO: add argument description
1102 Action - TODO: add argument description
1106 EFI_SUCCESS - TODO: Add description for return value
1107 EFI_SUCCESS - TODO: Add description for return value
1108 EFI_SUCCESS - TODO: Add description for return value
1109 EFI_SUCCESS - TODO: Add description for return value
1110 EFI_DEVICE_ERROR - TODO: Add description for return value
1111 EFI_DEVICE_ERROR - TODO: Add description for return value
1112 EFI_SUCCESS - TODO: Add description for return value
1113 EFI_DEVICE_ERROR - TODO: Add description for return value
1114 EFI_SUCCESS - TODO: Add description for return value
1121 // Default is to read capacity, unless..
1123 *Action
= ACTION_READ_CAPACITY
;
1125 if (NumberOfSenseKeys
== 0) {
1126 *Action
= ACTION_NO_ACTION
;
1130 if (!ScsiDiskHaveSenseKey (SenseData
, NumberOfSenseKeys
)) {
1132 // No Sense Key returned from last submitted command
1134 *Action
= ACTION_NO_ACTION
;
1138 if (ScsiDiskIsNoMedia (SenseData
, NumberOfSenseKeys
)) {
1139 ScsiDiskDevice
->BlkIo
.Media
->MediaPresent
= FALSE
;
1140 ScsiDiskDevice
->BlkIo
.Media
->LastBlock
= 0;
1141 *Action
= ACTION_NO_ACTION
;
1145 if (ScsiDiskIsMediaChange (SenseData
, NumberOfSenseKeys
)) {
1146 ScsiDiskDevice
->BlkIo
.Media
->MediaId
++;
1150 if (ScsiDiskIsMediaError (SenseData
, NumberOfSenseKeys
)) {
1151 ScsiDiskDevice
->BlkIo
.Media
->MediaPresent
= FALSE
;
1152 ScsiDiskDevice
->BlkIo
.Media
->LastBlock
= 0;
1153 return EFI_DEVICE_ERROR
;
1156 if (ScsiDiskIsHardwareError (SenseData
, NumberOfSenseKeys
)) {
1157 return EFI_DEVICE_ERROR
;
1160 if (!ScsiDiskIsDriveReady (SenseData
, NumberOfSenseKeys
, &RetryLater
)) {
1162 *Action
= ACTION_RETRY_COMMAND_LATER
;
1166 return EFI_DEVICE_ERROR
;
1173 ScsiDiskReadCapacity (
1174 SCSI_DISK_DEV
*ScsiDiskDevice
,
1176 EFI_SCSI_SENSE_DATA
**SenseDataArray
,
1177 UINTN
*NumberOfSenseKeys
1181 Routine Description:
1183 TODO: Add function description
1187 ScsiDiskDevice - TODO: add argument description
1188 NeedRetry - TODO: add argument description
1189 SenseDataArray - TODO: add argument description
1190 NumberOfSenseKeys - TODO: add argument description
1194 EFI_SUCCESS - TODO: Add description for return value
1195 EFI_DEVICE_ERROR - TODO: Add description for return value
1196 EFI_DEVICE_ERROR - TODO: Add description for return value
1197 EFI_DEVICE_ERROR - TODO: Add description for return value
1198 EFI_DEVICE_ERROR - TODO: Add description for return value
1199 EFI_DEVICE_ERROR - TODO: Add description for return value
1200 EFI_DEVICE_ERROR - TODO: Add description for return value
1201 EFI_DEVICE_ERROR - TODO: Add description for return value
1202 EFI_DEVICE_ERROR - TODO: Add description for return value
1203 EFI_DEVICE_ERROR - TODO: Add description for return value
1207 EFI_SCSI_DISK_CAPACITY_DATA CapacityData
;
1209 UINT8 HostAdapterStatus
;
1211 EFI_STATUS CommandStatus
;
1215 UINT8 SenseDataLength
;
1217 SenseDataLength
= 0;
1218 ZeroMem (&CapacityData
, sizeof (EFI_SCSI_DISK_CAPACITY_DATA
));
1219 DataLength
= sizeof (EFI_SCSI_DISK_CAPACITY_DATA
);
1221 *NumberOfSenseKeys
= 0;
1224 // submit Read Capacity Command. in this call,not request sense data
1226 CommandStatus
= SubmitReadCapacityCommand (
1227 ScsiDiskDevice
->ScsiIo
,
1228 EfiScsiStallSeconds (1),
1233 (VOID
*) &CapacityData
,
1237 if (CommandStatus
== EFI_SUCCESS
) {
1239 // no need to check HostAdapterStatus and TargetStatus
1241 GetMediaInfo (ScsiDiskDevice
, &CapacityData
);
1243 } else if (CommandStatus
== EFI_NOT_READY
) {
1245 // no need to check HostAdapterStatus and TargetStatus
1248 return EFI_DEVICE_ERROR
;
1249 } else if ((CommandStatus
== EFI_INVALID_PARAMETER
) || (CommandStatus
== EFI_UNSUPPORTED
)) {
1251 // no need to check HostAdapterStatus and TargetStatus
1254 return EFI_DEVICE_ERROR
;
1257 // go ahead to check HostAdapterStatus and TargetStatus
1258 // (EFI_TIMEOUT, EFI_DEVICE_ERROR, EFI_WARN_BUFFER_TOO_SMALL)
1261 Status
= CheckHostAdapterStatus (HostAdapterStatus
);
1262 if ((Status
== EFI_TIMEOUT
) || (Status
== EFI_NOT_READY
)) {
1264 return EFI_DEVICE_ERROR
;
1265 } else if (Status
== EFI_DEVICE_ERROR
) {
1267 // reset the scsi channel
1269 ScsiDiskDevice
->ScsiIo
->ResetBus (ScsiDiskDevice
->ScsiIo
);
1271 return EFI_DEVICE_ERROR
;
1274 Status
= CheckTargetStatus (TargetStatus
);
1275 if (Status
== EFI_NOT_READY
) {
1277 // reset the scsi device
1279 ScsiDiskDevice
->ScsiIo
->ResetDevice (ScsiDiskDevice
->ScsiIo
);
1281 return EFI_DEVICE_ERROR
;
1282 } else if (Status
== EFI_DEVICE_ERROR
) {
1284 return EFI_DEVICE_ERROR
;
1288 // if goes here, meant SubmitReadCapacityCommand() failed.
1289 // if ScsiDiskRequestSenseKeys() succeeds at last,
1290 // better retry SubmitReadCapacityCommand(). (by setting *NeedRetry = TRUE)
1293 for (Index
= 0; Index
< MaxRetry
; Index
++) {
1295 Status
= ScsiDiskRequestSenseKeys (
1302 if (!EFI_ERROR (Status
)) {
1304 return EFI_DEVICE_ERROR
;
1308 return EFI_DEVICE_ERROR
;
1312 // ScsiDiskRequestSenseKeys() failed after several rounds of retry.
1313 // set *NeedRetry = FALSE to avoid the outside caller try again.
1316 return EFI_DEVICE_ERROR
;
1320 CheckHostAdapterStatus (
1321 UINT8 HostAdapterStatus
1325 Routine Description:
1327 TODO: Add function description
1331 HostAdapterStatus - TODO: add argument description
1335 EFI_SUCCESS - TODO: Add description for return value
1336 EFI_TIMEOUT - TODO: Add description for return value
1337 EFI_NOT_READY - TODO: Add description for return value
1338 EFI_DEVICE_ERROR - TODO: Add description for return value
1339 EFI_SUCCESS - TODO: Add description for return value
1343 switch (HostAdapterStatus
) {
1344 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_OK
:
1347 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_SELECTION_TIMEOUT
:
1348 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_TIMEOUT
:
1349 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_TIMEOUT_COMMAND
:
1352 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_MESSAGE_REJECT
:
1353 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_PARITY_ERROR
:
1354 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_REQUEST_SENSE_FAILED
:
1355 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN
:
1356 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_BUS_RESET
:
1357 return EFI_NOT_READY
;
1359 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_BUS_FREE
:
1360 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_PHASE_ERROR
:
1361 return EFI_DEVICE_ERROR
;
1374 Routine Description:
1376 TODO: Add function description
1380 TargetStatus - TODO: add argument description
1384 EFI_SUCCESS - TODO: Add description for return value
1385 EFI_NOT_READY - TODO: Add description for return value
1386 EFI_DEVICE_ERROR - TODO: Add description for return value
1387 EFI_SUCCESS - TODO: Add description for return value
1391 switch (TargetStatus
) {
1392 case EFI_SCSI_IO_STATUS_TARGET_GOOD
:
1393 case EFI_SCSI_IO_STATUS_TARGET_CHECK_CONDITION
:
1394 case EFI_SCSI_IO_STATUS_TARGET_CONDITION_MET
:
1397 case EFI_SCSI_IO_STATUS_TARGET_INTERMEDIATE
:
1398 case EFI_SCSI_IO_STATUS_TARGET_INTERMEDIATE_CONDITION_MET
:
1399 case EFI_SCSI_IO_STATUS_TARGET_BUSY
:
1400 case EFI_SCSI_IO_STATUS_TARGET_COMMOND_TERMINATED
:
1401 case EFI_SCSI_IO_STATUS_TARGET_QUEUE_FULL
:
1402 return EFI_NOT_READY
;
1404 case EFI_SCSI_IO_STATUS_TARGET_RESERVATION_CONFLICT
:
1405 return EFI_DEVICE_ERROR
;
1414 ScsiDiskRequestSenseKeys (
1415 SCSI_DISK_DEV
*ScsiDiskDevice
,
1417 EFI_SCSI_SENSE_DATA
**SenseDataArray
,
1418 UINTN
*NumberOfSenseKeys
,
1419 BOOLEAN AskResetIfError
1421 // TODO: function comment should start with '/*++'
1423 Retrieve all sense keys from the device.
1424 When encountering error during the process,
1425 if retrieve sense keys before error encounterred,
1426 return the sense keys with return status set to EFI_SUCCESS,
1427 and NeedRetry set to FALSE; otherwize, return the proper return
1430 // TODO: function comment should end with '--*/'
1431 // TODO: function comment is missing 'Routine Description:'
1432 // TODO: function comment is missing 'Arguments:'
1433 // TODO: function comment is missing 'Returns:'
1434 // TODO: ScsiDiskDevice - add argument and description to function comment
1435 // TODO: NeedRetry - add argument and description to function comment
1436 // TODO: SenseDataArray - add argument and description to function comment
1437 // TODO: NumberOfSenseKeys - add argument and description to function comment
1438 // TODO: AskResetIfError - add argument and description to function comment
1439 // TODO: EFI_SUCCESS - add return value to function comment
1440 // TODO: EFI_DEVICE_ERROR - add return value to function comment
1441 // TODO: EFI_SUCCESS - add return value to function comment
1443 EFI_SCSI_SENSE_DATA
*PtrSenseData
;
1444 UINT8 SenseDataLength
;
1447 EFI_STATUS FallStatus
;
1448 UINT8 HostAdapterStatus
;
1451 FallStatus
= EFI_SUCCESS
;
1452 SenseDataLength
= sizeof (EFI_SCSI_SENSE_DATA
);
1455 ScsiDiskDevice
->SenseData
,
1456 sizeof (EFI_SCSI_SENSE_DATA
) * (ScsiDiskDevice
->SenseDataNumber
)
1459 *NumberOfSenseKeys
= 0;
1460 *SenseDataArray
= ScsiDiskDevice
->SenseData
;
1461 PtrSenseData
= ScsiDiskDevice
->SenseData
;
1463 for (SenseReq
= TRUE
; SenseReq
;) {
1465 Status
= SubmitRequestSenseCommand (
1466 ScsiDiskDevice
->ScsiIo
,
1467 EfiScsiStallSeconds (2),
1473 if ((Status
== EFI_SUCCESS
) || (Status
== EFI_WARN_BUFFER_TOO_SMALL
)) {
1474 FallStatus
= EFI_SUCCESS
;
1475 } else if ((Status
== EFI_TIMEOUT
) || (Status
== EFI_NOT_READY
)) {
1477 FallStatus
= EFI_DEVICE_ERROR
;
1478 } else if ((Status
== EFI_INVALID_PARAMETER
) || (Status
== EFI_UNSUPPORTED
)) {
1480 FallStatus
= EFI_DEVICE_ERROR
;
1481 } else if (Status
== EFI_DEVICE_ERROR
) {
1482 if (AskResetIfError
) {
1483 ScsiDiskDevice
->ScsiIo
->ResetDevice (ScsiDiskDevice
->ScsiIo
);
1486 FallStatus
= EFI_DEVICE_ERROR
;
1489 if (EFI_ERROR (FallStatus
)) {
1490 if (*NumberOfSenseKeys
!= 0) {
1494 return EFI_DEVICE_ERROR
;
1498 (*NumberOfSenseKeys
) += 1;
1501 // no more sense key or number of sense keys exceeds predefined,
1504 if ((PtrSenseData
->Sense_Key
== EFI_SCSI_SK_NO_SENSE
) ||
1505 (*NumberOfSenseKeys
== ScsiDiskDevice
->SenseDataNumber
)) {
1518 SCSI_DISK_DEV
*ScsiDiskDevice
,
1519 EFI_SCSI_DISK_CAPACITY_DATA
*Capacity
1523 Routine Description:
1525 TODO: Add function description
1529 ScsiDiskDevice - TODO: add argument description
1530 Capacity - TODO: add argument description
1534 TODO: add return values
1538 ScsiDiskDevice
->BlkIo
.Media
->LastBlock
= (Capacity
->LastLba3
<< 24) |
1539 (Capacity
->LastLba2
<< 16) |
1540 (Capacity
->LastLba1
<< 8) |
1543 ScsiDiskDevice
->BlkIo
.Media
->MediaPresent
= TRUE
;
1544 ScsiDiskDevice
->BlkIo
.Media
->BlockSize
= (Capacity
->BlockSize3
<< 24) |
1545 (Capacity
->BlockSize2
<< 16) |
1546 (Capacity
->BlockSize1
<< 8) |
1547 Capacity
->BlockSize0
;
1548 if (ScsiDiskDevice
->DeviceType
== EFI_SCSI_TYPE_DISK
) {
1549 ScsiDiskDevice
->BlkIo
.Media
->BlockSize
= 0x200;
1552 if (ScsiDiskDevice
->DeviceType
== EFI_SCSI_TYPE_CDROM
) {
1553 ScsiDiskDevice
->BlkIo
.Media
->BlockSize
= 0x800;
1559 SCSI_DISK_DEV
*ScsiDiskDevice
1563 Routine Description:
1565 TODO: Add function description
1569 ScsiDiskDevice - TODO: add argument description
1573 TODO: add return values
1577 ScsiDiskDevice
->FixedDevice
= (BOOLEAN
) (ScsiDiskDevice
->InquiryData
.RMB
? 0 : 1);
1578 ScsiDiskDevice
->BlkIoMedia
.RemovableMedia
= (BOOLEAN
) (!ScsiDiskDevice
->FixedDevice
);
1582 ScsiDiskReadSectors (
1583 SCSI_DISK_DEV
*ScsiDiskDevice
,
1586 UINTN NumberOfBlocks
1590 Routine Description:
1592 TODO: Add function description
1596 ScsiDiskDevice - TODO: add argument description
1597 Buffer - TODO: add argument description
1598 Lba - TODO: add argument description
1599 NumberOfBlocks - TODO: add argument description
1603 EFI_DEVICE_ERROR - TODO: Add description for return value
1604 EFI_DEVICE_ERROR - TODO: Add description for return value
1605 EFI_SUCCESS - TODO: Add description for return value
1609 UINTN BlocksRemaining
;
1621 EFI_SCSI_SENSE_DATA
*SenseData
;
1622 UINTN NumberOfSenseKeys
;
1625 NumberOfSenseKeys
= 0;
1627 Status
= EFI_SUCCESS
;
1629 BlocksRemaining
= NumberOfBlocks
;
1630 BlockSize
= ScsiDiskDevice
->BlkIo
.Media
->BlockSize
;
1632 // limit the data bytes that can be transferred by one Read(10) Command
1637 Lba32
= (UINT32
) Lba
;
1639 while (BlocksRemaining
> 0) {
1641 if (BlocksRemaining
<= MaxBlock
) {
1643 SectorCount
= (UINT16
) BlocksRemaining
;
1646 SectorCount
= MaxBlock
;
1649 ByteCount
= SectorCount
* BlockSize
;
1650 Timeout
= EfiScsiStallSeconds (2);
1653 for (Index
= 0; Index
< MaxRetry
; Index
++) {
1655 Status
= ScsiDiskRead10 (
1666 if (!EFI_ERROR (Status
)) {
1671 return EFI_DEVICE_ERROR
;
1676 if ((Index
== MaxRetry
) && (Status
!= EFI_SUCCESS
)) {
1677 return EFI_DEVICE_ERROR
;
1681 // actual transferred sectors
1683 SectorCount
= ByteCount
/ BlockSize
;
1685 Lba32
+= SectorCount
;
1686 PtrBuffer
= PtrBuffer
+ SectorCount
* BlockSize
;
1687 BlocksRemaining
-= SectorCount
;
1694 ScsiDiskWriteSectors (
1695 SCSI_DISK_DEV
*ScsiDiskDevice
,
1698 UINTN NumberOfBlocks
1702 Routine Description:
1704 TODO: Add function description
1708 ScsiDiskDevice - TODO: add argument description
1709 Buffer - TODO: add argument description
1710 Lba - TODO: add argument description
1711 NumberOfBlocks - TODO: add argument description
1715 EFI_DEVICE_ERROR - TODO: Add description for return value
1716 EFI_DEVICE_ERROR - TODO: Add description for return value
1717 EFI_SUCCESS - TODO: Add description for return value
1721 UINTN BlocksRemaining
;
1733 EFI_SCSI_SENSE_DATA
*SenseData
;
1734 UINTN NumberOfSenseKeys
;
1737 NumberOfSenseKeys
= 0;
1739 Status
= EFI_SUCCESS
;
1741 BlocksRemaining
= NumberOfBlocks
;
1742 BlockSize
= ScsiDiskDevice
->BlkIo
.Media
->BlockSize
;
1744 // limit the data bytes that can be transferred by one Write(10) Command
1749 Lba32
= (UINT32
) Lba
;
1751 while (BlocksRemaining
> 0) {
1753 if (BlocksRemaining
<= MaxBlock
) {
1755 SectorCount
= (UINT16
) BlocksRemaining
;
1758 SectorCount
= MaxBlock
;
1761 ByteCount
= SectorCount
* BlockSize
;
1762 Timeout
= EfiScsiStallSeconds (2);
1764 for (Index
= 0; Index
< MaxRetry
; Index
++) {
1765 Status
= ScsiDiskWrite10 (
1776 if (!EFI_ERROR (Status
)) {
1781 return EFI_DEVICE_ERROR
;
1785 if ((Index
== MaxRetry
) && (Status
!= EFI_SUCCESS
)) {
1786 return EFI_DEVICE_ERROR
;
1789 // actual transferred sectors
1791 SectorCount
= ByteCount
/ BlockSize
;
1793 Lba32
+= SectorCount
;
1794 PtrBuffer
= PtrBuffer
+ SectorCount
* BlockSize
;
1795 BlocksRemaining
-= SectorCount
;
1803 SCSI_DISK_DEV
*ScsiDiskDevice
,
1805 EFI_SCSI_SENSE_DATA
**SenseDataArray
,
1806 UINTN
*NumberOfSenseKeys
,
1815 Routine Description:
1817 TODO: Add function description
1821 ScsiDiskDevice - TODO: add argument description
1822 NeedRetry - TODO: add argument description
1823 SenseDataArray - TODO: add argument description
1824 NumberOfSenseKeys - TODO: add argument description
1825 Timeout - TODO: add argument description
1826 DataBuffer - TODO: add argument description
1827 DataLength - TODO: add argument description
1828 StartLba - TODO: add argument description
1829 SectorSize - TODO: add argument description
1833 TODO: add return values
1837 UINT8 SenseDataLength
;
1839 UINT8 HostAdapterStatus
;
1843 *NumberOfSenseKeys
= 0;
1844 SenseDataLength
= 0;
1845 Status
= SubmitRead10Command (
1846 ScsiDiskDevice
->ScsiIo
,
1862 SCSI_DISK_DEV
*ScsiDiskDevice
,
1864 EFI_SCSI_SENSE_DATA
**SenseDataArray
,
1865 UINTN
*NumberOfSenseKeys
,
1874 Routine Description:
1876 TODO: Add function description
1880 ScsiDiskDevice - TODO: add argument description
1881 NeedRetry - TODO: add argument description
1882 SenseDataArray - TODO: add argument description
1883 NumberOfSenseKeys - TODO: add argument description
1884 Timeout - TODO: add argument description
1885 DataBuffer - TODO: add argument description
1886 DataLength - TODO: add argument description
1887 StartLba - TODO: add argument description
1888 SectorSize - TODO: add argument description
1892 TODO: add return values
1897 UINT8 SenseDataLength
;
1898 UINT8 HostAdapterStatus
;
1902 *NumberOfSenseKeys
= 0;
1903 SenseDataLength
= 0;
1904 Status
= SubmitWrite10Command (
1905 ScsiDiskDevice
->ScsiIo
,
1921 IN EFI_SCSI_SENSE_DATA
*SenseData
,
1922 IN UINTN SenseCounts
1926 Routine Description:
1928 TODO: Add function description
1932 SenseData - TODO: add argument description
1933 SenseCounts - TODO: add argument description
1937 TODO: add return values
1941 EFI_SCSI_SENSE_DATA
*SensePtr
;
1946 SensePtr
= SenseData
;
1948 for (Index
= 0; Index
< SenseCounts
; Index
++) {
1951 // Sense Key is EFI_SCSI_SK_NOT_READY (0x2),
1952 // Additional Sense Code is ASC_NO_MEDIA (0x3A)
1954 if ((SensePtr
->Sense_Key
== EFI_SCSI_SK_NOT_READY
) &&
1955 (SensePtr
->Addnl_Sense_Code
== EFI_SCSI_ASC_NO_MEDIA
)) {
1966 ScsiDiskIsMediaError (
1967 IN EFI_SCSI_SENSE_DATA
*SenseData
,
1968 IN UINTN SenseCounts
1972 Routine Description:
1974 TODO: Add function description
1978 SenseData - TODO: add argument description
1979 SenseCounts - TODO: add argument description
1983 TODO: add return values
1987 EFI_SCSI_SENSE_DATA
*SensePtr
;
1992 SensePtr
= SenseData
;
1994 for (Index
= 0; Index
< SenseCounts
; Index
++) {
1996 switch (SensePtr
->Sense_Key
) {
1998 case EFI_SCSI_SK_MEDIUM_ERROR
:
2000 // Sense Key is EFI_SCSI_SK_MEDIUM_ERROR (0x3)
2002 switch (SensePtr
->Addnl_Sense_Code
) {
2007 case EFI_SCSI_ASC_MEDIA_ERR1
:
2012 case EFI_SCSI_ASC_MEDIA_ERR2
:
2017 case EFI_SCSI_ASC_MEDIA_ERR3
:
2018 case EFI_SCSI_ASC_MEDIA_ERR4
:
2028 case EFI_SCSI_SK_NOT_READY
:
2030 // Sense Key is EFI_SCSI_SK_NOT_READY (0x2)
2032 switch (SensePtr
->Addnl_Sense_Code
) {
2034 // Additional Sense Code is ASC_MEDIA_UPSIDE_DOWN (0x6)
2036 case EFI_SCSI_ASC_MEDIA_UPSIDE_DOWN
:
2056 ScsiDiskIsHardwareError (
2057 IN EFI_SCSI_SENSE_DATA
*SenseData
,
2058 IN UINTN SenseCounts
2062 Routine Description:
2064 TODO: Add function description
2068 SenseData - TODO: add argument description
2069 SenseCounts - TODO: add argument description
2073 TODO: add return values
2077 EFI_SCSI_SENSE_DATA
*SensePtr
;
2082 SensePtr
= SenseData
;
2084 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2087 // Sense Key is EFI_SCSI_SK_HARDWARE_ERROR (0x4)
2089 if (SensePtr
->Sense_Key
== EFI_SCSI_SK_HARDWARE_ERROR
) {
2100 ScsiDiskIsMediaChange (
2101 IN EFI_SCSI_SENSE_DATA
*SenseData
,
2102 IN UINTN SenseCounts
2106 Routine Description:
2108 TODO: Add function description
2112 SenseData - TODO: add argument description
2113 SenseCounts - TODO: add argument description
2117 TODO: add return values
2121 EFI_SCSI_SENSE_DATA
*SensePtr
;
2123 BOOLEAN IsMediaChanged
;
2125 IsMediaChanged
= FALSE
;
2126 SensePtr
= SenseData
;
2128 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2130 // Sense Key is EFI_SCSI_SK_UNIT_ATTENTION (0x6),
2131 // Additional sense code is EFI_SCSI_ASC_MEDIA_CHANGE (0x28)
2133 if ((SensePtr
->Sense_Key
== EFI_SCSI_SK_UNIT_ATTENTION
) &&
2134 (SensePtr
->Addnl_Sense_Code
== EFI_SCSI_ASC_MEDIA_CHANGE
)) {
2135 IsMediaChanged
= TRUE
;
2141 return IsMediaChanged
;
2145 ScsiDiskIsResetBefore (
2146 IN EFI_SCSI_SENSE_DATA
*SenseData
,
2147 IN UINTN SenseCounts
2151 Routine Description:
2153 TODO: Add function description
2157 SenseData - TODO: add argument description
2158 SenseCounts - TODO: add argument description
2162 TODO: add return values
2166 EFI_SCSI_SENSE_DATA
*SensePtr
;
2168 BOOLEAN IsResetBefore
;
2170 IsResetBefore
= FALSE
;
2171 SensePtr
= SenseData
;
2173 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2176 // Sense Key is EFI_SCSI_SK_UNIT_ATTENTION (0x6)
2177 // Additional Sense Code is EFI_SCSI_ASC_RESET (0x29)
2179 if ((SensePtr
->Sense_Key
== EFI_SCSI_SK_UNIT_ATTENTION
) &&
2180 (SensePtr
->Addnl_Sense_Code
== EFI_SCSI_ASC_RESET
)) {
2181 IsResetBefore
= TRUE
;
2187 return IsResetBefore
;
2191 ScsiDiskIsDriveReady (
2192 IN EFI_SCSI_SENSE_DATA
*SenseData
,
2193 IN UINTN SenseCounts
,
2194 OUT BOOLEAN
*RetryLater
2198 Routine Description:
2200 TODO: Add function description
2204 SenseData - TODO: add argument description
2205 SenseCounts - TODO: add argument description
2206 RetryLater - TODO: add argument description
2210 TODO: add return values
2214 EFI_SCSI_SENSE_DATA
*SensePtr
;
2219 *RetryLater
= FALSE
;
2220 SensePtr
= SenseData
;
2222 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2224 switch (SensePtr
->Sense_Key
) {
2226 case EFI_SCSI_SK_NOT_READY
:
2228 // Sense Key is EFI_SCSI_SK_NOT_READY (0x2)
2230 switch (SensePtr
->Addnl_Sense_Code
) {
2231 case EFI_SCSI_ASC_NOT_READY
:
2233 // Additional Sense Code is EFI_SCSI_ASC_NOT_READY (0x4)
2235 switch (SensePtr
->Addnl_Sense_Code_Qualifier
) {
2236 case EFI_SCSI_ASCQ_IN_PROGRESS
:
2238 // Additional Sense Code Qualifier is
2239 // EFI_SCSI_ASCQ_IN_PROGRESS (0x1)
2247 *RetryLater
= FALSE
;
2268 ScsiDiskHaveSenseKey (
2269 IN EFI_SCSI_SENSE_DATA
*SenseData
,
2270 IN UINTN SenseCounts
2274 Routine Description:
2276 TODO: Add function description
2280 SenseData - TODO: add argument description
2281 SenseCounts - TODO: add argument description
2285 TODO: add return values
2289 EFI_SCSI_SENSE_DATA
*SensePtr
;
2291 BOOLEAN HaveSenseKey
;
2293 if (SenseCounts
== 0) {
2294 HaveSenseKey
= FALSE
;
2296 HaveSenseKey
= TRUE
;
2299 SensePtr
= SenseData
;
2301 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2304 // Sense Key is SK_NO_SENSE (0x0)
2306 if ((SensePtr
->Sense_Key
== EFI_SCSI_SK_NO_SENSE
) &&
2308 HaveSenseKey
= FALSE
;
2314 return HaveSenseKey
;
2318 ReleaseScsiDiskDeviceResources (
2319 IN SCSI_DISK_DEV
*ScsiDiskDevice
2323 Routine Description:
2325 TODO: Add function description
2329 ScsiDiskDevice - TODO: add argument description
2333 TODO: add return values
2337 if (ScsiDiskDevice
== NULL
) {
2341 if (ScsiDiskDevice
->SenseData
!= NULL
) {
2342 gBS
->FreePool (ScsiDiskDevice
->SenseData
);
2343 ScsiDiskDevice
->SenseData
= NULL
;
2346 if (ScsiDiskDevice
->ControllerNameTable
!= NULL
) {
2347 FreeUnicodeStringTable (ScsiDiskDevice
->ControllerNameTable
);
2348 ScsiDiskDevice
->ControllerNameTable
= NULL
;
2351 gBS
->FreePool (ScsiDiskDevice
);
2353 ScsiDiskDevice
= NULL
;