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