Home | History | Annotate | Download | only in UsbBusPei
      1 /** @file
      2 Usb Hub Request Support In PEI Phase
      3 
      4 Copyright (c) 2006 - 2014, 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   Get a given hub port status.
     23 
     24   @param  PeiServices   General-purpose services that are available to every PEIM.
     25   @param  UsbIoPpi      Indicates the PEI_USB_IO_PPI instance.
     26   @param  Port          Usb hub port number (starting from 1).
     27   @param  PortStatus    Current Hub port status and change status.
     28 
     29   @retval EFI_SUCCESS       Port status is obtained successfully.
     30   @retval EFI_DEVICE_ERROR  Cannot get the port status due to a hardware error.
     31   @retval Others            Other failure occurs.
     32 
     33 **/
     34 EFI_STATUS
     35 PeiHubGetPortStatus (
     36   IN  EFI_PEI_SERVICES    **PeiServices,
     37   IN  PEI_USB_IO_PPI      *UsbIoPpi,
     38   IN  UINT8               Port,
     39   OUT UINT32              *PortStatus
     40   )
     41 {
     42   EFI_USB_DEVICE_REQUEST  DeviceRequest;
     43 
     44   ZeroMem (&DeviceRequest, sizeof (EFI_USB_DEVICE_REQUEST));
     45 
     46   //
     47   // Fill Device request packet
     48   //
     49   DeviceRequest.RequestType = USB_HUB_GET_PORT_STATUS_REQ_TYPE;
     50   DeviceRequest.Request     = USB_HUB_GET_PORT_STATUS;
     51   DeviceRequest.Index       = Port;
     52   DeviceRequest.Length      = (UINT16) sizeof (UINT32);
     53 
     54 
     55   return UsbIoPpi->UsbControlTransfer (
     56                      PeiServices,
     57                      UsbIoPpi,
     58                      &DeviceRequest,
     59                      EfiUsbDataIn,
     60                      PcdGet32 (PcdUsbTransferTimeoutValue),
     61                      PortStatus,
     62                      sizeof (UINT32)
     63                      );
     64 
     65 }
     66 
     67 /**
     68   Set specified feature to a given hub port.
     69 
     70   @param  PeiServices   General-purpose services that are available to every PEIM.
     71   @param  UsbIoPpi      Indicates the PEI_USB_IO_PPI instance.
     72   @param  Port          Usb hub port number (starting from 1).
     73   @param  Value         New feature value.
     74 
     75   @retval EFI_SUCCESS       Port feature is set successfully.
     76   @retval EFI_DEVICE_ERROR  Cannot set the port feature due to a hardware error.
     77   @retval Others            Other failure occurs.
     78 
     79 **/
     80 EFI_STATUS
     81 PeiHubSetPortFeature (
     82   IN EFI_PEI_SERVICES    **PeiServices,
     83   IN PEI_USB_IO_PPI      *UsbIoPpi,
     84   IN UINT8               Port,
     85   IN UINT8               Value
     86   )
     87 {
     88   EFI_USB_DEVICE_REQUEST      DeviceRequest;
     89 
     90   ZeroMem (&DeviceRequest, sizeof (EFI_USB_DEVICE_REQUEST));
     91 
     92   //
     93   // Fill Device request packet
     94   //
     95   DeviceRequest.RequestType = USB_HUB_SET_PORT_FEATURE_REQ_TYPE;
     96   DeviceRequest.Request     = USB_HUB_SET_PORT_FEATURE;
     97   DeviceRequest.Value       = Value;
     98   DeviceRequest.Index       = Port;
     99 
    100   return UsbIoPpi->UsbControlTransfer (
    101                      PeiServices,
    102                      UsbIoPpi,
    103                      &DeviceRequest,
    104                      EfiUsbNoData,
    105                      PcdGet32 (PcdUsbTransferTimeoutValue),
    106                      NULL,
    107                      0
    108                      );
    109 }
    110 
    111 /**
    112   Clear specified feature on a given hub port.
    113 
    114   @param  PeiServices   General-purpose services that are available to every PEIM.
    115   @param  UsbIoPpi      Indicates the PEI_USB_IO_PPI instance.
    116   @param  Port          Usb hub port number (starting from 1).
    117   @param  Value         Feature value that will be cleared from the hub port.
    118 
    119   @retval EFI_SUCCESS       Port feature is cleared successfully.
    120   @retval EFI_DEVICE_ERROR  Cannot clear the port feature due to a hardware error.
    121   @retval Others            Other failure occurs.
    122 
    123 **/
    124 EFI_STATUS
    125 PeiHubClearPortFeature (
    126   IN EFI_PEI_SERVICES    **PeiServices,
    127   IN PEI_USB_IO_PPI      *UsbIoPpi,
    128   IN UINT8               Port,
    129   IN UINT8               Value
    130   )
    131 {
    132   EFI_USB_DEVICE_REQUEST      DeviceRequest;
    133 
    134   ZeroMem (&DeviceRequest, sizeof (EFI_USB_DEVICE_REQUEST));
    135 
    136   //
    137   // Fill Device request packet
    138   //
    139   DeviceRequest.RequestType = USB_HUB_CLEAR_FEATURE_PORT_REQ_TYPE;
    140   DeviceRequest.Request     = USB_HUB_CLEAR_FEATURE_PORT;
    141   DeviceRequest.Value       = Value;
    142   DeviceRequest.Index       = Port;
    143 
    144   return UsbIoPpi->UsbControlTransfer (
    145                      PeiServices,
    146                      UsbIoPpi,
    147                      &DeviceRequest,
    148                      EfiUsbNoData,
    149                      PcdGet32 (PcdUsbTransferTimeoutValue),
    150                      NULL,
    151                      0
    152                      );
    153 }
    154 
    155 /**
    156   Get a given hub status.
    157 
    158   @param  PeiServices   General-purpose services that are available to every PEIM.
    159   @param  UsbIoPpi      Indicates the PEI_USB_IO_PPI instance.
    160   @param  HubStatus     Current Hub status and change status.
    161 
    162   @retval EFI_SUCCESS       Hub status is obtained successfully.
    163   @retval EFI_DEVICE_ERROR  Cannot get the hub status due to a hardware error.
    164   @retval Others            Other failure occurs.
    165 
    166 **/
    167 EFI_STATUS
    168 PeiHubGetHubStatus (
    169   IN  EFI_PEI_SERVICES    **PeiServices,
    170   IN  PEI_USB_IO_PPI      *UsbIoPpi,
    171   OUT UINT32              *HubStatus
    172   )
    173 {
    174   EFI_USB_DEVICE_REQUEST  DeviceRequest;
    175 
    176   ZeroMem (&DeviceRequest, sizeof (EFI_USB_DEVICE_REQUEST));
    177 
    178   //
    179   // Fill Device request packet
    180   //
    181   DeviceRequest.RequestType = USB_HUB_GET_HUB_STATUS_REQ_TYPE;
    182   DeviceRequest.Request     = USB_HUB_GET_HUB_STATUS;
    183   DeviceRequest.Length      = (UINT16) sizeof (UINT32);
    184 
    185   return UsbIoPpi->UsbControlTransfer (
    186                      PeiServices,
    187                      UsbIoPpi,
    188                      &DeviceRequest,
    189                      EfiUsbDataIn,
    190                      PcdGet32 (PcdUsbTransferTimeoutValue),
    191                      HubStatus,
    192                      sizeof (UINT32)
    193                      );
    194 }
    195 
    196 /**
    197   Set specified feature to a given hub.
    198 
    199   @param  PeiServices   General-purpose services that are available to every PEIM.
    200   @param  UsbIoPpi      Indicates the PEI_USB_IO_PPI instance.
    201   @param  Value         New feature value.
    202 
    203   @retval EFI_SUCCESS       Port feature is set successfully.
    204   @retval EFI_DEVICE_ERROR  Cannot set the port feature due to a hardware error.
    205   @retval Others            Other failure occurs.
    206 
    207 **/
    208 EFI_STATUS
    209 PeiHubSetHubFeature (
    210   IN EFI_PEI_SERVICES    **PeiServices,
    211   IN PEI_USB_IO_PPI      *UsbIoPpi,
    212   IN UINT8               Value
    213   )
    214 {
    215   EFI_USB_DEVICE_REQUEST      DeviceRequest;
    216 
    217   ZeroMem (&DeviceRequest, sizeof (EFI_USB_DEVICE_REQUEST));
    218 
    219   //
    220   // Fill Device request packet
    221   //
    222   DeviceRequest.RequestType = USB_HUB_SET_HUB_FEATURE_REQ_TYPE;
    223   DeviceRequest.Request     = USB_HUB_SET_HUB_FEATURE;
    224   DeviceRequest.Value       = Value;
    225 
    226   return UsbIoPpi->UsbControlTransfer (
    227                      PeiServices,
    228                      UsbIoPpi,
    229                      &DeviceRequest,
    230                      EfiUsbNoData,
    231                      PcdGet32 (PcdUsbTransferTimeoutValue),
    232                      NULL,
    233                      0
    234                      );
    235 }
    236 
    237 /**
    238   Clear specified feature on a given hub.
    239 
    240   @param  PeiServices   General-purpose services that are available to every PEIM.
    241   @param  UsbIoPpi      Indicates the PEI_USB_IO_PPI instance.
    242   @param  Value         Feature value that will be cleared from the hub port.
    243 
    244   @retval EFI_SUCCESS       Hub feature is cleared successfully.
    245   @retval EFI_DEVICE_ERROR  Cannot clear the hub feature due to a hardware error.
    246   @retval Others            Other failure occurs.
    247 
    248 **/
    249 EFI_STATUS
    250 PeiHubClearHubFeature (
    251   IN EFI_PEI_SERVICES    **PeiServices,
    252   IN PEI_USB_IO_PPI      *UsbIoPpi,
    253   IN UINT8               Value
    254   )
    255 {
    256   EFI_USB_DEVICE_REQUEST      DeviceRequest;
    257 
    258   ZeroMem (&DeviceRequest, sizeof (EFI_USB_DEVICE_REQUEST));
    259 
    260   //
    261   // Fill Device request packet
    262   //
    263   DeviceRequest.RequestType = USB_HUB_CLEAR_FEATURE_REQ_TYPE;
    264   DeviceRequest.Request     = USB_HUB_CLEAR_FEATURE;
    265   DeviceRequest.Value       = Value;
    266 
    267   return  UsbIoPpi->UsbControlTransfer (
    268                       PeiServices,
    269                       UsbIoPpi,
    270                       &DeviceRequest,
    271                       EfiUsbNoData,
    272                       PcdGet32 (PcdUsbTransferTimeoutValue),
    273                       NULL,
    274                       0
    275                       );
    276 }
    277 
    278 /**
    279   Get a given hub descriptor.
    280 
    281   @param  PeiServices    General-purpose services that are available to every PEIM.
    282   @param  UsbIoPpi       Indicates the PEI_USB_IO_PPI instance.
    283   @param  DescriptorSize The length of Hub Descriptor buffer.
    284   @param  HubDescriptor  Caller allocated buffer to store the hub descriptor if
    285                          successfully returned.
    286 
    287   @retval EFI_SUCCESS       Hub descriptor is obtained successfully.
    288   @retval EFI_DEVICE_ERROR  Cannot get the hub descriptor due to a hardware error.
    289   @retval Others            Other failure occurs.
    290 
    291 **/
    292 EFI_STATUS
    293 PeiGetHubDescriptor (
    294   IN  EFI_PEI_SERVICES          **PeiServices,
    295   IN  PEI_USB_IO_PPI            *UsbIoPpi,
    296   IN  UINTN                     DescriptorSize,
    297   OUT EFI_USB_HUB_DESCRIPTOR    *HubDescriptor
    298   )
    299 {
    300   EFI_USB_DEVICE_REQUEST      DevReq;
    301   ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
    302 
    303   //
    304   // Fill Device request packet
    305   //
    306   DevReq.RequestType = USB_RT_HUB | 0x80;
    307   DevReq.Request     = USB_HUB_GET_DESCRIPTOR;
    308   DevReq.Value       = USB_DT_HUB << 8;
    309   DevReq.Length      = (UINT16)DescriptorSize;
    310 
    311   return  UsbIoPpi->UsbControlTransfer (
    312                       PeiServices,
    313                       UsbIoPpi,
    314                       &DevReq,
    315                       EfiUsbDataIn,
    316                       PcdGet32 (PcdUsbTransferTimeoutValue),
    317                       HubDescriptor,
    318                       (UINT16)DescriptorSize
    319                       );
    320 }
    321 
    322 /**
    323   Get a given SuperSpeed hub descriptor.
    324 
    325   @param  PeiServices       General-purpose services that are available to every PEIM.
    326   @param  UsbIoPpi          Indicates the PEI_USB_IO_PPI instance.
    327   @param  HubDescriptor     Caller allocated buffer to store the hub descriptor if
    328                             successfully returned.
    329 
    330   @retval EFI_SUCCESS       Hub descriptor is obtained successfully.
    331   @retval EFI_DEVICE_ERROR  Cannot get the hub descriptor due to a hardware error.
    332   @retval Others            Other failure occurs.
    333 
    334 **/
    335 EFI_STATUS
    336 PeiGetSuperSpeedHubDesc (
    337   IN  EFI_PEI_SERVICES          **PeiServices,
    338   IN  PEI_USB_IO_PPI            *UsbIoPpi,
    339   OUT EFI_USB_HUB_DESCRIPTOR    *HubDescriptor
    340   )
    341 {
    342   EFI_USB_DEVICE_REQUEST        DevReq;
    343   ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
    344 
    345   //
    346   // Fill Device request packet
    347   //
    348   DevReq.RequestType = USB_RT_HUB | 0x80;
    349   DevReq.Request     = USB_HUB_GET_DESCRIPTOR;
    350   DevReq.Value       = USB_DT_SUPERSPEED_HUB << 8;
    351   DevReq.Length      = 12;
    352 
    353   return  UsbIoPpi->UsbControlTransfer (
    354                       PeiServices,
    355                       UsbIoPpi,
    356                       &DevReq,
    357                       EfiUsbDataIn,
    358                       PcdGet32 (PcdUsbTransferTimeoutValue),
    359                       HubDescriptor,
    360                       12
    361                       );
    362 }
    363 
    364 /**
    365   Read the whole usb hub descriptor. It is necessary
    366   to do it in two steps because hub descriptor is of
    367   variable length.
    368 
    369   @param  PeiServices       General-purpose services that are available to every PEIM.
    370   @param  PeiUsbDevice      Indicates the hub controller device.
    371   @param  UsbIoPpi          Indicates the PEI_USB_IO_PPI instance.
    372   @param  HubDescriptor     Caller allocated buffer to store the hub descriptor if
    373                             successfully returned.
    374 
    375   @retval EFI_SUCCESS       Hub descriptor is obtained successfully.
    376   @retval EFI_DEVICE_ERROR  Cannot get the hub descriptor due to a hardware error.
    377   @retval Others            Other failure occurs.
    378 
    379 **/
    380 EFI_STATUS
    381 PeiUsbHubReadDesc (
    382   IN EFI_PEI_SERVICES           **PeiServices,
    383   IN PEI_USB_DEVICE             *PeiUsbDevice,
    384   IN PEI_USB_IO_PPI             *UsbIoPpi,
    385   OUT EFI_USB_HUB_DESCRIPTOR    *HubDescriptor
    386   )
    387 {
    388   EFI_STATUS Status;
    389 
    390   if (PeiUsbDevice->DeviceSpeed == EFI_USB_SPEED_SUPER) {
    391     //
    392     // Get the super speed hub descriptor
    393     //
    394     Status = PeiGetSuperSpeedHubDesc (PeiServices, UsbIoPpi, HubDescriptor);
    395   } else {
    396 
    397     //
    398     // First get the hub descriptor length
    399     //
    400     Status = PeiGetHubDescriptor (PeiServices, UsbIoPpi, 2, HubDescriptor);
    401 
    402     if (EFI_ERROR (Status)) {
    403       return Status;
    404     }
    405 
    406     //
    407     // Get the whole hub descriptor
    408     //
    409     Status = PeiGetHubDescriptor (PeiServices, UsbIoPpi, HubDescriptor->Length, HubDescriptor);
    410   }
    411 
    412   return Status;
    413 }
    414 
    415 /**
    416   USB hub control transfer to set the hub depth.
    417 
    418   @param  PeiServices       General-purpose services that are available to every PEIM.
    419   @param  PeiUsbDevice      Indicates the hub controller device.
    420   @param  UsbIoPpi          Indicates the PEI_USB_IO_PPI instance.
    421 
    422   @retval EFI_SUCCESS       Depth of the hub is set.
    423   @retval Others            Failed to set the depth.
    424 
    425 **/
    426 EFI_STATUS
    427 PeiUsbHubCtrlSetHubDepth (
    428   IN EFI_PEI_SERVICES           **PeiServices,
    429   IN PEI_USB_DEVICE             *PeiUsbDevice,
    430   IN PEI_USB_IO_PPI             *UsbIoPpi
    431   )
    432 {
    433   EFI_USB_DEVICE_REQUEST        DevReq;
    434   ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
    435 
    436   //
    437   // Fill Device request packet
    438   //
    439   DevReq.RequestType = USB_RT_HUB;
    440   DevReq.Request     = USB_HUB_REQ_SET_DEPTH;
    441   DevReq.Value       = PeiUsbDevice->Tier;
    442   DevReq.Length      = 0;
    443 
    444   return  UsbIoPpi->UsbControlTransfer (
    445                       PeiServices,
    446                       UsbIoPpi,
    447                       &DevReq,
    448                       EfiUsbNoData,
    449                       PcdGet32 (PcdUsbTransferTimeoutValue),
    450                       NULL,
    451                       0
    452                       );
    453 }
    454 
    455 /**
    456   Configure a given hub.
    457 
    458   @param  PeiServices    General-purpose services that are available to every PEIM.
    459   @param  PeiUsbDevice   Indicating the hub controller device that will be configured
    460 
    461   @retval EFI_SUCCESS       Hub configuration is done successfully.
    462   @retval EFI_DEVICE_ERROR  Cannot configure the hub due to a hardware error.
    463 
    464 **/
    465 EFI_STATUS
    466 PeiDoHubConfig (
    467   IN EFI_PEI_SERVICES    **PeiServices,
    468   IN PEI_USB_DEVICE      *PeiUsbDevice
    469   )
    470 {
    471   EFI_USB_HUB_DESCRIPTOR  HubDescriptor;
    472   EFI_STATUS              Status;
    473   EFI_USB_HUB_STATUS      HubStatus;
    474   UINTN                   Index;
    475   PEI_USB_IO_PPI          *UsbIoPpi;
    476 
    477   ZeroMem (&HubDescriptor, sizeof (HubDescriptor));
    478   UsbIoPpi = &PeiUsbDevice->UsbIoPpi;
    479 
    480   //
    481   // Get the hub descriptor
    482   //
    483   Status = PeiUsbHubReadDesc (
    484             PeiServices,
    485             PeiUsbDevice,
    486             UsbIoPpi,
    487             &HubDescriptor
    488             );
    489   if (EFI_ERROR (Status)) {
    490     return EFI_DEVICE_ERROR;
    491   }
    492 
    493   PeiUsbDevice->DownStreamPortNo = HubDescriptor.NbrPorts;
    494 
    495   if (PeiUsbDevice->DeviceSpeed == EFI_USB_SPEED_SUPER) {
    496     DEBUG ((EFI_D_INFO, "PeiDoHubConfig: Set Hub Depth as 0x%x\n", PeiUsbDevice->Tier));
    497     PeiUsbHubCtrlSetHubDepth (
    498       PeiServices,
    499       PeiUsbDevice,
    500       UsbIoPpi
    501       );
    502   } else {
    503     //
    504     //  Power all the hub ports
    505     //
    506     for (Index = 0; Index < PeiUsbDevice->DownStreamPortNo; Index++) {
    507       Status = PeiHubSetPortFeature (
    508                 PeiServices,
    509                 UsbIoPpi,
    510                 (UINT8) (Index + 1),
    511                 EfiUsbPortPower
    512                 );
    513       if (EFI_ERROR (Status)) {
    514         DEBUG (( EFI_D_ERROR, "PeiDoHubConfig: PeiHubSetPortFeature EfiUsbPortPower failed %x\n", Index));
    515         continue;
    516       }
    517     }
    518 
    519     DEBUG (( EFI_D_INFO, "PeiDoHubConfig: HubDescriptor.PwrOn2PwrGood: 0x%x\n", HubDescriptor.PwrOn2PwrGood));
    520     if (HubDescriptor.PwrOn2PwrGood > 0) {
    521       MicroSecondDelay (HubDescriptor.PwrOn2PwrGood * USB_SET_PORT_POWER_STALL);
    522     }
    523 
    524     //
    525     // Clear Hub Status Change
    526     //
    527     Status = PeiHubGetHubStatus (
    528               PeiServices,
    529               UsbIoPpi,
    530               (UINT32 *) &HubStatus
    531               );
    532     if (EFI_ERROR (Status)) {
    533       return EFI_DEVICE_ERROR;
    534     } else {
    535       //
    536       // Hub power supply change happens
    537       //
    538       if ((HubStatus.HubChangeStatus & HUB_CHANGE_LOCAL_POWER) != 0) {
    539         PeiHubClearHubFeature (
    540           PeiServices,
    541           UsbIoPpi,
    542           C_HUB_LOCAL_POWER
    543           );
    544       }
    545       //
    546       // Hub change overcurrent happens
    547       //
    548       if ((HubStatus.HubChangeStatus & HUB_CHANGE_OVERCURRENT) != 0) {
    549         PeiHubClearHubFeature (
    550           PeiServices,
    551           UsbIoPpi,
    552           C_HUB_OVER_CURRENT
    553           );
    554       }
    555     }
    556   }
    557 
    558   return EFI_SUCCESS;
    559 }
    560 
    561 /**
    562   Send reset signal over the given root hub port.
    563 
    564   @param  PeiServices    General-purpose services that are available to every PEIM.
    565   @param  UsbIoPpi       Indicates the PEI_USB_IO_PPI instance.
    566   @param  PortNum        Usb hub port number (starting from 1).
    567 
    568 **/
    569 VOID
    570 PeiResetHubPort (
    571   IN EFI_PEI_SERVICES    **PeiServices,
    572   IN PEI_USB_IO_PPI      *UsbIoPpi,
    573   IN UINT8               PortNum
    574   )
    575 {
    576   EFI_STATUS          Status;
    577   UINTN               Index;
    578   EFI_USB_PORT_STATUS HubPortStatus;
    579 
    580   MicroSecondDelay (100 * 1000);
    581 
    582   //
    583   // reset root port
    584   //
    585   PeiHubSetPortFeature (
    586     PeiServices,
    587     UsbIoPpi,
    588     PortNum,
    589     EfiUsbPortReset
    590     );
    591 
    592   //
    593   // Drive the reset signal for worst 20ms. Check USB 2.0 Spec
    594   // section 7.1.7.5 for timing requirements.
    595   //
    596   MicroSecondDelay (USB_SET_PORT_RESET_STALL);
    597 
    598   //
    599   // Check USB_PORT_STAT_C_RESET bit to see if the resetting state is done.
    600   //
    601   ZeroMem (&HubPortStatus, sizeof (EFI_USB_PORT_STATUS));
    602 
    603   for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) {
    604     Status = PeiHubGetPortStatus (
    605                PeiServices,
    606                UsbIoPpi,
    607                PortNum,
    608                (UINT32 *) &HubPortStatus
    609                );
    610 
    611     if (EFI_ERROR (Status)) {
    612       return;
    613     }
    614 
    615     if (USB_BIT_IS_SET (HubPortStatus.PortChangeStatus, USB_PORT_STAT_C_RESET)) {
    616       break;
    617     }
    618 
    619     MicroSecondDelay (USB_WAIT_PORT_STS_CHANGE_STALL);
    620   }
    621 
    622   if (Index == USB_WAIT_PORT_STS_CHANGE_LOOP) {
    623     DEBUG ((EFI_D_ERROR, "PeiResetHubPort: reset not finished in time on port %d\n", PortNum));
    624     return;
    625   }
    626 
    627   //
    628   // clear reset change root port
    629   //
    630   PeiHubClearPortFeature (
    631     PeiServices,
    632     UsbIoPpi,
    633     PortNum,
    634     EfiUsbPortResetChange
    635     );
    636 
    637   MicroSecondDelay (1 * 1000);
    638 
    639   PeiHubClearPortFeature (
    640     PeiServices,
    641     UsbIoPpi,
    642     PortNum,
    643     EfiUsbPortConnectChange
    644     );
    645 
    646   //
    647   // Set port enable
    648   //
    649   PeiHubSetPortFeature (
    650     PeiServices,
    651     UsbIoPpi,
    652     PortNum,
    653     EfiUsbPortEnable
    654     );
    655 
    656   //
    657   // Clear any change status
    658   //
    659 
    660   PeiHubClearPortFeature (
    661     PeiServices,
    662     UsbIoPpi,
    663     PortNum,
    664     EfiUsbPortEnableChange
    665     );
    666 
    667   MicroSecondDelay (10 * 1000);
    668 
    669   return;
    670 }
    671