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