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