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