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