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