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 - 2016, 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   UINT32    RegVal;
    417 
    418   PortNumber = (UINT8)(Ehc->HcStructParams & HCSP_NPORTS);
    419   for (Index = 0; Index < PortNumber; Index++) {
    420     //
    421     // Do not clear port status bits on initialization.  Otherwise devices will
    422     // not enumerate properly at startup.
    423     //
    424     RegVal  = EhcReadOpReg(Ehc, EHC_PORT_STAT_OFFSET + 4 * Index);
    425     RegVal &= ~PORTSC_CHANGE_MASK;
    426     RegVal |= PORTSC_POWER;
    427     EhcWriteOpReg (Ehc, EHC_PORT_STAT_OFFSET + 4 * Index, RegVal);
    428   }
    429 }
    430 
    431 /**
    432   Initialize the HC hardware.
    433   EHCI spec lists the five things to do to initialize the hardware.
    434   1. Program CTRLDSSEGMENT.
    435   2. Set USBINTR to enable interrupts.
    436   3. Set periodic list base.
    437   4. Set USBCMD, interrupt threshold, frame list size etc.
    438   5. Write 1 to CONFIGFLAG to route all ports to EHCI.
    439 
    440   @param  Ehc             The EHCI device.
    441 
    442   @retval EFI_SUCCESS     The EHCI has come out of halt state.
    443   @retval EFI_TIMEOUT     Time out happened.
    444 
    445 **/
    446 EFI_STATUS
    447 EhcInitHC (
    448   IN PEI_USB2_HC_DEV      *Ehc
    449   )
    450 {
    451   EFI_STATUS              Status;
    452   EFI_PHYSICAL_ADDRESS        TempPtr;
    453   UINTN               PageNumber;
    454 
    455   ASSERT (EhcIsHalt (Ehc));
    456 
    457   //
    458   // Allocate the periodic frame and associated memeory
    459   // management facilities if not already done.
    460   //
    461   if (Ehc->PeriodFrame != NULL) {
    462     EhcFreeSched (Ehc);
    463   }
    464   PageNumber =  sizeof(PEI_URB)/PAGESIZE +1;
    465   Status = PeiServicesAllocatePages (
    466              EfiBootServicesCode,
    467              PageNumber,
    468              &TempPtr
    469              );
    470   Ehc->Urb = (PEI_URB *) ((UINTN) TempPtr);
    471   if (Ehc->Urb  == NULL) {
    472     return Status;
    473   }
    474 
    475   EhcPowerOnAllPorts (Ehc);
    476   MicroSecondDelay (EHC_ROOT_PORT_RECOVERY_STALL);
    477 
    478   Status = EhcInitSched (Ehc);
    479 
    480   if (EFI_ERROR (Status)) {
    481     return Status;
    482   }
    483   //
    484   // 1. Program the CTRLDSSEGMENT register with the high 32 bit addr
    485   //
    486   EhcWriteOpReg (Ehc, EHC_CTRLDSSEG_OFFSET, Ehc->High32bitAddr);
    487 
    488   //
    489   // 2. Clear USBINTR to disable all the interrupt. UEFI works by polling
    490   //
    491   EhcWriteOpReg (Ehc, EHC_USBINTR_OFFSET, 0);
    492 
    493   //
    494   // 3. Program periodic frame list, already done in EhcInitSched
    495   // 4. Start the Host Controller
    496   //
    497   EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RUN);
    498 
    499   //
    500   // 5. Set all ports routing to EHC
    501   //
    502   EhcSetOpRegBit (Ehc, EHC_CONFIG_FLAG_OFFSET, CONFIGFLAG_ROUTE_EHC);
    503 
    504   //
    505   // Wait roothub port power stable
    506   //
    507   MicroSecondDelay (EHC_ROOT_PORT_RECOVERY_STALL);
    508 
    509   Status = EhcEnablePeriodSchd (Ehc, EHC_GENERIC_TIMEOUT);
    510 
    511   if (EFI_ERROR (Status)) {
    512     return Status;
    513   }
    514 
    515   Status = EhcEnableAsyncSchd (Ehc, EHC_GENERIC_TIMEOUT);
    516 
    517   if (EFI_ERROR (Status)) {
    518     return Status;
    519   }
    520 
    521   return EFI_SUCCESS;
    522 }
    523 
    524 /**
    525   Submits bulk transfer to a bulk endpoint of a USB device.
    526 
    527   @param  PeiServices           The pointer of EFI_PEI_SERVICES.
    528   @param  This                  The pointer of PEI_USB2_HOST_CONTROLLER_PPI.
    529   @param  DeviceAddress         Target device address.
    530   @param  EndPointAddress       Endpoint number and its direction in bit 7.
    531   @param  DeviceSpeed           Device speed, Low speed device doesn't support
    532                                 bulk transfer.
    533   @param  MaximumPacketLength   Maximum packet size the endpoint is capable of
    534                                 sending or receiving.
    535   @param  Data                  Array of pointers to the buffers of data to transmit
    536                                 from or receive into.
    537   @param  DataLength            The lenght of the data buffer.
    538   @param  DataToggle            On input, the initial data toggle for the transfer;
    539                                 On output, it is updated to to next data toggle to use of
    540                                 the subsequent bulk transfer.
    541   @param  TimeOut               Indicates the maximum time, in millisecond, which the
    542                                 transfer is allowed to complete.
    543                                 If Timeout is 0, then the caller must wait for the function
    544                                 to be completed until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.
    545   @param  Translator            A pointr to the transaction translator data.
    546   @param  TransferResult        A pointer to the detailed result information of the
    547                                 bulk transfer.
    548 
    549   @retval EFI_SUCCESS           The transfer was completed successfully.
    550   @retval EFI_OUT_OF_RESOURCES  The transfer failed due to lack of resource.
    551   @retval EFI_INVALID_PARAMETER Parameters are invalid.
    552   @retval EFI_TIMEOUT           The transfer failed due to timeout.
    553   @retval EFI_DEVICE_ERROR      The transfer failed due to host controller error.
    554 
    555 **/
    556 EFI_STATUS
    557 EFIAPI
    558 EhcBulkTransfer (
    559   IN EFI_PEI_SERVICES                     **PeiServices,
    560   IN PEI_USB2_HOST_CONTROLLER_PPI         *This,
    561   IN  UINT8                               DeviceAddress,
    562   IN  UINT8                               EndPointAddress,
    563   IN  UINT8                               DeviceSpeed,
    564   IN  UINTN                               MaximumPacketLength,
    565   IN  OUT VOID                            *Data[EFI_USB_MAX_BULK_BUFFER_NUM],
    566   IN  OUT UINTN                           *DataLength,
    567   IN  OUT UINT8                           *DataToggle,
    568   IN  UINTN                               TimeOut,
    569   IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
    570   OUT UINT32                              *TransferResult
    571   )
    572 {
    573   PEI_USB2_HC_DEV         *Ehc;
    574   PEI_URB                 *Urb;
    575   EFI_STATUS              Status;
    576 
    577   //
    578   // Validate the parameters
    579   //
    580   if ((DataLength == NULL) || (*DataLength == 0) ||
    581       (Data == NULL) || (Data[0] == NULL) || (TransferResult == NULL)) {
    582     return EFI_INVALID_PARAMETER;
    583   }
    584 
    585   if ((*DataToggle != 0) && (*DataToggle != 1)) {
    586     return EFI_INVALID_PARAMETER;
    587   }
    588 
    589   if ((DeviceSpeed == EFI_USB_SPEED_LOW) ||
    590       ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||
    591       ((EFI_USB_SPEED_HIGH == DeviceSpeed) && (MaximumPacketLength > 512))) {
    592     return EFI_INVALID_PARAMETER;
    593   }
    594 
    595   Ehc =PEI_RECOVERY_USB_EHC_DEV_FROM_EHCI_THIS(This);
    596   *TransferResult = EFI_USB_ERR_SYSTEM;
    597   Status          = EFI_DEVICE_ERROR;
    598 
    599   if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {
    600     EhcAckAllInterrupt (Ehc);
    601     goto ON_EXIT;
    602   }
    603 
    604   EhcAckAllInterrupt (Ehc);
    605 
    606   //
    607   // Create a new URB, insert it into the asynchronous
    608   // schedule list, then poll the execution status.
    609   //
    610   Urb = EhcCreateUrb (
    611           Ehc,
    612           DeviceAddress,
    613           EndPointAddress,
    614           DeviceSpeed,
    615           *DataToggle,
    616           MaximumPacketLength,
    617           Translator,
    618           EHC_BULK_TRANSFER,
    619           NULL,
    620           Data[0],
    621           *DataLength,
    622           NULL,
    623           NULL,
    624           1
    625           );
    626 
    627   if (Urb == NULL) {
    628     Status = EFI_OUT_OF_RESOURCES;
    629     goto ON_EXIT;
    630   }
    631 
    632   EhcLinkQhToAsync (Ehc, Urb->Qh);
    633   Status = EhcExecTransfer (Ehc, Urb, TimeOut);
    634   EhcUnlinkQhFromAsync (Ehc, Urb->Qh);
    635 
    636   *TransferResult = Urb->Result;
    637   *DataLength     = Urb->Completed;
    638   *DataToggle     = Urb->DataToggle;
    639 
    640   if (*TransferResult == EFI_USB_NOERROR) {
    641     Status = EFI_SUCCESS;
    642   }
    643 
    644   EhcAckAllInterrupt (Ehc);
    645   EhcFreeUrb (Ehc, Urb);
    646 
    647 ON_EXIT:
    648   return Status;
    649 }
    650 
    651 /**
    652   Retrieves the number of root hub ports.
    653 
    654   @param[in]  PeiServices   The pointer to the PEI Services Table.
    655   @param[in]  This          The pointer to this instance of the
    656                             PEI_USB2_HOST_CONTROLLER_PPI.
    657   @param[out] PortNumber    The pointer to the number of the root hub ports.
    658 
    659   @retval EFI_SUCCESS           The port number was retrieved successfully.
    660   @retval EFI_INVALID_PARAMETER PortNumber is NULL.
    661 
    662 **/
    663 EFI_STATUS
    664 EFIAPI
    665 EhcGetRootHubPortNumber (
    666   IN EFI_PEI_SERVICES                       **PeiServices,
    667   IN PEI_USB2_HOST_CONTROLLER_PPI           *This,
    668   OUT UINT8                                 *PortNumber
    669   )
    670 {
    671 
    672   PEI_USB2_HC_DEV             *EhcDev;
    673   EhcDev = PEI_RECOVERY_USB_EHC_DEV_FROM_EHCI_THIS (This);
    674 
    675   if (PortNumber == NULL) {
    676     return EFI_INVALID_PARAMETER;
    677   }
    678 
    679   *PortNumber = (UINT8)(EhcDev->HcStructParams & HCSP_NPORTS);
    680   return EFI_SUCCESS;
    681 
    682 }
    683 
    684 /**
    685   Clears a feature for the specified root hub port.
    686 
    687   @param  PeiServices           The pointer of EFI_PEI_SERVICES.
    688   @param  This                  The pointer of PEI_USB2_HOST_CONTROLLER_PPI.
    689   @param  PortNumber            Specifies the root hub port whose feature
    690                                 is requested to be cleared.
    691   @param  PortFeature           Indicates the feature selector associated with the
    692                                 feature clear request.
    693 
    694   @retval EFI_SUCCESS            The feature specified by PortFeature was cleared
    695                                  for the USB root hub port specified by PortNumber.
    696   @retval EFI_INVALID_PARAMETER  PortNumber is invalid or PortFeature is invalid.
    697 
    698 **/
    699 EFI_STATUS
    700 EFIAPI
    701 EhcClearRootHubPortFeature (
    702   IN EFI_PEI_SERVICES                       **PeiServices,
    703   IN PEI_USB2_HOST_CONTROLLER_PPI           *This,
    704   IN  UINT8                 PortNumber,
    705   IN  EFI_USB_PORT_FEATURE  PortFeature
    706   )
    707 {
    708   PEI_USB2_HC_DEV         *Ehc;
    709   UINT32                  Offset;
    710   UINT32                  State;
    711   UINT32                  TotalPort;
    712   EFI_STATUS              Status;
    713 
    714   Ehc       = PEI_RECOVERY_USB_EHC_DEV_FROM_EHCI_THIS (This);
    715   Status    = EFI_SUCCESS;
    716 
    717   TotalPort = (Ehc->HcStructParams & HCSP_NPORTS);
    718 
    719   if (PortNumber >= TotalPort) {
    720     Status = EFI_INVALID_PARAMETER;
    721     goto ON_EXIT;
    722   }
    723 
    724   Offset  = EHC_PORT_STAT_OFFSET + (4 * PortNumber);
    725   State   = EhcReadOpReg (Ehc, Offset);
    726   State &= ~PORTSC_CHANGE_MASK;
    727 
    728   switch (PortFeature) {
    729   case EfiUsbPortEnable:
    730     //
    731     // Clear PORT_ENABLE feature means disable port.
    732     //
    733     State &= ~PORTSC_ENABLED;
    734     EhcWriteOpReg (Ehc, Offset, State);
    735     break;
    736 
    737   case EfiUsbPortSuspend:
    738     //
    739     // A write of zero to this bit is ignored by the host
    740     // controller. The host controller will unconditionally
    741     // set this bit to a zero when:
    742     //   1. software sets the Forct Port Resume bit to a zero from a one.
    743     //   2. software sets the Port Reset bit to a one frome a zero.
    744     //
    745     State &= ~PORSTSC_RESUME;
    746     EhcWriteOpReg (Ehc, Offset, State);
    747     break;
    748 
    749   case EfiUsbPortReset:
    750     //
    751     // Clear PORT_RESET means clear the reset signal.
    752     //
    753     State &= ~PORTSC_RESET;
    754     EhcWriteOpReg (Ehc, Offset, State);
    755     break;
    756 
    757   case EfiUsbPortOwner:
    758     //
    759     // Clear port owner means this port owned by EHC
    760     //
    761     State &= ~PORTSC_OWNER;
    762     EhcWriteOpReg (Ehc, Offset, State);
    763     break;
    764 
    765   case EfiUsbPortConnectChange:
    766     //
    767     // Clear connect status change
    768     //
    769     State |= PORTSC_CONN_CHANGE;
    770     EhcWriteOpReg (Ehc, Offset, State);
    771     break;
    772 
    773   case EfiUsbPortEnableChange:
    774     //
    775     // Clear enable status change
    776     //
    777     State |= PORTSC_ENABLE_CHANGE;
    778     EhcWriteOpReg (Ehc, Offset, State);
    779     break;
    780 
    781   case EfiUsbPortOverCurrentChange:
    782     //
    783     // Clear PortOverCurrent change
    784     //
    785     State |= PORTSC_OVERCUR_CHANGE;
    786     EhcWriteOpReg (Ehc, Offset, State);
    787     break;
    788 
    789   case EfiUsbPortPower:
    790   case EfiUsbPortSuspendChange:
    791   case EfiUsbPortResetChange:
    792     //
    793     // Not supported or not related operation
    794     //
    795     break;
    796 
    797   default:
    798     Status = EFI_INVALID_PARAMETER;
    799     break;
    800   }
    801 
    802 ON_EXIT:
    803   return Status;
    804 }
    805 
    806 /**
    807   Sets a feature for the specified root hub port.
    808 
    809   @param  PeiServices           The pointer of EFI_PEI_SERVICES
    810   @param  This                  The pointer of PEI_USB2_HOST_CONTROLLER_PPI
    811   @param  PortNumber            Root hub port to set.
    812   @param  PortFeature           Feature to set.
    813 
    814   @retval EFI_SUCCESS            The feature specified by PortFeature was set.
    815   @retval EFI_INVALID_PARAMETER  PortNumber is invalid or PortFeature is invalid.
    816   @retval EFI_TIMEOUT            The time out occurred.
    817 
    818 **/
    819 EFI_STATUS
    820 EFIAPI
    821 EhcSetRootHubPortFeature (
    822   IN EFI_PEI_SERVICES                       **PeiServices,
    823   IN PEI_USB2_HOST_CONTROLLER_PPI           *This,
    824   IN UINT8                                  PortNumber,
    825   IN EFI_USB_PORT_FEATURE                   PortFeature
    826   )
    827 {
    828   PEI_USB2_HC_DEV         *Ehc;
    829   UINT32                  Offset;
    830   UINT32                  State;
    831   UINT32                  TotalPort;
    832   EFI_STATUS              Status;
    833 
    834   Ehc       = PEI_RECOVERY_USB_EHC_DEV_FROM_EHCI_THIS (This);
    835   Status    = EFI_SUCCESS;
    836 
    837   TotalPort = (Ehc->HcStructParams & HCSP_NPORTS);
    838 
    839   if (PortNumber >= TotalPort) {
    840     Status = EFI_INVALID_PARAMETER;
    841     goto ON_EXIT;
    842   }
    843 
    844   Offset  = (UINT32) (EHC_PORT_STAT_OFFSET + (4 * PortNumber));
    845   State   = EhcReadOpReg (Ehc, Offset);
    846 
    847   //
    848   // Mask off the port status change bits, these bits are
    849   // write clean bit
    850   //
    851   State &= ~PORTSC_CHANGE_MASK;
    852 
    853   switch (PortFeature) {
    854   case EfiUsbPortEnable:
    855     //
    856     // Sofeware can't set this bit, Port can only be enable by
    857     // EHCI as a part of the reset and enable
    858     //
    859     State |= PORTSC_ENABLED;
    860     EhcWriteOpReg (Ehc, Offset, State);
    861     break;
    862 
    863   case EfiUsbPortSuspend:
    864     State |= PORTSC_SUSPEND;
    865     EhcWriteOpReg (Ehc, Offset, State);
    866     break;
    867 
    868   case EfiUsbPortReset:
    869     //
    870     // Make sure Host Controller not halt before reset it
    871     //
    872     if (EhcIsHalt (Ehc)) {
    873       Status = EhcRunHC (Ehc, EHC_GENERIC_TIMEOUT);
    874 
    875       if (EFI_ERROR (Status)) {
    876         break;
    877       }
    878     }
    879 
    880     //
    881     // Set one to PortReset bit must also set zero to PortEnable bit
    882     //
    883     State |= PORTSC_RESET;
    884     State &= ~PORTSC_ENABLED;
    885     EhcWriteOpReg (Ehc, Offset, State);
    886     break;
    887 
    888   case EfiUsbPortPower:
    889     //
    890     // Not supported, ignore the operation
    891     //
    892     Status = EFI_SUCCESS;
    893     break;
    894 
    895   case EfiUsbPortOwner:
    896     State |= PORTSC_OWNER;
    897     EhcWriteOpReg (Ehc, Offset, State);
    898     break;
    899 
    900   default:
    901     Status = EFI_INVALID_PARAMETER;
    902   }
    903 
    904 ON_EXIT:
    905   return Status;
    906 }
    907 
    908 /**
    909   Retrieves the current status of a USB root hub port.
    910 
    911   @param  PeiServices            The pointer of EFI_PEI_SERVICES.
    912   @param  This                   The pointer of PEI_USB2_HOST_CONTROLLER_PPI.
    913   @param  PortNumber             The root hub port to retrieve the state from.
    914   @param  PortStatus             Variable to receive the port state.
    915 
    916   @retval EFI_SUCCESS            The status of the USB root hub port specified.
    917                                  by PortNumber was returned in PortStatus.
    918   @retval EFI_INVALID_PARAMETER  PortNumber is invalid.
    919 
    920 **/
    921 EFI_STATUS
    922 EFIAPI
    923 EhcGetRootHubPortStatus (
    924   IN EFI_PEI_SERVICES                       **PeiServices,
    925   IN PEI_USB2_HOST_CONTROLLER_PPI           *This,
    926   IN  UINT8                                 PortNumber,
    927   OUT EFI_USB_PORT_STATUS                   *PortStatus
    928   )
    929 {
    930   PEI_USB2_HC_DEV         *Ehc;
    931   UINT32                  Offset;
    932   UINT32                  State;
    933   UINT32                  TotalPort;
    934   UINTN                   Index;
    935   UINTN                   MapSize;
    936   EFI_STATUS              Status;
    937 
    938   if (PortStatus == NULL) {
    939     return EFI_INVALID_PARAMETER;
    940   }
    941 
    942   Ehc       =  PEI_RECOVERY_USB_EHC_DEV_FROM_EHCI_THIS(This);
    943   Status    = EFI_SUCCESS;
    944 
    945   TotalPort = (Ehc->HcStructParams & HCSP_NPORTS);
    946 
    947   if (PortNumber >= TotalPort) {
    948     Status = EFI_INVALID_PARAMETER;
    949     goto ON_EXIT;
    950   }
    951 
    952   Offset                        = (UINT32) (EHC_PORT_STAT_OFFSET + (4 * PortNumber));
    953   PortStatus->PortStatus        = 0;
    954   PortStatus->PortChangeStatus  = 0;
    955 
    956   State                         = EhcReadOpReg (Ehc, Offset);
    957 
    958   //
    959   // Identify device speed. If in K state, it is low speed.
    960   // If the port is enabled after reset, the device is of
    961   // high speed. The USB bus driver should retrieve the actual
    962   // port speed after reset.
    963   //
    964   if (EHC_BIT_IS_SET (State, PORTSC_LINESTATE_K)) {
    965     PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;
    966 
    967   } else if (EHC_BIT_IS_SET (State, PORTSC_ENABLED)) {
    968     PortStatus->PortStatus |= USB_PORT_STAT_HIGH_SPEED;
    969   }
    970 
    971   //
    972   // Convert the EHCI port/port change state to UEFI status
    973   //
    974   MapSize = sizeof (mUsbPortStateMap) / sizeof (USB_PORT_STATE_MAP);
    975 
    976   for (Index = 0; Index < MapSize; Index++) {
    977     if (EHC_BIT_IS_SET (State, mUsbPortStateMap[Index].HwState)) {
    978       PortStatus->PortStatus = (UINT16) (PortStatus->PortStatus | mUsbPortStateMap[Index].UefiState);
    979     }
    980   }
    981 
    982   MapSize = sizeof (mUsbPortChangeMap) / sizeof (USB_PORT_STATE_MAP);
    983 
    984   for (Index = 0; Index < MapSize; Index++) {
    985     if (EHC_BIT_IS_SET (State, mUsbPortChangeMap[Index].HwState)) {
    986       PortStatus->PortChangeStatus = (UINT16) (PortStatus->PortChangeStatus | mUsbPortChangeMap[Index].UefiState);
    987     }
    988   }
    989 
    990 ON_EXIT:
    991   return Status;
    992 }
    993 
    994 /**
    995   Submits control transfer to a target USB device.
    996 
    997   @param  PeiServices            The pointer of EFI_PEI_SERVICES.
    998   @param  This                   The pointer of PEI_USB2_HOST_CONTROLLER_PPI.
    999   @param  DeviceAddress          The target device address.
   1000   @param  DeviceSpeed            Target device speed.
   1001   @param  MaximumPacketLength    Maximum packet size the default control transfer
   1002                                  endpoint is capable of sending or receiving.
   1003   @param  Request                USB device request to send.
   1004   @param  TransferDirection      Specifies the data direction for the data stage.
   1005   @param  Data                   Data buffer to be transmitted or received from USB device.
   1006   @param  DataLength             The size (in bytes) of the data buffer.
   1007   @param  TimeOut                Indicates the maximum timeout, in millisecond.
   1008                                  If Timeout is 0, then the caller must wait for the function
   1009                                  to be completed until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.
   1010   @param  Translator             Transaction translator to be used by this device.
   1011   @param  TransferResult         Return the result of this control transfer.
   1012 
   1013   @retval EFI_SUCCESS            Transfer was completed successfully.
   1014   @retval EFI_OUT_OF_RESOURCES   The transfer failed due to lack of resources.
   1015   @retval EFI_INVALID_PARAMETER  Some parameters are invalid.
   1016   @retval EFI_TIMEOUT            Transfer failed due to timeout.
   1017   @retval EFI_DEVICE_ERROR       Transfer failed due to host controller or device error.
   1018 
   1019 **/
   1020 EFI_STATUS
   1021 EFIAPI
   1022 EhcControlTransfer (
   1023   IN  EFI_PEI_SERVICES                    **PeiServices,
   1024   IN  PEI_USB2_HOST_CONTROLLER_PPI        *This,
   1025   IN  UINT8                               DeviceAddress,
   1026   IN  UINT8                               DeviceSpeed,
   1027   IN  UINTN                               MaximumPacketLength,
   1028   IN  EFI_USB_DEVICE_REQUEST              *Request,
   1029   IN  EFI_USB_DATA_DIRECTION              TransferDirection,
   1030   IN  OUT VOID                            *Data,
   1031   IN  OUT UINTN                           *DataLength,
   1032   IN  UINTN                               TimeOut,
   1033   IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
   1034   OUT UINT32                              *TransferResult
   1035   )
   1036 {
   1037   PEI_USB2_HC_DEV         *Ehc;
   1038   PEI_URB                 *Urb;
   1039   UINT8                   Endpoint;
   1040   EFI_STATUS              Status;
   1041 
   1042   //
   1043   // Validate parameters
   1044   //
   1045   if ((Request == NULL) || (TransferResult == NULL)) {
   1046     return EFI_INVALID_PARAMETER;
   1047   }
   1048 
   1049   if ((TransferDirection != EfiUsbDataIn) &&
   1050       (TransferDirection != EfiUsbDataOut) &&
   1051       (TransferDirection != EfiUsbNoData)) {
   1052     return EFI_INVALID_PARAMETER;
   1053   }
   1054 
   1055   if ((TransferDirection == EfiUsbNoData) &&
   1056       ((Data != NULL) || (*DataLength != 0))) {
   1057     return EFI_INVALID_PARAMETER;
   1058   }
   1059 
   1060   if ((TransferDirection != EfiUsbNoData) &&
   1061      ((Data == NULL) || (*DataLength == 0))) {
   1062     return EFI_INVALID_PARAMETER;
   1063   }
   1064 
   1065   if ((MaximumPacketLength != 8)  && (MaximumPacketLength != 16) &&
   1066       (MaximumPacketLength != 32) && (MaximumPacketLength != 64)) {
   1067     return EFI_INVALID_PARAMETER;
   1068   }
   1069 
   1070 
   1071   if ((DeviceSpeed == EFI_USB_SPEED_LOW) ||
   1072       ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||
   1073       ((EFI_USB_SPEED_HIGH == DeviceSpeed) && (MaximumPacketLength > 512))) {
   1074     return EFI_INVALID_PARAMETER;
   1075   }
   1076 
   1077   Ehc             = PEI_RECOVERY_USB_EHC_DEV_FROM_EHCI_THIS (This);
   1078 
   1079   Status          = EFI_DEVICE_ERROR;
   1080   *TransferResult = EFI_USB_ERR_SYSTEM;
   1081 
   1082   if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {
   1083     EhcAckAllInterrupt (Ehc);
   1084     goto ON_EXIT;
   1085   }
   1086 
   1087   EhcAckAllInterrupt (Ehc);
   1088 
   1089   //
   1090   // Create a new URB, insert it into the asynchronous
   1091   // schedule list, then poll the execution status.
   1092   //
   1093   //
   1094   // Encode the direction in address, although default control
   1095   // endpoint is bidirectional. EhcCreateUrb expects this
   1096   // combination of Ep addr and its direction.
   1097   //
   1098   Endpoint = (UINT8) (0 | ((TransferDirection == EfiUsbDataIn) ? 0x80 : 0));
   1099   Urb = EhcCreateUrb (
   1100           Ehc,
   1101           DeviceAddress,
   1102           Endpoint,
   1103           DeviceSpeed,
   1104           0,
   1105           MaximumPacketLength,
   1106           Translator,
   1107           EHC_CTRL_TRANSFER,
   1108           Request,
   1109           Data,
   1110           *DataLength,
   1111           NULL,
   1112           NULL,
   1113           1
   1114           );
   1115 
   1116   if (Urb == NULL) {
   1117     Status = EFI_OUT_OF_RESOURCES;
   1118     goto ON_EXIT;
   1119   }
   1120 
   1121   EhcLinkQhToAsync (Ehc, Urb->Qh);
   1122   Status = EhcExecTransfer (Ehc, Urb, TimeOut);
   1123   EhcUnlinkQhFromAsync (Ehc, Urb->Qh);
   1124 
   1125   //
   1126   // Get the status from URB. The result is updated in EhcCheckUrbResult
   1127   // which is called by EhcExecTransfer
   1128   //
   1129   *TransferResult = Urb->Result;
   1130   *DataLength     = Urb->Completed;
   1131 
   1132   if (*TransferResult == EFI_USB_NOERROR) {
   1133     Status = EFI_SUCCESS;
   1134   }
   1135 
   1136   EhcAckAllInterrupt (Ehc);
   1137   EhcFreeUrb (Ehc, Urb);
   1138 
   1139 ON_EXIT:
   1140   return Status;
   1141 }
   1142 
   1143 /**
   1144   @param  FileHandle  Handle of the file being invoked.
   1145   @param  PeiServices Describes the list of possible PEI Services.
   1146 
   1147   @retval EFI_SUCCESS            PPI successfully installed.
   1148 
   1149 **/
   1150 EFI_STATUS
   1151 EFIAPI
   1152 EhcPeimEntry (
   1153   IN EFI_PEI_FILE_HANDLE     FileHandle,
   1154   IN CONST EFI_PEI_SERVICES  **PeiServices
   1155   )
   1156 {
   1157   PEI_USB_CONTROLLER_PPI      *ChipSetUsbControllerPpi;
   1158   EFI_STATUS                  Status;
   1159   UINT8                       Index;
   1160   UINTN                       ControllerType;
   1161   UINTN                       BaseAddress;
   1162   UINTN                       MemPages;
   1163   PEI_USB2_HC_DEV             *EhcDev;
   1164   EFI_PHYSICAL_ADDRESS        TempPtr;
   1165 
   1166   //
   1167   // Shadow this PEIM to run from memory
   1168   //
   1169   if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) {
   1170     return EFI_SUCCESS;
   1171   }
   1172 
   1173   Status = PeiServicesLocatePpi (
   1174              &gPeiUsbControllerPpiGuid,
   1175              0,
   1176              NULL,
   1177              (VOID **) &ChipSetUsbControllerPpi
   1178              );
   1179   if (EFI_ERROR (Status)) {
   1180     return EFI_UNSUPPORTED;
   1181   }
   1182 
   1183   Index = 0;
   1184   while (TRUE) {
   1185     Status = ChipSetUsbControllerPpi->GetUsbController (
   1186                                         (EFI_PEI_SERVICES **) PeiServices,
   1187                                         ChipSetUsbControllerPpi,
   1188                                         Index,
   1189                                         &ControllerType,
   1190                                         &BaseAddress
   1191                                         );
   1192     //
   1193     // When status is error, meant no controller is found
   1194     //
   1195     if (EFI_ERROR (Status)) {
   1196       break;
   1197     }
   1198 
   1199     //
   1200     // This PEIM is for UHC type controller.
   1201     //
   1202     if (ControllerType != PEI_EHCI_CONTROLLER) {
   1203       Index++;
   1204       continue;
   1205     }
   1206 
   1207     MemPages = sizeof (PEI_USB2_HC_DEV) / PAGESIZE + 1;
   1208     Status = PeiServicesAllocatePages (
   1209                EfiBootServicesCode,
   1210                MemPages,
   1211                &TempPtr
   1212                );
   1213     if (EFI_ERROR (Status)) {
   1214       return EFI_OUT_OF_RESOURCES;
   1215     }
   1216 
   1217     ZeroMem((VOID *)(UINTN)TempPtr, MemPages*PAGESIZE);
   1218     EhcDev = (PEI_USB2_HC_DEV *) ((UINTN) TempPtr);
   1219 
   1220     EhcDev->Signature = USB2_HC_DEV_SIGNATURE;
   1221 
   1222     EhcDev->UsbHostControllerBaseAddress = (UINT32) BaseAddress;
   1223 
   1224 
   1225     EhcDev->HcStructParams = EhcReadCapRegister (EhcDev, EHC_HCSPARAMS_OFFSET);
   1226     EhcDev->HcCapParams    = EhcReadCapRegister (EhcDev, EHC_HCCPARAMS_OFFSET);
   1227     EhcDev->CapLen         = EhcReadCapRegister (EhcDev, EHC_CAPLENGTH_OFFSET) & 0x0FF;
   1228     //
   1229     // Initialize Uhc's hardware
   1230     //
   1231     Status = InitializeUsbHC (EhcDev);
   1232     if (EFI_ERROR (Status)) {
   1233       return Status;
   1234     }
   1235 
   1236     EhcDev->Usb2HostControllerPpi.ControlTransfer          = EhcControlTransfer;
   1237     EhcDev->Usb2HostControllerPpi.BulkTransfer             = EhcBulkTransfer;
   1238     EhcDev->Usb2HostControllerPpi.GetRootHubPortNumber     = EhcGetRootHubPortNumber;
   1239     EhcDev->Usb2HostControllerPpi.GetRootHubPortStatus     = EhcGetRootHubPortStatus;
   1240     EhcDev->Usb2HostControllerPpi.SetRootHubPortFeature    = EhcSetRootHubPortFeature;
   1241     EhcDev->Usb2HostControllerPpi.ClearRootHubPortFeature  = EhcClearRootHubPortFeature;
   1242 
   1243     EhcDev->PpiDescriptor.Flags = (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
   1244     EhcDev->PpiDescriptor.Guid = &gPeiUsb2HostControllerPpiGuid;
   1245     EhcDev->PpiDescriptor.Ppi = &EhcDev->Usb2HostControllerPpi;
   1246 
   1247     Status = PeiServicesInstallPpi (&EhcDev->PpiDescriptor);
   1248     if (EFI_ERROR (Status)) {
   1249       Index++;
   1250       continue;
   1251     }
   1252 
   1253     Index++;
   1254   }
   1255 
   1256   return EFI_SUCCESS;
   1257 }
   1258 
   1259 /**
   1260   @param  EhcDev                 EHCI Device.
   1261 
   1262   @retval EFI_SUCCESS            EHCI successfully initialized.
   1263   @retval EFI_ABORTED            EHCI was failed to be initialized.
   1264 
   1265 **/
   1266 EFI_STATUS
   1267 InitializeUsbHC (
   1268   IN PEI_USB2_HC_DEV      *EhcDev
   1269   )
   1270 {
   1271   EFI_STATUS  Status;
   1272 
   1273 
   1274   EhcResetHC (EhcDev, EHC_RESET_TIMEOUT);
   1275 
   1276   Status = EhcInitHC (EhcDev);
   1277 
   1278   if (EFI_ERROR (Status)) {
   1279     return EFI_ABORTED;
   1280   }
   1281 
   1282   return EFI_SUCCESS;
   1283 }
   1284