1 /** @file
2 The module to produce Usb Bus PPI.
3 
4 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
5 
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions
8 of the BSD License which accompanies this distribution.  The
9 full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
11 
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 
15 **/
16 
17 #include "UsbPeim.h"
18 #include "HubPeim.h"
19 #include "PeiUsbLib.h"
20 
21 //
22 // UsbIo PPI interface function
23 //
24 PEI_USB_IO_PPI         mUsbIoPpi = {
25   PeiUsbControlTransfer,
26   PeiUsbBulkTransfer,
27   PeiUsbGetInterfaceDescriptor,
28   PeiUsbGetEndpointDescriptor,
29   PeiUsbPortReset
30 };
31 
32 EFI_PEI_PPI_DESCRIPTOR mUsbIoPpiList = {
33   (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
34   &gPeiUsbIoPpiGuid,
35   NULL
36 };
37 
38 /**
39   The enumeration routine to detect device change.
40 
41   @param  PeiServices            Describes the list of possible PEI Services.
42   @param  UsbHcPpi               The pointer of PEI_USB_HOST_CONTROLLER_PPI instance.
43   @param  Usb2HcPpi              The pointer of PEI_USB2_HOST_CONTROLLER_PPI instance.
44 
45   @retval EFI_SUCCESS            The usb is enumerated successfully.
46   @retval EFI_OUT_OF_RESOURCES   Can't allocate memory resource.
47   @retval Others                 Other failure occurs.
48 
49 **/
50 EFI_STATUS
51 PeiUsbEnumeration (
52   IN EFI_PEI_SERVICES               **PeiServices,
53   IN PEI_USB_HOST_CONTROLLER_PPI    *UsbHcPpi,
54   IN PEI_USB2_HOST_CONTROLLER_PPI    *Usb2HcPpi
55   );
56 
57 /**
58   Configure new detected usb device.
59 
60   @param  PeiServices            Describes the list of possible PEI Services.
61   @param  PeiUsbDevice           The pointer of PEI_USB_DEVICE instance.
62   @param  Port                   The port to be configured.
63   @param  DeviceAddress          The device address to be configured.
64 
65   @retval EFI_SUCCESS            The new detected usb device is configured successfully.
66   @retval EFI_OUT_OF_RESOURCES   Can't allocate memory resource.
67   @retval Others                 Other failure occurs.
68 
69 **/
70 EFI_STATUS
71 PeiConfigureUsbDevice (
72   IN     EFI_PEI_SERVICES    **PeiServices,
73   IN     PEI_USB_DEVICE      *PeiUsbDevice,
74   IN     UINT8               Port,
75   IN OUT UINT8               *DeviceAddress
76   );
77 
78 /**
79   Get all configurations from a detected usb device.
80 
81   @param  PeiServices            Describes the list of possible PEI Services.
82   @param  PeiUsbDevice           The pointer of PEI_USB_DEVICE instance.
83 
84   @retval EFI_SUCCESS            The new detected usb device is configured successfully.
85   @retval EFI_OUT_OF_RESOURCES   Can't allocate memory resource.
86   @retval Others                 Other failure occurs.
87 
88 **/
89 EFI_STATUS
90 PeiUsbGetAllConfiguration (
91   IN EFI_PEI_SERVICES   **PeiServices,
92   IN PEI_USB_DEVICE     *PeiUsbDevice
93   );
94 
95 /**
96   Get the start position of next wanted descriptor.
97 
98   @param  Buffer            Buffer containing data to parse.
99   @param  Length            Buffer length.
100   @param  DescType          Descriptor type.
101   @param  DescLength        Descriptor length.
102   @param  ParsedBytes       Bytes has been parsed.
103 
104   @retval EFI_SUCCESS       Get wanted descriptor successfully.
105   @retval EFI_DEVICE_ERROR  Error occurred.
106 
107 **/
108 EFI_STATUS
109 GetExpectedDescriptor (
110   IN  UINT8       *Buffer,
111   IN  UINTN       Length,
112   IN  UINT8       DescType,
113   IN  UINT8       DescLength,
114   OUT UINTN       *ParsedBytes
115   );
116 
117 /**
118   The entrypoint of the module, it will enumerate all HCs.
119 
120   @param  FileHandle             Handle of the file being invoked.
121   @param  PeiServices            Describes the list of possible PEI Services.
122 
123   @retval EFI_SUCCESS            Usb initialization is done successfully.
124   @retval EFI_OUT_OF_RESOURCES   Can't allocate memory resource.
125   @retval EFI_UNSUPPORTED        Can't find required PPI.
126 
127 **/
128 EFI_STATUS
129 EFIAPI
PeimInitializeUsb(IN EFI_PEI_FILE_HANDLE FileHandle,IN CONST EFI_PEI_SERVICES ** PeiServices)130 PeimInitializeUsb (
131   IN EFI_PEI_FILE_HANDLE        FileHandle,
132   IN CONST EFI_PEI_SERVICES     **PeiServices
133   )
134 {
135   EFI_STATUS                   Status;
136   UINTN                        Index;
137   PEI_USB_HOST_CONTROLLER_PPI  *UsbHcPpi;
138   PEI_USB2_HOST_CONTROLLER_PPI *Usb2HcPpi;
139 
140   if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) {
141     return EFI_SUCCESS;
142   }
143 
144   //
145   // gPeiUsbHostControllerPpiGuid and gPeiUsb2HostControllerPpiGuid should not
146   // be produced at the same time
147   //
148   Index = 0;
149   while (TRUE) {
150     //
151     // Get UsbHcPpi at first.
152     //
153     Status = PeiServicesLocatePpi (
154                &gPeiUsbHostControllerPpiGuid,
155                Index,
156                NULL,
157                (VOID **) &UsbHcPpi
158                );
159     if (EFI_ERROR (Status)) {
160       //
161       // No more host controller, break out
162       //
163       break;
164     }
165     PeiUsbEnumeration ((EFI_PEI_SERVICES **) PeiServices, UsbHcPpi, NULL);
166     Index++;
167   }
168 
169   if (Index == 0) {
170     //
171     // Then try to get Usb2HcPpi.
172     //
173     while (TRUE) {
174       Status = PeiServicesLocatePpi (
175                  &gPeiUsb2HostControllerPpiGuid,
176                  Index,
177                  NULL,
178                  (VOID **) &Usb2HcPpi
179                  );
180       if (EFI_ERROR (Status)) {
181         //
182         // No more host controller, break out
183         //
184         break;
185       }
186       PeiUsbEnumeration ((EFI_PEI_SERVICES **) PeiServices, NULL, Usb2HcPpi);
187       Index++;
188     }
189   }
190 
191   if (Index == 0) {
192     return EFI_UNSUPPORTED;
193   }
194 
195   return EFI_SUCCESS;
196 }
197 
198 /**
199   The Hub Enumeration just scans the hub ports one time. It also
200   doesn't support hot-plug.
201 
202   @param  PeiServices            Describes the list of possible PEI Services.
203   @param  PeiUsbDevice           The pointer of PEI_USB_DEVICE instance.
204   @param  CurrentAddress         The DeviceAddress of usb device.
205 
206   @retval EFI_SUCCESS            The usb hub is enumerated successfully.
207   @retval EFI_OUT_OF_RESOURCES   Can't allocate memory resource.
208   @retval Others                 Other failure occurs.
209 
210 **/
211 EFI_STATUS
PeiHubEnumeration(IN EFI_PEI_SERVICES ** PeiServices,IN PEI_USB_DEVICE * PeiUsbDevice,IN UINT8 * CurrentAddress)212 PeiHubEnumeration (
213   IN EFI_PEI_SERVICES               **PeiServices,
214   IN PEI_USB_DEVICE                 *PeiUsbDevice,
215   IN UINT8                          *CurrentAddress
216   )
217 {
218   UINTN                 Index;
219   EFI_STATUS            Status;
220   PEI_USB_IO_PPI        *UsbIoPpi;
221   EFI_USB_PORT_STATUS   PortStatus;
222   UINTN                 MemPages;
223   EFI_PHYSICAL_ADDRESS  AllocateAddress;
224   PEI_USB_DEVICE        *NewPeiUsbDevice;
225   UINTN                 InterfaceIndex;
226   UINTN                 EndpointIndex;
227 
228 
229   UsbIoPpi    = &PeiUsbDevice->UsbIoPpi;
230 
231   DEBUG ((EFI_D_INFO, "PeiHubEnumeration: DownStreamPortNo: %x\n", PeiUsbDevice->DownStreamPortNo));
232 
233   for (Index = 0; Index < PeiUsbDevice->DownStreamPortNo; Index++) {
234 
235     Status = PeiHubGetPortStatus (
236               PeiServices,
237               UsbIoPpi,
238               (UINT8) (Index + 1),
239               (UINT32 *) &PortStatus
240               );
241 
242     if (EFI_ERROR (Status)) {
243       continue;
244     }
245 
246     DEBUG ((EFI_D_INFO, "USB Status --- Port: %x ConnectChange[%04x] Status[%04x]\n", Index, PortStatus.PortChangeStatus, PortStatus.PortStatus));
247     //
248     // Only handle connection/enable/overcurrent/reset change.
249     //
250     if ((PortStatus.PortChangeStatus & (USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE | USB_PORT_STAT_C_OVERCURRENT | USB_PORT_STAT_C_RESET)) == 0) {
251       continue;
252     } else {
253       if (IsPortConnect (PortStatus.PortStatus)) {
254         //
255         // Begin to deal with the new device
256         //
257         MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;
258         Status = PeiServicesAllocatePages (
259                    EfiBootServicesCode,
260                    MemPages,
261                    &AllocateAddress
262                    );
263         if (EFI_ERROR (Status)) {
264           return EFI_OUT_OF_RESOURCES;
265         }
266 
267         NewPeiUsbDevice = (PEI_USB_DEVICE *) ((UINTN) AllocateAddress);
268         ZeroMem (NewPeiUsbDevice, sizeof (PEI_USB_DEVICE));
269 
270         NewPeiUsbDevice->Signature        = PEI_USB_DEVICE_SIGNATURE;
271         NewPeiUsbDevice->DeviceAddress    = 0;
272         NewPeiUsbDevice->MaxPacketSize0   = 8;
273         NewPeiUsbDevice->DataToggle       = 0;
274         CopyMem (
275           &(NewPeiUsbDevice->UsbIoPpi),
276           &mUsbIoPpi,
277           sizeof (PEI_USB_IO_PPI)
278           );
279         CopyMem (
280           &(NewPeiUsbDevice->UsbIoPpiList),
281           &mUsbIoPpiList,
282           sizeof (EFI_PEI_PPI_DESCRIPTOR)
283           );
284         NewPeiUsbDevice->UsbIoPpiList.Ppi = &NewPeiUsbDevice->UsbIoPpi;
285         NewPeiUsbDevice->AllocateAddress  = (UINTN) AllocateAddress;
286         NewPeiUsbDevice->UsbHcPpi         = PeiUsbDevice->UsbHcPpi;
287         NewPeiUsbDevice->Usb2HcPpi        = PeiUsbDevice->Usb2HcPpi;
288         NewPeiUsbDevice->Tier             = (UINT8) (PeiUsbDevice->Tier + 1);
289         NewPeiUsbDevice->IsHub            = 0x0;
290         NewPeiUsbDevice->DownStreamPortNo = 0x0;
291 
292         if (((PortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) == 0) ||
293              ((PortStatus.PortStatus & (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE)) == 0)) {
294           //
295           // If the port already has reset change flag and is connected and enabled, skip the port reset logic.
296           //
297           PeiResetHubPort (PeiServices, UsbIoPpi, (UINT8)(Index + 1));
298 
299           PeiHubGetPortStatus (
300              PeiServices,
301              UsbIoPpi,
302              (UINT8) (Index + 1),
303              (UINT32 *) &PortStatus
304              );
305         } else {
306           PeiHubClearPortFeature (
307             PeiServices,
308             UsbIoPpi,
309             (UINT8) (Index + 1),
310             EfiUsbPortResetChange
311             );
312         }
313 
314         NewPeiUsbDevice->DeviceSpeed = (UINT8) PeiUsbGetDeviceSpeed (PortStatus.PortStatus);
315         DEBUG ((EFI_D_INFO, "Device Speed =%d\n", PeiUsbDevice->DeviceSpeed));
316 
317         if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_SUPER_SPEED)){
318           NewPeiUsbDevice->MaxPacketSize0 = 512;
319         } else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_HIGH_SPEED)) {
320           NewPeiUsbDevice->MaxPacketSize0 = 64;
321         } else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_LOW_SPEED)) {
322           NewPeiUsbDevice->MaxPacketSize0 = 8;
323         } else {
324           NewPeiUsbDevice->MaxPacketSize0 = 8;
325         }
326 
327         if(NewPeiUsbDevice->DeviceSpeed != EFI_USB_SPEED_HIGH) {
328           if (PeiUsbDevice->DeviceSpeed == EFI_USB_SPEED_HIGH) {
329             NewPeiUsbDevice->Translator.TranslatorPortNumber = (UINT8)Index;
330             NewPeiUsbDevice->Translator.TranslatorHubAddress = *CurrentAddress;
331           } else {
332             CopyMem(&(NewPeiUsbDevice->Translator), &(PeiUsbDevice->Translator), sizeof(EFI_USB2_HC_TRANSACTION_TRANSLATOR));
333           }
334         }
335 
336         //
337         // Configure that Usb Device
338         //
339         Status = PeiConfigureUsbDevice (
340                   PeiServices,
341                   NewPeiUsbDevice,
342                   (UINT8) (Index + 1),
343                   CurrentAddress
344                   );
345 
346         if (EFI_ERROR (Status)) {
347           continue;
348         }
349         DEBUG ((EFI_D_INFO, "PeiHubEnumeration: PeiConfigureUsbDevice Success\n"));
350 
351         Status = PeiServicesInstallPpi (&NewPeiUsbDevice->UsbIoPpiList);
352 
353         if (NewPeiUsbDevice->InterfaceDesc->InterfaceClass == 0x09) {
354           NewPeiUsbDevice->IsHub  = 0x1;
355 
356           Status = PeiDoHubConfig (PeiServices, NewPeiUsbDevice);
357           if (EFI_ERROR (Status)) {
358             return Status;
359           }
360 
361           PeiHubEnumeration (PeiServices, NewPeiUsbDevice, CurrentAddress);
362         }
363 
364         for (InterfaceIndex = 1; InterfaceIndex < NewPeiUsbDevice->ConfigDesc->NumInterfaces; InterfaceIndex++) {
365           //
366           // Begin to deal with the new device
367           //
368           MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;
369           Status = PeiServicesAllocatePages (
370                      EfiBootServicesCode,
371                      MemPages,
372                      &AllocateAddress
373                      );
374           if (EFI_ERROR (Status)) {
375             return EFI_OUT_OF_RESOURCES;
376           }
377           CopyMem ((VOID *)(UINTN)AllocateAddress, NewPeiUsbDevice, sizeof (PEI_USB_DEVICE));
378           NewPeiUsbDevice = (PEI_USB_DEVICE *) ((UINTN) AllocateAddress);
379           NewPeiUsbDevice->AllocateAddress  = (UINTN) AllocateAddress;
380           NewPeiUsbDevice->UsbIoPpiList.Ppi = &NewPeiUsbDevice->UsbIoPpi;
381           NewPeiUsbDevice->InterfaceDesc = NewPeiUsbDevice->InterfaceDescList[InterfaceIndex];
382           for (EndpointIndex = 0; EndpointIndex < NewPeiUsbDevice->InterfaceDesc->NumEndpoints; EndpointIndex++) {
383             NewPeiUsbDevice->EndpointDesc[EndpointIndex] = NewPeiUsbDevice->EndpointDescList[InterfaceIndex][EndpointIndex];
384           }
385 
386           Status = PeiServicesInstallPpi (&NewPeiUsbDevice->UsbIoPpiList);
387 
388           if (NewPeiUsbDevice->InterfaceDesc->InterfaceClass == 0x09) {
389             NewPeiUsbDevice->IsHub  = 0x1;
390 
391             Status = PeiDoHubConfig (PeiServices, NewPeiUsbDevice);
392             if (EFI_ERROR (Status)) {
393               return Status;
394             }
395 
396             PeiHubEnumeration (PeiServices, NewPeiUsbDevice, CurrentAddress);
397           }
398         }
399       }
400     }
401   }
402 
403 
404   return EFI_SUCCESS;
405 }
406 
407 /**
408   The enumeration routine to detect device change.
409 
410   @param  PeiServices            Describes the list of possible PEI Services.
411   @param  UsbHcPpi               The pointer of PEI_USB_HOST_CONTROLLER_PPI instance.
412   @param  Usb2HcPpi              The pointer of PEI_USB2_HOST_CONTROLLER_PPI instance.
413 
414   @retval EFI_SUCCESS            The usb is enumerated successfully.
415   @retval EFI_OUT_OF_RESOURCES   Can't allocate memory resource.
416   @retval Others                 Other failure occurs.
417 
418 **/
419 EFI_STATUS
PeiUsbEnumeration(IN EFI_PEI_SERVICES ** PeiServices,IN PEI_USB_HOST_CONTROLLER_PPI * UsbHcPpi,IN PEI_USB2_HOST_CONTROLLER_PPI * Usb2HcPpi)420 PeiUsbEnumeration (
421   IN EFI_PEI_SERVICES               **PeiServices,
422   IN PEI_USB_HOST_CONTROLLER_PPI    *UsbHcPpi,
423   IN PEI_USB2_HOST_CONTROLLER_PPI   *Usb2HcPpi
424   )
425 {
426   UINT8                 NumOfRootPort;
427   EFI_STATUS            Status;
428   UINT8                 Index;
429   EFI_USB_PORT_STATUS   PortStatus;
430   PEI_USB_DEVICE        *PeiUsbDevice;
431   UINTN                 MemPages;
432   EFI_PHYSICAL_ADDRESS  AllocateAddress;
433   UINT8                 CurrentAddress;
434   UINTN                 InterfaceIndex;
435   UINTN                 EndpointIndex;
436 
437   CurrentAddress = 0;
438   if (Usb2HcPpi != NULL) {
439     Usb2HcPpi->GetRootHubPortNumber (
440                 PeiServices,
441                 Usb2HcPpi,
442                 (UINT8 *) &NumOfRootPort
443                 );
444   } else if (UsbHcPpi != NULL) {
445     UsbHcPpi->GetRootHubPortNumber (
446                 PeiServices,
447                 UsbHcPpi,
448                 (UINT8 *) &NumOfRootPort
449                 );
450   } else {
451     ASSERT (FALSE);
452     return EFI_INVALID_PARAMETER;
453   }
454 
455   DEBUG ((EFI_D_INFO, "PeiUsbEnumeration: NumOfRootPort: %x\n", NumOfRootPort));
456 
457   for (Index = 0; Index < NumOfRootPort; Index++) {
458     //
459     // First get root port status to detect changes happen
460     //
461     if (Usb2HcPpi != NULL) {
462       Usb2HcPpi->GetRootHubPortStatus (
463                   PeiServices,
464                   Usb2HcPpi,
465                   (UINT8) Index,
466                   &PortStatus
467                   );
468     } else {
469       UsbHcPpi->GetRootHubPortStatus (
470                   PeiServices,
471                   UsbHcPpi,
472                   (UINT8) Index,
473                   &PortStatus
474                   );
475     }
476     DEBUG ((EFI_D_INFO, "USB Status --- Port: %x ConnectChange[%04x] Status[%04x]\n", Index, PortStatus.PortChangeStatus, PortStatus.PortStatus));
477     //
478     // Only handle connection/enable/overcurrent/reset change.
479     //
480     if ((PortStatus.PortChangeStatus & (USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE | USB_PORT_STAT_C_OVERCURRENT | USB_PORT_STAT_C_RESET)) == 0) {
481       continue;
482     } else {
483       if (IsPortConnect (PortStatus.PortStatus)) {
484         MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;
485         Status = PeiServicesAllocatePages (
486                    EfiBootServicesCode,
487                    MemPages,
488                    &AllocateAddress
489                    );
490         if (EFI_ERROR (Status)) {
491           return EFI_OUT_OF_RESOURCES;
492         }
493 
494         PeiUsbDevice = (PEI_USB_DEVICE *) ((UINTN) AllocateAddress);
495         ZeroMem (PeiUsbDevice, sizeof (PEI_USB_DEVICE));
496 
497         PeiUsbDevice->Signature         = PEI_USB_DEVICE_SIGNATURE;
498         PeiUsbDevice->DeviceAddress     = 0;
499         PeiUsbDevice->MaxPacketSize0    = 8;
500         PeiUsbDevice->DataToggle        = 0;
501         CopyMem (
502           &(PeiUsbDevice->UsbIoPpi),
503           &mUsbIoPpi,
504           sizeof (PEI_USB_IO_PPI)
505           );
506         CopyMem (
507           &(PeiUsbDevice->UsbIoPpiList),
508           &mUsbIoPpiList,
509           sizeof (EFI_PEI_PPI_DESCRIPTOR)
510           );
511         PeiUsbDevice->UsbIoPpiList.Ppi  = &PeiUsbDevice->UsbIoPpi;
512         PeiUsbDevice->AllocateAddress   = (UINTN) AllocateAddress;
513         PeiUsbDevice->UsbHcPpi          = UsbHcPpi;
514         PeiUsbDevice->Usb2HcPpi         = Usb2HcPpi;
515         PeiUsbDevice->IsHub             = 0x0;
516         PeiUsbDevice->DownStreamPortNo  = 0x0;
517 
518         if (((PortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) == 0) ||
519              ((PortStatus.PortStatus & (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE)) == 0)) {
520           //
521           // If the port already has reset change flag and is connected and enabled, skip the port reset logic.
522           //
523           ResetRootPort (
524             PeiServices,
525             PeiUsbDevice->UsbHcPpi,
526             PeiUsbDevice->Usb2HcPpi,
527             Index,
528             0
529             );
530 
531           if (Usb2HcPpi != NULL) {
532             Usb2HcPpi->GetRootHubPortStatus (
533                          PeiServices,
534                          Usb2HcPpi,
535                          (UINT8) Index,
536                          &PortStatus
537                          );
538           } else {
539             UsbHcPpi->GetRootHubPortStatus (
540                         PeiServices,
541                         UsbHcPpi,
542                         (UINT8) Index,
543                         &PortStatus
544                         );
545           }
546         } else {
547           if (Usb2HcPpi != NULL) {
548             Usb2HcPpi->ClearRootHubPortFeature (
549                         PeiServices,
550                         Usb2HcPpi,
551                         (UINT8) Index,
552                         EfiUsbPortResetChange
553                         );
554           } else {
555             UsbHcPpi->ClearRootHubPortFeature (
556                         PeiServices,
557                         UsbHcPpi,
558                         (UINT8) Index,
559                         EfiUsbPortResetChange
560                         );
561           }
562         }
563 
564         PeiUsbDevice->DeviceSpeed = (UINT8) PeiUsbGetDeviceSpeed (PortStatus.PortStatus);
565         DEBUG ((EFI_D_INFO, "Device Speed =%d\n", PeiUsbDevice->DeviceSpeed));
566 
567         if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_SUPER_SPEED)){
568           PeiUsbDevice->MaxPacketSize0 = 512;
569         } else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_HIGH_SPEED)) {
570           PeiUsbDevice->MaxPacketSize0 = 64;
571         } else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_LOW_SPEED)) {
572           PeiUsbDevice->MaxPacketSize0 = 8;
573         } else {
574           PeiUsbDevice->MaxPacketSize0 = 8;
575         }
576 
577         //
578         // Configure that Usb Device
579         //
580         Status = PeiConfigureUsbDevice (
581                   PeiServices,
582                   PeiUsbDevice,
583                   Index,
584                   &CurrentAddress
585                   );
586 
587         if (EFI_ERROR (Status)) {
588           continue;
589         }
590         DEBUG ((EFI_D_INFO, "PeiUsbEnumeration: PeiConfigureUsbDevice Success\n"));
591 
592         Status = PeiServicesInstallPpi (&PeiUsbDevice->UsbIoPpiList);
593 
594         if (PeiUsbDevice->InterfaceDesc->InterfaceClass == 0x09) {
595           PeiUsbDevice->IsHub = 0x1;
596 
597           Status = PeiDoHubConfig (PeiServices, PeiUsbDevice);
598           if (EFI_ERROR (Status)) {
599             return Status;
600           }
601 
602           PeiHubEnumeration (PeiServices, PeiUsbDevice, &CurrentAddress);
603         }
604 
605         for (InterfaceIndex = 1; InterfaceIndex < PeiUsbDevice->ConfigDesc->NumInterfaces; InterfaceIndex++) {
606           //
607           // Begin to deal with the new device
608           //
609           MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;
610           Status = PeiServicesAllocatePages (
611                      EfiBootServicesCode,
612                      MemPages,
613                      &AllocateAddress
614                      );
615           if (EFI_ERROR (Status)) {
616             return EFI_OUT_OF_RESOURCES;
617           }
618           CopyMem ((VOID *)(UINTN)AllocateAddress, PeiUsbDevice, sizeof (PEI_USB_DEVICE));
619           PeiUsbDevice = (PEI_USB_DEVICE *) ((UINTN) AllocateAddress);
620           PeiUsbDevice->AllocateAddress  = (UINTN) AllocateAddress;
621           PeiUsbDevice->UsbIoPpiList.Ppi = &PeiUsbDevice->UsbIoPpi;
622           PeiUsbDevice->InterfaceDesc = PeiUsbDevice->InterfaceDescList[InterfaceIndex];
623           for (EndpointIndex = 0; EndpointIndex < PeiUsbDevice->InterfaceDesc->NumEndpoints; EndpointIndex++) {
624             PeiUsbDevice->EndpointDesc[EndpointIndex] = PeiUsbDevice->EndpointDescList[InterfaceIndex][EndpointIndex];
625           }
626 
627           Status = PeiServicesInstallPpi (&PeiUsbDevice->UsbIoPpiList);
628 
629           if (PeiUsbDevice->InterfaceDesc->InterfaceClass == 0x09) {
630             PeiUsbDevice->IsHub = 0x1;
631 
632             Status = PeiDoHubConfig (PeiServices, PeiUsbDevice);
633             if (EFI_ERROR (Status)) {
634               return Status;
635             }
636 
637             PeiHubEnumeration (PeiServices, PeiUsbDevice, &CurrentAddress);
638           }
639         }
640       } else {
641         //
642         // Disconnect change happen, currently we don't support
643         //
644       }
645     }
646   }
647 
648   return EFI_SUCCESS;
649 }
650 
651 /**
652   Configure new detected usb device.
653 
654   @param  PeiServices            Describes the list of possible PEI Services.
655   @param  PeiUsbDevice           The pointer of PEI_USB_DEVICE instance.
656   @param  Port                   The port to be configured.
657   @param  DeviceAddress          The device address to be configured.
658 
659   @retval EFI_SUCCESS            The new detected usb device is configured successfully.
660   @retval EFI_OUT_OF_RESOURCES   Can't allocate memory resource.
661   @retval Others                 Other failure occurs.
662 
663 **/
664 EFI_STATUS
PeiConfigureUsbDevice(IN EFI_PEI_SERVICES ** PeiServices,IN PEI_USB_DEVICE * PeiUsbDevice,IN UINT8 Port,IN OUT UINT8 * DeviceAddress)665 PeiConfigureUsbDevice (
666   IN EFI_PEI_SERVICES   **PeiServices,
667   IN PEI_USB_DEVICE     *PeiUsbDevice,
668   IN UINT8              Port,
669   IN OUT UINT8          *DeviceAddress
670   )
671 {
672   EFI_USB_DEVICE_DESCRIPTOR   DeviceDescriptor;
673   EFI_STATUS                  Status;
674   PEI_USB_IO_PPI              *UsbIoPpi;
675   UINT8                       Retry;
676 
677   UsbIoPpi = &PeiUsbDevice->UsbIoPpi;
678   Status   = EFI_SUCCESS;
679   ZeroMem (&DeviceDescriptor, sizeof (EFI_USB_DEVICE_DESCRIPTOR));
680   //
681   // Get USB device descriptor
682   //
683 
684   for (Retry = 0; Retry < 3; Retry ++) {
685     Status = PeiUsbGetDescriptor (
686                PeiServices,
687                UsbIoPpi,
688                (USB_DT_DEVICE << 8),
689                0,
690                8,
691                &DeviceDescriptor
692                );
693 
694     if (!EFI_ERROR (Status)) {
695       DEBUG ((EFI_D_INFO, "PeiUsbGet Device Descriptor the %d time Success\n", Retry));
696       break;
697     }
698   }
699 
700   if (Retry == 3) {
701     DEBUG ((EFI_D_ERROR, "PeiUsbGet Device Descriptor fail: %x %r\n", Retry, Status));
702     return Status;
703   }
704 
705   if ((DeviceDescriptor.BcdUSB >= 0x0300) && (DeviceDescriptor.MaxPacketSize0 == 9)) {
706     PeiUsbDevice->MaxPacketSize0 = 1 << 9;
707   } else {
708     PeiUsbDevice->MaxPacketSize0 = DeviceDescriptor.MaxPacketSize0;
709   }
710 
711   (*DeviceAddress) ++;
712 
713   Status = PeiUsbSetDeviceAddress (
714             PeiServices,
715             UsbIoPpi,
716             *DeviceAddress
717             );
718 
719   if (EFI_ERROR (Status)) {
720     DEBUG ((EFI_D_ERROR, "PeiUsbSetDeviceAddress Failed: %r\n", Status));
721     return Status;
722   }
723   MicroSecondDelay (USB_SET_DEVICE_ADDRESS_STALL);
724 
725   PeiUsbDevice->DeviceAddress = *DeviceAddress;
726 
727   //
728   // Get whole USB device descriptor
729   //
730   Status = PeiUsbGetDescriptor (
731             PeiServices,
732             UsbIoPpi,
733             (USB_DT_DEVICE << 8),
734             0,
735             (UINT16) sizeof (EFI_USB_DEVICE_DESCRIPTOR),
736             &DeviceDescriptor
737             );
738 
739   if (EFI_ERROR (Status)) {
740     DEBUG ((EFI_D_ERROR, "PeiUsbGetDescriptor First Failed\n"));
741     return Status;
742   }
743 
744   //
745   // Get its default configuration and its first interface
746   //
747   Status = PeiUsbGetAllConfiguration (
748             PeiServices,
749             PeiUsbDevice
750             );
751   if (EFI_ERROR (Status)) {
752     return Status;
753   }
754   MicroSecondDelay (USB_GET_CONFIG_DESCRIPTOR_STALL);
755 
756   Status = PeiUsbSetConfiguration (
757             PeiServices,
758             UsbIoPpi
759             );
760 
761   if (EFI_ERROR (Status)) {
762     return Status;
763   }
764 
765   return EFI_SUCCESS;
766 }
767 
768 /**
769   Get all configurations from a detected usb device.
770 
771   @param  PeiServices            Describes the list of possible PEI Services.
772   @param  PeiUsbDevice           The pointer of PEI_USB_DEVICE instance.
773 
774   @retval EFI_SUCCESS            The new detected usb device is configured successfully.
775   @retval EFI_OUT_OF_RESOURCES   Can't allocate memory resource.
776   @retval Others                 Other failure occurs.
777 
778 **/
779 EFI_STATUS
PeiUsbGetAllConfiguration(IN EFI_PEI_SERVICES ** PeiServices,IN PEI_USB_DEVICE * PeiUsbDevice)780 PeiUsbGetAllConfiguration (
781   IN EFI_PEI_SERVICES   **PeiServices,
782   IN PEI_USB_DEVICE     *PeiUsbDevice
783   )
784 {
785   EFI_STATUS                Status;
786   EFI_USB_CONFIG_DESCRIPTOR *ConfigDesc;
787   PEI_USB_IO_PPI            *UsbIoPpi;
788   UINT16                    ConfigDescLength;
789   UINT8                     *Ptr;
790   UINTN                     SkipBytes;
791   UINTN                     LengthLeft;
792   UINTN                     InterfaceIndex;
793   UINTN                     Index;
794   UINTN                     NumOfEndpoint;
795 
796   UsbIoPpi = &PeiUsbDevice->UsbIoPpi;
797 
798   //
799   // First get its 4-byte configuration descriptor
800   //
801   Status = PeiUsbGetDescriptor (
802             PeiServices,
803             UsbIoPpi,
804             (USB_DT_CONFIG << 8), // Value
805             0,      // Index
806             4,      // Length
807             PeiUsbDevice->ConfigurationData
808             );
809 
810   if (EFI_ERROR (Status)) {
811     DEBUG ((EFI_D_ERROR, "PeiUsbGet Config Descriptor First Failed\n"));
812     return Status;
813   }
814   MicroSecondDelay (USB_GET_CONFIG_DESCRIPTOR_STALL);
815 
816   ConfigDesc        = (EFI_USB_CONFIG_DESCRIPTOR *) PeiUsbDevice->ConfigurationData;
817   ConfigDescLength  = ConfigDesc->TotalLength;
818 
819   //
820   // Then we get the total descriptors for this configuration
821   //
822   Status = PeiUsbGetDescriptor (
823             PeiServices,
824             UsbIoPpi,
825             (USB_DT_CONFIG << 8),
826             0,
827             ConfigDescLength,
828             PeiUsbDevice->ConfigurationData
829             );
830 
831   if (EFI_ERROR (Status)) {
832     DEBUG ((EFI_D_ERROR, "PeiUsbGet Config Descriptor all Failed\n"));
833     return Status;
834   }
835   //
836   // Parse this configuration descriptor
837   // First get the current config descriptor;
838   //
839   Status = GetExpectedDescriptor (
840             PeiUsbDevice->ConfigurationData,
841             ConfigDescLength,
842             USB_DT_CONFIG,
843             (UINT8) sizeof (EFI_USB_CONFIG_DESCRIPTOR),
844             &SkipBytes
845             );
846 
847   if (EFI_ERROR (Status)) {
848     return Status;
849   }
850 
851   Ptr                       = PeiUsbDevice->ConfigurationData + SkipBytes;
852   PeiUsbDevice->ConfigDesc  = (EFI_USB_CONFIG_DESCRIPTOR *) Ptr;
853 
854   Ptr += sizeof (EFI_USB_CONFIG_DESCRIPTOR);
855   LengthLeft = ConfigDescLength - SkipBytes - sizeof (EFI_USB_CONFIG_DESCRIPTOR);
856 
857   for (InterfaceIndex = 0; InterfaceIndex < PeiUsbDevice->ConfigDesc->NumInterfaces; InterfaceIndex++) {
858 
859     //
860     // Get the interface descriptor
861     //
862     Status = GetExpectedDescriptor (
863               Ptr,
864               LengthLeft,
865               USB_DT_INTERFACE,
866               (UINT8) sizeof (EFI_USB_INTERFACE_DESCRIPTOR),
867               &SkipBytes
868               );
869 
870     if (EFI_ERROR (Status)) {
871       return Status;
872     }
873 
874     Ptr += SkipBytes;
875     if (InterfaceIndex == 0) {
876       PeiUsbDevice->InterfaceDesc = (EFI_USB_INTERFACE_DESCRIPTOR *) Ptr;
877     }
878     PeiUsbDevice->InterfaceDescList[InterfaceIndex] = (EFI_USB_INTERFACE_DESCRIPTOR *) Ptr;
879 
880     Ptr += sizeof (EFI_USB_INTERFACE_DESCRIPTOR);
881     LengthLeft -= SkipBytes;
882     LengthLeft -= sizeof (EFI_USB_INTERFACE_DESCRIPTOR);
883 
884     //
885     // Parse all the endpoint descriptor within this interface
886     //
887     NumOfEndpoint = PeiUsbDevice->InterfaceDescList[InterfaceIndex]->NumEndpoints;
888     ASSERT (NumOfEndpoint <= MAX_ENDPOINT);
889 
890     for (Index = 0; Index < NumOfEndpoint; Index++) {
891       //
892       // Get the endpoint descriptor
893       //
894       Status = GetExpectedDescriptor (
895                 Ptr,
896                 LengthLeft,
897                 USB_DT_ENDPOINT,
898                 (UINT8) sizeof (EFI_USB_ENDPOINT_DESCRIPTOR),
899                 &SkipBytes
900                 );
901 
902       if (EFI_ERROR (Status)) {
903         return Status;
904       }
905 
906       Ptr += SkipBytes;
907       if (InterfaceIndex == 0) {
908         PeiUsbDevice->EndpointDesc[Index] = (EFI_USB_ENDPOINT_DESCRIPTOR *) Ptr;
909       }
910       PeiUsbDevice->EndpointDescList[InterfaceIndex][Index] = (EFI_USB_ENDPOINT_DESCRIPTOR *) Ptr;
911 
912       Ptr += sizeof (EFI_USB_ENDPOINT_DESCRIPTOR);
913       LengthLeft -= SkipBytes;
914       LengthLeft -= sizeof (EFI_USB_ENDPOINT_DESCRIPTOR);
915     }
916   }
917 
918   return EFI_SUCCESS;
919 }
920 
921 /**
922   Get the start position of next wanted descriptor.
923 
924   @param  Buffer            Buffer containing data to parse.
925   @param  Length            Buffer length.
926   @param  DescType          Descriptor type.
927   @param  DescLength        Descriptor length.
928   @param  ParsedBytes       Bytes has been parsed.
929 
930   @retval EFI_SUCCESS       Get wanted descriptor successfully.
931   @retval EFI_DEVICE_ERROR  Error occurred.
932 
933 **/
934 EFI_STATUS
GetExpectedDescriptor(IN UINT8 * Buffer,IN UINTN Length,IN UINT8 DescType,IN UINT8 DescLength,OUT UINTN * ParsedBytes)935 GetExpectedDescriptor (
936   IN  UINT8       *Buffer,
937   IN  UINTN       Length,
938   IN  UINT8       DescType,
939   IN  UINT8       DescLength,
940   OUT UINTN       *ParsedBytes
941   )
942 {
943   UINT16  DescriptorHeader;
944   UINT8   Len;
945   UINT8   *Ptr;
946   UINTN   Parsed;
947 
948   Parsed  = 0;
949   Ptr     = Buffer;
950 
951   while (TRUE) {
952     //
953     // Buffer length should not less than Desc length
954     //
955     if (Length < DescLength) {
956       return EFI_DEVICE_ERROR;
957     }
958 
959     DescriptorHeader  = (UINT16) (*Ptr + ((*(Ptr + 1)) << 8));
960 
961     Len               = Buffer[0];
962 
963     //
964     // Check to see if it is a start of expected descriptor
965     //
966     if (DescriptorHeader == ((DescType << 8) | DescLength)) {
967       break;
968     }
969 
970     if ((UINT8) (DescriptorHeader >> 8) == DescType) {
971       if (Len > DescLength) {
972         return EFI_DEVICE_ERROR;
973       }
974     }
975     //
976     // Descriptor length should be at least 2
977     // and should not exceed the buffer length
978     //
979     if (Len < 2) {
980       return EFI_DEVICE_ERROR;
981     }
982 
983     if (Len > Length) {
984       return EFI_DEVICE_ERROR;
985     }
986     //
987     // Skip this mismatch descriptor
988     //
989     Length -= Len;
990     Ptr += Len;
991     Parsed += Len;
992   }
993 
994   *ParsedBytes = Parsed;
995 
996   return EFI_SUCCESS;
997 }
998 
999 /**
1000   Send reset signal over the given root hub port.
1001 
1002   @param  PeiServices       Describes the list of possible PEI Services.
1003   @param  UsbHcPpi          The pointer of PEI_USB_HOST_CONTROLLER_PPI instance.
1004   @param  Usb2HcPpi         The pointer of PEI_USB2_HOST_CONTROLLER_PPI instance.
1005   @param  PortNum           The port to be reset.
1006   @param  RetryIndex        The retry times.
1007 
1008 **/
1009 VOID
ResetRootPort(IN EFI_PEI_SERVICES ** PeiServices,IN PEI_USB_HOST_CONTROLLER_PPI * UsbHcPpi,IN PEI_USB2_HOST_CONTROLLER_PPI * Usb2HcPpi,IN UINT8 PortNum,IN UINT8 RetryIndex)1010 ResetRootPort (
1011   IN EFI_PEI_SERVICES               **PeiServices,
1012   IN PEI_USB_HOST_CONTROLLER_PPI    *UsbHcPpi,
1013   IN PEI_USB2_HOST_CONTROLLER_PPI   *Usb2HcPpi,
1014   IN UINT8                          PortNum,
1015   IN UINT8                          RetryIndex
1016   )
1017 {
1018   EFI_STATUS             Status;
1019   UINTN                  Index;
1020   EFI_USB_PORT_STATUS    PortStatus;
1021 
1022 
1023   if (Usb2HcPpi != NULL) {
1024     MicroSecondDelay (200 * 1000);
1025 
1026     //
1027     // reset root port
1028     //
1029     Status = Usb2HcPpi->SetRootHubPortFeature (
1030                          PeiServices,
1031                          Usb2HcPpi,
1032                          PortNum,
1033                          EfiUsbPortReset
1034                          );
1035 
1036     if (EFI_ERROR (Status)) {
1037       DEBUG ((EFI_D_ERROR, "SetRootHubPortFeature EfiUsbPortReset Failed\n"));
1038       return;
1039     }
1040 
1041     //
1042     // Drive the reset signal for at least 50ms. Check USB 2.0 Spec
1043     // section 7.1.7.5 for timing requirements.
1044     //
1045     MicroSecondDelay (USB_SET_ROOT_PORT_RESET_STALL);
1046 
1047     //
1048     // clear reset root port
1049     //
1050     Status = Usb2HcPpi->ClearRootHubPortFeature (
1051                          PeiServices,
1052                          Usb2HcPpi,
1053                          PortNum,
1054                          EfiUsbPortReset
1055                          );
1056 
1057     if (EFI_ERROR (Status)) {
1058       DEBUG ((EFI_D_ERROR, "ClearRootHubPortFeature EfiUsbPortReset Failed\n"));
1059       return;
1060     }
1061 
1062     MicroSecondDelay (USB_CLR_ROOT_PORT_RESET_STALL);
1063 
1064     //
1065     // USB host controller won't clear the RESET bit until
1066     // reset is actually finished.
1067     //
1068     ZeroMem (&PortStatus, sizeof (EFI_USB_PORT_STATUS));
1069 
1070     for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) {
1071       Status = Usb2HcPpi->GetRootHubPortStatus (
1072                             PeiServices,
1073                             Usb2HcPpi,
1074                             PortNum,
1075                             &PortStatus
1076                             );
1077       if (EFI_ERROR (Status)) {
1078         return;
1079       }
1080 
1081       if (!USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_RESET)) {
1082         break;
1083       }
1084 
1085       MicroSecondDelay (USB_WAIT_PORT_STS_CHANGE_STALL);
1086     }
1087 
1088     if (Index == USB_WAIT_PORT_STS_CHANGE_LOOP) {
1089       DEBUG ((EFI_D_ERROR, "ResetRootPort: reset not finished in time on port %d\n", PortNum));
1090       return;
1091     }
1092 
1093     Usb2HcPpi->ClearRootHubPortFeature (
1094                 PeiServices,
1095                 Usb2HcPpi,
1096                 PortNum,
1097                 EfiUsbPortResetChange
1098                 );
1099 
1100     Usb2HcPpi->ClearRootHubPortFeature (
1101                 PeiServices,
1102                 Usb2HcPpi,
1103                 PortNum,
1104                 EfiUsbPortConnectChange
1105                 );
1106 
1107     //
1108     // Set port enable
1109     //
1110     Usb2HcPpi->SetRootHubPortFeature(
1111                 PeiServices,
1112                 Usb2HcPpi,
1113                 PortNum,
1114                 EfiUsbPortEnable
1115                 );
1116 
1117     Usb2HcPpi->ClearRootHubPortFeature (
1118                 PeiServices,
1119                 Usb2HcPpi,
1120                 PortNum,
1121                 EfiUsbPortEnableChange
1122                 );
1123 
1124     MicroSecondDelay ((RetryIndex + 1) * 50 * 1000);
1125   } else {
1126     MicroSecondDelay (200 * 1000);
1127 
1128     //
1129     // reset root port
1130     //
1131     Status = UsbHcPpi->SetRootHubPortFeature (
1132                          PeiServices,
1133                          UsbHcPpi,
1134                          PortNum,
1135                          EfiUsbPortReset
1136                          );
1137 
1138     if (EFI_ERROR (Status)) {
1139       DEBUG ((EFI_D_ERROR, "SetRootHubPortFeature EfiUsbPortReset Failed\n"));
1140       return;
1141     }
1142 
1143     //
1144     // Drive the reset signal for at least 50ms. Check USB 2.0 Spec
1145     // section 7.1.7.5 for timing requirements.
1146     //
1147     MicroSecondDelay (USB_SET_ROOT_PORT_RESET_STALL);
1148 
1149     //
1150     // clear reset root port
1151     //
1152     Status = UsbHcPpi->ClearRootHubPortFeature (
1153                          PeiServices,
1154                          UsbHcPpi,
1155                          PortNum,
1156                          EfiUsbPortReset
1157                          );
1158 
1159     if (EFI_ERROR (Status)) {
1160       DEBUG ((EFI_D_ERROR, "ClearRootHubPortFeature EfiUsbPortReset Failed\n"));
1161       return;
1162     }
1163 
1164     MicroSecondDelay (USB_CLR_ROOT_PORT_RESET_STALL);
1165 
1166     //
1167     // USB host controller won't clear the RESET bit until
1168     // reset is actually finished.
1169     //
1170     ZeroMem (&PortStatus, sizeof (EFI_USB_PORT_STATUS));
1171 
1172     for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) {
1173       Status = UsbHcPpi->GetRootHubPortStatus (
1174                            PeiServices,
1175                            UsbHcPpi,
1176                            PortNum,
1177                            &PortStatus
1178                            );
1179       if (EFI_ERROR (Status)) {
1180         return;
1181       }
1182 
1183       if (!USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_RESET)) {
1184         break;
1185       }
1186 
1187       MicroSecondDelay (USB_WAIT_PORT_STS_CHANGE_STALL);
1188     }
1189 
1190     if (Index == USB_WAIT_PORT_STS_CHANGE_LOOP) {
1191       DEBUG ((EFI_D_ERROR, "ResetRootPort: reset not finished in time on port %d\n", PortNum));
1192       return;
1193     }
1194 
1195     UsbHcPpi->ClearRootHubPortFeature (
1196                 PeiServices,
1197                 UsbHcPpi,
1198                 PortNum,
1199                 EfiUsbPortResetChange
1200                 );
1201 
1202     UsbHcPpi->ClearRootHubPortFeature (
1203                 PeiServices,
1204                 UsbHcPpi,
1205                 PortNum,
1206                 EfiUsbPortConnectChange
1207                 );
1208 
1209     //
1210     // Set port enable
1211     //
1212     UsbHcPpi->SetRootHubPortFeature(
1213                 PeiServices,
1214                 UsbHcPpi,
1215                 PortNum,
1216                 EfiUsbPortEnable
1217                 );
1218 
1219     UsbHcPpi->ClearRootHubPortFeature (
1220                 PeiServices,
1221                 UsbHcPpi,
1222                 PortNum,
1223                 EfiUsbPortEnableChange
1224                 );
1225 
1226     MicroSecondDelay ((RetryIndex + 1) * 50 * 1000);
1227   }
1228   return;
1229 }
1230 
1231 
1232