]> git.proxmox.com Git - mirror_edk2.git/blob - EdkModulePkg/Bus/Scsi/ScsiDisk/Dxe/ScsiDisk.c
Updated MSA by putting Specification element at the end of the header section
[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 switch (Status) {
878 //
879 // no need to check HostAdapterStatus and TargetStatus
880 //
881 case EFI_SUCCESS:
882 case EFI_WARN_BUFFER_TOO_SMALL:
883 ParseInquiryData (ScsiDiskDevice);
884 return EFI_SUCCESS;
885
886 case EFI_NOT_READY:
887 *NeedRetry = TRUE;
888 return EFI_DEVICE_ERROR;
889
890 case EFI_INVALID_PARAMETER:
891 case EFI_UNSUPPORTED:
892 *NeedRetry = FALSE;
893 return EFI_DEVICE_ERROR;
894
895 //
896 // go ahead to check HostAdapterStatus and TargetStatus
897 // (EFI_TIMEOUT, EFI_DEVICE_ERROR)
898 //
899 default:
900 break;
901 }
902
903 Status = CheckHostAdapterStatus (HostAdapterStatus);
904 switch (Status) {
905 case EFI_SUCCESS:
906 break;
907
908 case EFI_TIMEOUT:
909 case EFI_NOT_READY:
910 *NeedRetry = TRUE;
911 return EFI_DEVICE_ERROR;
912
913 case EFI_DEVICE_ERROR:
914 //
915 // reset the scsi channel
916 //
917 ScsiDiskDevice->ScsiIo->ResetBus (ScsiDiskDevice->ScsiIo);
918 *NeedRetry = FALSE;
919 return EFI_DEVICE_ERROR;
920 }
921
922 Status = CheckTargetStatus (TargetStatus);
923 switch (Status) {
924 case EFI_SUCCESS:
925 break;
926
927 case EFI_NOT_READY:
928 //
929 // reset the scsi device
930 //
931 ScsiDiskDevice->ScsiIo->ResetDevice (ScsiDiskDevice->ScsiIo);
932 *NeedRetry = TRUE;
933 return EFI_DEVICE_ERROR;
934
935 case EFI_DEVICE_ERROR:
936 *NeedRetry = FALSE;
937 return EFI_DEVICE_ERROR;
938 }
939
940 //
941 // if goes here, meant SubmitInquiryCommand() failed.
942 // if ScsiDiskRequestSenseKeys() succeeds at last,
943 // better retry SubmitInquiryCommand(). (by setting *NeedRetry = TRUE)
944 //
945 MaxRetry = 3;
946 for (Index = 0; Index < MaxRetry; Index++) {
947
948 Status = ScsiDiskRequestSenseKeys (
949 ScsiDiskDevice,
950 NeedRetry,
951 &SenseDataArray,
952 &NumberOfSenseKeys,
953 TRUE
954 );
955 if (!EFI_ERROR (Status)) {
956 *NeedRetry = TRUE;
957 return EFI_DEVICE_ERROR;
958 }
959
960 if (!*NeedRetry) {
961 return EFI_DEVICE_ERROR;
962 }
963 }
964 //
965 // ScsiDiskRequestSenseKeys() failed after several rounds of retry.
966 // set *NeedRetry = FALSE to avoid the outside caller try again.
967 //
968 *NeedRetry = FALSE;
969 return EFI_DEVICE_ERROR;
970 }
971
972 EFI_STATUS
973 ScsiDiskTestUnitReady (
974 SCSI_DISK_DEV *ScsiDiskDevice,
975 BOOLEAN *NeedRetry,
976 EFI_SCSI_SENSE_DATA **SenseDataArray,
977 UINTN *NumberOfSenseKeys
978 )
979 // TODO: function comment should start with '/*++'
980 /*
981 When Test Unit Ready command succeeds,
982 retrieve Sense Keys via Request Sense;
983 When Test Unit Ready command encounters any error caused by host adapter or
984 target, return error without retrieving Sense Keys.
985 */
986 // TODO: function comment should end with '--*/'
987 // TODO: function comment is missing 'Routine Description:'
988 // TODO: function comment is missing 'Arguments:'
989 // TODO: function comment is missing 'Returns:'
990 // TODO: ScsiDiskDevice - add argument and description to function comment
991 // TODO: NeedRetry - add argument and description to function comment
992 // TODO: SenseDataArray - add argument and description to function comment
993 // TODO: NumberOfSenseKeys - add argument and description to function comment
994 // TODO: EFI_DEVICE_ERROR - add return value to function comment
995 // TODO: EFI_DEVICE_ERROR - add return value to function comment
996 // TODO: EFI_DEVICE_ERROR - add return value to function comment
997 // TODO: EFI_DEVICE_ERROR - add return value to function comment
998 // TODO: EFI_DEVICE_ERROR - add return value to function comment
999 // TODO: EFI_DEVICE_ERROR - add return value to function comment
1000 // TODO: EFI_SUCCESS - add return value to function comment
1001 // TODO: EFI_DEVICE_ERROR - add return value to function comment
1002 // TODO: EFI_DEVICE_ERROR - add return value to function comment
1003 {
1004 EFI_STATUS Status;
1005 UINT8 SenseDataLength;
1006 UINT8 HostAdapterStatus;
1007 UINT8 TargetStatus;
1008 UINT8 Index;
1009 UINT8 MaxRetry;
1010
1011 SenseDataLength = 0;
1012 *NumberOfSenseKeys = 0;
1013
1014 //
1015 // Parameter 3 and 4: do not require sense data, retrieve it when needed.
1016 //
1017 Status = SubmitTestUnitReadyCommand (
1018 ScsiDiskDevice->ScsiIo,
1019 EfiScsiStallSeconds (1),
1020 NULL,
1021 &SenseDataLength,
1022 &HostAdapterStatus,
1023 &TargetStatus
1024 );
1025 switch (Status) {
1026 //
1027 // no need to check HostAdapterStatus and TargetStatus
1028 //
1029 case EFI_NOT_READY:
1030 *NeedRetry = TRUE;
1031 return EFI_DEVICE_ERROR;
1032
1033 case EFI_INVALID_PARAMETER:
1034 case EFI_UNSUPPORTED:
1035 *NeedRetry = FALSE;
1036 return EFI_DEVICE_ERROR;
1037
1038 //
1039 // go ahead to check HostAdapterStatus and TargetStatus
1040 //
1041 default:
1042 break;
1043 }
1044
1045 Status = CheckHostAdapterStatus (HostAdapterStatus);
1046 switch (Status) {
1047 case EFI_SUCCESS:
1048 break;
1049
1050 case EFI_TIMEOUT:
1051 case EFI_NOT_READY:
1052 *NeedRetry = TRUE;
1053 return EFI_DEVICE_ERROR;
1054
1055 case EFI_DEVICE_ERROR:
1056 //
1057 // reset the scsi channel
1058 //
1059 ScsiDiskDevice->ScsiIo->ResetBus (ScsiDiskDevice->ScsiIo);
1060 *NeedRetry = FALSE;
1061 return EFI_DEVICE_ERROR;
1062 }
1063
1064 Status = CheckTargetStatus (TargetStatus);
1065 switch (Status) {
1066 case EFI_SUCCESS:
1067 break;
1068
1069 case EFI_NOT_READY:
1070 //
1071 // reset the scsi device
1072 //
1073 ScsiDiskDevice->ScsiIo->ResetDevice (ScsiDiskDevice->ScsiIo);
1074 *NeedRetry = TRUE;
1075 return EFI_DEVICE_ERROR;
1076
1077 case EFI_DEVICE_ERROR:
1078 *NeedRetry = FALSE;
1079 return EFI_DEVICE_ERROR;
1080 }
1081
1082 MaxRetry = 3;
1083 for (Index = 0; Index < MaxRetry; Index++) {
1084
1085 Status = ScsiDiskRequestSenseKeys (
1086 ScsiDiskDevice,
1087 NeedRetry,
1088 SenseDataArray,
1089 NumberOfSenseKeys,
1090 FALSE
1091 );
1092 if (!EFI_ERROR (Status)) {
1093 return EFI_SUCCESS;
1094 }
1095
1096 if (!*NeedRetry) {
1097 return EFI_DEVICE_ERROR;
1098 }
1099 }
1100 //
1101 // ScsiDiskRequestSenseKeys() failed after several rounds of retry.
1102 // set *NeedRetry = FALSE to avoid the outside caller try again.
1103 //
1104 *NeedRetry = FALSE;
1105 return EFI_DEVICE_ERROR;
1106 }
1107
1108 EFI_STATUS
1109 DetectMediaParsingSenseKeys (
1110 SCSI_DISK_DEV *ScsiDiskDevice,
1111 EFI_SCSI_SENSE_DATA *SenseData,
1112 UINTN NumberOfSenseKeys,
1113 UINTN *Action
1114 )
1115 /*++
1116
1117 Routine Description:
1118
1119 TODO: Add function description
1120
1121 Arguments:
1122
1123 ScsiDiskDevice - TODO: add argument description
1124 SenseData - TODO: add argument description
1125 NumberOfSenseKeys - TODO: add argument description
1126 Action - TODO: add argument description
1127
1128 Returns:
1129
1130 EFI_SUCCESS - TODO: Add description for return value
1131 EFI_SUCCESS - TODO: Add description for return value
1132 EFI_SUCCESS - TODO: Add description for return value
1133 EFI_SUCCESS - TODO: Add description for return value
1134 EFI_DEVICE_ERROR - TODO: Add description for return value
1135 EFI_DEVICE_ERROR - TODO: Add description for return value
1136 EFI_SUCCESS - TODO: Add description for return value
1137 EFI_DEVICE_ERROR - TODO: Add description for return value
1138 EFI_SUCCESS - TODO: Add description for return value
1139
1140 --*/
1141 {
1142 BOOLEAN RetryLater;
1143
1144 //
1145 // Default is to read capacity, unless..
1146 //
1147 *Action = ACTION_READ_CAPACITY;
1148
1149 if (NumberOfSenseKeys == 0) {
1150 *Action = ACTION_NO_ACTION;
1151 return EFI_SUCCESS;
1152 }
1153
1154 if (!ScsiDiskHaveSenseKey (SenseData, NumberOfSenseKeys)) {
1155 //
1156 // No Sense Key returned from last submitted command
1157 //
1158 *Action = ACTION_NO_ACTION;
1159 return EFI_SUCCESS;
1160 }
1161
1162 if (ScsiDiskIsNoMedia (SenseData, NumberOfSenseKeys)) {
1163 ScsiDiskDevice->BlkIo.Media->MediaPresent = FALSE;
1164 ScsiDiskDevice->BlkIo.Media->LastBlock = 0;
1165 *Action = ACTION_NO_ACTION;
1166 return EFI_SUCCESS;
1167 }
1168
1169 if (ScsiDiskIsMediaChange (SenseData, NumberOfSenseKeys)) {
1170 ScsiDiskDevice->BlkIo.Media->MediaId++;
1171 return EFI_SUCCESS;
1172 }
1173
1174 if (ScsiDiskIsMediaError (SenseData, NumberOfSenseKeys)) {
1175 ScsiDiskDevice->BlkIo.Media->MediaPresent = FALSE;
1176 ScsiDiskDevice->BlkIo.Media->LastBlock = 0;
1177 return EFI_DEVICE_ERROR;
1178 }
1179
1180 if (ScsiDiskIsHardwareError (SenseData, NumberOfSenseKeys)) {
1181 return EFI_DEVICE_ERROR;
1182 }
1183
1184 if (!ScsiDiskIsDriveReady (SenseData, NumberOfSenseKeys, &RetryLater)) {
1185 if (RetryLater) {
1186 *Action = ACTION_RETRY_COMMAND_LATER;
1187 return EFI_SUCCESS;
1188 }
1189
1190 return EFI_DEVICE_ERROR;
1191 }
1192
1193 return EFI_SUCCESS;
1194 }
1195
1196 EFI_STATUS
1197 ScsiDiskReadCapacity (
1198 SCSI_DISK_DEV *ScsiDiskDevice,
1199 BOOLEAN *NeedRetry,
1200 EFI_SCSI_SENSE_DATA **SenseDataArray,
1201 UINTN *NumberOfSenseKeys
1202 )
1203 /*++
1204
1205 Routine Description:
1206
1207 TODO: Add function description
1208
1209 Arguments:
1210
1211 ScsiDiskDevice - TODO: add argument description
1212 NeedRetry - TODO: add argument description
1213 SenseDataArray - TODO: add argument description
1214 NumberOfSenseKeys - TODO: add argument description
1215
1216 Returns:
1217
1218 EFI_SUCCESS - TODO: Add description for return value
1219 EFI_DEVICE_ERROR - TODO: Add description for return value
1220 EFI_DEVICE_ERROR - TODO: Add description for return value
1221 EFI_DEVICE_ERROR - TODO: Add description for return value
1222 EFI_DEVICE_ERROR - TODO: Add description for return value
1223 EFI_DEVICE_ERROR - TODO: Add description for return value
1224 EFI_DEVICE_ERROR - TODO: Add description for return value
1225 EFI_DEVICE_ERROR - TODO: Add description for return value
1226 EFI_DEVICE_ERROR - TODO: Add description for return value
1227 EFI_DEVICE_ERROR - TODO: Add description for return value
1228
1229 --*/
1230 {
1231 EFI_SCSI_DISK_CAPACITY_DATA CapacityData;
1232 UINT32 DataLength;
1233 UINT8 HostAdapterStatus;
1234 UINT8 TargetStatus;
1235 EFI_STATUS CommandStatus;
1236 EFI_STATUS Status;
1237 UINT8 Index;
1238 UINT8 MaxRetry;
1239 UINT8 SenseDataLength;
1240
1241 SenseDataLength = 0;
1242 ZeroMem (&CapacityData, sizeof (EFI_SCSI_DISK_CAPACITY_DATA));
1243 DataLength = sizeof (EFI_SCSI_DISK_CAPACITY_DATA);
1244
1245 *NumberOfSenseKeys = 0;
1246 *NeedRetry = FALSE;
1247 //
1248 // submit Read Capacity Command. in this call,not request sense data
1249 //
1250 CommandStatus = SubmitReadCapacityCommand (
1251 ScsiDiskDevice->ScsiIo,
1252 EfiScsiStallSeconds (1),
1253 NULL,
1254 &SenseDataLength,
1255 &HostAdapterStatus,
1256 &TargetStatus,
1257 (VOID *) &CapacityData,
1258 &DataLength,
1259 FALSE
1260 );
1261 switch (CommandStatus) {
1262 //
1263 // no need to check HostAdapterStatus and TargetStatus
1264 //
1265 case EFI_SUCCESS:
1266 GetMediaInfo (ScsiDiskDevice, &CapacityData);
1267 return EFI_SUCCESS;
1268
1269 case EFI_NOT_READY:
1270 *NeedRetry = TRUE;
1271 return EFI_DEVICE_ERROR;
1272
1273 case EFI_INVALID_PARAMETER:
1274 case EFI_UNSUPPORTED:
1275 *NeedRetry = FALSE;
1276 return EFI_DEVICE_ERROR;
1277
1278 //
1279 // go ahead to check HostAdapterStatus and TargetStatus
1280 // (EFI_TIMEOUT, EFI_DEVICE_ERROR, EFI_WARN_BUFFER_TOO_SMALL)
1281 //
1282 default:
1283 break;
1284 }
1285
1286 Status = CheckHostAdapterStatus (HostAdapterStatus);
1287 switch (Status) {
1288 case EFI_SUCCESS:
1289 break;
1290
1291 case EFI_TIMEOUT:
1292 case EFI_NOT_READY:
1293 *NeedRetry = TRUE;
1294 return EFI_DEVICE_ERROR;
1295
1296 case EFI_DEVICE_ERROR:
1297 //
1298 // reset the scsi channel
1299 //
1300 ScsiDiskDevice->ScsiIo->ResetBus (ScsiDiskDevice->ScsiIo);
1301 *NeedRetry = FALSE;
1302 return EFI_DEVICE_ERROR;
1303 }
1304
1305 Status = CheckTargetStatus (TargetStatus);
1306 switch (Status) {
1307 case EFI_SUCCESS:
1308 break;
1309
1310 case EFI_NOT_READY:
1311 //
1312 // reset the scsi device
1313 //
1314 ScsiDiskDevice->ScsiIo->ResetDevice (ScsiDiskDevice->ScsiIo);
1315 *NeedRetry = TRUE;
1316 return EFI_DEVICE_ERROR;
1317
1318 case EFI_DEVICE_ERROR:
1319 *NeedRetry = FALSE;
1320 return EFI_DEVICE_ERROR;
1321 }
1322
1323 //
1324 // if goes here, meant SubmitReadCapacityCommand() failed.
1325 // if ScsiDiskRequestSenseKeys() succeeds at last,
1326 // better retry SubmitReadCapacityCommand(). (by setting *NeedRetry = TRUE)
1327 //
1328 MaxRetry = 3;
1329 for (Index = 0; Index < MaxRetry; Index++) {
1330
1331 Status = ScsiDiskRequestSenseKeys (
1332 ScsiDiskDevice,
1333 NeedRetry,
1334 SenseDataArray,
1335 NumberOfSenseKeys,
1336 TRUE
1337 );
1338 if (!EFI_ERROR (Status)) {
1339 *NeedRetry = TRUE;
1340 return EFI_DEVICE_ERROR;
1341 }
1342
1343 if (!*NeedRetry) {
1344 return EFI_DEVICE_ERROR;
1345 }
1346 }
1347 //
1348 // ScsiDiskRequestSenseKeys() failed after several rounds of retry.
1349 // set *NeedRetry = FALSE to avoid the outside caller try again.
1350 //
1351 *NeedRetry = FALSE;
1352 return EFI_DEVICE_ERROR;
1353 }
1354
1355 EFI_STATUS
1356 CheckHostAdapterStatus (
1357 UINT8 HostAdapterStatus
1358 )
1359 /*++
1360
1361 Routine Description:
1362
1363 TODO: Add function description
1364
1365 Arguments:
1366
1367 HostAdapterStatus - TODO: add argument description
1368
1369 Returns:
1370
1371 EFI_SUCCESS - TODO: Add description for return value
1372 EFI_TIMEOUT - TODO: Add description for return value
1373 EFI_NOT_READY - TODO: Add description for return value
1374 EFI_DEVICE_ERROR - TODO: Add description for return value
1375 EFI_SUCCESS - TODO: Add description for return value
1376
1377 --*/
1378 {
1379 switch (HostAdapterStatus) {
1380 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_OK:
1381 return EFI_SUCCESS;
1382
1383 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_SELECTION_TIMEOUT:
1384 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_TIMEOUT:
1385 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_TIMEOUT_COMMAND:
1386 return EFI_TIMEOUT;
1387
1388 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_MESSAGE_REJECT:
1389 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_PARITY_ERROR:
1390 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_REQUEST_SENSE_FAILED:
1391 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN:
1392 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_BUS_RESET:
1393 return EFI_NOT_READY;
1394
1395 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_BUS_FREE:
1396 case EFI_SCSI_IO_STATUS_HOST_ADAPTER_PHASE_ERROR:
1397 return EFI_DEVICE_ERROR;
1398
1399 default:
1400 return EFI_SUCCESS;
1401 }
1402 }
1403
1404 EFI_STATUS
1405 CheckTargetStatus (
1406 UINT8 TargetStatus
1407 )
1408 /*++
1409
1410 Routine Description:
1411
1412 TODO: Add function description
1413
1414 Arguments:
1415
1416 TargetStatus - TODO: add argument description
1417
1418 Returns:
1419
1420 EFI_SUCCESS - TODO: Add description for return value
1421 EFI_NOT_READY - TODO: Add description for return value
1422 EFI_DEVICE_ERROR - TODO: Add description for return value
1423 EFI_SUCCESS - TODO: Add description for return value
1424
1425 --*/
1426 {
1427 switch (TargetStatus) {
1428 case EFI_SCSI_IO_STATUS_TARGET_GOOD:
1429 case EFI_SCSI_IO_STATUS_TARGET_CHECK_CONDITION:
1430 case EFI_SCSI_IO_STATUS_TARGET_CONDITION_MET:
1431 return EFI_SUCCESS;
1432
1433 case EFI_SCSI_IO_STATUS_TARGET_INTERMEDIATE:
1434 case EFI_SCSI_IO_STATUS_TARGET_INTERMEDIATE_CONDITION_MET:
1435 case EFI_SCSI_IO_STATUS_TARGET_BUSY:
1436 case EFI_SCSI_IO_STATUS_TARGET_COMMOND_TERMINATED:
1437 case EFI_SCSI_IO_STATUS_TARGET_QUEUE_FULL:
1438 return EFI_NOT_READY;
1439
1440 case EFI_SCSI_IO_STATUS_TARGET_RESERVATION_CONFLICT:
1441 return EFI_DEVICE_ERROR;
1442 break;
1443
1444 default:
1445 return EFI_SUCCESS;
1446 }
1447 }
1448
1449 EFI_STATUS
1450 ScsiDiskRequestSenseKeys (
1451 SCSI_DISK_DEV *ScsiDiskDevice,
1452 BOOLEAN *NeedRetry,
1453 EFI_SCSI_SENSE_DATA **SenseDataArray,
1454 UINTN *NumberOfSenseKeys,
1455 BOOLEAN AskResetIfError
1456 )
1457 // TODO: function comment should start with '/*++'
1458 /*
1459 Retrieve all sense keys from the device.
1460 When encountering error during the process,
1461 if retrieve sense keys before error encounterred,
1462 return the sense keys with return status set to EFI_SUCCESS,
1463 and NeedRetry set to FALSE; otherwize, return the proper return
1464 status.
1465 */
1466 // TODO: function comment should end with '--*/'
1467 // TODO: function comment is missing 'Routine Description:'
1468 // TODO: function comment is missing 'Arguments:'
1469 // TODO: function comment is missing 'Returns:'
1470 // TODO: ScsiDiskDevice - add argument and description to function comment
1471 // TODO: NeedRetry - add argument and description to function comment
1472 // TODO: SenseDataArray - add argument and description to function comment
1473 // TODO: NumberOfSenseKeys - add argument and description to function comment
1474 // TODO: AskResetIfError - add argument and description to function comment
1475 // TODO: EFI_SUCCESS - add return value to function comment
1476 // TODO: EFI_DEVICE_ERROR - add return value to function comment
1477 // TODO: EFI_SUCCESS - add return value to function comment
1478 {
1479 EFI_SCSI_SENSE_DATA *PtrSenseData;
1480 UINT8 SenseDataLength;
1481 BOOLEAN SenseReq;
1482 EFI_STATUS Status;
1483 EFI_STATUS FallStatus;
1484 UINT8 HostAdapterStatus;
1485 UINT8 TargetStatus;
1486
1487 FallStatus = EFI_SUCCESS;
1488 SenseDataLength = sizeof (EFI_SCSI_SENSE_DATA);
1489
1490 ZeroMem (
1491 ScsiDiskDevice->SenseData,
1492 sizeof (EFI_SCSI_SENSE_DATA) * (ScsiDiskDevice->SenseDataNumber)
1493 );
1494
1495 *NumberOfSenseKeys = 0;
1496 *SenseDataArray = ScsiDiskDevice->SenseData;
1497 PtrSenseData = ScsiDiskDevice->SenseData;
1498
1499 for (SenseReq = TRUE; SenseReq;) {
1500
1501 Status = SubmitRequestSenseCommand (
1502 ScsiDiskDevice->ScsiIo,
1503 EfiScsiStallSeconds (2),
1504 PtrSenseData,
1505 &SenseDataLength,
1506 &HostAdapterStatus,
1507 &TargetStatus
1508 );
1509 switch (Status) {
1510
1511 case EFI_SUCCESS:
1512
1513 //
1514 // fall through
1515 //
1516 case EFI_WARN_BUFFER_TOO_SMALL:
1517 FallStatus = EFI_SUCCESS;
1518 break;
1519
1520 case EFI_TIMEOUT:
1521
1522 //
1523 // fall through
1524 //
1525 case EFI_NOT_READY:
1526 *NeedRetry = TRUE;
1527 FallStatus = EFI_DEVICE_ERROR;
1528 break;
1529
1530 case EFI_INVALID_PARAMETER:
1531 case EFI_UNSUPPORTED:
1532 *NeedRetry = FALSE;
1533 FallStatus = EFI_DEVICE_ERROR;
1534 break;
1535
1536 case EFI_DEVICE_ERROR:
1537 if (AskResetIfError) {
1538 ScsiDiskDevice->ScsiIo->ResetDevice (ScsiDiskDevice->ScsiIo);
1539 }
1540
1541 FallStatus = EFI_DEVICE_ERROR;
1542 break;
1543 }
1544
1545 if (EFI_ERROR (FallStatus)) {
1546 if (*NumberOfSenseKeys != 0) {
1547 *NeedRetry = FALSE;
1548 return EFI_SUCCESS;
1549 } else {
1550 return EFI_DEVICE_ERROR;
1551 }
1552 }
1553
1554 (*NumberOfSenseKeys) += 1;
1555
1556 //
1557 // no more sense key or number of sense keys exceeds predefined,
1558 // skip the loop.
1559 //
1560 if ((PtrSenseData->Sense_Key == EFI_SCSI_SK_NO_SENSE) ||
1561 (*NumberOfSenseKeys == ScsiDiskDevice->SenseDataNumber)) {
1562 SenseReq = FALSE;
1563 }
1564
1565 PtrSenseData += 1;
1566
1567 }
1568
1569 return EFI_SUCCESS;
1570 }
1571
1572 VOID
1573 GetMediaInfo (
1574 SCSI_DISK_DEV *ScsiDiskDevice,
1575 EFI_SCSI_DISK_CAPACITY_DATA *Capacity
1576 )
1577 /*++
1578
1579 Routine Description:
1580
1581 TODO: Add function description
1582
1583 Arguments:
1584
1585 ScsiDiskDevice - TODO: add argument description
1586 Capacity - TODO: add argument description
1587
1588 Returns:
1589
1590 TODO: add return values
1591
1592 --*/
1593 {
1594 ScsiDiskDevice->BlkIo.Media->LastBlock = (Capacity->LastLba3 << 24) |
1595 (Capacity->LastLba2 << 16) |
1596 (Capacity->LastLba1 << 8) |
1597 Capacity->LastLba0;
1598
1599 ScsiDiskDevice->BlkIo.Media->MediaPresent = TRUE;
1600 ScsiDiskDevice->BlkIo.Media->BlockSize = (Capacity->BlockSize3 << 24) |
1601 (Capacity->BlockSize2 << 16) |
1602 (Capacity->BlockSize1 << 8) |
1603 Capacity->BlockSize0;
1604 if (ScsiDiskDevice->DeviceType == EFI_SCSI_TYPE_DISK) {
1605 ScsiDiskDevice->BlkIo.Media->BlockSize = 0x200;
1606 }
1607
1608 if (ScsiDiskDevice->DeviceType == EFI_SCSI_TYPE_CDROM) {
1609 ScsiDiskDevice->BlkIo.Media->BlockSize = 0x800;
1610 }
1611 }
1612
1613 VOID
1614 ParseInquiryData (
1615 SCSI_DISK_DEV *ScsiDiskDevice
1616 )
1617 /*++
1618
1619 Routine Description:
1620
1621 TODO: Add function description
1622
1623 Arguments:
1624
1625 ScsiDiskDevice - TODO: add argument description
1626
1627 Returns:
1628
1629 TODO: add return values
1630
1631 --*/
1632 {
1633 ScsiDiskDevice->FixedDevice = (BOOLEAN) (ScsiDiskDevice->InquiryData.RMB ? 0 : 1);
1634 ScsiDiskDevice->BlkIoMedia.RemovableMedia = (BOOLEAN) (!ScsiDiskDevice->FixedDevice);
1635 }
1636
1637 EFI_STATUS
1638 ScsiDiskReadSectors (
1639 SCSI_DISK_DEV *ScsiDiskDevice,
1640 VOID *Buffer,
1641 EFI_LBA Lba,
1642 UINTN NumberOfBlocks
1643 )
1644 /*++
1645
1646 Routine Description:
1647
1648 TODO: Add function description
1649
1650 Arguments:
1651
1652 ScsiDiskDevice - TODO: add argument description
1653 Buffer - TODO: add argument description
1654 Lba - TODO: add argument description
1655 NumberOfBlocks - TODO: add argument description
1656
1657 Returns:
1658
1659 EFI_DEVICE_ERROR - TODO: Add description for return value
1660 EFI_DEVICE_ERROR - TODO: Add description for return value
1661 EFI_SUCCESS - TODO: Add description for return value
1662
1663 --*/
1664 {
1665 UINTN BlocksRemaining;
1666 UINT32 Lba32;
1667 UINT8 *PtrBuffer;
1668 UINT32 BlockSize;
1669 UINT32 ByteCount;
1670 UINT32 MaxBlock;
1671 UINT32 SectorCount;
1672 UINT64 Timeout;
1673 EFI_STATUS Status;
1674 UINT8 Index;
1675 UINT8 MaxRetry;
1676 BOOLEAN NeedRetry;
1677 EFI_SCSI_SENSE_DATA *SenseData;
1678 UINT8 SenseDataLength;
1679 UINTN NumberOfSenseKeys;
1680
1681 SenseData = NULL;
1682 SenseDataLength = 0;
1683 NumberOfSenseKeys = 0;
1684
1685 Status = EFI_SUCCESS;
1686
1687 BlocksRemaining = NumberOfBlocks;
1688 BlockSize = ScsiDiskDevice->BlkIo.Media->BlockSize;
1689 //
1690 // limit the data bytes that can be transferred by one Read(10) Command
1691 //
1692 MaxBlock = 65536;
1693
1694 PtrBuffer = Buffer;
1695 Lba32 = (UINT32) Lba;
1696
1697 while (BlocksRemaining > 0) {
1698
1699 if (BlocksRemaining <= MaxBlock) {
1700
1701 SectorCount = (UINT16) BlocksRemaining;
1702 } else {
1703
1704 SectorCount = MaxBlock;
1705 }
1706
1707 ByteCount = SectorCount * BlockSize;
1708 Timeout = EfiScsiStallSeconds (2);
1709
1710 MaxRetry = 2;
1711 for (Index = 0; Index < MaxRetry; Index++) {
1712
1713 Status = ScsiDiskRead10 (
1714 ScsiDiskDevice,
1715 &NeedRetry,
1716 &SenseData,
1717 &NumberOfSenseKeys,
1718 Timeout,
1719 PtrBuffer,
1720 &ByteCount,
1721 Lba32,
1722 SectorCount
1723 );
1724 if (!EFI_ERROR (Status)) {
1725 break;
1726 }
1727
1728 if (!NeedRetry) {
1729 return EFI_DEVICE_ERROR;
1730 }
1731
1732 }
1733
1734 if ((Index == MaxRetry) && (Status != EFI_SUCCESS)) {
1735 return EFI_DEVICE_ERROR;
1736 }
1737
1738 //
1739 // actual transferred sectors
1740 //
1741 SectorCount = ByteCount / BlockSize;
1742
1743 Lba32 += SectorCount;
1744 PtrBuffer = PtrBuffer + SectorCount * BlockSize;
1745 BlocksRemaining -= SectorCount;
1746 }
1747
1748 return EFI_SUCCESS;
1749 }
1750
1751 EFI_STATUS
1752 ScsiDiskWriteSectors (
1753 SCSI_DISK_DEV *ScsiDiskDevice,
1754 VOID *Buffer,
1755 EFI_LBA Lba,
1756 UINTN NumberOfBlocks
1757 )
1758 /*++
1759
1760 Routine Description:
1761
1762 TODO: Add function description
1763
1764 Arguments:
1765
1766 ScsiDiskDevice - TODO: add argument description
1767 Buffer - TODO: add argument description
1768 Lba - TODO: add argument description
1769 NumberOfBlocks - TODO: add argument description
1770
1771 Returns:
1772
1773 EFI_DEVICE_ERROR - TODO: Add description for return value
1774 EFI_DEVICE_ERROR - TODO: Add description for return value
1775 EFI_SUCCESS - TODO: Add description for return value
1776
1777 --*/
1778 {
1779 UINTN BlocksRemaining;
1780 UINT32 Lba32;
1781 UINT8 *PtrBuffer;
1782 UINT32 BlockSize;
1783 UINT32 ByteCount;
1784 UINT32 MaxBlock;
1785 UINT32 SectorCount;
1786 UINT64 Timeout;
1787 EFI_STATUS Status;
1788 UINT8 Index;
1789 UINT8 MaxRetry;
1790 BOOLEAN NeedRetry;
1791 EFI_SCSI_SENSE_DATA *SenseData;
1792 UINT8 SenseDataLength;
1793 UINTN NumberOfSenseKeys;
1794
1795 SenseData = NULL;
1796 SenseDataLength = 0;
1797 NumberOfSenseKeys = 0;
1798
1799 Status = EFI_SUCCESS;
1800
1801 BlocksRemaining = NumberOfBlocks;
1802 BlockSize = ScsiDiskDevice->BlkIo.Media->BlockSize;
1803 //
1804 // limit the data bytes that can be transferred by one Write(10) Command
1805 //
1806 MaxBlock = 65536;
1807
1808 PtrBuffer = Buffer;
1809 Lba32 = (UINT32) Lba;
1810
1811 while (BlocksRemaining > 0) {
1812
1813 if (BlocksRemaining <= MaxBlock) {
1814
1815 SectorCount = (UINT16) BlocksRemaining;
1816 } else {
1817
1818 SectorCount = MaxBlock;
1819 }
1820
1821 ByteCount = SectorCount * BlockSize;
1822 Timeout = EfiScsiStallSeconds (2);
1823 MaxRetry = 2;
1824 for (Index = 0; Index < MaxRetry; Index++) {
1825 Status = ScsiDiskWrite10 (
1826 ScsiDiskDevice,
1827 &NeedRetry,
1828 &SenseData,
1829 &NumberOfSenseKeys,
1830 Timeout,
1831 PtrBuffer,
1832 &ByteCount,
1833 Lba32,
1834 SectorCount
1835 );
1836 if (!EFI_ERROR (Status)) {
1837 break;
1838 }
1839
1840 if (!NeedRetry) {
1841 return EFI_DEVICE_ERROR;
1842 }
1843 }
1844
1845 if ((Index == MaxRetry) && (Status != EFI_SUCCESS)) {
1846 return EFI_DEVICE_ERROR;
1847 }
1848 //
1849 // actual transferred sectors
1850 //
1851 SectorCount = ByteCount / BlockSize;
1852
1853 Lba32 += SectorCount;
1854 PtrBuffer = PtrBuffer + SectorCount * BlockSize;
1855 BlocksRemaining -= SectorCount;
1856 }
1857
1858 return EFI_SUCCESS;
1859 }
1860
1861 EFI_STATUS
1862 ScsiDiskRead10 (
1863 SCSI_DISK_DEV *ScsiDiskDevice,
1864 BOOLEAN *NeedRetry,
1865 EFI_SCSI_SENSE_DATA **SenseDataArray,
1866 UINTN *NumberOfSenseKeys,
1867 UINT64 Timeout,
1868 UINT8 *DataBuffer,
1869 UINT32 *DataLength,
1870 UINT32 StartLba,
1871 UINT32 SectorSize
1872 )
1873 /*++
1874
1875 Routine Description:
1876
1877 TODO: Add function description
1878
1879 Arguments:
1880
1881 ScsiDiskDevice - TODO: add argument description
1882 NeedRetry - TODO: add argument description
1883 SenseDataArray - TODO: add argument description
1884 NumberOfSenseKeys - TODO: add argument description
1885 Timeout - TODO: add argument description
1886 DataBuffer - TODO: add argument description
1887 DataLength - TODO: add argument description
1888 StartLba - TODO: add argument description
1889 SectorSize - TODO: add argument description
1890
1891 Returns:
1892
1893 TODO: add return values
1894
1895 --*/
1896 {
1897 UINT8 SenseDataLength;
1898 EFI_STATUS Status;
1899 UINT8 HostAdapterStatus;
1900 UINT8 TargetStatus;
1901
1902 *NeedRetry = FALSE;
1903 *NumberOfSenseKeys = 0;
1904 SenseDataLength = 0;
1905 Status = SubmitRead10Command (
1906 ScsiDiskDevice->ScsiIo,
1907 Timeout,
1908 NULL,
1909 &SenseDataLength,
1910 &HostAdapterStatus,
1911 &TargetStatus,
1912 DataBuffer,
1913 DataLength,
1914 StartLba,
1915 SectorSize
1916 );
1917 return Status;
1918 }
1919
1920 EFI_STATUS
1921 ScsiDiskWrite10 (
1922 SCSI_DISK_DEV *ScsiDiskDevice,
1923 BOOLEAN *NeedRetry,
1924 EFI_SCSI_SENSE_DATA **SenseDataArray,
1925 UINTN *NumberOfSenseKeys,
1926 UINT64 Timeout,
1927 UINT8 *DataBuffer,
1928 UINT32 *DataLength,
1929 UINT32 StartLba,
1930 UINT32 SectorSize
1931 )
1932 /*++
1933
1934 Routine Description:
1935
1936 TODO: Add function description
1937
1938 Arguments:
1939
1940 ScsiDiskDevice - TODO: add argument description
1941 NeedRetry - TODO: add argument description
1942 SenseDataArray - TODO: add argument description
1943 NumberOfSenseKeys - TODO: add argument description
1944 Timeout - TODO: add argument description
1945 DataBuffer - TODO: add argument description
1946 DataLength - TODO: add argument description
1947 StartLba - TODO: add argument description
1948 SectorSize - TODO: add argument description
1949
1950 Returns:
1951
1952 TODO: add return values
1953
1954 --*/
1955 {
1956 EFI_STATUS Status;
1957 UINT8 SenseDataLength;
1958 UINT8 HostAdapterStatus;
1959 UINT8 TargetStatus;
1960
1961 *NeedRetry = FALSE;
1962 *NumberOfSenseKeys = 0;
1963 SenseDataLength = 0;
1964 Status = SubmitWrite10Command (
1965 ScsiDiskDevice->ScsiIo,
1966 Timeout,
1967 NULL,
1968 &SenseDataLength,
1969 &HostAdapterStatus,
1970 &TargetStatus,
1971 DataBuffer,
1972 DataLength,
1973 StartLba,
1974 SectorSize
1975 );
1976 return Status;
1977 }
1978
1979 BOOLEAN
1980 ScsiDiskIsNoMedia (
1981 IN EFI_SCSI_SENSE_DATA *SenseData,
1982 IN UINTN SenseCounts
1983 )
1984 /*++
1985
1986 Routine Description:
1987
1988 TODO: Add function description
1989
1990 Arguments:
1991
1992 SenseData - TODO: add argument description
1993 SenseCounts - TODO: add argument description
1994
1995 Returns:
1996
1997 TODO: add return values
1998
1999 --*/
2000 {
2001 EFI_SCSI_SENSE_DATA *SensePtr;
2002 UINTN Index;
2003 BOOLEAN IsNoMedia;
2004
2005 IsNoMedia = FALSE;
2006 SensePtr = SenseData;
2007
2008 for (Index = 0; Index < SenseCounts; Index++) {
2009
2010 //
2011 // Sense Key is EFI_SCSI_SK_NOT_READY (0x2),
2012 // Additional Sense Code is ASC_NO_MEDIA (0x3A)
2013 //
2014 if ((SensePtr->Sense_Key == EFI_SCSI_SK_NOT_READY) &&
2015 (SensePtr->Addnl_Sense_Code == EFI_SCSI_ASC_NO_MEDIA)) {
2016 IsNoMedia = TRUE;
2017 }
2018
2019 SensePtr++;
2020 }
2021
2022 return IsNoMedia;
2023 }
2024
2025 BOOLEAN
2026 ScsiDiskIsMediaError (
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 switch (SensePtr->Sense_Key) {
2057
2058 case EFI_SCSI_SK_MEDIUM_ERROR:
2059 //
2060 // Sense Key is EFI_SCSI_SK_MEDIUM_ERROR (0x3)
2061 //
2062 switch (SensePtr->Addnl_Sense_Code) {
2063
2064 //
2065 // fall through
2066 //
2067 case EFI_SCSI_ASC_MEDIA_ERR1:
2068
2069 //
2070 // fall through
2071 //
2072 case EFI_SCSI_ASC_MEDIA_ERR2:
2073
2074 //
2075 // fall through
2076 //
2077 case EFI_SCSI_ASC_MEDIA_ERR3:
2078 case EFI_SCSI_ASC_MEDIA_ERR4:
2079 IsError = TRUE;
2080 break;
2081
2082 default:
2083 break;
2084 }
2085
2086 break;
2087
2088 case EFI_SCSI_SK_NOT_READY:
2089 //
2090 // Sense Key is EFI_SCSI_SK_NOT_READY (0x2)
2091 //
2092 switch (SensePtr->Addnl_Sense_Code) {
2093 //
2094 // Additional Sense Code is ASC_MEDIA_UPSIDE_DOWN (0x6)
2095 //
2096 case EFI_SCSI_ASC_MEDIA_UPSIDE_DOWN:
2097 IsError = TRUE;
2098 break;
2099
2100 default:
2101 break;
2102 }
2103 break;
2104
2105 default:
2106 break;
2107 }
2108
2109 SensePtr++;
2110 }
2111
2112 return IsError;
2113 }
2114
2115 BOOLEAN
2116 ScsiDiskIsHardwareError (
2117 IN EFI_SCSI_SENSE_DATA *SenseData,
2118 IN UINTN SenseCounts
2119 )
2120 /*++
2121
2122 Routine Description:
2123
2124 TODO: Add function description
2125
2126 Arguments:
2127
2128 SenseData - TODO: add argument description
2129 SenseCounts - TODO: add argument description
2130
2131 Returns:
2132
2133 TODO: add return values
2134
2135 --*/
2136 {
2137 EFI_SCSI_SENSE_DATA *SensePtr;
2138 UINTN Index;
2139 BOOLEAN IsError;
2140
2141 IsError = FALSE;
2142 SensePtr = SenseData;
2143
2144 for (Index = 0; Index < SenseCounts; Index++) {
2145
2146 //
2147 // Sense Key is EFI_SCSI_SK_HARDWARE_ERROR (0x4)
2148 //
2149 if (SensePtr->Sense_Key == EFI_SCSI_SK_HARDWARE_ERROR) {
2150 IsError = TRUE;
2151 }
2152
2153 SensePtr++;
2154 }
2155
2156 return IsError;
2157 }
2158
2159 BOOLEAN
2160 ScsiDiskIsMediaChange (
2161 IN EFI_SCSI_SENSE_DATA *SenseData,
2162 IN UINTN SenseCounts
2163 )
2164 /*++
2165
2166 Routine Description:
2167
2168 TODO: Add function description
2169
2170 Arguments:
2171
2172 SenseData - TODO: add argument description
2173 SenseCounts - TODO: add argument description
2174
2175 Returns:
2176
2177 TODO: add return values
2178
2179 --*/
2180 {
2181 EFI_SCSI_SENSE_DATA *SensePtr;
2182 UINTN Index;
2183 BOOLEAN IsMediaChanged;
2184
2185 IsMediaChanged = FALSE;
2186 SensePtr = SenseData;
2187
2188 for (Index = 0; Index < SenseCounts; Index++) {
2189 //
2190 // Sense Key is EFI_SCSI_SK_UNIT_ATTENTION (0x6),
2191 // Additional sense code is EFI_SCSI_ASC_MEDIA_CHANGE (0x28)
2192 //
2193 if ((SensePtr->Sense_Key == EFI_SCSI_SK_UNIT_ATTENTION) &&
2194 (SensePtr->Addnl_Sense_Code == EFI_SCSI_ASC_MEDIA_CHANGE)) {
2195 IsMediaChanged = TRUE;
2196 }
2197
2198 SensePtr++;
2199 }
2200
2201 return IsMediaChanged;
2202 }
2203
2204 BOOLEAN
2205 ScsiDiskIsResetBefore (
2206 IN EFI_SCSI_SENSE_DATA *SenseData,
2207 IN UINTN SenseCounts
2208 )
2209 /*++
2210
2211 Routine Description:
2212
2213 TODO: Add function description
2214
2215 Arguments:
2216
2217 SenseData - TODO: add argument description
2218 SenseCounts - TODO: add argument description
2219
2220 Returns:
2221
2222 TODO: add return values
2223
2224 --*/
2225 {
2226 EFI_SCSI_SENSE_DATA *SensePtr;
2227 UINTN Index;
2228 BOOLEAN IsResetBefore;
2229
2230 IsResetBefore = FALSE;
2231 SensePtr = SenseData;
2232
2233 for (Index = 0; Index < SenseCounts; Index++) {
2234
2235 //
2236 // Sense Key is EFI_SCSI_SK_UNIT_ATTENTION (0x6)
2237 // Additional Sense Code is EFI_SCSI_ASC_RESET (0x29)
2238 //
2239 if ((SensePtr->Sense_Key == EFI_SCSI_SK_UNIT_ATTENTION) &&
2240 (SensePtr->Addnl_Sense_Code == EFI_SCSI_ASC_RESET)) {
2241 IsResetBefore = TRUE;
2242 }
2243
2244 SensePtr++;
2245 }
2246
2247 return IsResetBefore;
2248 }
2249
2250 BOOLEAN
2251 ScsiDiskIsDriveReady (
2252 IN EFI_SCSI_SENSE_DATA *SenseData,
2253 IN UINTN SenseCounts,
2254 OUT BOOLEAN *RetryLater
2255 )
2256 /*++
2257
2258 Routine Description:
2259
2260 TODO: Add function description
2261
2262 Arguments:
2263
2264 SenseData - TODO: add argument description
2265 SenseCounts - TODO: add argument description
2266 RetryLater - TODO: add argument description
2267
2268 Returns:
2269
2270 TODO: add return values
2271
2272 --*/
2273 {
2274 EFI_SCSI_SENSE_DATA *SensePtr;
2275 UINTN Index;
2276 BOOLEAN IsReady;
2277
2278 IsReady = TRUE;
2279 *RetryLater = FALSE;
2280 SensePtr = SenseData;
2281
2282 for (Index = 0; Index < SenseCounts; Index++) {
2283
2284 switch (SensePtr->Sense_Key) {
2285
2286 case EFI_SCSI_SK_NOT_READY:
2287 //
2288 // Sense Key is EFI_SCSI_SK_NOT_READY (0x2)
2289 //
2290 switch (SensePtr->Addnl_Sense_Code) {
2291 case EFI_SCSI_ASC_NOT_READY:
2292 //
2293 // Additional Sense Code is EFI_SCSI_ASC_NOT_READY (0x4)
2294 //
2295 switch (SensePtr->Addnl_Sense_Code_Qualifier) {
2296 case EFI_SCSI_ASCQ_IN_PROGRESS:
2297 //
2298 // Additional Sense Code Qualifier is
2299 // EFI_SCSI_ASCQ_IN_PROGRESS (0x1)
2300 //
2301 IsReady = FALSE;
2302 *RetryLater = TRUE;
2303 break;
2304
2305 default:
2306 IsReady = FALSE;
2307 *RetryLater = FALSE;
2308 break;
2309 }
2310 break;
2311
2312 default:
2313 break;
2314 }
2315 break;
2316
2317 default:
2318 break;
2319 }
2320
2321 SensePtr++;
2322 }
2323
2324 return IsReady;
2325 }
2326
2327 BOOLEAN
2328 ScsiDiskHaveSenseKey (
2329 IN EFI_SCSI_SENSE_DATA *SenseData,
2330 IN UINTN SenseCounts
2331 )
2332 /*++
2333
2334 Routine Description:
2335
2336 TODO: Add function description
2337
2338 Arguments:
2339
2340 SenseData - TODO: add argument description
2341 SenseCounts - TODO: add argument description
2342
2343 Returns:
2344
2345 TODO: add return values
2346
2347 --*/
2348 {
2349 EFI_SCSI_SENSE_DATA *SensePtr;
2350 UINTN Index;
2351 BOOLEAN HaveSenseKey;
2352
2353 if (SenseCounts == 0) {
2354 HaveSenseKey = FALSE;
2355 } else {
2356 HaveSenseKey = TRUE;
2357 }
2358
2359 SensePtr = SenseData;
2360
2361 for (Index = 0; Index < SenseCounts; Index++) {
2362
2363 //
2364 // Sense Key is SK_NO_SENSE (0x0)
2365 //
2366 if ((SensePtr->Sense_Key == EFI_SCSI_SK_NO_SENSE) &&
2367 (Index == 0)) {
2368 HaveSenseKey = FALSE;
2369 }
2370
2371 SensePtr++;
2372 }
2373
2374 return HaveSenseKey;
2375 }
2376
2377 VOID
2378 ReleaseScsiDiskDeviceResources (
2379 IN SCSI_DISK_DEV *ScsiDiskDevice
2380 )
2381 /*++
2382
2383 Routine Description:
2384
2385 TODO: Add function description
2386
2387 Arguments:
2388
2389 ScsiDiskDevice - TODO: add argument description
2390
2391 Returns:
2392
2393 TODO: add return values
2394
2395 --*/
2396 {
2397 if (ScsiDiskDevice == NULL) {
2398 return ;
2399 }
2400
2401 if (ScsiDiskDevice->SenseData != NULL) {
2402 gBS->FreePool (ScsiDiskDevice->SenseData);
2403 ScsiDiskDevice->SenseData = NULL;
2404 }
2405
2406 if (ScsiDiskDevice->ControllerNameTable != NULL) {
2407 FreeUnicodeStringTable (ScsiDiskDevice->ControllerNameTable);
2408 ScsiDiskDevice->ControllerNameTable = NULL;
2409 }
2410
2411 gBS->FreePool (ScsiDiskDevice);
2412
2413 ScsiDiskDevice = NULL;
2414 }