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