Home | History | Annotate | Download | only in EhciPei
      1 /** @file
      2 PEIM to produce gPeiUsb2HostControllerPpiGuid based on gPeiUsbControllerPpiGuid
      3 which is used to enable recovery function from USB Drivers.
      4 
      5 Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>
      6 
      7 This program and the accompanying materials
      8 are licensed and made available under the terms and conditions
      9 of the BSD License which accompanies this distribution.  The
     10 full text of the license may be found at
     11 http://opensource.org/licenses/bsd-license.php
     12 
     13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     15 
     16 **/
     17 
     18 #include "EhcPeim.h"
     19 
     20 //
     21 // Two arrays used to translate the EHCI port state (change)
     22 // to the UEFI protocol's port state (change).
     23 //
     24 USB_PORT_STATE_MAP  mUsbPortStateMap[] = {
     25   {PORTSC_CONN,     USB_PORT_STAT_CONNECTION},
     26   {PORTSC_ENABLED,  USB_PORT_STAT_ENABLE},
     27   {PORTSC_SUSPEND,  USB_PORT_STAT_SUSPEND},
     28   {PORTSC_OVERCUR,  USB_PORT_STAT_OVERCURRENT},
     29   {PORTSC_RESET,    USB_PORT_STAT_RESET},
     30   {PORTSC_POWER,    USB_PORT_STAT_POWER},
     31   {PORTSC_OWNER,    USB_PORT_STAT_OWNER}
     32 };
     33 
     34 USB_PORT_STATE_MAP  mUsbPortChangeMap[] = {
     35   {PORTSC_CONN_CHANGE,    USB_PORT_STAT_C_CONNECTION},
     36   {PORTSC_ENABLE_CHANGE,  USB_PORT_STAT_C_ENABLE},
     37   {PORTSC_OVERCUR_CHANGE, USB_PORT_STAT_C_OVERCURRENT}
     38 };
     39 
     40 /**
     41   Read Ehc Operation register.
     42 
     43   @param  Ehc       The EHCI device.
     44   @param  Offset    The operation register offset.
     45 
     46   @retval the register content read.
     47 
     48 **/
     49 UINT32
     50 EhcReadOpReg (
     51   IN  PEI_USB2_HC_DEV     *Ehc,
     52   IN  UINT32              Offset
     53   )
     54 {
     55   UINT32                  Data;
     56 
     57   ASSERT (Ehc->CapLen != 0);
     58 
     59   Data = MmioRead32 (Ehc->UsbHostControllerBaseAddress + Ehc->CapLen + Offset);
     60 
     61   return Data;
     62 }
     63 
     64 /**
     65   Write the data to the EHCI operation register.
     66 
     67   @param  Ehc       The EHCI device.
     68   @param  Offset    EHCI operation register offset.
     69   @param  Data      The data to write.
     70 
     71 **/
     72 VOID
     73 EhcWriteOpReg (
     74   IN PEI_USB2_HC_DEV      *Ehc,
     75   IN UINT32               Offset,
     76   IN UINT32               Data
     77   )
     78 {
     79 
     80   ASSERT (Ehc->CapLen != 0);
     81 
     82   MmioWrite32(Ehc->UsbHostControllerBaseAddress + Ehc->CapLen + Offset, Data);
     83 
     84 }
     85 
     86 /**
     87   Set one bit of the operational register while keeping other bits.
     88 
     89   @param  Ehc       The EHCI device.
     90   @param  Offset    The offset of the operational register.
     91   @param  Bit       The bit mask of the register to set.
     92 
     93 **/
     94 VOID
     95 EhcSetOpRegBit (
     96   IN PEI_USB2_HC_DEV      *Ehc,
     97   IN UINT32               Offset,
     98   IN UINT32               Bit
     99   )
    100 {
    101   UINT32                  Data;
    102 
    103   Data  = EhcReadOpReg (Ehc, Offset);
    104   Data |= Bit;
    105   EhcWriteOpReg (Ehc, Offset, Data);
    106 }
    107 
    108 /**
    109   Clear one bit of the operational register while keeping other bits.
    110 
    111   @param  Ehc       The EHCI device.
    112   @param  Offset    The offset of the operational register.
    113   @param  Bit       The bit mask of the register to clear.
    114 
    115 **/
    116 VOID
    117 EhcClearOpRegBit (
    118   IN PEI_USB2_HC_DEV      *Ehc,
    119   IN UINT32               Offset,
    120   IN UINT32               Bit
    121   )
    122 {
    123   UINT32                  Data;
    124 
    125   Data  = EhcReadOpReg (Ehc, Offset);
    126   Data &= ~Bit;
    127   EhcWriteOpReg (Ehc, Offset, Data);
    128 }
    129 
    130 /**
    131   Wait the operation register's bit as specified by Bit
    132   to become set (or clear).
    133 
    134   @param  Ehc           The EHCI device.
    135   @param  Offset        The offset of the operational register.
    136   @param  Bit           The bit mask of the register to wait for.
    137   @param  WaitToSet     Wait the bit to set or clear.
    138   @param  Timeout       The time to wait before abort (in millisecond).
    139 
    140   @retval EFI_SUCCESS   The bit successfully changed by host controller.
    141   @retval EFI_TIMEOUT   The time out occurred.
    142 
    143 **/
    144 EFI_STATUS
    145 EhcWaitOpRegBit (
    146   IN PEI_USB2_HC_DEV      *Ehc,
    147   IN UINT32               Offset,
    148   IN UINT32               Bit,
    149   IN BOOLEAN              WaitToSet,
    150   IN UINT32               Timeout
    151   )
    152 {
    153   UINT32                  Index;
    154 
    155   for (Index = 0; Index < Timeout / EHC_SYNC_POLL_INTERVAL + 1; Index++) {
    156     if (EHC_REG_BIT_IS_SET (Ehc, Offset, Bit) == WaitToSet) {
    157       return EFI_SUCCESS;
    158     }
    159 
    160     MicroSecondDelay (EHC_SYNC_POLL_INTERVAL);
    161   }
    162 
    163   return EFI_TIMEOUT;
    164 }
    165 
    166 /**
    167   Read EHCI capability register.
    168 
    169   @param  Ehc       The EHCI device.
    170   @param  Offset    Capability register address.
    171 
    172   @retval the register content read.
    173 
    174 **/
    175 UINT32
    176 EhcReadCapRegister (
    177   IN  PEI_USB2_HC_DEV     *Ehc,
    178   IN  UINT32              Offset
    179   )
    180 {
    181   UINT32                  Data;
    182 
    183   Data = MmioRead32(Ehc->UsbHostControllerBaseAddress + Offset);
    184 
    185   return Data;
    186 }
    187 
    188 /**
    189   Set door bell and wait it to be ACKed by host controller.
    190   This function is used to synchronize with the hardware.
    191 
    192   @param  Ehc       The EHCI device.
    193   @param  Timeout   The time to wait before abort (in millisecond, ms).
    194 
    195   @retval EFI_TIMEOUT       Time out happened while waiting door bell to set.
    196   @retval EFI_SUCCESS       Synchronized with the hardware.
    197 
    198 **/
    199 EFI_STATUS
    200 EhcSetAndWaitDoorBell (
    201   IN  PEI_USB2_HC_DEV     *Ehc,
    202   IN  UINT32              Timeout
    203   )
    204 {
    205   EFI_STATUS              Status;
    206   UINT32                  Data;
    207 
    208   EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_IAAD);
    209 
    210   Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_IAA, TRUE, Timeout);
    211 
    212   //
    213   // ACK the IAA bit in USBSTS register. Make sure other
    214   // interrupt bits are not ACKed. These bits are WC (Write Clean).
    215   //
    216   Data  = EhcReadOpReg (Ehc, EHC_USBSTS_OFFSET);
    217   Data &= ~USBSTS_INTACK_MASK;
    218   Data |= USBSTS_IAA;
    219 
    220   EhcWriteOpReg (Ehc, EHC_USBSTS_OFFSET, Data);
    221 
    222   return Status;
    223 }
    224 
    225 /**
    226   Clear all the interrutp status bits, these bits
    227   are Write-Clean.
    228 
    229   @param  Ehc       The EHCI device.
    230 
    231 **/
    232 VOID
    233 EhcAckAllInterrupt (
    234   IN  PEI_USB2_HC_DEV         *Ehc
    235   )
    236 {
    237   EhcWriteOpReg (Ehc, EHC_USBSTS_OFFSET, USBSTS_INTACK_MASK);
    238 }
    239 
    240 /**
    241   Enable the periodic schedule then wait EHC to
    242   actually enable it.
    243 
    244   @param  Ehc       The EHCI device.
    245   @param  Timeout   The time to wait before abort (in millisecond, ms).
    246 
    247   @retval EFI_TIMEOUT       Time out happened while enabling periodic schedule.
    248   @retval EFI_SUCCESS       The periodical schedule is enabled.
    249 
    250 **/
    251 EFI_STATUS
    252 EhcEnablePeriodSchd (
    253   IN PEI_USB2_HC_DEV      *Ehc,
    254   IN UINT32               Timeout
    255   )
    256 {
    257   EFI_STATUS              Status;
    258 
    259   EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_ENABLE_PERIOD);
    260 
    261   Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_PERIOD_ENABLED, TRUE, Timeout);
    262   return Status;
    263 }
    264 
    265 /**
    266   Enable asynchrounous schedule.
    267 
    268   @param  Ehc       The EHCI device.
    269   @param  Timeout   Time to wait before abort.
    270 
    271   @retval EFI_SUCCESS       The EHCI asynchronous schedule is enabled.
    272   @retval Others            Failed to enable the asynchronous scheudle.
    273 
    274 **/
    275 EFI_STATUS
    276 EhcEnableAsyncSchd (
    277   IN PEI_USB2_HC_DEV      *Ehc,
    278   IN UINT32               Timeout
    279   )
    280 {
    281   EFI_STATUS              Status;
    282 
    283   EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_ENABLE_ASYNC);
    284 
    285   Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_ASYNC_ENABLED, TRUE, Timeout);
    286   return Status;
    287 }
    288 
    289 /**
    290   Check whether Ehc is halted.
    291 
    292   @param  Ehc       The EHCI device.
    293 
    294   @retval TRUE      The controller is halted.
    295   @retval FALSE     The controller isn't halted.
    296 
    297 **/
    298 BOOLEAN
    299 EhcIsHalt (
    300   IN PEI_USB2_HC_DEV      *Ehc
    301   )
    302 {
    303   return EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT);
    304 }
    305 
    306 /**
    307   Check whether system error occurred.
    308 
    309   @param  Ehc       The EHCI device.
    310 
    311   @retval TRUE      System error happened.
    312   @retval FALSE     No system error.
    313 
    314 **/
    315 BOOLEAN
    316 EhcIsSysError (
    317   IN PEI_USB2_HC_DEV      *Ehc
    318   )
    319 {
    320   return EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_SYS_ERROR);
    321 }
    322 
    323 /**
    324   Reset the host controller.
    325 
    326   @param  Ehc             The EHCI device.
    327   @param  Timeout         Time to wait before abort (in millisecond, ms).
    328 
    329   @retval EFI_TIMEOUT     The transfer failed due to time out.
    330   @retval Others          Failed to reset the host.
    331 
    332 **/
    333 EFI_STATUS
    334 EhcResetHC (
    335   IN PEI_USB2_HC_DEV      *Ehc,
    336   IN UINT32               Timeout
    337   )
    338 {
    339   EFI_STATUS              Status;
    340 
    341   //
    342   // Host can only be reset when it is halt. If not so, halt it
    343   //
    344   if (!EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT)) {
    345     Status = EhcHaltHC (Ehc, Timeout);
    346 
    347     if (EFI_ERROR (Status)) {
    348       return Status;
    349     }
    350   }
    351 
    352   EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RESET);
    353   Status = EhcWaitOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RESET, FALSE, Timeout);
    354   return Status;
    355 }
    356 
    357 /**
    358   Halt the host controller.
    359 
    360   @param  Ehc             The EHCI device.
    361   @param  Timeout         Time to wait before abort.
    362 
    363   @retval EFI_TIMEOUT     Failed to halt the controller before Timeout.
    364   @retval EFI_SUCCESS     The EHCI is halt.
    365 
    366 **/
    367 EFI_STATUS
    368 EhcHaltHC (
    369   IN PEI_USB2_HC_DEV     *Ehc,
    370   IN UINT32              Timeout
    371   )
    372 {
    373   EFI_STATUS              Status;
    374 
    375   EhcClearOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RUN);
    376   Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT, TRUE, Timeout);
    377   return Status;
    378 }
    379 
    380 /**
    381   Set the EHCI to run.
    382 
    383   @param  Ehc             The EHCI device.
    384   @param  Timeout         Time to wait before abort.
    385 
    386   @retval EFI_SUCCESS     The EHCI is running.
    387   @retval Others          Failed to set the EHCI to run.
    388 
    389 **/
    390 EFI_STATUS
    391 EhcRunHC (
    392   IN PEI_USB2_HC_DEV      *Ehc,
    393   IN UINT32               Timeout
    394   )
    395 {
    396   EFI_STATUS              Status;
    397 
    398   EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RUN);
    399   Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT, FALSE, Timeout);
    400   return Status;
    401 }
    402 
    403 /**
    404   Power On All EHCI Ports.
    405 
    406   @param  Ehc             The EHCI device.
    407 
    408 **/
    409 VOID
    410 EhcPowerOnAllPorts (
    411   IN PEI_USB2_HC_DEV          *Ehc
    412   )
    413 {
    414   UINT8 PortNumber;
    415   UINT8 Index;
    416 
    417   PortNumber = (UINT8)(Ehc->HcStructParams & HCSP_NPORTS);
    418   for (Index = 0; Index < PortNumber; Index++) {
    419     EhcSetOpRegBit (Ehc, EHC_PORT_STAT_OFFSET + 4 * Index, PORTSC_POWER);
    420   }
    421 }
    422 
    423 /**
    424   Initialize the HC hardware.
    425   EHCI spec lists the five things to do to initialize the hardware.
    426   1. Program CTRLDSSEGMENT.
    427   2. Set USBINTR to enable interrupts.
    428   3. Set periodic list base.
    429   4. Set USBCMD, interrupt threshold, frame list size etc.
    430   5. Write 1 to CONFIGFLAG to route all ports to EHCI.
    431 
    432   @param  Ehc             The EHCI device.
    433 
    434   @retval EFI_SUCCESS     The EHCI has come out of halt state.
    435   @retval EFI_TIMEOUT     Time out happened.
    436 
    437 **/
    438 EFI_STATUS
    439 EhcInitHC (
    440   IN PEI_USB2_HC_DEV      *Ehc
    441   )
    442 {
    443   EFI_STATUS              Status;
    444   EFI_PHYSICAL_ADDRESS        TempPtr;
    445   UINTN               PageNumber;
    446 
    447   ASSERT (EhcIsHalt (Ehc));
    448 
    449   //
    450   // Allocate the periodic frame and associated memeory
    451   // management facilities if not already done.
    452   //
    453   if (Ehc->PeriodFrame != NULL) {
    454     EhcFreeSched (Ehc);
    455   }
    456   PageNumber =  sizeof(PEI_URB)/PAGESIZE +1;
    457   Status = PeiServicesAllocatePages (
    458              EfiBootServicesCode,
    459              PageNumber,
    460              &TempPtr
    461              );
    462   Ehc->Urb = (PEI_URB *) ((UINTN) TempPtr);
    463   if (Ehc->Urb  == NULL) {
    464     return Status;
    465   }
    466 
    467   EhcPowerOnAllPorts (Ehc);
    468   MicroSecondDelay (EHC_ROOT_PORT_RECOVERY_STALL);
    469 
    470   Status = EhcInitSched (Ehc);
    471 
    472   if (EFI_ERROR (Status)) {
    473     return Status;
    474   }
    475   //
    476   // 1. Program the CTRLDSSEGMENT register with the high 32 bit addr
    477   //
    478   EhcWriteOpReg (Ehc, EHC_CTRLDSSEG_OFFSET, Ehc->High32bitAddr);
    479 
    480   //
    481   // 2. Clear USBINTR to disable all the interrupt. UEFI works by polling
    482   //
    483   EhcWriteOpReg (Ehc, EHC_USBINTR_OFFSET, 0);
    484 
    485   //
    486   // 3. Program periodic frame list, already done in EhcInitSched
    487   // 4. Start the Host Controller
    488   //
    489   EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RUN);
    490 
    491   //
    492   // 5. Set all ports routing to EHC
    493   //
    494   EhcSetOpRegBit (Ehc, EHC_CONFIG_FLAG_OFFSET, CONFIGFLAG_ROUTE_EHC);
    495 
    496   //
    497   // Wait roothub port power stable
    498   //
    499   MicroSecondDelay (EHC_ROOT_PORT_RECOVERY_STALL);
    500 
    501   Status = EhcEnablePeriodSchd (Ehc, EHC_GENERIC_TIMEOUT);
    502 
    503   if (EFI_ERROR (Status)) {
    504     return Status;
    505   }
    506 
    507   Status = EhcEnableAsyncSchd (Ehc, EHC_GENERIC_TIMEOUT);
    508 
    509   if (EFI_ERROR (Status)) {
    510     return Status;
    511   }
    512 
    513   return EFI_SUCCESS;
    514 }
    515 
    516 /**
    517   Submits bulk transfer to a bulk endpoint of a USB device.
    518 
    519   @param  PeiServices           The pointer of EFI_PEI_SERVICES.
    520   @param  This                  The pointer of PEI_USB2_HOST_CONTROLLER_PPI.
    521   @param  DeviceAddress         Target device address.
    522   @param  EndPointAddress       Endpoint number and its direction in bit 7.
    523   @param  DeviceSpeed           Device speed, Low speed device doesn't support
    524                                 bulk transfer.
    525   @param  MaximumPacketLength   Maximum packet size the endpoint is capable of
    526                                 sending or receiving.
    527   @param  Data                  Array of pointers to the buffers of data to transmit
    528                                 from or receive into.
    529   @param  DataLength            The lenght of the data buffer.
    530   @param  DataToggle            On input, the initial data toggle for the transfer;
    531                                 On output, it is updated to to next data toggle to use of
    532                                 the subsequent bulk transfer.
    533   @param  TimeOut               Indicates the maximum time, in millisecond, which the
    534                                 transfer is allowed to complete.
    535                                 If Timeout is 0, then the caller must wait for the function
    536                                 to be completed until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.
    537   @param  Translator            A pointr to the transaction translator data.
    538   @param  TransferResult        A pointer to the detailed result information of the
    539                                 bulk transfer.
    540 
    541   @retval EFI_SUCCESS           The transfer was completed successfully.
    542   @retval EFI_OUT_OF_RESOURCES  The transfer failed due to lack of resource.
    543   @retval EFI_INVALID_PARAMETER Parameters are invalid.
    544   @retval EFI_TIMEOUT           The transfer failed due to timeout.
    545   @retval EFI_DEVICE_ERROR      The transfer failed due to host controller error.
    546 
    547 **/
    548 EFI_STATUS
    549 EFIAPI
    550 EhcBulkTransfer (
    551   IN EFI_PEI_SERVICES                     **PeiServices,
    552   IN PEI_USB2_HOST_CONTROLLER_PPI         *This,
    553   IN  UINT8                               DeviceAddress,
    554   IN  UINT8                               EndPointAddress,
    555   IN  UINT8                               DeviceSpeed,
    556   IN  UINTN                               MaximumPacketLength,
    557   IN  OUT VOID                            *Data[EFI_USB_MAX_BULK_BUFFER_NUM],
    558   IN  OUT UINTN                           *DataLength,
    559   IN  OUT UINT8                           *DataToggle,
    560   IN  UINTN                               TimeOut,
    561   IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
    562   OUT UINT32                              *TransferResult
    563   )
    564 {
    565   PEI_USB2_HC_DEV         *Ehc;
    566   PEI_URB                 *Urb;
    567   EFI_STATUS              Status;
    568 
    569   //
    570   // Validate the parameters
    571   //
    572   if ((DataLength == NULL) || (*DataLength == 0) ||
    573       (Data == NULL) || (Data[0] == NULL) || (TransferResult == NULL)) {
    574     return EFI_INVALID_PARAMETER;
    575   }
    576 
    577   if ((*DataToggle != 0) && (*DataToggle != 1)) {
    578     return EFI_INVALID_PARAMETER;
    579   }
    580 
    581   if ((DeviceSpeed == EFI_USB_SPEED_LOW) ||
    582       ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||
    583       ((EFI_USB_SPEED_HIGH == DeviceSpeed) && (MaximumPacketLength > 512))) {
    584     return EFI_INVALID_PARAMETER;
    585   }
    586 
    587   Ehc =PEI_RECOVERY_USB_EHC_DEV_FROM_EHCI_THIS(This);
    588   *TransferResult = EFI_USB_ERR_SYSTEM;
    589   Status          = EFI_DEVICE_ERROR;
    590 
    591   if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {
    592     EhcAckAllInterrupt (Ehc);
    593     goto ON_EXIT;
    594   }
    595 
    596   EhcAckAllInterrupt (Ehc);
    597 
    598   //
    599   // Create a new URB, insert it into the asynchronous
    600   // schedule list, then poll the execution status.
    601   //
    602   Urb = EhcCreateUrb (
    603           Ehc,
    604           DeviceAddress,
    605           EndPointAddress,
    606           DeviceSpeed,
    607           *DataToggle,
    608           MaximumPacketLength,
    609           Translator,
    610           EHC_BULK_TRANSFER,
    611           NULL,
    612           Data[0],
    613           *DataLength,
    614           NULL,
    615           NULL,
    616           1
    617           );
    618 
    619   if (Urb == NULL) {
    620     Status = EFI_OUT_OF_RESOURCES;
    621     goto ON_EXIT;
    622   }
    623 
    624   EhcLinkQhToAsync (Ehc, Urb->Qh);
    625   Status = EhcExecTransfer (Ehc, Urb, TimeOut);
    626   EhcUnlinkQhFromAsync (Ehc, Urb->Qh);
    627 
    628   *TransferResult = Urb->Result;
    629   *DataLength     = Urb->Completed;
    630   *DataToggle     = Urb->DataToggle;
    631 
    632   if (*TransferResult == EFI_USB_NOERROR) {
    633     Status = EFI_SUCCESS;
    634   }
    635 
    636   EhcAckAllInterrupt (Ehc);
    637   EhcFreeUrb (Ehc, Urb);
    638 
    639 ON_EXIT:
    640   return Status;
    641 }
    642 
    643 /**
    644   Retrieves the number of root hub ports.
    645 
    646   @param[in]  PeiServices   The pointer to the PEI Services Table.
    647   @param[in]  This          The pointer to this instance of the
    648                             PEI_USB2_HOST_CONTROLLER_PPI.
    649   @param[out] PortNumber    The pointer to the number of the root hub ports.
    650 
    651   @retval EFI_SUCCESS           The port number was retrieved successfully.
    652   @retval EFI_INVALID_PARAMETER PortNumber is NULL.
    653 
    654 **/
    655 EFI_STATUS
    656 EFIAPI
    657 EhcGetRootHubPortNumber (
    658   IN EFI_PEI_SERVICES                       **PeiServices,
    659   IN PEI_USB2_HOST_CONTROLLER_PPI           *This,
    660   OUT UINT8                                 *PortNumber
    661   )
    662 {
    663 
    664   PEI_USB2_HC_DEV             *EhcDev;
    665   EhcDev = PEI_RECOVERY_USB_EHC_DEV_FROM_EHCI_THIS (This);
    666 
    667   if (PortNumber == NULL) {
    668     return EFI_INVALID_PARAMETER;
    669   }
    670 
    671   *PortNumber = (UINT8)(EhcDev->HcStructParams & HCSP_NPORTS);
    672   return EFI_SUCCESS;
    673 
    674 }
    675 
    676 /**
    677   Clears a feature for the specified root hub port.
    678 
    679   @param  PeiServices           The pointer of EFI_PEI_SERVICES.
    680   @param  This                  The pointer of PEI_USB2_HOST_CONTROLLER_PPI.
    681   @param  PortNumber            Specifies the root hub port whose feature
    682                                 is requested to be cleared.
    683   @param  PortFeature           Indicates the feature selector associated with the
    684                                 feature clear request.
    685 
    686   @retval EFI_SUCCESS            The feature specified by PortFeature was cleared
    687                                  for the USB root hub port specified by PortNumber.
    688   @retval EFI_INVALID_PARAMETER  PortNumber is invalid or PortFeature is invalid.
    689 
    690 **/
    691 EFI_STATUS
    692 EFIAPI
    693 EhcClearRootHubPortFeature (
    694   IN EFI_PEI_SERVICES                       **PeiServices,
    695   IN PEI_USB2_HOST_CONTROLLER_PPI           *This,
    696   IN  UINT8                 PortNumber,
    697   IN  EFI_USB_PORT_FEATURE  PortFeature
    698   )
    699 {
    700   PEI_USB2_HC_DEV         *Ehc;
    701   UINT32                  Offset;
    702   UINT32                  State;
    703   UINT32                  TotalPort;
    704   EFI_STATUS              Status;
    705 
    706   Ehc       = PEI_RECOVERY_USB_EHC_DEV_FROM_EHCI_THIS (This);
    707   Status    = EFI_SUCCESS;
    708 
    709   TotalPort = (Ehc->HcStructParams & HCSP_NPORTS);
    710 
    711   if (PortNumber >= TotalPort) {
    712     Status = EFI_INVALID_PARAMETER;
    713     goto ON_EXIT;
    714   }
    715 
    716   Offset  = EHC_PORT_STAT_OFFSET + (4 * PortNumber);
    717   State   = EhcReadOpReg (Ehc, Offset);
    718   State &= ~PORTSC_CHANGE_MASK;
    719 
    720   switch (PortFeature) {
    721   case EfiUsbPortEnable:
    722     //
    723     // Clear PORT_ENABLE feature means disable port.
    724     //
    725     State &= ~PORTSC_ENABLED;
    726     EhcWriteOpReg (Ehc, Offset, State);
    727     break;
    728 
    729   case EfiUsbPortSuspend:
    730     //
    731     // A write of zero to this bit is ignored by the host
    732     // controller. The host controller will unconditionally
    733     // set this bit to a zero when:
    734     //   1. software sets the Forct Port Resume bit to a zero from a one.
    735     //   2. software sets the Port Reset bit to a one frome a zero.
    736     //
    737     State &= ~PORSTSC_RESUME;
    738     EhcWriteOpReg (Ehc, Offset, State);
    739     break;
    740 
    741   case EfiUsbPortReset:
    742     //
    743     // Clear PORT_RESET means clear the reset signal.
    744     //
    745     State &= ~PORTSC_RESET;
    746     EhcWriteOpReg (Ehc, Offset, State);
    747     break;
    748 
    749   case EfiUsbPortOwner:
    750     //
    751     // Clear port owner means this port owned by EHC
    752     //
    753     State &= ~PORTSC_OWNER;
    754     EhcWriteOpReg (Ehc, Offset, State);
    755     break;
    756 
    757   case EfiUsbPortConnectChange:
    758     //
    759     // Clear connect status change
    760     //
    761     State |= PORTSC_CONN_CHANGE;
    762     EhcWriteOpReg (Ehc, Offset, State);
    763     break;
    764 
    765   case EfiUsbPortEnableChange:
    766     //
    767     // Clear enable status change
    768     //
    769     State |= PORTSC_ENABLE_CHANGE;
    770     EhcWriteOpReg (Ehc, Offset, State);
    771     break;
    772 
    773   case EfiUsbPortOverCurrentChange:
    774     //
    775     // Clear PortOverCurrent change
    776     //
    777     State |= PORTSC_OVERCUR_CHANGE;
    778     EhcWriteOpReg (Ehc, Offset, State);
    779     break;
    780 
    781   case EfiUsbPortPower:
    782   case EfiUsbPortSuspendChange:
    783   case EfiUsbPortResetChange:
    784     //
    785     // Not supported or not related operation
    786     //
    787     break;
    788 
    789   default:
    790     Status = EFI_INVALID_PARAMETER;
    791     break;
    792   }
    793 
    794 ON_EXIT:
    795   return Status;
    796 }
    797 
    798 /**
    799   Sets a feature for the specified root hub port.
    800 
    801   @param  PeiServices           The pointer of EFI_PEI_SERVICES
    802   @param  This                  The pointer of PEI_USB2_HOST_CONTROLLER_PPI
    803   @param  PortNumber            Root hub port to set.
    804   @param  PortFeature           Feature to set.
    805 
    806   @retval EFI_SUCCESS            The feature specified by PortFeature was set.
    807   @retval EFI_INVALID_PARAMETER  PortNumber is invalid or PortFeature is invalid.
    808   @retval EFI_TIMEOUT            The time out occurred.
    809 
    810 **/
    811 EFI_STATUS
    812 EFIAPI
    813 EhcSetRootHubPortFeature (
    814   IN EFI_PEI_SERVICES                       **PeiServices,
    815   IN PEI_USB2_HOST_CONTROLLER_PPI           *This,
    816   IN UINT8                                  PortNumber,
    817   IN EFI_USB_PORT_FEATURE                   PortFeature
    818   )
    819 {
    820   PEI_USB2_HC_DEV         *Ehc;
    821   UINT32                  Offset;
    822   UINT32                  State;
    823   UINT32                  TotalPort;
    824   EFI_STATUS              Status;
    825 
    826   Ehc       = PEI_RECOVERY_USB_EHC_DEV_FROM_EHCI_THIS (This);
    827   Status    = EFI_SUCCESS;
    828 
    829   TotalPort = (Ehc->HcStructParams & HCSP_NPORTS);
    830 
    831   if (PortNumber >= TotalPort) {
    832     Status = EFI_INVALID_PARAMETER;
    833     goto ON_EXIT;
    834   }
    835 
    836   Offset  = (UINT32) (EHC_PORT_STAT_OFFSET + (4 * PortNumber));
    837   State   = EhcReadOpReg (Ehc, Offset);
    838 
    839   //
    840   // Mask off the port status change bits, these bits are
    841   // write clean bit
    842   //
    843   State &= ~PORTSC_CHANGE_MASK;
    844 
    845   switch (PortFeature) {
    846   case EfiUsbPortEnable:
    847     //
    848     // Sofeware can't set this bit, Port can only be enable by
    849     // EHCI as a part of the reset and enable
    850     //
    851     State |= PORTSC_ENABLED;
    852     EhcWriteOpReg (Ehc, Offset, State);
    853     break;
    854 
    855   case EfiUsbPortSuspend:
    856     State |= PORTSC_SUSPEND;
    857     EhcWriteOpReg (Ehc, Offset, State);
    858     break;
    859 
    860   case EfiUsbPortReset:
    861     //
    862     // Make sure Host Controller not halt before reset it
    863     //
    864     if (EhcIsHalt (Ehc)) {
    865       Status = EhcRunHC (Ehc, EHC_GENERIC_TIMEOUT);
    866 
    867       if (EFI_ERROR (Status)) {
    868         break;
    869       }
    870     }
    871 
    872     //
    873     // Set one to PortReset bit must also set zero to PortEnable bit
    874     //
    875     State |= PORTSC_RESET;
    876     State &= ~PORTSC_ENABLED;
    877     EhcWriteOpReg (Ehc, Offset, State);
    878     break;
    879 
    880   case EfiUsbPortPower:
    881     //
    882     // Not supported, ignore the operation
    883     //
    884     Status = EFI_SUCCESS;
    885     break;
    886 
    887   case EfiUsbPortOwner:
    888     State |= PORTSC_OWNER;
    889     EhcWriteOpReg (Ehc, Offset, State);
    890     break;
    891 
    892   default:
    893     Status = EFI_INVALID_PARAMETER;
    894   }
    895 
    896 ON_EXIT:
    897   return Status;
    898 }
    899 
    900 /**
    901   Retrieves the current status of a USB root hub port.
    902 
    903   @param  PeiServices            The pointer of EFI_PEI_SERVICES.
    904   @param  This                   The pointer of PEI_USB2_HOST_CONTROLLER_PPI.
    905   @param  PortNumber             The root hub port to retrieve the state from.
    906   @param  PortStatus             Variable to receive the port state.
    907 
    908   @retval EFI_SUCCESS            The status of the USB root hub port specified.
    909                                  by PortNumber was returned in PortStatus.
    910   @retval EFI_INVALID_PARAMETER  PortNumber is invalid.
    911 
    912 **/
    913 EFI_STATUS
    914 EFIAPI
    915 EhcGetRootHubPortStatus (
    916   IN EFI_PEI_SERVICES                       **PeiServices,
    917   IN PEI_USB2_HOST_CONTROLLER_PPI           *This,
    918   IN  UINT8                                 PortNumber,
    919   OUT EFI_USB_PORT_STATUS                   *PortStatus
    920   )
    921 {
    922   PEI_USB2_HC_DEV         *Ehc;
    923   UINT32                  Offset;
    924   UINT32                  State;
    925   UINT32                  TotalPort;
    926   UINTN                   Index;
    927   UINTN                   MapSize;
    928   EFI_STATUS              Status;
    929 
    930   if (PortStatus == NULL) {
    931     return EFI_INVALID_PARAMETER;
    932   }
    933 
    934   Ehc       =  PEI_RECOVERY_USB_EHC_DEV_FROM_EHCI_THIS(This);
    935   Status    = EFI_SUCCESS;
    936 
    937   TotalPort = (Ehc->HcStructParams & HCSP_NPORTS);
    938 
    939   if (PortNumber >= TotalPort) {
    940     Status = EFI_INVALID_PARAMETER;
    941     goto ON_EXIT;
    942   }
    943 
    944   Offset                        = (UINT32) (EHC_PORT_STAT_OFFSET + (4 * PortNumber));
    945   PortStatus->PortStatus        = 0;
    946   PortStatus->PortChangeStatus  = 0;
    947 
    948   State                         = EhcReadOpReg (Ehc, Offset);
    949 
    950   //
    951   // Identify device speed. If in K state, it is low speed.
    952   // If the port is enabled after reset, the device is of
    953   // high speed. The USB bus driver should retrieve the actual
    954   // port speed after reset.
    955   //
    956   if (EHC_BIT_IS_SET (State, PORTSC_LINESTATE_K)) {
    957     PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;
    958 
    959   } else if (EHC_BIT_IS_SET (State, PORTSC_ENABLED)) {
    960     PortStatus->PortStatus |= USB_PORT_STAT_HIGH_SPEED;
    961   }
    962 
    963   //
    964   // Convert the EHCI port/port change state to UEFI status
    965   //
    966   MapSize = sizeof (mUsbPortStateMap) / sizeof (USB_PORT_STATE_MAP);
    967 
    968   for (Index = 0; Index < MapSize; Index++) {
    969     if (EHC_BIT_IS_SET (State, mUsbPortStateMap[Index].HwState)) {
    970       PortStatus->PortStatus = (UINT16) (PortStatus->PortStatus | mUsbPortStateMap[Index].UefiState);
    971     }
    972   }
    973 
    974   MapSize = sizeof (mUsbPortChangeMap) / sizeof (USB_PORT_STATE_MAP);
    975 
    976   for (Index = 0; Index < MapSize; Index++) {
    977     if (EHC_BIT_IS_SET (State, mUsbPortChangeMap[Index].HwState)) {
    978       PortStatus->PortChangeStatus = (UINT16) (PortStatus->PortChangeStatus | mUsbPortChangeMap[Index].UefiState);
    979     }
    980   }
    981 
    982 ON_EXIT:
    983   return Status;
    984 }
    985 
    986 /**
    987   Submits control transfer to a target USB device.
    988 
    989   @param  PeiServices            The pointer of EFI_PEI_SERVICES.
    990   @param  This                   The pointer of PEI_USB2_HOST_CONTROLLER_PPI.
    991   @param  DeviceAddress          The target device address.
    992   @param  DeviceSpeed            Target device speed.
    993   @param  MaximumPacketLength    Maximum packet size the default control transfer
    994                                  endpoint is capable of sending or receiving.
    995   @param  Request                USB device request to send.
    996   @param  TransferDirection      Specifies the data direction for the data stage.
    997   @param  Data                   Data buffer to be transmitted or received from USB device.
    998   @param  DataLength             The size (in bytes) of the data buffer.
    999   @param  TimeOut                Indicates the maximum timeout, in millisecond.
   1000                                  If Timeout is 0, then the caller must wait for the function
   1001                                  to be completed until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.
   1002   @param  Translator             Transaction translator to be used by this device.
   1003   @param  TransferResult         Return the result of this control transfer.
   1004 
   1005   @retval EFI_SUCCESS            Transfer was completed successfully.
   1006   @retval EFI_OUT_OF_RESOURCES   The transfer failed due to lack of resources.
   1007   @retval EFI_INVALID_PARAMETER  Some parameters are invalid.
   1008   @retval EFI_TIMEOUT            Transfer failed due to timeout.
   1009   @retval EFI_DEVICE_ERROR       Transfer failed due to host controller or device error.
   1010 
   1011 **/
   1012 EFI_STATUS
   1013 EFIAPI
   1014 EhcControlTransfer (
   1015   IN  EFI_PEI_SERVICES                    **PeiServices,
   1016   IN  PEI_USB2_HOST_CONTROLLER_PPI        *This,
   1017   IN  UINT8                               DeviceAddress,
   1018   IN  UINT8                               DeviceSpeed,
   1019   IN  UINTN                               MaximumPacketLength,
   1020   IN  EFI_USB_DEVICE_REQUEST              *Request,
   1021   IN  EFI_USB_DATA_DIRECTION              TransferDirection,
   1022   IN  OUT VOID                            *Data,
   1023   IN  OUT UINTN                           *DataLength,
   1024   IN  UINTN                               TimeOut,
   1025   IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
   1026   OUT UINT32                              *TransferResult
   1027   )
   1028 {
   1029   PEI_USB2_HC_DEV         *Ehc;
   1030   PEI_URB                 *Urb;
   1031   UINT8                   Endpoint;
   1032   EFI_STATUS              Status;
   1033 
   1034   //
   1035   // Validate parameters
   1036   //
   1037   if ((Request == NULL) || (TransferResult == NULL)) {
   1038     return EFI_INVALID_PARAMETER;
   1039   }
   1040 
   1041   if ((TransferDirection != EfiUsbDataIn) &&
   1042       (TransferDirection != EfiUsbDataOut) &&
   1043       (TransferDirection != EfiUsbNoData)) {
   1044     return EFI_INVALID_PARAMETER;
   1045   }
   1046 
   1047   if ((TransferDirection == EfiUsbNoData) &&
   1048       ((Data != NULL) || (*DataLength != 0))) {
   1049     return EFI_INVALID_PARAMETER;
   1050   }
   1051 
   1052   if ((TransferDirection != EfiUsbNoData) &&
   1053      ((Data == NULL) || (*DataLength == 0))) {
   1054     return EFI_INVALID_PARAMETER;
   1055   }
   1056 
   1057   if ((MaximumPacketLength != 8)  && (MaximumPacketLength != 16) &&
   1058       (MaximumPacketLength != 32) && (MaximumPacketLength != 64)) {
   1059     return EFI_INVALID_PARAMETER;
   1060   }
   1061 
   1062 
   1063   if ((DeviceSpeed == EFI_USB_SPEED_LOW) ||
   1064       ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||
   1065       ((EFI_USB_SPEED_HIGH == DeviceSpeed) && (MaximumPacketLength > 512))) {
   1066     return EFI_INVALID_PARAMETER;
   1067   }
   1068 
   1069   Ehc             = PEI_RECOVERY_USB_EHC_DEV_FROM_EHCI_THIS (This);
   1070 
   1071   Status          = EFI_DEVICE_ERROR;
   1072   *TransferResult = EFI_USB_ERR_SYSTEM;
   1073 
   1074   if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {
   1075     EhcAckAllInterrupt (Ehc);
   1076     goto ON_EXIT;
   1077   }
   1078 
   1079   EhcAckAllInterrupt (Ehc);
   1080 
   1081   //
   1082   // Create a new URB, insert it into the asynchronous
   1083   // schedule list, then poll the execution status.
   1084   //
   1085   //
   1086   // Encode the direction in address, although default control
   1087   // endpoint is bidirectional. EhcCreateUrb expects this
   1088   // combination of Ep addr and its direction.
   1089   //
   1090   Endpoint = (UINT8) (0 | ((TransferDirection == EfiUsbDataIn) ? 0x80 : 0));
   1091   Urb = EhcCreateUrb (
   1092           Ehc,
   1093           DeviceAddress,
   1094           Endpoint,
   1095           DeviceSpeed,
   1096           0,
   1097           MaximumPacketLength,
   1098           Translator,
   1099           EHC_CTRL_TRANSFER,
   1100           Request,
   1101           Data,
   1102           *DataLength,
   1103           NULL,
   1104           NULL,
   1105           1
   1106           );
   1107 
   1108   if (Urb == NULL) {
   1109     Status = EFI_OUT_OF_RESOURCES;
   1110     goto ON_EXIT;
   1111   }
   1112 
   1113   EhcLinkQhToAsync (Ehc, Urb->Qh);
   1114   Status = EhcExecTransfer (Ehc, Urb, TimeOut);
   1115   EhcUnlinkQhFromAsync (Ehc, Urb->Qh);
   1116 
   1117   //
   1118   // Get the status from URB. The result is updated in EhcCheckUrbResult
   1119   // which is called by EhcExecTransfer
   1120   //
   1121   *TransferResult = Urb->Result;
   1122   *DataLength     = Urb->Completed;
   1123 
   1124   if (*TransferResult == EFI_USB_NOERROR) {
   1125     Status = EFI_SUCCESS;
   1126   }
   1127 
   1128   EhcAckAllInterrupt (Ehc);
   1129   EhcFreeUrb (Ehc, Urb);
   1130 
   1131 ON_EXIT:
   1132   return Status;
   1133 }
   1134 
   1135 /**
   1136   @param  FileHandle  Handle of the file being invoked.
   1137   @param  PeiServices Describes the list of possible PEI Services.
   1138 
   1139   @retval EFI_SUCCESS            PPI successfully installed.
   1140 
   1141 **/
   1142 EFI_STATUS
   1143 EFIAPI
   1144 EhcPeimEntry (
   1145   IN EFI_PEI_FILE_HANDLE     FileHandle,
   1146   IN CONST EFI_PEI_SERVICES  **PeiServices
   1147   )
   1148 {
   1149   PEI_USB_CONTROLLER_PPI      *ChipSetUsbControllerPpi;
   1150   EFI_STATUS                  Status;
   1151   UINT8                       Index;
   1152   UINTN                       ControllerType;
   1153   UINTN                       BaseAddress;
   1154   UINTN                       MemPages;
   1155   PEI_USB2_HC_DEV             *EhcDev;
   1156   EFI_PHYSICAL_ADDRESS        TempPtr;
   1157 
   1158   //
   1159   // Shadow this PEIM to run from memory
   1160   //
   1161   if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) {
   1162     return EFI_SUCCESS;
   1163   }
   1164 
   1165   Status = PeiServicesLocatePpi (
   1166              &gPeiUsbControllerPpiGuid,
   1167              0,
   1168              NULL,
   1169              (VOID **) &ChipSetUsbControllerPpi
   1170              );
   1171   if (EFI_ERROR (Status)) {
   1172     return EFI_UNSUPPORTED;
   1173   }
   1174 
   1175   Index = 0;
   1176   while (TRUE) {
   1177     Status = ChipSetUsbControllerPpi->GetUsbController (
   1178                                         (EFI_PEI_SERVICES **) PeiServices,
   1179                                         ChipSetUsbControllerPpi,
   1180                                         Index,
   1181                                         &ControllerType,
   1182                                         &BaseAddress
   1183                                         );
   1184     //
   1185     // When status is error, meant no controller is found
   1186     //
   1187     if (EFI_ERROR (Status)) {
   1188       break;
   1189     }
   1190 
   1191     //
   1192     // This PEIM is for UHC type controller.
   1193     //
   1194     if (ControllerType != PEI_EHCI_CONTROLLER) {
   1195       Index++;
   1196       continue;
   1197     }
   1198 
   1199     MemPages = sizeof (PEI_USB2_HC_DEV) / PAGESIZE + 1;
   1200     Status = PeiServicesAllocatePages (
   1201                EfiBootServicesCode,
   1202                MemPages,
   1203                &TempPtr
   1204                );
   1205     if (EFI_ERROR (Status)) {
   1206       return EFI_OUT_OF_RESOURCES;
   1207     }
   1208 
   1209     ZeroMem((VOID *)(UINTN)TempPtr, MemPages*PAGESIZE);
   1210     EhcDev = (PEI_USB2_HC_DEV *) ((UINTN) TempPtr);
   1211 
   1212     EhcDev->Signature = USB2_HC_DEV_SIGNATURE;
   1213 
   1214     EhcDev->UsbHostControllerBaseAddress = (UINT32) BaseAddress;
   1215 
   1216 
   1217     EhcDev->HcStructParams = EhcReadCapRegister (EhcDev, EHC_HCSPARAMS_OFFSET);
   1218     EhcDev->HcCapParams    = EhcReadCapRegister (EhcDev, EHC_HCCPARAMS_OFFSET);
   1219     EhcDev->CapLen         = EhcReadCapRegister (EhcDev, EHC_CAPLENGTH_OFFSET) & 0x0FF;
   1220     //
   1221     // Initialize Uhc's hardware
   1222     //
   1223     Status = InitializeUsbHC (EhcDev);
   1224     if (EFI_ERROR (Status)) {
   1225       return Status;
   1226     }
   1227 
   1228     EhcDev->Usb2HostControllerPpi.ControlTransfer          = EhcControlTransfer;
   1229     EhcDev->Usb2HostControllerPpi.BulkTransfer             = EhcBulkTransfer;
   1230     EhcDev->Usb2HostControllerPpi.GetRootHubPortNumber     = EhcGetRootHubPortNumber;
   1231     EhcDev->Usb2HostControllerPpi.GetRootHubPortStatus     = EhcGetRootHubPortStatus;
   1232     EhcDev->Usb2HostControllerPpi.SetRootHubPortFeature    = EhcSetRootHubPortFeature;
   1233     EhcDev->Usb2HostControllerPpi.ClearRootHubPortFeature  = EhcClearRootHubPortFeature;
   1234 
   1235     EhcDev->PpiDescriptor.Flags = (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
   1236     EhcDev->PpiDescriptor.Guid = &gPeiUsb2HostControllerPpiGuid;
   1237     EhcDev->PpiDescriptor.Ppi = &EhcDev->Usb2HostControllerPpi;
   1238 
   1239     Status = PeiServicesInstallPpi (&EhcDev->PpiDescriptor);
   1240     if (EFI_ERROR (Status)) {
   1241       Index++;
   1242       continue;
   1243     }
   1244 
   1245     Index++;
   1246   }
   1247 
   1248   return EFI_SUCCESS;
   1249 }
   1250 
   1251 /**
   1252   @param  EhcDev                 EHCI Device.
   1253 
   1254   @retval EFI_SUCCESS            EHCI successfully initialized.
   1255   @retval EFI_ABORTED            EHCI was failed to be initialized.
   1256 
   1257 **/
   1258 EFI_STATUS
   1259 InitializeUsbHC (
   1260   IN PEI_USB2_HC_DEV      *EhcDev
   1261   )
   1262 {
   1263   EFI_STATUS  Status;
   1264 
   1265 
   1266   EhcResetHC (EhcDev, EHC_RESET_TIMEOUT);
   1267 
   1268   Status = EhcInitHC (EhcDev);
   1269 
   1270   if (EFI_ERROR (Status)) {
   1271     return EFI_ABORTED;
   1272   }
   1273 
   1274   return EFI_SUCCESS;
   1275 }
   1276