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