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