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