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