]> git.proxmox.com Git - mirror_edk2.git/blob - EdkModulePkg/Bus/Scsi/ScsiDisk/Dxe/ScsiDisk.c
10134e864e3a4147399efca08306ae5e67feb231
[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 0xa,
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 UINTN NumberOfSenseKeys;
1618
1619 SenseData = NULL;
1620 NumberOfSenseKeys = 0;
1621
1622 Status = EFI_SUCCESS;
1623
1624 BlocksRemaining = NumberOfBlocks;
1625 BlockSize = ScsiDiskDevice->BlkIo.Media->BlockSize;
1626 //
1627 // limit the data bytes that can be transferred by one Read(10) Command
1628 //
1629 MaxBlock = 65536;
1630
1631 PtrBuffer = Buffer;
1632 Lba32 = (UINT32) Lba;
1633
1634 while (BlocksRemaining > 0) {
1635
1636 if (BlocksRemaining <= MaxBlock) {
1637
1638 SectorCount = (UINT16) BlocksRemaining;
1639 } else {
1640
1641 SectorCount = MaxBlock;
1642 }
1643
1644 ByteCount = SectorCount * BlockSize;
1645 Timeout = EfiScsiStallSeconds (2);
1646
1647 MaxRetry = 2;
1648 for (Index = 0; Index < MaxRetry; Index++) {
1649
1650 Status = ScsiDiskRead10 (
1651 ScsiDiskDevice,
1652 &NeedRetry,
1653 &SenseData,
1654 &NumberOfSenseKeys,
1655 Timeout,
1656 PtrBuffer,
1657 &ByteCount,
1658 Lba32,
1659 SectorCount
1660 );
1661 if (!EFI_ERROR (Status)) {
1662 break;
1663 }
1664
1665 if (!NeedRetry) {
1666 return EFI_DEVICE_ERROR;
1667 }
1668
1669 }
1670
1671 if ((Index == MaxRetry) && (Status != EFI_SUCCESS)) {
1672 return EFI_DEVICE_ERROR;
1673 }
1674
1675 //
1676 // actual transferred sectors
1677 //
1678 SectorCount = ByteCount / BlockSize;
1679
1680 Lba32 += SectorCount;
1681 PtrBuffer = PtrBuffer + SectorCount * BlockSize;
1682 BlocksRemaining -= SectorCount;
1683 }
1684
1685 return EFI_SUCCESS;
1686 }
1687
1688 EFI_STATUS
1689 ScsiDiskWriteSectors (
1690 SCSI_DISK_DEV *ScsiDiskDevice,
1691 VOID *Buffer,
1692 EFI_LBA Lba,
1693 UINTN NumberOfBlocks
1694 )
1695 /*++
1696
1697 Routine Description:
1698
1699 TODO: Add function description
1700
1701 Arguments:
1702
1703 ScsiDiskDevice - TODO: add argument description
1704 Buffer - TODO: add argument description
1705 Lba - TODO: add argument description
1706 NumberOfBlocks - TODO: add argument description
1707
1708 Returns:
1709
1710 EFI_DEVICE_ERROR - TODO: Add description for return value
1711 EFI_DEVICE_ERROR - TODO: Add description for return value
1712 EFI_SUCCESS - TODO: Add description for return value
1713
1714 --*/
1715 {
1716 UINTN BlocksRemaining;
1717 UINT32 Lba32;
1718 UINT8 *PtrBuffer;
1719 UINT32 BlockSize;
1720 UINT32 ByteCount;
1721 UINT32 MaxBlock;
1722 UINT32 SectorCount;
1723 UINT64 Timeout;
1724 EFI_STATUS Status;
1725 UINT8 Index;
1726 UINT8 MaxRetry;
1727 BOOLEAN NeedRetry;
1728 EFI_SCSI_SENSE_DATA *SenseData;
1729 UINTN NumberOfSenseKeys;
1730
1731 SenseData = NULL;
1732 NumberOfSenseKeys = 0;
1733
1734 Status = EFI_SUCCESS;
1735
1736 BlocksRemaining = NumberOfBlocks;
1737 BlockSize = ScsiDiskDevice->BlkIo.Media->BlockSize;
1738 //
1739 // limit the data bytes that can be transferred by one Write(10) Command
1740 //
1741 MaxBlock = 65536;
1742
1743 PtrBuffer = Buffer;
1744 Lba32 = (UINT32) Lba;
1745
1746 while (BlocksRemaining > 0) {
1747
1748 if (BlocksRemaining <= MaxBlock) {
1749
1750 SectorCount = (UINT16) BlocksRemaining;
1751 } else {
1752
1753 SectorCount = MaxBlock;
1754 }
1755
1756 ByteCount = SectorCount * BlockSize;
1757 Timeout = EfiScsiStallSeconds (2);
1758 MaxRetry = 2;
1759 for (Index = 0; Index < MaxRetry; Index++) {
1760 Status = ScsiDiskWrite10 (
1761 ScsiDiskDevice,
1762 &NeedRetry,
1763 &SenseData,
1764 &NumberOfSenseKeys,
1765 Timeout,
1766 PtrBuffer,
1767 &ByteCount,
1768 Lba32,
1769 SectorCount
1770 );
1771 if (!EFI_ERROR (Status)) {
1772 break;
1773 }
1774
1775 if (!NeedRetry) {
1776 return EFI_DEVICE_ERROR;
1777 }
1778 }
1779
1780 if ((Index == MaxRetry) && (Status != EFI_SUCCESS)) {
1781 return EFI_DEVICE_ERROR;
1782 }
1783 //
1784 // actual transferred sectors
1785 //
1786 SectorCount = ByteCount / BlockSize;
1787
1788 Lba32 += SectorCount;
1789 PtrBuffer = PtrBuffer + SectorCount * BlockSize;
1790 BlocksRemaining -= SectorCount;
1791 }
1792
1793 return EFI_SUCCESS;
1794 }
1795
1796 EFI_STATUS
1797 ScsiDiskRead10 (
1798 SCSI_DISK_DEV *ScsiDiskDevice,
1799 BOOLEAN *NeedRetry,
1800 EFI_SCSI_SENSE_DATA **SenseDataArray,
1801 UINTN *NumberOfSenseKeys,
1802 UINT64 Timeout,
1803 UINT8 *DataBuffer,
1804 UINT32 *DataLength,
1805 UINT32 StartLba,
1806 UINT32 SectorSize
1807 )
1808 /*++
1809
1810 Routine Description:
1811
1812 TODO: Add function description
1813
1814 Arguments:
1815
1816 ScsiDiskDevice - TODO: add argument description
1817 NeedRetry - TODO: add argument description
1818 SenseDataArray - TODO: add argument description
1819 NumberOfSenseKeys - TODO: add argument description
1820 Timeout - TODO: add argument description
1821 DataBuffer - TODO: add argument description
1822 DataLength - TODO: add argument description
1823 StartLba - TODO: add argument description
1824 SectorSize - TODO: add argument description
1825
1826 Returns:
1827
1828 TODO: add return values
1829
1830 --*/
1831 {
1832 UINT8 SenseDataLength;
1833 EFI_STATUS Status;
1834 UINT8 HostAdapterStatus;
1835 UINT8 TargetStatus;
1836
1837 *NeedRetry = FALSE;
1838 *NumberOfSenseKeys = 0;
1839 SenseDataLength = 0;
1840 Status = SubmitRead10Command (
1841 ScsiDiskDevice->ScsiIo,
1842 Timeout,
1843 NULL,
1844 &SenseDataLength,
1845 &HostAdapterStatus,
1846 &TargetStatus,
1847 DataBuffer,
1848 DataLength,
1849 StartLba,
1850 SectorSize
1851 );
1852 return Status;
1853 }
1854
1855 EFI_STATUS
1856 ScsiDiskWrite10 (
1857 SCSI_DISK_DEV *ScsiDiskDevice,
1858 BOOLEAN *NeedRetry,
1859 EFI_SCSI_SENSE_DATA **SenseDataArray,
1860 UINTN *NumberOfSenseKeys,
1861 UINT64 Timeout,
1862 UINT8 *DataBuffer,
1863 UINT32 *DataLength,
1864 UINT32 StartLba,
1865 UINT32 SectorSize
1866 )
1867 /*++
1868
1869 Routine Description:
1870
1871 TODO: Add function description
1872
1873 Arguments:
1874
1875 ScsiDiskDevice - TODO: add argument description
1876 NeedRetry - TODO: add argument description
1877 SenseDataArray - TODO: add argument description
1878 NumberOfSenseKeys - TODO: add argument description
1879 Timeout - TODO: add argument description
1880 DataBuffer - TODO: add argument description
1881 DataLength - TODO: add argument description
1882 StartLba - TODO: add argument description
1883 SectorSize - TODO: add argument description
1884
1885 Returns:
1886
1887 TODO: add return values
1888
1889 --*/
1890 {
1891 EFI_STATUS Status;
1892 UINT8 SenseDataLength;
1893 UINT8 HostAdapterStatus;
1894 UINT8 TargetStatus;
1895
1896 *NeedRetry = FALSE;
1897 *NumberOfSenseKeys = 0;
1898 SenseDataLength = 0;
1899 Status = SubmitWrite10Command (
1900 ScsiDiskDevice->ScsiIo,
1901 Timeout,
1902 NULL,
1903 &SenseDataLength,
1904 &HostAdapterStatus,
1905 &TargetStatus,
1906 DataBuffer,
1907 DataLength,
1908 StartLba,
1909 SectorSize
1910 );
1911 return Status;
1912 }
1913
1914 BOOLEAN
1915 ScsiDiskIsNoMedia (
1916 IN EFI_SCSI_SENSE_DATA *SenseData,
1917 IN UINTN SenseCounts
1918 )
1919 /*++
1920
1921 Routine Description:
1922
1923 TODO: Add function description
1924
1925 Arguments:
1926
1927 SenseData - TODO: add argument description
1928 SenseCounts - TODO: add argument description
1929
1930 Returns:
1931
1932 TODO: add return values
1933
1934 --*/
1935 {
1936 EFI_SCSI_SENSE_DATA *SensePtr;
1937 UINTN Index;
1938 BOOLEAN IsNoMedia;
1939
1940 IsNoMedia = FALSE;
1941 SensePtr = SenseData;
1942
1943 for (Index = 0; Index < SenseCounts; Index++) {
1944
1945 //
1946 // Sense Key is EFI_SCSI_SK_NOT_READY (0x2),
1947 // Additional Sense Code is ASC_NO_MEDIA (0x3A)
1948 //
1949 if ((SensePtr->Sense_Key == EFI_SCSI_SK_NOT_READY) &&
1950 (SensePtr->Addnl_Sense_Code == EFI_SCSI_ASC_NO_MEDIA)) {
1951 IsNoMedia = TRUE;
1952 }
1953
1954 SensePtr++;
1955 }
1956
1957 return IsNoMedia;
1958 }
1959
1960 BOOLEAN
1961 ScsiDiskIsMediaError (
1962 IN EFI_SCSI_SENSE_DATA *SenseData,
1963 IN UINTN SenseCounts
1964 )
1965 /*++
1966
1967 Routine Description:
1968
1969 TODO: Add function description
1970
1971 Arguments:
1972
1973 SenseData - TODO: add argument description
1974 SenseCounts - TODO: add argument description
1975
1976 Returns:
1977
1978 TODO: add return values
1979
1980 --*/
1981 {
1982 EFI_SCSI_SENSE_DATA *SensePtr;
1983 UINTN Index;
1984 BOOLEAN IsError;
1985
1986 IsError = FALSE;
1987 SensePtr = SenseData;
1988
1989 for (Index = 0; Index < SenseCounts; Index++) {
1990
1991 switch (SensePtr->Sense_Key) {
1992
1993 case EFI_SCSI_SK_MEDIUM_ERROR:
1994 //
1995 // Sense Key is EFI_SCSI_SK_MEDIUM_ERROR (0x3)
1996 //
1997 switch (SensePtr->Addnl_Sense_Code) {
1998
1999 //
2000 // fall through
2001 //
2002 case EFI_SCSI_ASC_MEDIA_ERR1:
2003
2004 //
2005 // fall through
2006 //
2007 case EFI_SCSI_ASC_MEDIA_ERR2:
2008
2009 //
2010 // fall through
2011 //
2012 case EFI_SCSI_ASC_MEDIA_ERR3:
2013 case EFI_SCSI_ASC_MEDIA_ERR4:
2014 IsError = TRUE;
2015 break;
2016
2017 default:
2018 break;
2019 }
2020
2021 break;
2022
2023 case EFI_SCSI_SK_NOT_READY:
2024 //
2025 // Sense Key is EFI_SCSI_SK_NOT_READY (0x2)
2026 //
2027 switch (SensePtr->Addnl_Sense_Code) {
2028 //
2029 // Additional Sense Code is ASC_MEDIA_UPSIDE_DOWN (0x6)
2030 //
2031 case EFI_SCSI_ASC_MEDIA_UPSIDE_DOWN:
2032 IsError = TRUE;
2033 break;
2034
2035 default:
2036 break;
2037 }
2038 break;
2039
2040 default:
2041 break;
2042 }
2043
2044 SensePtr++;
2045 }
2046
2047 return IsError;
2048 }
2049
2050 BOOLEAN
2051 ScsiDiskIsHardwareError (
2052 IN EFI_SCSI_SENSE_DATA *SenseData,
2053 IN UINTN SenseCounts
2054 )
2055 /*++
2056
2057 Routine Description:
2058
2059 TODO: Add function description
2060
2061 Arguments:
2062
2063 SenseData - TODO: add argument description
2064 SenseCounts - TODO: add argument description
2065
2066 Returns:
2067
2068 TODO: add return values
2069
2070 --*/
2071 {
2072 EFI_SCSI_SENSE_DATA *SensePtr;
2073 UINTN Index;
2074 BOOLEAN IsError;
2075
2076 IsError = FALSE;
2077 SensePtr = SenseData;
2078
2079 for (Index = 0; Index < SenseCounts; Index++) {
2080
2081 //
2082 // Sense Key is EFI_SCSI_SK_HARDWARE_ERROR (0x4)
2083 //
2084 if (SensePtr->Sense_Key == EFI_SCSI_SK_HARDWARE_ERROR) {
2085 IsError = TRUE;
2086 }
2087
2088 SensePtr++;
2089 }
2090
2091 return IsError;
2092 }
2093
2094 BOOLEAN
2095 ScsiDiskIsMediaChange (
2096 IN EFI_SCSI_SENSE_DATA *SenseData,
2097 IN UINTN SenseCounts
2098 )
2099 /*++
2100
2101 Routine Description:
2102
2103 TODO: Add function description
2104
2105 Arguments:
2106
2107 SenseData - TODO: add argument description
2108 SenseCounts - TODO: add argument description
2109
2110 Returns:
2111
2112 TODO: add return values
2113
2114 --*/
2115 {
2116 EFI_SCSI_SENSE_DATA *SensePtr;
2117 UINTN Index;
2118 BOOLEAN IsMediaChanged;
2119
2120 IsMediaChanged = FALSE;
2121 SensePtr = SenseData;
2122
2123 for (Index = 0; Index < SenseCounts; Index++) {
2124 //
2125 // Sense Key is EFI_SCSI_SK_UNIT_ATTENTION (0x6),
2126 // Additional sense code is EFI_SCSI_ASC_MEDIA_CHANGE (0x28)
2127 //
2128 if ((SensePtr->Sense_Key == EFI_SCSI_SK_UNIT_ATTENTION) &&
2129 (SensePtr->Addnl_Sense_Code == EFI_SCSI_ASC_MEDIA_CHANGE)) {
2130 IsMediaChanged = TRUE;
2131 }
2132
2133 SensePtr++;
2134 }
2135
2136 return IsMediaChanged;
2137 }
2138
2139 BOOLEAN
2140 ScsiDiskIsResetBefore (
2141 IN EFI_SCSI_SENSE_DATA *SenseData,
2142 IN UINTN SenseCounts
2143 )
2144 /*++
2145
2146 Routine Description:
2147
2148 TODO: Add function description
2149
2150 Arguments:
2151
2152 SenseData - TODO: add argument description
2153 SenseCounts - TODO: add argument description
2154
2155 Returns:
2156
2157 TODO: add return values
2158
2159 --*/
2160 {
2161 EFI_SCSI_SENSE_DATA *SensePtr;
2162 UINTN Index;
2163 BOOLEAN IsResetBefore;
2164
2165 IsResetBefore = FALSE;
2166 SensePtr = SenseData;
2167
2168 for (Index = 0; Index < SenseCounts; Index++) {
2169
2170 //
2171 // Sense Key is EFI_SCSI_SK_UNIT_ATTENTION (0x6)
2172 // Additional Sense Code is EFI_SCSI_ASC_RESET (0x29)
2173 //
2174 if ((SensePtr->Sense_Key == EFI_SCSI_SK_UNIT_ATTENTION) &&
2175 (SensePtr->Addnl_Sense_Code == EFI_SCSI_ASC_RESET)) {
2176 IsResetBefore = TRUE;
2177 }
2178
2179 SensePtr++;
2180 }
2181
2182 return IsResetBefore;
2183 }
2184
2185 BOOLEAN
2186 ScsiDiskIsDriveReady (
2187 IN EFI_SCSI_SENSE_DATA *SenseData,
2188 IN UINTN SenseCounts,
2189 OUT BOOLEAN *RetryLater
2190 )
2191 /*++
2192
2193 Routine Description:
2194
2195 TODO: Add function description
2196
2197 Arguments:
2198
2199 SenseData - TODO: add argument description
2200 SenseCounts - TODO: add argument description
2201 RetryLater - TODO: add argument description
2202
2203 Returns:
2204
2205 TODO: add return values
2206
2207 --*/
2208 {
2209 EFI_SCSI_SENSE_DATA *SensePtr;
2210 UINTN Index;
2211 BOOLEAN IsReady;
2212
2213 IsReady = TRUE;
2214 *RetryLater = FALSE;
2215 SensePtr = SenseData;
2216
2217 for (Index = 0; Index < SenseCounts; Index++) {
2218
2219 switch (SensePtr->Sense_Key) {
2220
2221 case EFI_SCSI_SK_NOT_READY:
2222 //
2223 // Sense Key is EFI_SCSI_SK_NOT_READY (0x2)
2224 //
2225 switch (SensePtr->Addnl_Sense_Code) {
2226 case EFI_SCSI_ASC_NOT_READY:
2227 //
2228 // Additional Sense Code is EFI_SCSI_ASC_NOT_READY (0x4)
2229 //
2230 switch (SensePtr->Addnl_Sense_Code_Qualifier) {
2231 case EFI_SCSI_ASCQ_IN_PROGRESS:
2232 //
2233 // Additional Sense Code Qualifier is
2234 // EFI_SCSI_ASCQ_IN_PROGRESS (0x1)
2235 //
2236 IsReady = FALSE;
2237 *RetryLater = TRUE;
2238 break;
2239
2240 default:
2241 IsReady = FALSE;
2242 *RetryLater = FALSE;
2243 break;
2244 }
2245 break;
2246
2247 default:
2248 break;
2249 }
2250 break;
2251
2252 default:
2253 break;
2254 }
2255
2256 SensePtr++;
2257 }
2258
2259 return IsReady;
2260 }
2261
2262 BOOLEAN
2263 ScsiDiskHaveSenseKey (
2264 IN EFI_SCSI_SENSE_DATA *SenseData,
2265 IN UINTN SenseCounts
2266 )
2267 /*++
2268
2269 Routine Description:
2270
2271 TODO: Add function description
2272
2273 Arguments:
2274
2275 SenseData - TODO: add argument description
2276 SenseCounts - TODO: add argument description
2277
2278 Returns:
2279
2280 TODO: add return values
2281
2282 --*/
2283 {
2284 EFI_SCSI_SENSE_DATA *SensePtr;
2285 UINTN Index;
2286 BOOLEAN HaveSenseKey;
2287
2288 if (SenseCounts == 0) {
2289 HaveSenseKey = FALSE;
2290 } else {
2291 HaveSenseKey = TRUE;
2292 }
2293
2294 SensePtr = SenseData;
2295
2296 for (Index = 0; Index < SenseCounts; Index++) {
2297
2298 //
2299 // Sense Key is SK_NO_SENSE (0x0)
2300 //
2301 if ((SensePtr->Sense_Key == EFI_SCSI_SK_NO_SENSE) &&
2302 (Index == 0)) {
2303 HaveSenseKey = FALSE;
2304 }
2305
2306 SensePtr++;
2307 }
2308
2309 return HaveSenseKey;
2310 }
2311
2312 VOID
2313 ReleaseScsiDiskDeviceResources (
2314 IN SCSI_DISK_DEV *ScsiDiskDevice
2315 )
2316 /*++
2317
2318 Routine Description:
2319
2320 TODO: Add function description
2321
2322 Arguments:
2323
2324 ScsiDiskDevice - TODO: add argument description
2325
2326 Returns:
2327
2328 TODO: add return values
2329
2330 --*/
2331 {
2332 if (ScsiDiskDevice == NULL) {
2333 return ;
2334 }
2335
2336 if (ScsiDiskDevice->SenseData != NULL) {
2337 gBS->FreePool (ScsiDiskDevice->SenseData);
2338 ScsiDiskDevice->SenseData = NULL;
2339 }
2340
2341 if (ScsiDiskDevice->ControllerNameTable != NULL) {
2342 FreeUnicodeStringTable (ScsiDiskDevice->ControllerNameTable);
2343 ScsiDiskDevice->ControllerNameTable = NULL;
2344 }
2345
2346 gBS->FreePool (ScsiDiskDevice);
2347
2348 ScsiDiskDevice = NULL;
2349 }