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