]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c
The driver and library in MdePkg, MdeModulePkg and Nt32Pkg that don't depend on PI...
[mirror_edk2.git] / MdeModulePkg / Bus / Scsi / ScsiDiskDxe / ScsiDisk.c
1 /** @file
2 SCSI disk driver that layers on every SCSI IO protocol in the system.
3
4 Copyright (c) 2006 - 2008, Intel Corporation. <BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include <Uefi.h>
16
17
18 #include <Protocol/ScsiIo.h>
19 #include <Protocol/ComponentName.h>
20 #include <Protocol/BlockIo.h>
21 #include <Protocol/DriverBinding.h>
22 #include <Protocol/ScsiPassThruExt.h>
23
24 #include <Library/DebugLib.h>
25 #include <Library/UefiDriverEntryPoint.h>
26 #include <Library/UefiLib.h>
27 #include <Library/BaseMemoryLib.h>
28 #include <Library/ScsiLib.h>
29 #include <Library/UefiBootServicesTableLib.h>
30
31 #include "ScsiDisk.h"
32
33 EFI_DRIVER_BINDING_PROTOCOL gScsiDiskDriverBinding = {
34 ScsiDiskDriverBindingSupported,
35 ScsiDiskDriverBindingStart,
36 ScsiDiskDriverBindingStop,
37 0xa,
38 NULL,
39 NULL
40 };
41
42 /**
43 The user Entry Point for module ScsiDisk. The user code starts with this function.
44
45 @param[in] ImageHandle The firmware allocated handle for the EFI image.
46 @param[in] SystemTable A pointer to the EFI System Table.
47
48 @retval EFI_SUCCESS The entry point is executed successfully.
49 @retval other Some error occurs when executing this entry point.
50
51 **/
52 EFI_STATUS
53 EFIAPI
54 InitializeScsiDisk(
55 IN EFI_HANDLE ImageHandle,
56 IN EFI_SYSTEM_TABLE *SystemTable
57 )
58 {
59 EFI_STATUS Status;
60
61 //
62 // Install driver model protocol(s).
63 //
64 Status = EfiLibInstallDriverBindingComponentName2 (
65 ImageHandle,
66 SystemTable,
67 &gScsiDiskDriverBinding,
68 ImageHandle,
69 &gScsiDiskComponentName,
70 &gScsiDiskComponentName2
71 );
72 ASSERT_EFI_ERROR (Status);
73
74
75 return Status;
76 }
77
78 EFI_STATUS
79 EFIAPI
80 ScsiDiskDriverBindingSupported (
81 IN EFI_DRIVER_BINDING_PROTOCOL *This,
82 IN EFI_HANDLE Controller,
83 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
84 )
85 /*++
86
87 Routine Description:
88
89 Test to see if this driver supports ControllerHandle. Any ControllerHandle
90 that has ScsiIoProtocol installed will be supported.
91
92 Arguments:
93
94 This - Protocol instance pointer.
95 Controller - Handle of device to test
96 RemainingDevicePath - Not used
97
98 Returns:
99
100 EFI_SUCCESS - This driver supports this device.
101 EFI_UNSUPPORTED - This driver does not support this device.
102
103
104 --*/
105 {
106 EFI_STATUS Status;
107 EFI_SCSI_IO_PROTOCOL *ScsiIo;
108 UINT8 DeviceType;
109
110 Status = gBS->OpenProtocol (
111 Controller,
112 &gEfiScsiIoProtocolGuid,
113 (VOID **) &ScsiIo,
114 This->DriverBindingHandle,
115 Controller,
116 EFI_OPEN_PROTOCOL_BY_DRIVER
117 );
118 if (EFI_ERROR (Status)) {
119 return Status;
120 }
121
122 Status = ScsiIo->GetDeviceType (ScsiIo, &DeviceType);
123 if (!EFI_ERROR (Status)) {
124 if ((DeviceType == EFI_SCSI_TYPE_DISK) || (DeviceType == EFI_SCSI_TYPE_CDROM)) {
125 Status = EFI_SUCCESS;
126 } else {
127 Status = EFI_UNSUPPORTED;
128 }
129 }
130
131 gBS->CloseProtocol (
132 Controller,
133 &gEfiScsiIoProtocolGuid,
134 This->DriverBindingHandle,
135 Controller
136 );
137 return Status;
138 }
139
140 EFI_STATUS
141 EFIAPI
142 ScsiDiskDriverBindingStart (
143 IN EFI_DRIVER_BINDING_PROTOCOL *This,
144 IN EFI_HANDLE Controller,
145 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
146 )
147 /*++
148
149 Routine Description:
150
151 Start SCSI Disk Driver, and attach BlockIoProtocol to it.
152
153 Arguments:
154
155 This - Protocol instance pointer.
156 Controller - Handle of device to test
157 RemainingDevicePath - Not used
158
159 Returns:
160
161 EFI_SUCCESS - This driver supports this device.
162 EFI_UNSUPPORTED - This driver does not support this device.
163
164
165 --*/
166 {
167 EFI_STATUS Status;
168 EFI_SCSI_IO_PROTOCOL *ScsiIo;
169 SCSI_DISK_DEV *ScsiDiskDevice;
170 BOOLEAN Temp;
171 UINT8 Index;
172 UINT8 MaxRetry;
173 BOOLEAN NeedRetry;
174
175 Status = gBS->AllocatePool (
176 EfiBootServicesData,
177 sizeof (SCSI_DISK_DEV),
178 (VOID **) &ScsiDiskDevice
179 );
180 if (EFI_ERROR (Status)) {
181 return Status;
182 }
183
184 ZeroMem (ScsiDiskDevice, sizeof (SCSI_DISK_DEV));
185
186 Status = gBS->OpenProtocol (
187 Controller,
188 &gEfiScsiIoProtocolGuid,
189 (VOID **) &ScsiIo,
190 This->DriverBindingHandle,
191 Controller,
192 EFI_OPEN_PROTOCOL_BY_DRIVER
193 );
194 if (EFI_ERROR (Status)) {
195 gBS->FreePool (ScsiDiskDevice);
196 return Status;
197 }
198
199 ScsiDiskDevice->Signature = SCSI_DISK_DEV_SIGNATURE;
200 ScsiDiskDevice->ScsiIo = ScsiIo;
201 ScsiDiskDevice->BlkIo.Media = &ScsiDiskDevice->BlkIoMedia;
202 ScsiDiskDevice->BlkIo.Reset = ScsiDiskReset;
203 ScsiDiskDevice->BlkIo.ReadBlocks = ScsiDiskReadBlocks;
204 ScsiDiskDevice->BlkIo.WriteBlocks = ScsiDiskWriteBlocks;
205 ScsiDiskDevice->BlkIo.FlushBlocks = ScsiDiskFlushBlocks;
206 ScsiDiskDevice->Handle = Controller;
207
208 ScsiIo->GetDeviceType (ScsiIo, &(ScsiDiskDevice->DeviceType));
209 switch (ScsiDiskDevice->DeviceType) {
210 case EFI_SCSI_TYPE_DISK:
211 ScsiDiskDevice->BlkIo.Media->BlockSize = 0x200;
212 break;
213
214 case EFI_SCSI_TYPE_CDROM:
215 ScsiDiskDevice->BlkIo.Media->BlockSize = 0x800;
216 break;
217 }
218 //
219 // The Sense Data Array's initial size is 6
220 //
221 ScsiDiskDevice->SenseDataNumber = 6;
222 Status = gBS->AllocatePool (
223 EfiBootServicesData,
224 sizeof (EFI_SCSI_SENSE_DATA) * ScsiDiskDevice->SenseDataNumber,
225 (VOID **) &(ScsiDiskDevice->SenseData)
226 );
227 if (EFI_ERROR (Status)) {
228 gBS->CloseProtocol (
229 Controller,
230 &gEfiScsiIoProtocolGuid,
231 This->DriverBindingHandle,
232 Controller
233 );
234 gBS->FreePool (ScsiDiskDevice);
235 return Status;
236 }
237
238 ZeroMem (
239 ScsiDiskDevice->SenseData,
240 sizeof (EFI_SCSI_SENSE_DATA) * ScsiDiskDevice->SenseDataNumber
241 );
242
243 //
244 // Retrive device information
245 //
246 MaxRetry = 2;
247 for (Index = 0; Index < MaxRetry; Index++) {
248 Status = ScsiDiskInquiryDevice (ScsiDiskDevice, &NeedRetry);
249 if (!EFI_ERROR (Status)) {
250 break;
251 }
252
253 if (!NeedRetry) {
254 gBS->FreePool (ScsiDiskDevice->SenseData);
255 gBS->CloseProtocol (
256 Controller,
257 &gEfiScsiIoProtocolGuid,
258 This->DriverBindingHandle,
259 Controller
260 );
261 gBS->FreePool (ScsiDiskDevice);
262 return EFI_DEVICE_ERROR;
263 }
264 }
265 //
266 // The second parameter "TRUE" means must
267 // retrieve media capacity
268 //
269 Status = ScsiDiskDetectMedia (ScsiDiskDevice, TRUE, &Temp);
270 if (!EFI_ERROR (Status)) {
271 Status = gBS->InstallMultipleProtocolInterfaces (
272 &Controller,
273 &gEfiBlockIoProtocolGuid,
274 &ScsiDiskDevice->BlkIo,
275 NULL
276 );
277 }
278
279 if (EFI_ERROR (Status)) {
280 gBS->FreePool (ScsiDiskDevice->SenseData);
281 gBS->CloseProtocol (
282 Controller,
283 &gEfiScsiIoProtocolGuid,
284 This->DriverBindingHandle,
285 Controller
286 );
287 gBS->FreePool (ScsiDiskDevice);
288 return Status;
289 }
290
291 ScsiDiskDevice->ControllerNameTable = NULL;
292 AddUnicodeString2 (
293 "eng",
294 gScsiDiskComponentName.SupportedLanguages,
295 &ScsiDiskDevice->ControllerNameTable,
296 L"SCSI Disk Device",
297 TRUE
298 );
299 AddUnicodeString2 (
300 "en",
301 gScsiDiskComponentName2.SupportedLanguages,
302 &ScsiDiskDevice->ControllerNameTable,
303 L"SCSI Disk Device",
304 FALSE
305 );
306
307
308 return EFI_SUCCESS;
309
310 }
311
312 EFI_STATUS
313 EFIAPI
314 ScsiDiskDriverBindingStop (
315 IN EFI_DRIVER_BINDING_PROTOCOL *This,
316 IN EFI_HANDLE Controller,
317 IN UINTN NumberOfChildren,
318 IN EFI_HANDLE *ChildHandleBuffer
319 )
320 /*++
321
322 Routine Description:
323
324 Stop this driver on ControllerHandle. Support stoping any child handles
325 created by this driver.
326
327 Arguments:
328
329 This - Protocol instance pointer.
330 Controller - Handle of device to stop driver on
331 NumberOfChildren - Number of Children in the ChildHandleBuffer
332 ChildHandleBuffer - List of handles for the children we need to stop.
333
334 Returns:
335
336 EFI_SUCCESS
337 EFI_DEVICE_ERROR
338 others
339
340 --*/
341 {
342 EFI_BLOCK_IO_PROTOCOL *BlkIo;
343 SCSI_DISK_DEV *ScsiDiskDevice;
344 EFI_STATUS Status;
345
346 Status = gBS->OpenProtocol (
347 Controller,
348 &gEfiBlockIoProtocolGuid,
349 (VOID **) &BlkIo,
350 This->DriverBindingHandle,
351 Controller,
352 EFI_OPEN_PROTOCOL_GET_PROTOCOL
353 );
354 if (EFI_ERROR (Status)) {
355 return Status;
356 }
357
358 ScsiDiskDevice = SCSI_DISK_DEV_FROM_THIS (BlkIo);
359 Status = gBS->UninstallProtocolInterface (
360 Controller,
361 &gEfiBlockIoProtocolGuid,
362 &ScsiDiskDevice->BlkIo
363 );
364 if (!EFI_ERROR (Status)) {
365 gBS->CloseProtocol (
366 Controller,
367 &gEfiScsiIoProtocolGuid,
368 This->DriverBindingHandle,
369 Controller
370 );
371
372 ReleaseScsiDiskDeviceResources (ScsiDiskDevice);
373
374 return EFI_SUCCESS;
375 }
376 //
377 // errors met
378 //
379 return Status;
380 }
381
382
383 EFI_STATUS
384 EFIAPI
385 ScsiDiskReset (
386 IN EFI_BLOCK_IO_PROTOCOL *This,
387 IN BOOLEAN ExtendedVerification
388 )
389 /*++
390
391 Routine Description:
392
393 Reset SCSI Disk
394
395 Arguments:
396
397 This - The pointer of EFI_BLOCK_IO_PROTOCOL
398 ExtendedVerification - The flag about if extend verificate
399
400 Returns:
401
402 EFI_STATUS
403
404 --*/
405 {
406 EFI_TPL OldTpl;
407 SCSI_DISK_DEV *ScsiDiskDevice;
408 EFI_STATUS Status;
409
410 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
411
412 ScsiDiskDevice = SCSI_DISK_DEV_FROM_THIS (This);
413
414 Status = ScsiDiskDevice->ScsiIo->ResetDevice (ScsiDiskDevice->ScsiIo);
415
416 if (!ExtendedVerification) {
417 goto Done;
418 }
419
420 Status = ScsiDiskDevice->ScsiIo->ResetBus (ScsiDiskDevice->ScsiIo);
421
422 Done:
423 gBS->RestoreTPL (OldTpl);
424 return Status;
425 }
426
427 EFI_STATUS
428 EFIAPI
429 ScsiDiskReadBlocks (
430 IN EFI_BLOCK_IO_PROTOCOL *This,
431 IN UINT32 MediaId,
432 IN EFI_LBA LBA,
433 IN UINTN BufferSize,
434 OUT VOID *Buffer
435 )
436 /*++
437
438 Routine Description:
439
440 The function is to Read Block from SCSI Disk
441
442 Arguments:
443
444 This - The pointer of EFI_BLOCK_IO_PROTOCOL
445 MediaId - The Id of Media detected
446 LBA - The logic block address
447 BufferSize - The size of Buffer
448 Buffer - The buffer to fill the read out data
449
450 Returns:
451
452 EFI_INVALID_PARAMETER - Invalid parameter passed in.
453 EFI_SUCCESS - Successfully to read out block.
454 EFI_DEVICE_ERROR - Fail to detect media.
455 EFI_NO_MEDIA - Media is not present.
456 EFI_MEDIA_CHANGED - Media has changed.
457 EFI_BAD_BUFFER_SIZE - The buffer size is not multiple of BlockSize.
458
459 --*/
460 {
461 SCSI_DISK_DEV *ScsiDiskDevice;
462 EFI_BLOCK_IO_MEDIA *Media;
463 EFI_STATUS Status;
464 UINTN BlockSize;
465 UINTN NumberOfBlocks;
466 BOOLEAN MediaChange;
467 EFI_TPL OldTpl;
468
469 MediaChange = FALSE;
470 if (!Buffer) {
471 return EFI_INVALID_PARAMETER;
472 }
473
474 if (BufferSize == 0) {
475 return EFI_SUCCESS;
476 }
477
478 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
479
480 ScsiDiskDevice = SCSI_DISK_DEV_FROM_THIS (This);
481
482 if (!IsDeviceFixed (ScsiDiskDevice)) {
483
484 Status = ScsiDiskDetectMedia (ScsiDiskDevice, FALSE, &MediaChange);
485 if (EFI_ERROR (Status)) {
486 Status = EFI_DEVICE_ERROR;
487 goto Done;
488 }
489
490 if (MediaChange) {
491 gBS->ReinstallProtocolInterface (
492 ScsiDiskDevice->Handle,
493 &gEfiBlockIoProtocolGuid,
494 &ScsiDiskDevice->BlkIo,
495 &ScsiDiskDevice->BlkIo
496 );
497 }
498 }
499 //
500 // Get the intrinsic block size
501 //
502 Media = ScsiDiskDevice->BlkIo.Media;
503 BlockSize = Media->BlockSize;
504
505 NumberOfBlocks = BufferSize / BlockSize;
506
507 if (!(Media->MediaPresent)) {
508 Status = EFI_NO_MEDIA;
509 goto Done;
510 }
511
512 if (MediaId != Media->MediaId) {
513 Status = EFI_MEDIA_CHANGED;
514 goto Done;
515 }
516
517 if (BufferSize % BlockSize != 0) {
518 Status = EFI_BAD_BUFFER_SIZE;
519 goto Done;
520 }
521
522 if (LBA > Media->LastBlock) {
523 Status = EFI_INVALID_PARAMETER;
524 goto Done;
525 }
526
527 if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) {
528 Status = EFI_INVALID_PARAMETER;
529 goto Done;
530 }
531
532 if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) {
533 Status = EFI_INVALID_PARAMETER;
534 goto Done;
535 }
536
537 //
538 // If all the parameters are valid, then perform read sectors command
539 // to transfer data from device to host.
540 //
541 Status = ScsiDiskReadSectors (ScsiDiskDevice, Buffer, LBA, NumberOfBlocks);
542
543 Done:
544 gBS->RestoreTPL (OldTpl);
545 return Status;
546 }
547
548 EFI_STATUS
549 EFIAPI
550 ScsiDiskWriteBlocks (
551 IN EFI_BLOCK_IO_PROTOCOL *This,
552 IN UINT32 MediaId,
553 IN EFI_LBA LBA,
554 IN UINTN BufferSize,
555 IN VOID *Buffer
556 )
557 /*++
558
559 Routine Description:
560
561 The function is to Write Block to SCSI Disk
562
563 Arguments:
564
565 This - The pointer of EFI_BLOCK_IO_PROTOCOL
566 MediaId - The Id of Media detected
567 LBA - The logic block address
568 BufferSize - The size of Buffer
569 Buffer - The buffer to fill the read out data
570
571 Returns:
572
573 EFI_INVALID_PARAMETER - Invalid parameter passed in.
574 EFI_SUCCESS - Successfully to read out block.
575 EFI_DEVICE_ERROR - Fail to detect media.
576 EFI_NO_MEDIA - Media is not present.
577 EFI_MEDIA_CHANGED - Media has changed.
578 EFI_BAD_BUFFER_SIZE - The buffer size is not multiple of BlockSize.
579
580 --*/
581 {
582 SCSI_DISK_DEV *ScsiDiskDevice;
583 EFI_BLOCK_IO_MEDIA *Media;
584 EFI_STATUS Status;
585 UINTN BlockSize;
586 UINTN NumberOfBlocks;
587 BOOLEAN MediaChange;
588 EFI_TPL OldTpl;
589
590 MediaChange = FALSE;
591 if (!Buffer) {
592 return EFI_INVALID_PARAMETER;
593 }
594
595 if (BufferSize == 0) {
596 return EFI_SUCCESS;
597 }
598
599 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
600
601 ScsiDiskDevice = SCSI_DISK_DEV_FROM_THIS (This);
602
603 if (!IsDeviceFixed (ScsiDiskDevice)) {
604
605 Status = ScsiDiskDetectMedia (ScsiDiskDevice, FALSE, &MediaChange);
606 if (EFI_ERROR (Status)) {
607 Status = EFI_DEVICE_ERROR;
608 goto Done;
609 }
610
611 if (MediaChange) {
612 gBS->ReinstallProtocolInterface (
613 ScsiDiskDevice->Handle,
614 &gEfiBlockIoProtocolGuid,
615 &ScsiDiskDevice->BlkIo,
616 &ScsiDiskDevice->BlkIo
617 );
618 }
619 }
620 //
621 // Get the intrinsic block size
622 //
623 Media = ScsiDiskDevice->BlkIo.Media;
624 BlockSize = Media->BlockSize;
625
626 NumberOfBlocks = BufferSize / BlockSize;
627
628 if (!(Media->MediaPresent)) {
629 Status = EFI_NO_MEDIA;
630 goto Done;
631 }
632
633 if (MediaId != Media->MediaId) {
634 Status = EFI_MEDIA_CHANGED;
635 goto Done;
636 }
637
638 if (BufferSize % BlockSize != 0) {
639 Status = EFI_BAD_BUFFER_SIZE;
640 goto Done;
641 }
642
643 if (LBA > Media->LastBlock) {
644 Status = EFI_INVALID_PARAMETER;
645 goto Done;
646 }
647
648 if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) {
649 Status = EFI_INVALID_PARAMETER;
650 goto Done;
651 }
652
653 if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) {
654 Status = EFI_INVALID_PARAMETER;
655 goto Done;
656 }
657 //
658 // if all the parameters are valid, then perform read sectors command
659 // to transfer data from device to host.
660 //
661 Status = ScsiDiskWriteSectors (ScsiDiskDevice, Buffer, LBA, NumberOfBlocks);
662
663 Done:
664 gBS->RestoreTPL (OldTpl);
665 return Status;
666 }
667
668 EFI_STATUS
669 EFIAPI
670 ScsiDiskFlushBlocks (
671 IN EFI_BLOCK_IO_PROTOCOL *This
672 )
673 /*++
674
675 Routine Description:
676
677 Flush Block to Disk
678
679 Arguments:
680
681 This - The pointer of EFI_BLOCK_IO_PROTOCOL
682
683 Returns:
684
685 EFI_SUCCESS
686
687 --*/
688 {
689 //
690 // return directly
691 //
692 return EFI_SUCCESS;
693 }
694
695 EFI_STATUS
696 ScsiDiskDetectMedia (
697 SCSI_DISK_DEV *ScsiDiskDevice,
698 BOOLEAN MustReadCapacity,
699 BOOLEAN *MediaChange
700 )
701 /*++
702
703 Routine Description:
704
705 Dectect Device and read out capacity ,if error occurs, parse the sense key.
706
707 Arguments:
708
709 ScsiDiskDevice - The pointer of SCSI_DISK_DEV
710 MustReadCapacity - The flag about reading device capacity
711 MediaChange - The pointer of flag indicates if media has changed
712
713 Returns:
714
715 EFI_DEVICE_ERROR - Indicates that error occurs
716 EFI_SUCCESS - Successfully to detect media
717
718 --*/
719 {
720 EFI_STATUS Status;
721 EFI_STATUS ReadCapacityStatus;
722 EFI_SCSI_SENSE_DATA *SenseData;
723 UINTN NumberOfSenseKeys;
724 BOOLEAN NeedRetry;
725 BOOLEAN NeedReadCapacity;
726 UINT8 Index;
727 UINT8 MaxRetry;
728 EFI_BLOCK_IO_MEDIA OldMedia;
729 UINTN Action;
730
731 Status = EFI_SUCCESS;
732 ReadCapacityStatus = EFI_SUCCESS;
733 SenseData = NULL;
734 NumberOfSenseKeys = 0;
735 NeedReadCapacity = FALSE;
736 CopyMem (&OldMedia, ScsiDiskDevice->BlkIo.Media, sizeof (OldMedia));
737 *MediaChange = FALSE;
738 MaxRetry = 3;
739
740 for (Index = 0; Index < MaxRetry; Index++) {
741 Status = ScsiDiskTestUnitReady (
742 ScsiDiskDevice,
743 &NeedRetry,
744 &SenseData,
745 &NumberOfSenseKeys
746 );
747 if (!EFI_ERROR (Status)) {
748 break;
749 }
750
751 if (!NeedRetry) {
752 return Status;
753 }
754 }
755
756 if ((Index == MaxRetry) && EFI_ERROR (Status)) {
757 return EFI_DEVICE_ERROR;
758 }
759
760 Status = DetectMediaParsingSenseKeys (
761 ScsiDiskDevice,
762 SenseData,
763 NumberOfSenseKeys,
764 &Action
765 );
766 if (EFI_ERROR (Status)) {
767 return Status;
768 }
769 //
770 // ACTION_NO_ACTION: need not read capacity
771 // other action code: need read capacity
772 //
773 if (Action == ACTION_NO_ACTION) {
774 NeedReadCapacity = FALSE;
775 } else {
776 NeedReadCapacity = TRUE;
777 }
778
779 //
780 // either NeedReadCapacity is TRUE, or MustReadCapacity is TRUE,
781 // retrieve capacity via Read Capacity command
782 //
783 if (NeedReadCapacity || MustReadCapacity) {
784 //
785 // retrieve media information
786 //
787 MaxRetry = 3;
788 for (Index = 0; Index < MaxRetry; Index++) {
789
790 ReadCapacityStatus = ScsiDiskReadCapacity (
791 ScsiDiskDevice,
792 &NeedRetry,
793 &SenseData,
794 &NumberOfSenseKeys
795 );
796 if (EFI_ERROR (ReadCapacityStatus) && !NeedRetry) {
797 return EFI_DEVICE_ERROR;
798 }
799 //
800 // analyze sense key to action
801 //
802 Status = DetectMediaParsingSenseKeys (
803 ScsiDiskDevice,
804 SenseData,
805 NumberOfSenseKeys,
806 &Action
807 );
808 //
809 // if Status is error, it may indicate crisis error,
810 // so return without retry.
811 //
812 if (EFI_ERROR (Status)) {
813 return Status;
814 }
815
816 switch (Action) {
817 case ACTION_NO_ACTION:
818 //
819 // no retry
820 //
821 Index = MaxRetry;
822 break;
823
824 case ACTION_RETRY_COMMAND_LATER:
825 //
826 // retry the ReadCapacity later and continuously, until the condition
827 // no longer emerges.
828 // stall time is 100000us, or say 0.1 second.
829 //
830 gBS->Stall (100000);
831 Index = 0;
832 break;
833
834 default:
835 //
836 // other cases, just retry the command
837 //
838 break;
839 }
840 }
841
842 if ((Index == MaxRetry) && EFI_ERROR (ReadCapacityStatus)) {
843 return EFI_DEVICE_ERROR;
844 }
845 }
846
847 if (ScsiDiskDevice->BlkIo.Media->MediaId != OldMedia.MediaId) {
848 //
849 // Media change information got from the device
850 //
851 *MediaChange = TRUE;
852 }
853
854 if (ScsiDiskDevice->BlkIo.Media->ReadOnly != OldMedia.ReadOnly) {
855 *MediaChange = TRUE;
856 ScsiDiskDevice->BlkIo.Media->MediaId += 1;
857 }
858
859 if (ScsiDiskDevice->BlkIo.Media->BlockSize != OldMedia.BlockSize) {
860 *MediaChange = TRUE;
861 ScsiDiskDevice->BlkIo.Media->MediaId += 1;
862 }
863
864 if (ScsiDiskDevice->BlkIo.Media->LastBlock != OldMedia.LastBlock) {
865 *MediaChange = TRUE;
866 ScsiDiskDevice->BlkIo.Media->MediaId += 1;
867 }
868
869 if (ScsiDiskDevice->BlkIo.Media->MediaPresent != OldMedia.MediaPresent) {
870 if (ScsiDiskDevice->BlkIo.Media->MediaPresent) {
871 //
872 // when change from no media to media present, reset the MediaId to 1.
873 //
874 ScsiDiskDevice->BlkIo.Media->MediaId = 1;
875 } else {
876 //
877 // when no media, reset the MediaId to zero.
878 //
879 ScsiDiskDevice->BlkIo.Media->MediaId = 0;
880 }
881
882 *MediaChange = TRUE;
883 }
884
885 return EFI_SUCCESS;
886 }
887
888 EFI_STATUS
889 ScsiDiskInquiryDevice (
890 SCSI_DISK_DEV *ScsiDiskDevice,
891 BOOLEAN *NeedRetry
892 )
893 /*++
894
895 Routine Description:
896
897 Send out Inquiry command to Device
898
899 Arguments:
900
901 ScsiDiskDevice - The pointer of SCSI_DISK_DEV
902 NeedRetry - Indicates if needs try again when error happens
903
904 Returns:
905
906 EFI_DEVICE_ERROR - Indicates that error occurs
907 EFI_SUCCESS - Successfully to detect media
908
909 --*/
910 {
911 UINT32 InquiryDataLength;
912 UINT8 SenseDataLength;
913 UINT8 HostAdapterStatus;
914 UINT8 TargetStatus;
915 EFI_SCSI_SENSE_DATA *SenseDataArray;
916 UINTN NumberOfSenseKeys;
917 EFI_STATUS Status;
918 UINT8 MaxRetry;
919 UINT8 Index;
920
921 InquiryDataLength = sizeof (EFI_SCSI_INQUIRY_DATA);
922 SenseDataLength = 0;
923
924 Status = ScsiInquiryCommand (
925 ScsiDiskDevice->ScsiIo,
926 EfiScsiStallSeconds (1),
927 NULL,
928 &SenseDataLength,
929 &HostAdapterStatus,
930 &TargetStatus,
931 (VOID *) &(ScsiDiskDevice->InquiryData),
932 &InquiryDataLength,
933 FALSE
934 );
935 //
936 // no need to check HostAdapterStatus and TargetStatus
937 //
938 if ((Status == EFI_SUCCESS) || (Status == EFI_WARN_BUFFER_TOO_SMALL)) {
939 ParseInquiryData (ScsiDiskDevice);
940 return EFI_SUCCESS;
941
942 } else if (Status == EFI_NOT_READY) {
943 *NeedRetry = TRUE;
944 return EFI_DEVICE_ERROR;
945
946 } else if ((Status == EFI_INVALID_PARAMETER) || (Status == EFI_UNSUPPORTED)) {
947 *NeedRetry = FALSE;
948 return EFI_DEVICE_ERROR;
949 }
950 //
951 // go ahead to check HostAdapterStatus and TargetStatus
952 // (EFI_TIMEOUT, EFI_DEVICE_ERROR)
953 //
954
955 Status = CheckHostAdapterStatus (HostAdapterStatus);
956 if ((Status == EFI_TIMEOUT) || (Status == EFI_NOT_READY)) {
957 *NeedRetry = TRUE;
958 return EFI_DEVICE_ERROR;
959 } else if (Status == EFI_DEVICE_ERROR) {
960 //
961 // reset the scsi channel
962 //
963 ScsiDiskDevice->ScsiIo->ResetBus (ScsiDiskDevice->ScsiIo);
964 *NeedRetry = FALSE;
965 return EFI_DEVICE_ERROR;
966 }
967
968 Status = CheckTargetStatus (TargetStatus);
969 if (Status == EFI_NOT_READY) {
970 //
971 // reset the scsi device
972 //
973 ScsiDiskDevice->ScsiIo->ResetDevice (ScsiDiskDevice->ScsiIo);
974 *NeedRetry = TRUE;
975 return EFI_DEVICE_ERROR;
976
977 } else if (Status == EFI_DEVICE_ERROR) {
978 *NeedRetry = FALSE;
979 return EFI_DEVICE_ERROR;
980 }
981
982 //
983 // if goes here, meant SubmitInquiryCommand() failed.
984 // if ScsiDiskRequestSenseKeys() succeeds at last,
985 // better retry SubmitInquiryCommand(). (by setting *NeedRetry = TRUE)
986 //
987 MaxRetry = 3;
988 for (Index = 0; Index < MaxRetry; Index++) {
989 Status = ScsiDiskRequestSenseKeys (
990 ScsiDiskDevice,
991 NeedRetry,
992 &SenseDataArray,
993 &NumberOfSenseKeys,
994 TRUE
995 );
996 if (!EFI_ERROR (Status)) {
997 *NeedRetry = TRUE;
998 return EFI_DEVICE_ERROR;
999 }
1000
1001 if (!*NeedRetry) {
1002 return EFI_DEVICE_ERROR;
1003 }
1004 }
1005 //
1006 // ScsiDiskRequestSenseKeys() failed after several rounds of retry.
1007 // set *NeedRetry = FALSE to avoid the outside caller try again.
1008 //
1009 *NeedRetry = FALSE;
1010 return EFI_DEVICE_ERROR;
1011 }
1012
1013 EFI_STATUS
1014 ScsiDiskTestUnitReady (
1015 SCSI_DISK_DEV *ScsiDiskDevice,
1016 BOOLEAN *NeedRetry,
1017 EFI_SCSI_SENSE_DATA **SenseDataArray,
1018 UINTN *NumberOfSenseKeys
1019 )
1020 /*++
1021
1022 Routine Description:
1023
1024 When Test Unit Ready command succeeds, retrieve Sense Keys via Request Sense;
1025 When Test Unit Ready command encounters any error caused by host adapter or
1026 target, return error without retrieving Sense Keys.
1027
1028 Arguments:
1029
1030 ScsiDiskDevice - The pointer of SCSI_DISK_DEV
1031 NeedRetry - The pointer of flag indicates try again
1032 SenseDataArray - The pointer of an array of sense data
1033 NumberOfSenseKeys - The pointer of the number of sense data array
1034
1035 Returns:
1036
1037 EFI_DEVICE_ERROR - Indicates that error occurs
1038 EFI_SUCCESS - Successfully to test unit
1039
1040 --*/
1041 {
1042 EFI_STATUS Status;
1043 UINT8 SenseDataLength;
1044 UINT8 HostAdapterStatus;
1045 UINT8 TargetStatus;
1046 UINT8 Index;
1047 UINT8 MaxRetry;
1048
1049 SenseDataLength = 0;
1050 *NumberOfSenseKeys = 0;
1051
1052 //
1053 // Parameter 3 and 4: do not require sense data, retrieve it when needed.
1054 //
1055 Status = ScsiTestUnitReadyCommand (
1056 ScsiDiskDevice->ScsiIo,
1057 EfiScsiStallSeconds (1),
1058 NULL,
1059 &SenseDataLength,
1060 &HostAdapterStatus,
1061 &TargetStatus
1062 );
1063 //
1064 // no need to check HostAdapterStatus and TargetStatus
1065 //
1066 if (Status == EFI_NOT_READY) {
1067 *NeedRetry = TRUE;
1068 return EFI_DEVICE_ERROR;
1069
1070 } else if ((Status == EFI_INVALID_PARAMETER) || (Status == EFI_UNSUPPORTED)) {
1071 *NeedRetry = FALSE;
1072 return EFI_DEVICE_ERROR;
1073 }
1074 //
1075 // go ahead to check HostAdapterStatus and TargetStatus(in case of EFI_DEVICE_ERROR)
1076 //
1077
1078 Status = CheckHostAdapterStatus (HostAdapterStatus);
1079 if ((Status == EFI_TIMEOUT) || (Status == EFI_NOT_READY)) {
1080 *NeedRetry = TRUE;
1081 return EFI_DEVICE_ERROR;
1082
1083 } else if (Status == EFI_DEVICE_ERROR) {
1084 //
1085 // reset the scsi channel
1086 //
1087 ScsiDiskDevice->ScsiIo->ResetBus (ScsiDiskDevice->ScsiIo);
1088 *NeedRetry = FALSE;
1089 return EFI_DEVICE_ERROR;
1090 }
1091
1092 Status = CheckTargetStatus (TargetStatus);
1093 if (Status == EFI_NOT_READY) {
1094 //
1095 // reset the scsi device
1096 //
1097 ScsiDiskDevice->ScsiIo->ResetDevice (ScsiDiskDevice->ScsiIo);
1098 *NeedRetry = TRUE;
1099 return EFI_DEVICE_ERROR;
1100
1101 } else if (Status == EFI_DEVICE_ERROR) {
1102 *NeedRetry = FALSE;
1103 return EFI_DEVICE_ERROR;
1104 }
1105
1106 MaxRetry = 3;
1107 for (Index = 0; Index < MaxRetry; Index++) {
1108 Status = ScsiDiskRequestSenseKeys (
1109 ScsiDiskDevice,
1110 NeedRetry,
1111 SenseDataArray,
1112 NumberOfSenseKeys,
1113 FALSE
1114 );
1115 if (!EFI_ERROR (Status)) {
1116 return EFI_SUCCESS;
1117 }
1118
1119 if (!*NeedRetry) {
1120 return EFI_DEVICE_ERROR;
1121 }
1122 }
1123 //
1124 // ScsiDiskRequestSenseKeys() failed after several rounds of retry.
1125 // set *NeedRetry = FALSE to avoid the outside caller try again.
1126 //
1127 *NeedRetry = FALSE;
1128 return EFI_DEVICE_ERROR;
1129 }
1130
1131 EFI_STATUS
1132 DetectMediaParsingSenseKeys (
1133 SCSI_DISK_DEV *ScsiDiskDevice,
1134 EFI_SCSI_SENSE_DATA *SenseData,
1135 UINTN NumberOfSenseKeys,
1136 UINTN *Action
1137 )
1138 /*++
1139
1140 Routine Description:
1141
1142 Parsing Sense Keys which got from request sense command.
1143
1144 Arguments:
1145
1146 ScsiDiskDevice - The pointer of SCSI_DISK_DEV
1147 SenseData - The pointer of EFI_SCSI_SENSE_DATA
1148 NumberOfSenseKeys - The number of sense key
1149 Action - The pointer of action which indicates what is need to do next
1150
1151 Returns:
1152
1153 EFI_DEVICE_ERROR - Indicates that error occurs
1154 EFI_SUCCESS - Successfully to complete the parsing
1155
1156 --*/
1157 {
1158 BOOLEAN RetryLater;
1159
1160 //
1161 // Default is to read capacity, unless..
1162 //
1163 *Action = ACTION_READ_CAPACITY;
1164
1165 if (NumberOfSenseKeys == 0) {
1166 *Action = ACTION_NO_ACTION;
1167 return EFI_SUCCESS;
1168 }
1169
1170 if (!ScsiDiskHaveSenseKey (SenseData, NumberOfSenseKeys)) {
1171 //
1172 // No Sense Key returned from last submitted command
1173 //
1174 *Action = ACTION_NO_ACTION;
1175 return EFI_SUCCESS;
1176 }
1177
1178 if (ScsiDiskIsNoMedia (SenseData, NumberOfSenseKeys)) {
1179 ScsiDiskDevice->BlkIo.Media->MediaPresent = FALSE;
1180 ScsiDiskDevice->BlkIo.Media->LastBlock = 0;
1181 *Action = ACTION_NO_ACTION;
1182 return EFI_SUCCESS;
1183 }
1184
1185 if (ScsiDiskIsMediaChange (SenseData, NumberOfSenseKeys)) {
1186 ScsiDiskDevice->BlkIo.Media->MediaId++;
1187 return EFI_SUCCESS;
1188 }
1189
1190 if (ScsiDiskIsMediaError (SenseData, NumberOfSenseKeys)) {
1191 ScsiDiskDevice->BlkIo.Media->MediaPresent = FALSE;
1192 ScsiDiskDevice->BlkIo.Media->LastBlock = 0;
1193 return EFI_DEVICE_ERROR;
1194 }
1195
1196 if (ScsiDiskIsHardwareError (SenseData, NumberOfSenseKeys)) {
1197 return EFI_DEVICE_ERROR;
1198 }
1199
1200 if (!ScsiDiskIsDriveReady (SenseData, NumberOfSenseKeys, &RetryLater)) {
1201 if (RetryLater) {
1202 *Action = ACTION_RETRY_COMMAND_LATER;
1203 return EFI_SUCCESS;
1204 }
1205
1206 return EFI_DEVICE_ERROR;
1207 }
1208
1209 return EFI_SUCCESS;
1210 }
1211
1212 EFI_STATUS
1213 ScsiDiskReadCapacity (
1214 SCSI_DISK_DEV *ScsiDiskDevice,
1215 BOOLEAN *NeedRetry,
1216 EFI_SCSI_SENSE_DATA **SenseDataArray,
1217 UINTN *NumberOfSenseKeys
1218 )
1219 /*++
1220
1221 Routine Description:
1222
1223 Send read capacity command to device and get the device parameter
1224
1225 Arguments:
1226
1227 ScsiDiskDevice - The pointer of SCSI_DISK_DEV
1228 NeedRetry - The pointer of flag indicates if need a retry
1229 SenseDataArray - The pointer of an array of sense data
1230 NumberOfSenseKeys - The number of sense key
1231
1232 Returns:
1233
1234 EFI_DEVICE_ERROR - Indicates that error occurs
1235 EFI_SUCCESS - Successfully to read capacity
1236
1237 --*/
1238 {
1239 EFI_SCSI_DISK_CAPACITY_DATA CapacityData;
1240 UINT32 DataLength;
1241 UINT8 HostAdapterStatus;
1242 UINT8 TargetStatus;
1243 EFI_STATUS CommandStatus;
1244 EFI_STATUS Status;
1245 UINT8 Index;
1246 UINT8 MaxRetry;
1247 UINT8 SenseDataLength;
1248
1249 SenseDataLength = 0;
1250 ZeroMem (&CapacityData, sizeof (EFI_SCSI_DISK_CAPACITY_DATA));
1251 DataLength = sizeof (EFI_SCSI_DISK_CAPACITY_DATA);
1252
1253 *NumberOfSenseKeys = 0;
1254 *NeedRetry = FALSE;
1255 //
1256 // submit Read Capacity Command. in this call,not request sense data
1257 //
1258 CommandStatus = ScsiReadCapacityCommand (
1259 ScsiDiskDevice->ScsiIo,
1260 EfiScsiStallSeconds (1),
1261 NULL,
1262 &SenseDataLength,
1263 &HostAdapterStatus,
1264 &TargetStatus,
1265 (VOID *) &CapacityData,
1266 &DataLength,
1267 FALSE
1268 );
1269 //
1270 // no need to check HostAdapterStatus and TargetStatus
1271 //
1272 if (CommandStatus == EFI_SUCCESS) {
1273 GetMediaInfo (ScsiDiskDevice, &CapacityData);
1274 return EFI_SUCCESS;
1275
1276 } else if (CommandStatus == EFI_NOT_READY) {
1277 *NeedRetry = TRUE;
1278 return EFI_DEVICE_ERROR;
1279
1280 } else if ((CommandStatus == EFI_INVALID_PARAMETER) || (CommandStatus == EFI_UNSUPPORTED)) {
1281 *NeedRetry = FALSE;
1282 return EFI_DEVICE_ERROR;
1283 }
1284 //
1285 // go ahead to check HostAdapterStatus and TargetStatus
1286 // (EFI_TIMEOUT, EFI_DEVICE_ERROR, EFI_WARN_BUFFER_TOO_SMALL)
1287 //
1288
1289 Status = CheckHostAdapterStatus (HostAdapterStatus);
1290 if ((Status == EFI_TIMEOUT) || (Status == EFI_NOT_READY)) {
1291 *NeedRetry = TRUE;
1292 return EFI_DEVICE_ERROR;
1293
1294 } else if (Status == EFI_DEVICE_ERROR) {
1295 //
1296 // reset the scsi channel
1297 //
1298 ScsiDiskDevice->ScsiIo->ResetBus (ScsiDiskDevice->ScsiIo);
1299 *NeedRetry = FALSE;
1300 return EFI_DEVICE_ERROR;
1301 }
1302
1303 Status = CheckTargetStatus (TargetStatus);
1304 if (Status == EFI_NOT_READY) {
1305 //
1306 // reset the scsi device
1307 //
1308 ScsiDiskDevice->ScsiIo->ResetDevice (ScsiDiskDevice->ScsiIo);
1309 *NeedRetry = TRUE;
1310 return EFI_DEVICE_ERROR;
1311
1312 } else if (Status == EFI_DEVICE_ERROR) {
1313 *NeedRetry = FALSE;
1314 return EFI_DEVICE_ERROR;
1315 }
1316
1317 //
1318 // if goes here, meant SubmitReadCapacityCommand() failed.
1319 // if ScsiDiskRequestSenseKeys() succeeds at last,
1320 // better retry SubmitReadCapacityCommand(). (by setting *NeedRetry = TRUE)
1321 //
1322 MaxRetry = 3;
1323 for (Index = 0; Index < MaxRetry; Index++) {
1324
1325 Status = ScsiDiskRequestSenseKeys (
1326 ScsiDiskDevice,
1327 NeedRetry,
1328 SenseDataArray,
1329 NumberOfSenseKeys,
1330 TRUE
1331 );
1332 if (!EFI_ERROR (Status)) {
1333 *NeedRetry = TRUE;
1334 return EFI_DEVICE_ERROR;
1335 }
1336
1337 if (!*NeedRetry) {
1338 return EFI_DEVICE_ERROR;
1339 }
1340 }
1341 //
1342 // ScsiDiskRequestSenseKeys() failed after several rounds of retry.
1343 // set *NeedRetry = FALSE to avoid the outside caller try again.
1344 //
1345 *NeedRetry = FALSE;
1346 return EFI_DEVICE_ERROR;
1347 }
1348
1349 EFI_STATUS
1350 CheckHostAdapterStatus (
1351 UINT8 HostAdapterStatus
1352 )
1353 /*++
1354
1355 Routine Description:
1356
1357 Check the HostAdapter status
1358
1359 Arguments:
1360
1361 HostAdapterStatus - Host Adapter status
1362
1363 Returns:
1364
1365 EFI_SUCCESS
1366 EFI_TIMEOUT
1367 EFI_NOT_READY
1368 EFI_DEVICE_ERROR
1369
1370 --*/
1371 {
1372 switch (HostAdapterStatus) {
1373 case EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK:
1374 return EFI_SUCCESS;
1375
1376 case EFI_EXT_SCSI_STATUS_HOST_ADAPTER_SELECTION_TIMEOUT:
1377 case EFI_EXT_SCSI_STATUS_HOST_ADAPTER_TIMEOUT:
1378 case EFI_EXT_SCSI_STATUS_HOST_ADAPTER_TIMEOUT_COMMAND:
1379 return EFI_TIMEOUT;
1380
1381 case EFI_EXT_SCSI_STATUS_HOST_ADAPTER_MESSAGE_REJECT:
1382 case EFI_EXT_SCSI_STATUS_HOST_ADAPTER_PARITY_ERROR:
1383 case EFI_EXT_SCSI_STATUS_HOST_ADAPTER_REQUEST_SENSE_FAILED:
1384 case EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN:
1385 case EFI_EXT_SCSI_STATUS_HOST_ADAPTER_BUS_RESET:
1386 return EFI_NOT_READY;
1387
1388 case EFI_EXT_SCSI_STATUS_HOST_ADAPTER_BUS_FREE:
1389 case EFI_EXT_SCSI_STATUS_HOST_ADAPTER_PHASE_ERROR:
1390 return EFI_DEVICE_ERROR;
1391
1392 default:
1393 return EFI_SUCCESS;
1394 }
1395 }
1396
1397 EFI_STATUS
1398 CheckTargetStatus (
1399 UINT8 TargetStatus
1400 )
1401 /*++
1402
1403 Routine Description:
1404
1405 Check the target status
1406
1407 Arguments:
1408
1409 TargetStatus - Target status
1410
1411 Returns:
1412
1413 EFI_NOT_READY
1414 EFI_DEVICE_ERROR
1415 EFI_SUCCESS
1416
1417 --*/
1418 {
1419 switch (TargetStatus) {
1420 case EFI_EXT_SCSI_STATUS_TARGET_GOOD:
1421 case EFI_EXT_SCSI_STATUS_TARGET_CHECK_CONDITION:
1422 case EFI_EXT_SCSI_STATUS_TARGET_CONDITION_MET:
1423 return EFI_SUCCESS;
1424
1425 case EFI_EXT_SCSI_STATUS_TARGET_INTERMEDIATE:
1426 case EFI_EXT_SCSI_STATUS_TARGET_INTERMEDIATE_CONDITION_MET:
1427 case EFI_EXT_SCSI_STATUS_TARGET_BUSY:
1428 case EFI_EXT_SCSI_STATUS_TARGET_TASK_SET_FULL:
1429 return EFI_NOT_READY;
1430
1431 case EFI_EXT_SCSI_STATUS_TARGET_RESERVATION_CONFLICT:
1432 return EFI_DEVICE_ERROR;
1433 break;
1434
1435 default:
1436 return EFI_SUCCESS;
1437 }
1438 }
1439
1440 EFI_STATUS
1441 ScsiDiskRequestSenseKeys (
1442 SCSI_DISK_DEV *ScsiDiskDevice,
1443 BOOLEAN *NeedRetry,
1444 EFI_SCSI_SENSE_DATA **SenseDataArray,
1445 UINTN *NumberOfSenseKeys,
1446 BOOLEAN AskResetIfError
1447 )
1448 /*++
1449
1450 Routine Description:
1451
1452 Retrieve all sense keys from the device.
1453 When encountering error during the process,
1454 if retrieve sense keys before error encounterred,
1455 return the sense keys with return status set to EFI_SUCCESS,
1456 and NeedRetry set to FALSE; otherwize, return the proper return
1457 status.
1458
1459 Arguments:
1460
1461 ScsiDiskDevice - The pointer of SCSI_DISK_DEV
1462 NeedRetry - The pointer of flag indicates if need a retry
1463 SenseDataArray - The pointer of an array of sense data
1464 NumberOfSenseKeys - The number of sense key
1465 AskResetIfError - The flag indicates if need reset when error occurs
1466
1467 Returns:
1468
1469 EFI_DEVICE_ERROR - Indicates that error occurs
1470 EFI_SUCCESS - Successfully to request sense key
1471
1472 --*/
1473 {
1474 EFI_SCSI_SENSE_DATA *PtrSenseData;
1475 UINT8 SenseDataLength;
1476 BOOLEAN SenseReq;
1477 EFI_STATUS Status;
1478 EFI_STATUS FallStatus;
1479 UINT8 HostAdapterStatus;
1480 UINT8 TargetStatus;
1481
1482 FallStatus = EFI_SUCCESS;
1483 SenseDataLength = sizeof (EFI_SCSI_SENSE_DATA);
1484
1485 ZeroMem (
1486 ScsiDiskDevice->SenseData,
1487 sizeof (EFI_SCSI_SENSE_DATA) * (ScsiDiskDevice->SenseDataNumber)
1488 );
1489
1490 *NumberOfSenseKeys = 0;
1491 *SenseDataArray = ScsiDiskDevice->SenseData;
1492 PtrSenseData = ScsiDiskDevice->SenseData;
1493
1494 for (SenseReq = TRUE; SenseReq;) {
1495 Status = ScsiRequestSenseCommand (
1496 ScsiDiskDevice->ScsiIo,
1497 EfiScsiStallSeconds (2),
1498 PtrSenseData,
1499 &SenseDataLength,
1500 &HostAdapterStatus,
1501 &TargetStatus
1502 );
1503 if ((Status == EFI_SUCCESS) || (Status == EFI_WARN_BUFFER_TOO_SMALL)) {
1504 FallStatus = EFI_SUCCESS;
1505
1506 } else if ((Status == EFI_TIMEOUT) || (Status == EFI_NOT_READY)) {
1507 *NeedRetry = TRUE;
1508 FallStatus = EFI_DEVICE_ERROR;
1509
1510 } else if ((Status == EFI_INVALID_PARAMETER) || (Status == EFI_UNSUPPORTED)) {
1511 *NeedRetry = FALSE;
1512 FallStatus = EFI_DEVICE_ERROR;
1513
1514 } else if (Status == EFI_DEVICE_ERROR) {
1515 if (AskResetIfError) {
1516 ScsiDiskDevice->ScsiIo->ResetDevice (ScsiDiskDevice->ScsiIo);
1517 }
1518
1519 FallStatus = EFI_DEVICE_ERROR;
1520 }
1521
1522 if (EFI_ERROR (FallStatus)) {
1523 if (*NumberOfSenseKeys != 0) {
1524 *NeedRetry = FALSE;
1525 return EFI_SUCCESS;
1526 } else {
1527 return EFI_DEVICE_ERROR;
1528 }
1529 }
1530
1531 (*NumberOfSenseKeys) += 1;
1532
1533 //
1534 // no more sense key or number of sense keys exceeds predefined,
1535 // skip the loop.
1536 //
1537 if ((PtrSenseData->Sense_Key == EFI_SCSI_SK_NO_SENSE) ||
1538 (*NumberOfSenseKeys == ScsiDiskDevice->SenseDataNumber)) {
1539 SenseReq = FALSE;
1540 }
1541 PtrSenseData += 1;
1542 }
1543 return EFI_SUCCESS;
1544 }
1545
1546 VOID
1547 GetMediaInfo (
1548 SCSI_DISK_DEV *ScsiDiskDevice,
1549 EFI_SCSI_DISK_CAPACITY_DATA *Capacity
1550 )
1551 /*++
1552
1553 Routine Description:
1554
1555 Get information from media read capacity command
1556
1557 Arguments:
1558
1559 ScsiDiskDevice - The pointer of SCSI_DISK_DEV
1560 Capacity - The pointer of EFI_SCSI_DISK_CAPACITY_DATA
1561
1562 Returns:
1563
1564 NONE
1565
1566 --*/
1567 {
1568 ScsiDiskDevice->BlkIo.Media->LastBlock = (Capacity->LastLba3 << 24) |
1569 (Capacity->LastLba2 << 16) |
1570 (Capacity->LastLba1 << 8) |
1571 Capacity->LastLba0;
1572
1573 ScsiDiskDevice->BlkIo.Media->MediaPresent = TRUE;
1574 ScsiDiskDevice->BlkIo.Media->BlockSize = (Capacity->BlockSize3 << 24) |
1575 (Capacity->BlockSize2 << 16) |
1576 (Capacity->BlockSize1 << 8) |
1577 Capacity->BlockSize0;
1578 if (ScsiDiskDevice->DeviceType == EFI_SCSI_TYPE_DISK) {
1579 ScsiDiskDevice->BlkIo.Media->BlockSize = 0x200;
1580 }
1581
1582 if (ScsiDiskDevice->DeviceType == EFI_SCSI_TYPE_CDROM) {
1583 ScsiDiskDevice->BlkIo.Media->BlockSize = 0x800;
1584 }
1585 }
1586
1587 VOID
1588 ParseInquiryData (
1589 SCSI_DISK_DEV *ScsiDiskDevice
1590 )
1591 /*++
1592
1593 Routine Description:
1594
1595 Parse Inquiry data
1596
1597 Arguments:
1598
1599 ScsiDiskDevice - The pointer of SCSI_DISK_DEV
1600
1601 Returns:
1602
1603 NONE
1604
1605 --*/
1606 {
1607 ScsiDiskDevice->FixedDevice = (BOOLEAN) (ScsiDiskDevice->InquiryData.RMB ? 0 : 1);
1608 ScsiDiskDevice->BlkIoMedia.RemovableMedia = (BOOLEAN) (!ScsiDiskDevice->FixedDevice);
1609 }
1610
1611 EFI_STATUS
1612 EFIAPI
1613 ScsiDiskReadSectors (
1614 SCSI_DISK_DEV *ScsiDiskDevice,
1615 VOID *Buffer,
1616 EFI_LBA Lba,
1617 UINTN NumberOfBlocks
1618 )
1619 /*++
1620
1621 Routine Description:
1622
1623 Read sector from SCSI Disk
1624
1625 Arguments:
1626
1627 ScsiDiskDevice - The poiniter of SCSI_DISK_DEV
1628 Buffer - The buffer to fill in the read out data
1629 Lba - Logic block address
1630 NumberOfBlocks - The number of blocks to read
1631
1632 Returns:
1633
1634 EFI_DEVICE_ERROR
1635 EFI_SUCCESS
1636
1637 --*/
1638 {
1639 UINTN BlocksRemaining;
1640 UINT32 Lba32;
1641 UINT8 *PtrBuffer;
1642 UINT32 BlockSize;
1643 UINT32 ByteCount;
1644 UINT32 MaxBlock;
1645 UINT32 SectorCount;
1646 UINT64 Timeout;
1647 EFI_STATUS Status;
1648 UINT8 Index;
1649 UINT8 MaxRetry;
1650 BOOLEAN NeedRetry;
1651 EFI_SCSI_SENSE_DATA *SenseData;
1652 UINTN NumberOfSenseKeys;
1653
1654 SenseData = NULL;
1655 NumberOfSenseKeys = 0;
1656
1657 Status = EFI_SUCCESS;
1658
1659 BlocksRemaining = NumberOfBlocks;
1660 BlockSize = ScsiDiskDevice->BlkIo.Media->BlockSize;
1661 //
1662 // limit the data bytes that can be transferred by one Read(10) Command
1663 //
1664 MaxBlock = 65536;
1665
1666 PtrBuffer = Buffer;
1667 Lba32 = (UINT32) Lba;
1668
1669 while (BlocksRemaining > 0) {
1670
1671 if (BlocksRemaining <= MaxBlock) {
1672
1673 SectorCount = (UINT16) BlocksRemaining;
1674 } else {
1675
1676 SectorCount = MaxBlock;
1677 }
1678
1679 ByteCount = SectorCount * BlockSize;
1680 Timeout = EfiScsiStallSeconds (2);
1681
1682 MaxRetry = 2;
1683 for (Index = 0; Index < MaxRetry; Index++) {
1684
1685 Status = ScsiDiskRead10 (
1686 ScsiDiskDevice,
1687 &NeedRetry,
1688 &SenseData,
1689 &NumberOfSenseKeys,
1690 Timeout,
1691 PtrBuffer,
1692 &ByteCount,
1693 Lba32,
1694 SectorCount
1695 );
1696 if (!EFI_ERROR (Status)) {
1697 break;
1698 }
1699
1700 if (!NeedRetry) {
1701 return EFI_DEVICE_ERROR;
1702 }
1703
1704 }
1705
1706 if ((Index == MaxRetry) && (Status != EFI_SUCCESS)) {
1707 return EFI_DEVICE_ERROR;
1708 }
1709
1710 //
1711 // actual transferred sectors
1712 //
1713 SectorCount = ByteCount / BlockSize;
1714
1715 Lba32 += SectorCount;
1716 PtrBuffer = PtrBuffer + SectorCount * BlockSize;
1717 BlocksRemaining -= SectorCount;
1718 }
1719
1720 return EFI_SUCCESS;
1721 }
1722
1723 EFI_STATUS
1724 ScsiDiskWriteSectors (
1725 SCSI_DISK_DEV *ScsiDiskDevice,
1726 VOID *Buffer,
1727 EFI_LBA Lba,
1728 UINTN NumberOfBlocks
1729 )
1730 /*++
1731
1732 Routine Description:
1733
1734 Write SCSI Disk sectors
1735
1736 Arguments:
1737
1738 ScsiDiskDevice - The pointer of SCSI_DISK_DEV
1739 Buffer - The data buffer to write sector
1740 Lba - Logic block address
1741 NumberOfBlocks - The number of blocks to write
1742
1743 Returns:
1744
1745 EFI_DEVICE_ERROR
1746 EFI_SUCCESS
1747
1748 --*/
1749 {
1750 UINTN BlocksRemaining;
1751 UINT32 Lba32;
1752 UINT8 *PtrBuffer;
1753 UINT32 BlockSize;
1754 UINT32 ByteCount;
1755 UINT32 MaxBlock;
1756 UINT32 SectorCount;
1757 UINT64 Timeout;
1758 EFI_STATUS Status;
1759 UINT8 Index;
1760 UINT8 MaxRetry;
1761 BOOLEAN NeedRetry;
1762 EFI_SCSI_SENSE_DATA *SenseData;
1763 UINTN NumberOfSenseKeys;
1764
1765 SenseData = NULL;
1766 NumberOfSenseKeys = 0;
1767
1768 Status = EFI_SUCCESS;
1769
1770 BlocksRemaining = NumberOfBlocks;
1771 BlockSize = ScsiDiskDevice->BlkIo.Media->BlockSize;
1772 //
1773 // limit the data bytes that can be transferred by one Write(10) Command
1774 //
1775 MaxBlock = 65536;
1776
1777 PtrBuffer = Buffer;
1778 Lba32 = (UINT32) Lba;
1779
1780 while (BlocksRemaining > 0) {
1781
1782 if (BlocksRemaining <= MaxBlock) {
1783
1784 SectorCount = (UINT16) BlocksRemaining;
1785 } else {
1786
1787 SectorCount = MaxBlock;
1788 }
1789
1790 ByteCount = SectorCount * BlockSize;
1791 Timeout = EfiScsiStallSeconds (2);
1792 MaxRetry = 2;
1793 for (Index = 0; Index < MaxRetry; Index++) {
1794 Status = ScsiDiskWrite10 (
1795 ScsiDiskDevice,
1796 &NeedRetry,
1797 &SenseData,
1798 &NumberOfSenseKeys,
1799 Timeout,
1800 PtrBuffer,
1801 &ByteCount,
1802 Lba32,
1803 SectorCount
1804 );
1805 if (!EFI_ERROR (Status)) {
1806 break;
1807 }
1808
1809 if (!NeedRetry) {
1810 return EFI_DEVICE_ERROR;
1811 }
1812 }
1813
1814 if ((Index == MaxRetry) && (Status != EFI_SUCCESS)) {
1815 return EFI_DEVICE_ERROR;
1816 }
1817 //
1818 // actual transferred sectors
1819 //
1820 SectorCount = ByteCount / BlockSize;
1821
1822 Lba32 += SectorCount;
1823 PtrBuffer = PtrBuffer + SectorCount * BlockSize;
1824 BlocksRemaining -= SectorCount;
1825 }
1826
1827 return EFI_SUCCESS;
1828 }
1829
1830 EFI_STATUS
1831 ScsiDiskRead10 (
1832 SCSI_DISK_DEV *ScsiDiskDevice,
1833 BOOLEAN *NeedRetry,
1834 EFI_SCSI_SENSE_DATA **SenseDataArray,
1835 UINTN *NumberOfSenseKeys,
1836 UINT64 Timeout,
1837 UINT8 *DataBuffer,
1838 UINT32 *DataLength,
1839 UINT32 StartLba,
1840 UINT32 SectorSize
1841 )
1842 /*++
1843
1844 Routine Description:
1845
1846 Sumbmit Read command
1847
1848 Arguments:
1849
1850 ScsiDiskDevice - The pointer of ScsiDiskDevice
1851 NeedRetry - The pointer of flag indicates if needs retry if error happens
1852 SenseDataArray - The pointer of an array of sense data
1853 NumberOfSenseKeys - The number of sense key
1854 Timeout - The time to complete the command
1855 DataBuffer - The buffer to fill with the read out data
1856 DataLength - The length of buffer
1857 StartLba - The start logic block address
1858 SectorSize - The size of sector
1859
1860 Returns:
1861
1862 EFI_STATUS
1863
1864 --*/
1865 {
1866 UINT8 SenseDataLength;
1867 EFI_STATUS Status;
1868 UINT8 HostAdapterStatus;
1869 UINT8 TargetStatus;
1870
1871 *NeedRetry = FALSE;
1872 *NumberOfSenseKeys = 0;
1873 SenseDataLength = 0;
1874 Status = ScsiRead10Command (
1875 ScsiDiskDevice->ScsiIo,
1876 Timeout,
1877 NULL,
1878 &SenseDataLength,
1879 &HostAdapterStatus,
1880 &TargetStatus,
1881 DataBuffer,
1882 DataLength,
1883 StartLba,
1884 SectorSize
1885 );
1886 return Status;
1887 }
1888
1889 EFI_STATUS
1890 ScsiDiskWrite10 (
1891 SCSI_DISK_DEV *ScsiDiskDevice,
1892 BOOLEAN *NeedRetry,
1893 EFI_SCSI_SENSE_DATA **SenseDataArray,
1894 UINTN *NumberOfSenseKeys,
1895 UINT64 Timeout,
1896 UINT8 *DataBuffer,
1897 UINT32 *DataLength,
1898 UINT32 StartLba,
1899 UINT32 SectorSize
1900 )
1901 /*++
1902
1903 Routine Description:
1904
1905 Submit Write Command
1906
1907 Arguments:
1908
1909 ScsiDiskDevice - The pointer of ScsiDiskDevice
1910 NeedRetry - The pointer of flag indicates if needs retry if error happens
1911 SenseDataArray - The pointer of an array of sense data
1912 NumberOfSenseKeys - The number of sense key
1913 Timeout - The time to complete the command
1914 DataBuffer - The buffer to fill with the read out data
1915 DataLength - The length of buffer
1916 StartLba - The start logic block address
1917 SectorSize - The size of sector
1918
1919 Returns:
1920
1921 EFI_STATUS
1922
1923 --*/
1924 {
1925 EFI_STATUS Status;
1926 UINT8 SenseDataLength;
1927 UINT8 HostAdapterStatus;
1928 UINT8 TargetStatus;
1929
1930 *NeedRetry = FALSE;
1931 *NumberOfSenseKeys = 0;
1932 SenseDataLength = 0;
1933 Status = ScsiWrite10Command (
1934 ScsiDiskDevice->ScsiIo,
1935 Timeout,
1936 NULL,
1937 &SenseDataLength,
1938 &HostAdapterStatus,
1939 &TargetStatus,
1940 DataBuffer,
1941 DataLength,
1942 StartLba,
1943 SectorSize
1944 );
1945 return Status;
1946 }
1947
1948 BOOLEAN
1949 ScsiDiskIsNoMedia (
1950 IN EFI_SCSI_SENSE_DATA *SenseData,
1951 IN UINTN SenseCounts
1952 )
1953 /*++
1954
1955 Routine Description:
1956
1957 Check sense key to find if media presents
1958
1959 Arguments:
1960
1961 SenseData - The pointer of EFI_SCSI_SENSE_DATA
1962 SenseCounts - The number of sense key
1963
1964 Returns:
1965
1966 BOOLEAN
1967
1968 --*/
1969 {
1970 EFI_SCSI_SENSE_DATA *SensePtr;
1971 UINTN Index;
1972 BOOLEAN IsNoMedia;
1973
1974 IsNoMedia = FALSE;
1975 SensePtr = SenseData;
1976
1977 for (Index = 0; Index < SenseCounts; Index++) {
1978 //
1979 // Sense Key is EFI_SCSI_SK_NOT_READY (0x2),
1980 // Additional Sense Code is ASC_NO_MEDIA (0x3A)
1981 //
1982 if ((SensePtr->Sense_Key == EFI_SCSI_SK_NOT_READY) &&
1983 (SensePtr->Addnl_Sense_Code == EFI_SCSI_ASC_NO_MEDIA)) {
1984 IsNoMedia = TRUE;
1985 }
1986 SensePtr++;
1987 }
1988
1989 return IsNoMedia;
1990 }
1991
1992 BOOLEAN
1993 ScsiDiskIsMediaError (
1994 IN EFI_SCSI_SENSE_DATA *SenseData,
1995 IN UINTN SenseCounts
1996 )
1997 /*++
1998
1999 Routine Description:
2000
2001 Parse sense key
2002
2003 Arguments:
2004
2005 SenseData - The pointer of EFI_SCSI_SENSE_DATA
2006 SenseCounts - The number of sense key
2007
2008 Returns:
2009
2010 BOOLEAN
2011
2012 --*/
2013 {
2014 EFI_SCSI_SENSE_DATA *SensePtr;
2015 UINTN Index;
2016 BOOLEAN IsError;
2017
2018 IsError = FALSE;
2019 SensePtr = SenseData;
2020
2021 for (Index = 0; Index < SenseCounts; Index++) {
2022
2023 switch (SensePtr->Sense_Key) {
2024
2025 case EFI_SCSI_SK_MEDIUM_ERROR:
2026 //
2027 // Sense Key is EFI_SCSI_SK_MEDIUM_ERROR (0x3)
2028 //
2029 switch (SensePtr->Addnl_Sense_Code) {
2030
2031 //
2032 // fall through
2033 //
2034 case EFI_SCSI_ASC_MEDIA_ERR1:
2035
2036 //
2037 // fall through
2038 //
2039 case EFI_SCSI_ASC_MEDIA_ERR2:
2040
2041 //
2042 // fall through
2043 //
2044 case EFI_SCSI_ASC_MEDIA_ERR3:
2045 case EFI_SCSI_ASC_MEDIA_ERR4:
2046 IsError = TRUE;
2047 break;
2048
2049 default:
2050 break;
2051 }
2052
2053 break;
2054
2055 case EFI_SCSI_SK_NOT_READY:
2056 //
2057 // Sense Key is EFI_SCSI_SK_NOT_READY (0x2)
2058 //
2059 switch (SensePtr->Addnl_Sense_Code) {
2060 //
2061 // Additional Sense Code is ASC_MEDIA_UPSIDE_DOWN (0x6)
2062 //
2063 case EFI_SCSI_ASC_MEDIA_UPSIDE_DOWN:
2064 IsError = TRUE;
2065 break;
2066
2067 default:
2068 break;
2069 }
2070 break;
2071
2072 default:
2073 break;
2074 }
2075
2076 SensePtr++;
2077 }
2078
2079 return IsError;
2080 }
2081
2082 BOOLEAN
2083 ScsiDiskIsHardwareError (
2084 IN EFI_SCSI_SENSE_DATA *SenseData,
2085 IN UINTN SenseCounts
2086 )
2087 /*++
2088
2089 Routine Description:
2090
2091 Check sense key to find if hardware error happens
2092
2093 Arguments:
2094
2095 SenseData - The pointer of EFI_SCSI_SENSE_DATA
2096 SenseCounts - The number of sense key
2097
2098 Returns:
2099
2100 BOOLEAN
2101
2102 --*/
2103 {
2104 EFI_SCSI_SENSE_DATA *SensePtr;
2105 UINTN Index;
2106 BOOLEAN IsError;
2107
2108 IsError = FALSE;
2109 SensePtr = SenseData;
2110
2111 for (Index = 0; Index < SenseCounts; Index++) {
2112
2113 //
2114 // Sense Key is EFI_SCSI_SK_HARDWARE_ERROR (0x4)
2115 //
2116 if (SensePtr->Sense_Key == EFI_SCSI_SK_HARDWARE_ERROR) {
2117 IsError = TRUE;
2118 }
2119
2120 SensePtr++;
2121 }
2122
2123 return IsError;
2124 }
2125
2126 BOOLEAN
2127 ScsiDiskIsMediaChange (
2128 IN EFI_SCSI_SENSE_DATA *SenseData,
2129 IN UINTN SenseCounts
2130 )
2131 /*++
2132
2133 Routine Description:
2134
2135 Check sense key to find if media has changed
2136
2137 Arguments:
2138
2139 SenseData - The pointer of EFI_SCSI_SENSE_DATA
2140 SenseCounts - The number of sense key
2141
2142 Returns:
2143
2144 BOOLEAN
2145
2146 --*/
2147 {
2148 EFI_SCSI_SENSE_DATA *SensePtr;
2149 UINTN Index;
2150 BOOLEAN IsMediaChanged;
2151
2152 IsMediaChanged = FALSE;
2153 SensePtr = SenseData;
2154
2155 for (Index = 0; Index < SenseCounts; Index++) {
2156 //
2157 // Sense Key is EFI_SCSI_SK_UNIT_ATTENTION (0x6),
2158 // Additional sense code is EFI_SCSI_ASC_MEDIA_CHANGE (0x28)
2159 //
2160 if ((SensePtr->Sense_Key == EFI_SCSI_SK_UNIT_ATTENTION) &&
2161 (SensePtr->Addnl_Sense_Code == EFI_SCSI_ASC_MEDIA_CHANGE)) {
2162 IsMediaChanged = TRUE;
2163 }
2164
2165 SensePtr++;
2166 }
2167
2168 return IsMediaChanged;
2169 }
2170
2171 BOOLEAN
2172 ScsiDiskIsResetBefore (
2173 IN EFI_SCSI_SENSE_DATA *SenseData,
2174 IN UINTN SenseCounts
2175 )
2176 /*++
2177
2178 Routine Description:
2179
2180 Check sense key to find if reset happens
2181
2182 Arguments:
2183
2184 SenseData - The pointer of EFI_SCSI_SENSE_DATA
2185 SenseCounts - The number of sense key
2186
2187 Returns:
2188
2189 BOOLEAN
2190
2191 --*/
2192 {
2193 EFI_SCSI_SENSE_DATA *SensePtr;
2194 UINTN Index;
2195 BOOLEAN IsResetBefore;
2196
2197 IsResetBefore = FALSE;
2198 SensePtr = SenseData;
2199
2200 for (Index = 0; Index < SenseCounts; Index++) {
2201
2202 //
2203 // Sense Key is EFI_SCSI_SK_UNIT_ATTENTION (0x6)
2204 // Additional Sense Code is EFI_SCSI_ASC_RESET (0x29)
2205 //
2206 if ((SensePtr->Sense_Key == EFI_SCSI_SK_UNIT_ATTENTION) &&
2207 (SensePtr->Addnl_Sense_Code == EFI_SCSI_ASC_RESET)) {
2208 IsResetBefore = TRUE;
2209 }
2210
2211 SensePtr++;
2212 }
2213
2214 return IsResetBefore;
2215 }
2216
2217 BOOLEAN
2218 ScsiDiskIsDriveReady (
2219 IN EFI_SCSI_SENSE_DATA *SenseData,
2220 IN UINTN SenseCounts,
2221 OUT BOOLEAN *RetryLater
2222 )
2223 /*++
2224
2225 Routine Description:
2226
2227 Check sense key to find if the drive is ready
2228
2229 Arguments:
2230
2231 SenseData - The pointer of EFI_SCSI_SENSE_DATA
2232 SenseCounts - The number of sense key
2233 RetryLater - The flag means if need a retry
2234
2235 Returns:
2236
2237 BOOLEAN
2238
2239 --*/
2240 {
2241 EFI_SCSI_SENSE_DATA *SensePtr;
2242 UINTN Index;
2243 BOOLEAN IsReady;
2244
2245 IsReady = TRUE;
2246 *RetryLater = FALSE;
2247 SensePtr = SenseData;
2248
2249 for (Index = 0; Index < SenseCounts; Index++) {
2250
2251 switch (SensePtr->Sense_Key) {
2252
2253 case EFI_SCSI_SK_NOT_READY:
2254 //
2255 // Sense Key is EFI_SCSI_SK_NOT_READY (0x2)
2256 //
2257 switch (SensePtr->Addnl_Sense_Code) {
2258 case EFI_SCSI_ASC_NOT_READY:
2259 //
2260 // Additional Sense Code is EFI_SCSI_ASC_NOT_READY (0x4)
2261 //
2262 switch (SensePtr->Addnl_Sense_Code_Qualifier) {
2263 case EFI_SCSI_ASCQ_IN_PROGRESS:
2264 //
2265 // Additional Sense Code Qualifier is
2266 // EFI_SCSI_ASCQ_IN_PROGRESS (0x1)
2267 //
2268 IsReady = FALSE;
2269 *RetryLater = TRUE;
2270 break;
2271
2272 default:
2273 IsReady = FALSE;
2274 *RetryLater = FALSE;
2275 break;
2276 }
2277 break;
2278
2279 default:
2280 break;
2281 }
2282 break;
2283
2284 default:
2285 break;
2286 }
2287
2288 SensePtr++;
2289 }
2290
2291 return IsReady;
2292 }
2293
2294 BOOLEAN
2295 ScsiDiskHaveSenseKey (
2296 IN EFI_SCSI_SENSE_DATA *SenseData,
2297 IN UINTN SenseCounts
2298 )
2299 /*++
2300
2301 Routine Description:
2302
2303 Check sense key to find if it has sense key
2304
2305 Arguments:
2306
2307 SenseData - The pointer of EFI_SCSI_SENSE_DATA
2308 SenseCounts - The number of sense key
2309
2310 Returns:
2311
2312 BOOLEAN
2313
2314 --*/
2315 {
2316 EFI_SCSI_SENSE_DATA *SensePtr;
2317 UINTN Index;
2318 BOOLEAN HaveSenseKey;
2319
2320 if (SenseCounts == 0) {
2321 HaveSenseKey = FALSE;
2322 } else {
2323 HaveSenseKey = TRUE;
2324 }
2325
2326 SensePtr = SenseData;
2327
2328 for (Index = 0; Index < SenseCounts; Index++) {
2329
2330 //
2331 // Sense Key is SK_NO_SENSE (0x0)
2332 //
2333 if ((SensePtr->Sense_Key == EFI_SCSI_SK_NO_SENSE) &&
2334 (Index == 0)) {
2335 HaveSenseKey = FALSE;
2336 }
2337
2338 SensePtr++;
2339 }
2340
2341 return HaveSenseKey;
2342 }
2343
2344 VOID
2345 ReleaseScsiDiskDeviceResources (
2346 IN SCSI_DISK_DEV *ScsiDiskDevice
2347 )
2348 /*++
2349
2350 Routine Description:
2351
2352 Release resource about disk device
2353
2354 Arguments:
2355
2356 ScsiDiskDevice - The pointer of SCSI_DISK_DEV
2357
2358 Returns:
2359
2360 NONE
2361
2362 --*/
2363 {
2364 if (ScsiDiskDevice == NULL) {
2365 return ;
2366 }
2367
2368 if (ScsiDiskDevice->SenseData != NULL) {
2369 gBS->FreePool (ScsiDiskDevice->SenseData);
2370 ScsiDiskDevice->SenseData = NULL;
2371 }
2372
2373 if (ScsiDiskDevice->ControllerNameTable != NULL) {
2374 FreeUnicodeStringTable (ScsiDiskDevice->ControllerNameTable);
2375 ScsiDiskDevice->ControllerNameTable = NULL;
2376 }
2377
2378 gBS->FreePool (ScsiDiskDevice);
2379
2380 ScsiDiskDevice = NULL;
2381 }