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