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