]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Usb/UsbBotPei/UsbBotPeim.c
MdeModulePkg/UsbBotPei: Correct wrong media type detection logic in UsbBotPei
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbBotPei / UsbBotPeim.c
CommitLineData
4b1bf81c 1/** @file\r
2\r
c45bc179 3Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>\r
4b1bf81c 4 \r
5This program and the accompanying materials\r
6are licensed and made available under the terms and conditions\r
7of the BSD License which accompanies this distribution. The\r
8full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "UsbBotPeim.h"\r
17#include "BotPeim.h"\r
18\r
19//\r
20// Global function\r
21//\r
22EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList = {\r
23 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,\r
24 &gPeiUsbIoPpiGuid,\r
25 NotifyOnUsbIoPpi\r
26};\r
27\r
28EFI_PEI_RECOVERY_BLOCK_IO_PPI mRecoveryBlkIoPpi = {\r
29 BotGetNumberOfBlockDevices,\r
30 BotGetMediaInfo,\r
31 BotReadBlocks\r
32};\r
33\r
34EFI_PEI_PPI_DESCRIPTOR mPpiList = {\r
35 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,\r
36 &gEfiPeiVirtualBlockIoPpiGuid,\r
37 NULL\r
38};\r
39\r
40/**\r
41 Detect whether the removable media is present and whether it has changed.\r
42\r
43 @param[in] PeiServices General-purpose services that are available to every\r
44 PEIM.\r
45 @param[in] PeiBotDev Indicates the PEI_BOT_DEVICE instance.\r
46\r
47 @retval EFI_SUCCESS The media status is successfully checked.\r
48 @retval Other Failed to detect media.\r
49\r
50**/\r
51EFI_STATUS\r
52PeiBotDetectMedia (\r
53 IN EFI_PEI_SERVICES **PeiServices,\r
54 IN PEI_BOT_DEVICE *PeiBotDev\r
55 );\r
56\r
57/**\r
58 Initializes the Usb Bot. \r
59 \r
60 @param FileHandle Handle of the file being invoked.\r
61 @param PeiServices Describes the list of possible PEI Services.\r
62\r
63 @retval EFI_SUCCESS Usb bot driver is successfully initialized.\r
64 @retval EFI_OUT_OF_RESOURCES Can't initialize the driver.\r
65\r
66**/\r
67EFI_STATUS\r
68EFIAPI\r
69PeimInitializeUsbBot (\r
70 IN EFI_PEI_FILE_HANDLE FileHandle,\r
71 IN CONST EFI_PEI_SERVICES **PeiServices\r
72 )\r
73{\r
74 EFI_STATUS Status;\r
75 UINTN UsbIoPpiInstance;\r
76 EFI_PEI_PPI_DESCRIPTOR *TempPpiDescriptor;\r
77 PEI_USB_IO_PPI *UsbIoPpi;\r
78\r
79 //\r
80 // Shadow this PEIM to run from memory\r
81 //\r
82 if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) {\r
83 return EFI_SUCCESS;\r
84 }\r
85\r
86 //\r
87 // locate all usb io PPIs\r
88 //\r
89 for (UsbIoPpiInstance = 0; UsbIoPpiInstance < PEI_FAT_MAX_USB_IO_PPI; UsbIoPpiInstance++) {\r
90\r
91 Status = PeiServicesLocatePpi (\r
92 &gPeiUsbIoPpiGuid,\r
93 UsbIoPpiInstance,\r
94 &TempPpiDescriptor,\r
95 (VOID **) &UsbIoPpi\r
96 );\r
97 if (EFI_ERROR (Status)) {\r
98 break;\r
99 }\r
100 }\r
101 //\r
102 // Register a notify function\r
103 //\r
104 return PeiServicesNotifyPpi (&mNotifyList);\r
105}\r
106\r
107/**\r
108 UsbIo installation notification function. \r
109 \r
110 This function finds out all the current USB IO PPIs in the system and add them\r
111 into private data.\r
112\r
113 @param PeiServices Indirect reference to the PEI Services Table.\r
114 @param NotifyDesc Address of the notification descriptor data structure.\r
115 @param InvokePpi Address of the PPI that was invoked.\r
116\r
117 @retval EFI_SUCCESS The function completes successfully.\r
118\r
119**/\r
120EFI_STATUS\r
121EFIAPI\r
122NotifyOnUsbIoPpi (\r
123 IN EFI_PEI_SERVICES **PeiServices,\r
124 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,\r
125 IN VOID *InvokePpi\r
126 )\r
127{\r
128 PEI_USB_IO_PPI *UsbIoPpi;\r
129\r
130 UsbIoPpi = (PEI_USB_IO_PPI *) InvokePpi;\r
131\r
132 InitUsbBot (PeiServices, UsbIoPpi);\r
133\r
134 return EFI_SUCCESS;\r
135}\r
136\r
137/**\r
138 Initialize the usb bot device.\r
139\r
140 @param[in] PeiServices General-purpose services that are available to every\r
141 PEIM.\r
142 @param[in] UsbIoPpi Indicates the PEI_USB_IO_PPI instance.\r
143\r
144 @retval EFI_SUCCESS The usb bot device is initialized successfully.\r
145 @retval Other Failed to initialize media.\r
146\r
147**/\r
148EFI_STATUS\r
149InitUsbBot (\r
150 IN EFI_PEI_SERVICES **PeiServices,\r
151 IN PEI_USB_IO_PPI *UsbIoPpi\r
152 )\r
153{\r
154 PEI_BOT_DEVICE *PeiBotDevice;\r
155 EFI_STATUS Status;\r
156 EFI_USB_INTERFACE_DESCRIPTOR *InterfaceDesc;\r
157 UINTN MemPages;\r
158 EFI_PHYSICAL_ADDRESS AllocateAddress;\r
159 EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDesc;\r
160 UINT8 Index;\r
161\r
162 //\r
163 // Check its interface\r
164 //\r
165 Status = UsbIoPpi->UsbGetInterfaceDescriptor (\r
166 PeiServices,\r
167 UsbIoPpi,\r
168 &InterfaceDesc\r
169 );\r
170 if (EFI_ERROR (Status)) {\r
171 return Status;\r
172 }\r
173 //\r
174 // Check if it is the BOT device we support\r
175 //\r
176 if ((InterfaceDesc->InterfaceClass != 0x08) || (InterfaceDesc->InterfaceProtocol != 0x50)) {\r
177\r
178 return EFI_NOT_FOUND;\r
179 }\r
180\r
181 MemPages = sizeof (PEI_BOT_DEVICE) / EFI_PAGE_SIZE + 1;\r
182 Status = PeiServicesAllocatePages (\r
183 EfiBootServicesCode,\r
184 MemPages,\r
185 &AllocateAddress\r
186 );\r
187 if (EFI_ERROR (Status)) {\r
188 return Status;\r
189 }\r
190\r
191 PeiBotDevice = (PEI_BOT_DEVICE *) ((UINTN) AllocateAddress);\r
192\r
193 PeiBotDevice->Signature = PEI_BOT_DEVICE_SIGNATURE;\r
194 PeiBotDevice->UsbIoPpi = UsbIoPpi;\r
195 PeiBotDevice->AllocateAddress = (UINTN) AllocateAddress;\r
196 PeiBotDevice->BotInterface = InterfaceDesc;\r
197\r
198 //\r
199 // Default value\r
200 //\r
201 PeiBotDevice->Media.DeviceType = UsbMassStorage;\r
202 PeiBotDevice->Media.BlockSize = 0x200;\r
203\r
204 //\r
205 // Check its Bulk-in/Bulk-out endpoint\r
206 //\r
207 for (Index = 0; Index < 2; Index++) {\r
208 Status = UsbIoPpi->UsbGetEndpointDescriptor (\r
209 PeiServices,\r
210 UsbIoPpi,\r
211 Index,\r
212 &EndpointDesc\r
213 );\r
214\r
215 if (EFI_ERROR (Status)) {\r
216 return Status;\r
217 }\r
218\r
219 if ((EndpointDesc->EndpointAddress & 0x80) != 0) {\r
220 PeiBotDevice->BulkInEndpoint = EndpointDesc;\r
221 } else {\r
222 PeiBotDevice->BulkOutEndpoint = EndpointDesc;\r
223 }\r
224 }\r
225\r
226 CopyMem (\r
227 &(PeiBotDevice->BlkIoPpi),\r
228 &mRecoveryBlkIoPpi,\r
229 sizeof (EFI_PEI_RECOVERY_BLOCK_IO_PPI)\r
230 );\r
231 CopyMem (\r
232 &(PeiBotDevice->BlkIoPpiList),\r
233 &mPpiList,\r
234 sizeof (EFI_PEI_PPI_DESCRIPTOR)\r
235 );\r
236 PeiBotDevice->BlkIoPpiList.Ppi = &PeiBotDevice->BlkIoPpi;\r
237\r
238 Status = PeiUsbInquiry (PeiServices, PeiBotDevice);\r
239 if (EFI_ERROR (Status)) {\r
240 return Status;\r
241 }\r
242\r
243 Status = PeiServicesAllocatePages (\r
244 EfiBootServicesCode,\r
245 1,\r
246 &AllocateAddress\r
247 );\r
248 if (EFI_ERROR (Status)) {\r
249 return Status;\r
250 }\r
251\r
252 PeiBotDevice->SensePtr = (ATAPI_REQUEST_SENSE_DATA *) ((UINTN) AllocateAddress);\r
253\r
254 Status = PeiServicesInstallPpi (&PeiBotDevice->BlkIoPpiList);\r
255\r
256 if (EFI_ERROR (Status)) {\r
257 return Status;\r
258 }\r
259\r
260 return EFI_SUCCESS;\r
261}\r
262\r
263/**\r
264 Gets the count of block I/O devices that one specific block driver detects.\r
265\r
266 This function is used for getting the count of block I/O devices that one \r
267 specific block driver detects. To the PEI ATAPI driver, it returns the number\r
268 of all the detected ATAPI devices it detects during the enumeration process. \r
269 To the PEI legacy floppy driver, it returns the number of all the legacy \r
270 devices it finds during its enumeration process. If no device is detected, \r
271 then the function will return zero. \r
272 \r
273 @param[in] PeiServices General-purpose services that are available \r
274 to every PEIM.\r
275 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI \r
276 instance.\r
277 @param[out] NumberBlockDevices The number of block I/O devices discovered.\r
278\r
279 @retval EFI_SUCCESS Operation performed successfully.\r
280\r
281**/\r
282EFI_STATUS\r
283EFIAPI\r
284BotGetNumberOfBlockDevices (\r
285 IN EFI_PEI_SERVICES **PeiServices,\r
286 IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,\r
287 OUT UINTN *NumberBlockDevices\r
288 )\r
289{\r
290 //\r
291 // For Usb devices, this value should be always 1\r
292 //\r
293 *NumberBlockDevices = 1;\r
294 return EFI_SUCCESS;\r
295}\r
296\r
297/**\r
298 Gets a block device's media information.\r
299\r
300 This function will provide the caller with the specified block device's media \r
301 information. If the media changes, calling this function will update the media \r
302 information accordingly.\r
303\r
304 @param[in] PeiServices General-purpose services that are available to every\r
305 PEIM\r
306 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance.\r
307 @param[in] DeviceIndex Specifies the block device to which the function wants \r
308 to talk. Because the driver that implements Block I/O \r
309 PPIs will manage multiple block devices, the PPIs that \r
310 want to talk to a single device must specify the \r
311 device index that was assigned during the enumeration\r
312 process. This index is a number from one to \r
313 NumberBlockDevices.\r
314 @param[out] MediaInfo The media information of the specified block media. \r
315 The caller is responsible for the ownership of this \r
316 data structure.\r
317 \r
318 @retval EFI_SUCCESS Media information about the specified block device \r
319 was obtained successfully.\r
320 @retval EFI_DEVICE_ERROR Cannot get the media information due to a hardware \r
321 error.\r
322\r
323**/\r
324EFI_STATUS\r
325EFIAPI\r
326BotGetMediaInfo (\r
327 IN EFI_PEI_SERVICES **PeiServices,\r
328 IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,\r
329 IN UINTN DeviceIndex,\r
330 OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo\r
331 )\r
332{\r
333 PEI_BOT_DEVICE *PeiBotDev;\r
334 EFI_STATUS Status;\r
335\r
336 PeiBotDev = PEI_BOT_DEVICE_FROM_THIS (This);\r
337\r
338 //\r
339 // First test unit ready\r
340 //\r
341 PeiUsbTestUnitReady (\r
342 PeiServices,\r
343 PeiBotDev\r
344 );\r
345\r
346 Status = PeiBotDetectMedia (\r
347 PeiServices,\r
348 PeiBotDev\r
349 );\r
350\r
351 if (EFI_ERROR (Status)) {\r
352 return EFI_DEVICE_ERROR;\r
353 }\r
354\r
355 CopyMem (\r
356 MediaInfo,\r
357 &(PeiBotDev->Media),\r
358 sizeof (EFI_PEI_BLOCK_IO_MEDIA)\r
359 );\r
360\r
361 return EFI_SUCCESS;\r
362}\r
363\r
364/**\r
365 Reads the requested number of blocks from the specified block device.\r
366\r
367 The function reads the requested number of blocks from the device. All the \r
368 blocks are read, or an error is returned. If there is no media in the device,\r
369 the function returns EFI_NO_MEDIA.\r
370\r
371 @param[in] PeiServices General-purpose services that are available to \r
372 every PEIM.\r
373 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance.\r
374 @param[in] DeviceIndex Specifies the block device to which the function wants \r
375 to talk. Because the driver that implements Block I/O \r
376 PPIs will manage multiple block devices, the PPIs that \r
377 want to talk to a single device must specify the device \r
378 index that was assigned during the enumeration process. \r
379 This index is a number from one to NumberBlockDevices.\r
380 @param[in] StartLBA The starting logical block address (LBA) to read from\r
381 on the device\r
382 @param[in] BufferSize The size of the Buffer in bytes. This number must be\r
383 a multiple of the intrinsic block size of the device.\r
384 @param[out] Buffer A pointer to the destination buffer for the data.\r
385 The caller is responsible for the ownership of the \r
386 buffer.\r
387 \r
388 @retval EFI_SUCCESS The data was read correctly from the device.\r
389 @retval EFI_DEVICE_ERROR The device reported an error while attempting \r
390 to perform the read operation.\r
391 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not \r
392 valid, or the buffer is not properly aligned.\r
393 @retval EFI_NO_MEDIA There is no media in the device.\r
394 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of\r
395 the intrinsic block size of the device.\r
396\r
397**/\r
398EFI_STATUS\r
399EFIAPI\r
400BotReadBlocks (\r
401 IN EFI_PEI_SERVICES **PeiServices,\r
402 IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,\r
403 IN UINTN DeviceIndex,\r
404 IN EFI_PEI_LBA StartLBA,\r
405 IN UINTN BufferSize,\r
406 OUT VOID *Buffer\r
407 )\r
408{\r
409 PEI_BOT_DEVICE *PeiBotDev;\r
410 EFI_STATUS Status;\r
411 UINTN BlockSize;\r
412 UINTN NumberOfBlocks;\r
413\r
414 Status = EFI_SUCCESS;\r
415 PeiBotDev = PEI_BOT_DEVICE_FROM_THIS (This);\r
416\r
417 //\r
418 // Check parameters\r
419 //\r
420 if (Buffer == NULL) {\r
421 return EFI_INVALID_PARAMETER;\r
422 }\r
423\r
424 if (BufferSize == 0) {\r
425 return EFI_SUCCESS;\r
426 }\r
427\r
428 if (!PeiBotDev->Media.MediaPresent) {\r
429 return EFI_NO_MEDIA;\r
430 }\r
431\r
432 BlockSize = PeiBotDev->Media.BlockSize;\r
433\r
434 if (BufferSize % BlockSize != 0) {\r
435 Status = EFI_BAD_BUFFER_SIZE;\r
436 }\r
437\r
438 if (StartLBA > PeiBotDev->Media.LastBlock) {\r
439 Status = EFI_INVALID_PARAMETER;\r
440 }\r
441\r
442 NumberOfBlocks = BufferSize / (PeiBotDev->Media.BlockSize);\r
443\r
444 if (Status == EFI_SUCCESS) {\r
445\r
446 Status = PeiUsbTestUnitReady (\r
447 PeiServices,\r
448 PeiBotDev\r
449 );\r
450 if (Status == EFI_SUCCESS) {\r
451 Status = PeiUsbRead10 (\r
452 PeiServices,\r
453 PeiBotDev,\r
454 Buffer,\r
455 StartLBA,\r
456 1\r
457 );\r
458 }\r
459 } else {\r
460 //\r
461 // To generate sense data for DetectMedia use.\r
462 //\r
463 PeiUsbTestUnitReady (\r
464 PeiServices,\r
465 PeiBotDev\r
466 );\r
467 }\r
468\r
469 if (EFI_ERROR (Status)) {\r
470 //\r
471 // if any error encountered, detect what happened to the media and\r
472 // update the media info accordingly.\r
473 //\r
474 Status = PeiBotDetectMedia (\r
475 PeiServices,\r
476 PeiBotDev\r
477 );\r
478 if (Status != EFI_SUCCESS) {\r
479 return EFI_DEVICE_ERROR;\r
480 }\r
481\r
482 NumberOfBlocks = BufferSize / PeiBotDev->Media.BlockSize;\r
483\r
484 if (!(PeiBotDev->Media.MediaPresent)) {\r
485 return EFI_NO_MEDIA;\r
486 }\r
487\r
488 if (BufferSize % (PeiBotDev->Media.BlockSize) != 0) {\r
489 return EFI_BAD_BUFFER_SIZE;\r
490 }\r
491\r
492 if (StartLBA > PeiBotDev->Media.LastBlock) {\r
493 return EFI_INVALID_PARAMETER;\r
494 }\r
495\r
496 if ((StartLBA + NumberOfBlocks - 1) > PeiBotDev->Media.LastBlock) {\r
497 return EFI_INVALID_PARAMETER;\r
498 }\r
499\r
500 Status = PeiUsbRead10 (\r
501 PeiServices,\r
502 PeiBotDev,\r
503 Buffer,\r
504 StartLBA,\r
505 NumberOfBlocks\r
506 );\r
507\r
508 switch (Status) {\r
509\r
510 case EFI_SUCCESS:\r
511 return EFI_SUCCESS;\r
512\r
513 default:\r
514 return EFI_DEVICE_ERROR;\r
515 }\r
516 } else {\r
517 StartLBA += 1;\r
518 NumberOfBlocks -= 1;\r
519 Buffer = (UINT8 *) Buffer + PeiBotDev->Media.BlockSize;\r
520\r
521 if (NumberOfBlocks == 0) {\r
522 return EFI_SUCCESS;\r
523 }\r
524\r
525 Status = PeiUsbRead10 (\r
526 PeiServices,\r
527 PeiBotDev,\r
528 Buffer,\r
529 StartLBA,\r
530 NumberOfBlocks\r
531 );\r
532 switch (Status) {\r
533\r
534 case EFI_SUCCESS:\r
535 return EFI_SUCCESS;\r
536\r
537 default:\r
538 return EFI_DEVICE_ERROR;\r
539\r
540 }\r
541 }\r
542}\r
543\r
544/**\r
545 Detect whether the removable media is present and whether it has changed.\r
546\r
547 @param[in] PeiServices General-purpose services that are available to every\r
548 PEIM.\r
549 @param[in] PeiBotDev Indicates the PEI_BOT_DEVICE instance.\r
550\r
551 @retval EFI_SUCCESS The media status is successfully checked.\r
552 @retval Other Failed to detect media.\r
553\r
554**/\r
555EFI_STATUS\r
556PeiBotDetectMedia (\r
557 IN EFI_PEI_SERVICES **PeiServices,\r
558 IN PEI_BOT_DEVICE *PeiBotDev\r
559 )\r
560{\r
561 EFI_STATUS Status;\r
562 EFI_STATUS FloppyStatus;\r
563 UINTN SenseCounts;\r
564 BOOLEAN NeedReadCapacity;\r
565 EFI_PHYSICAL_ADDRESS AllocateAddress;\r
566 ATAPI_REQUEST_SENSE_DATA *SensePtr;\r
567 UINTN Retry;\r
568\r
569 //\r
570 // if there is no media present,or media not changed,\r
571 // the request sense command will detect faster than read capacity command.\r
572 // read capacity command can be bypassed, thus improve performance.\r
573 //\r
574 SenseCounts = 0;\r
575 NeedReadCapacity = TRUE;\r
576\r
577 Status = PeiServicesAllocatePages (\r
578 EfiBootServicesCode,\r
579 1,\r
580 &AllocateAddress\r
581 );\r
582 if (EFI_ERROR (Status)) {\r
583 return Status;\r
584 }\r
585\r
586 SensePtr = PeiBotDev->SensePtr;\r
587 ZeroMem (SensePtr, EFI_PAGE_SIZE);\r
588\r
589 Status = PeiUsbRequestSense (\r
590 PeiServices,\r
591 PeiBotDev,\r
592 &SenseCounts,\r
593 (UINT8 *) SensePtr\r
594 );\r
595\r
596 if (Status == EFI_SUCCESS) {\r
597 //\r
598 // No Media\r
599 //\r
600 if (IsNoMedia (SensePtr, SenseCounts)) {\r
601 NeedReadCapacity = FALSE;\r
602 PeiBotDev->Media.MediaPresent = FALSE;\r
603 PeiBotDev->Media.LastBlock = 0;\r
604 } else {\r
605 //\r
606 // Media Changed\r
607 //\r
608 if (IsMediaChange (SensePtr, SenseCounts)) {\r
609 PeiBotDev->Media.MediaPresent = TRUE;\r
610 }\r
611 //\r
612 // Media Error\r
613 //\r
614 if (IsMediaError (SensePtr, SenseCounts)) {\r
615 //\r
616 // if media error encountered, make it look like no media present.\r
617 //\r
618 PeiBotDev->Media.MediaPresent = FALSE;\r
619 PeiBotDev->Media.LastBlock = 0;\r
620 }\r
621\r
622 }\r
623\r
624 }\r
625\r
626 if (NeedReadCapacity) {\r
627 //\r
628 // Retry at most 4 times to detect media info\r
629 //\r
630 for (Retry = 0; Retry < 4; Retry++) {\r
631 switch (PeiBotDev->DeviceType) {\r
632 case USBCDROM:\r
633 Status = PeiUsbReadCapacity (\r
634 PeiServices,\r
635 PeiBotDev\r
636 );\r
637 break;\r
638\r
639 case USBFLOPPY2:\r
640 Status = PeiUsbReadFormattedCapacity (\r
641 PeiServices,\r
642 PeiBotDev\r
643 );\r
644 if (EFI_ERROR(Status)||\r
645 !PeiBotDev->Media.MediaPresent) {\r
646 //\r
647 // retry the ReadCapacity command\r
648 //\r
649 PeiBotDev->DeviceType = USBFLOPPY;\r
650 Status = EFI_DEVICE_ERROR;\r
651 }\r
652 break;\r
653\r
654 case USBFLOPPY:\r
655 Status = PeiUsbReadCapacity (\r
656 PeiServices,\r
657 PeiBotDev\r
658 );\r
c45bc179
FT
659 if (EFI_ERROR (Status)) {\r
660 //\r
661 // retry the ReadFormatCapacity command\r
662 //\r
663 PeiBotDev->DeviceType = USBFLOPPY2;\r
664 }\r
4b1bf81c 665 break;\r
666\r
667 default:\r
668 return EFI_INVALID_PARAMETER;\r
669 }\r
670\r
671 SenseCounts = 0;\r
672 ZeroMem (SensePtr, EFI_PAGE_SIZE);\r
673\r
674 if (Status == EFI_SUCCESS) {\r
675 break;\r
676 }\r
677\r
678 FloppyStatus = PeiUsbRequestSense (\r
679 PeiServices,\r
680 PeiBotDev,\r
681 &SenseCounts,\r
682 (UINT8 *) SensePtr\r
683 );\r
684\r
685 //\r
686 // If Request Sense data failed,retry.\r
687 //\r
688 if (EFI_ERROR (FloppyStatus)) {\r
689 continue;\r
690 }\r
691 //\r
692 // No Media\r
693 //\r
694 if (IsNoMedia (SensePtr, SenseCounts)) {\r
695 PeiBotDev->Media.MediaPresent = FALSE;\r
696 PeiBotDev->Media.LastBlock = 0;\r
697 break;\r
698 }\r
699\r
700 if (IsMediaError (SensePtr, SenseCounts)) {\r
701 //\r
702 // if media error encountered, make it look like no media present.\r
703 //\r
704 PeiBotDev->Media.MediaPresent = FALSE;\r
705 PeiBotDev->Media.LastBlock = 0;\r
706 break;\r
707 }\r
708 }\r
709 //\r
710 // ENDFOR\r
711 //\r
712 // tell whether the readcapacity process is successful or not\r
713 // ("Status" variable record the latest status returned\r
714 // by ReadCapacity )\r
715 //\r
716 if (Status != EFI_SUCCESS) {\r
717 return EFI_DEVICE_ERROR;\r
718 }\r
719 }\r
720\r
721 return EFI_SUCCESS;\r
722}\r