Home | History | Annotate | Download | only in XhciDxe
      1 /** @file
      2   The XHCI controller driver.
      3 
      4 Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
      5 This program and the accompanying materials
      6 are licensed and made available under the terms and conditions of the BSD License
      7 which accompanies this distribution.  The full text of the license may be found at
      8 http://opensource.org/licenses/bsd-license.php
      9 
     10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include "Xhci.h"
     16 
     17 //
     18 // Two arrays used to translate the XHCI port state (change)
     19 // to the UEFI protocol's port state (change).
     20 //
     21 USB_PORT_STATE_MAP  mUsbPortStateMap[] = {
     22   {XHC_PORTSC_CCS,   USB_PORT_STAT_CONNECTION},
     23   {XHC_PORTSC_PED,   USB_PORT_STAT_ENABLE},
     24   {XHC_PORTSC_OCA,   USB_PORT_STAT_OVERCURRENT},
     25   {XHC_PORTSC_RESET, USB_PORT_STAT_RESET}
     26 };
     27 
     28 USB_PORT_STATE_MAP  mUsbPortChangeMap[] = {
     29   {XHC_PORTSC_CSC, USB_PORT_STAT_C_CONNECTION},
     30   {XHC_PORTSC_PEC, USB_PORT_STAT_C_ENABLE},
     31   {XHC_PORTSC_OCC, USB_PORT_STAT_C_OVERCURRENT},
     32   {XHC_PORTSC_PRC, USB_PORT_STAT_C_RESET}
     33 };
     34 
     35 USB_CLEAR_PORT_MAP mUsbClearPortChangeMap[] = {
     36   {XHC_PORTSC_CSC, EfiUsbPortConnectChange},
     37   {XHC_PORTSC_PEC, EfiUsbPortEnableChange},
     38   {XHC_PORTSC_OCC, EfiUsbPortOverCurrentChange},
     39   {XHC_PORTSC_PRC, EfiUsbPortResetChange}
     40 };
     41 
     42 USB_PORT_STATE_MAP  mUsbHubPortStateMap[] = {
     43   {XHC_HUB_PORTSC_CCS,   USB_PORT_STAT_CONNECTION},
     44   {XHC_HUB_PORTSC_PED,   USB_PORT_STAT_ENABLE},
     45   {XHC_HUB_PORTSC_OCA,   USB_PORT_STAT_OVERCURRENT},
     46   {XHC_HUB_PORTSC_RESET, USB_PORT_STAT_RESET}
     47 };
     48 
     49 USB_PORT_STATE_MAP  mUsbHubPortChangeMap[] = {
     50   {XHC_HUB_PORTSC_CSC, USB_PORT_STAT_C_CONNECTION},
     51   {XHC_HUB_PORTSC_PEC, USB_PORT_STAT_C_ENABLE},
     52   {XHC_HUB_PORTSC_OCC, USB_PORT_STAT_C_OVERCURRENT},
     53   {XHC_HUB_PORTSC_PRC, USB_PORT_STAT_C_RESET}
     54 };
     55 
     56 USB_CLEAR_PORT_MAP mUsbHubClearPortChangeMap[] = {
     57   {XHC_HUB_PORTSC_CSC, EfiUsbPortConnectChange},
     58   {XHC_HUB_PORTSC_PEC, EfiUsbPortEnableChange},
     59   {XHC_HUB_PORTSC_OCC, EfiUsbPortOverCurrentChange},
     60   {XHC_HUB_PORTSC_PRC, EfiUsbPortResetChange},
     61   {XHC_HUB_PORTSC_BHRC, Usb3PortBHPortResetChange}
     62 };
     63 
     64 EFI_DRIVER_BINDING_PROTOCOL  gXhciDriverBinding = {
     65   XhcDriverBindingSupported,
     66   XhcDriverBindingStart,
     67   XhcDriverBindingStop,
     68   0x30,
     69   NULL,
     70   NULL
     71 };
     72 
     73 //
     74 // Template for Xhci's Usb2 Host Controller Protocol Instance.
     75 //
     76 EFI_USB2_HC_PROTOCOL gXhciUsb2HcTemplate = {
     77   XhcGetCapability,
     78   XhcReset,
     79   XhcGetState,
     80   XhcSetState,
     81   XhcControlTransfer,
     82   XhcBulkTransfer,
     83   XhcAsyncInterruptTransfer,
     84   XhcSyncInterruptTransfer,
     85   XhcIsochronousTransfer,
     86   XhcAsyncIsochronousTransfer,
     87   XhcGetRootHubPortStatus,
     88   XhcSetRootHubPortFeature,
     89   XhcClearRootHubPortFeature,
     90   0x3,
     91   0x0
     92 };
     93 
     94 /**
     95   Retrieves the capability of root hub ports.
     96 
     97   @param  This                  The EFI_USB2_HC_PROTOCOL instance.
     98   @param  MaxSpeed              Max speed supported by the controller.
     99   @param  PortNumber            Number of the root hub ports.
    100   @param  Is64BitCapable        Whether the controller supports 64-bit memory
    101                                 addressing.
    102 
    103   @retval EFI_SUCCESS           Host controller capability were retrieved successfully.
    104   @retval EFI_INVALID_PARAMETER Either of the three capability pointer is NULL.
    105 
    106 **/
    107 EFI_STATUS
    108 EFIAPI
    109 XhcGetCapability (
    110   IN  EFI_USB2_HC_PROTOCOL  *This,
    111   OUT UINT8                 *MaxSpeed,
    112   OUT UINT8                 *PortNumber,
    113   OUT UINT8                 *Is64BitCapable
    114   )
    115 {
    116   USB_XHCI_INSTANCE  *Xhc;
    117   EFI_TPL            OldTpl;
    118 
    119   if ((MaxSpeed == NULL) || (PortNumber == NULL) || (Is64BitCapable == NULL)) {
    120     return EFI_INVALID_PARAMETER;
    121   }
    122 
    123   OldTpl          = gBS->RaiseTPL (XHC_TPL);
    124 
    125   Xhc             = XHC_FROM_THIS (This);
    126   *MaxSpeed       = EFI_USB_SPEED_SUPER;
    127   *PortNumber     = (UINT8) (Xhc->HcSParams1.Data.MaxPorts);
    128   *Is64BitCapable = (UINT8) (Xhc->HcCParams.Data.Ac64);
    129   DEBUG ((EFI_D_INFO, "XhcGetCapability: %d ports, 64 bit %d\n", *PortNumber, *Is64BitCapable));
    130 
    131   gBS->RestoreTPL (OldTpl);
    132 
    133   return EFI_SUCCESS;
    134 }
    135 
    136 
    137 /**
    138   Provides software reset for the USB host controller.
    139 
    140   @param  This                  This EFI_USB2_HC_PROTOCOL instance.
    141   @param  Attributes            A bit mask of the reset operation to perform.
    142 
    143   @retval EFI_SUCCESS           The reset operation succeeded.
    144   @retval EFI_INVALID_PARAMETER Attributes is not valid.
    145   @retval EFI_UNSUPPOURTED      The type of reset specified by Attributes is
    146                                 not currently supported by the host controller.
    147   @retval EFI_DEVICE_ERROR      Host controller isn't halted to reset.
    148 
    149 **/
    150 EFI_STATUS
    151 EFIAPI
    152 XhcReset (
    153   IN EFI_USB2_HC_PROTOCOL  *This,
    154   IN UINT16                Attributes
    155   )
    156 {
    157   USB_XHCI_INSTANCE  *Xhc;
    158   EFI_STATUS         Status;
    159   EFI_TPL            OldTpl;
    160 
    161   Xhc = XHC_FROM_THIS (This);
    162 
    163   if (Xhc->DevicePath != NULL) {
    164     //
    165     // Report Status Code to indicate reset happens
    166     //
    167     REPORT_STATUS_CODE_WITH_DEVICE_PATH (
    168       EFI_PROGRESS_CODE,
    169       (EFI_IO_BUS_USB | EFI_IOB_PC_RESET),
    170       Xhc->DevicePath
    171       );
    172   }
    173 
    174   OldTpl = gBS->RaiseTPL (XHC_TPL);
    175 
    176   switch (Attributes) {
    177   case EFI_USB_HC_RESET_GLOBAL:
    178   //
    179   // Flow through, same behavior as Host Controller Reset
    180   //
    181   case EFI_USB_HC_RESET_HOST_CONTROLLER:
    182     if ((Xhc->DebugCapSupOffset != 0xFFFFFFFF) && ((XhcReadExtCapReg (Xhc, Xhc->DebugCapSupOffset) & 0xFF) == XHC_CAP_USB_DEBUG) &&
    183         ((XhcReadExtCapReg (Xhc, Xhc->DebugCapSupOffset + XHC_DC_DCCTRL) & BIT0) != 0)) {
    184       Status = EFI_SUCCESS;
    185       goto ON_EXIT;
    186     }
    187     //
    188     // Host Controller must be Halt when Reset it
    189     //
    190     if (!XhcIsHalt (Xhc)) {
    191       Status = XhcHaltHC (Xhc, XHC_GENERIC_TIMEOUT);
    192 
    193       if (EFI_ERROR (Status)) {
    194         Status = EFI_DEVICE_ERROR;
    195         goto ON_EXIT;
    196       }
    197     }
    198 
    199     Status = XhcResetHC (Xhc, XHC_RESET_TIMEOUT);
    200     ASSERT (!(XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_CNR)));
    201 
    202     if (EFI_ERROR (Status)) {
    203       goto ON_EXIT;
    204     }
    205     //
    206     // Clean up the asynchronous transfers, currently only
    207     // interrupt supports asynchronous operation.
    208     //
    209     XhciDelAllAsyncIntTransfers (Xhc);
    210     XhcFreeSched (Xhc);
    211 
    212     XhcInitSched (Xhc);
    213     break;
    214 
    215   case EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG:
    216   case EFI_USB_HC_RESET_HOST_WITH_DEBUG:
    217     Status = EFI_UNSUPPORTED;
    218     break;
    219 
    220   default:
    221     Status = EFI_INVALID_PARAMETER;
    222   }
    223 
    224 ON_EXIT:
    225   DEBUG ((EFI_D_INFO, "XhcReset: status %r\n", Status));
    226   gBS->RestoreTPL (OldTpl);
    227 
    228   return Status;
    229 }
    230 
    231 
    232 /**
    233   Retrieve the current state of the USB host controller.
    234 
    235   @param  This                   This EFI_USB2_HC_PROTOCOL instance.
    236   @param  State                  Variable to return the current host controller
    237                                  state.
    238 
    239   @retval EFI_SUCCESS            Host controller state was returned in State.
    240   @retval EFI_INVALID_PARAMETER  State is NULL.
    241   @retval EFI_DEVICE_ERROR       An error was encountered while attempting to
    242                                  retrieve the host controller's current state.
    243 
    244 **/
    245 EFI_STATUS
    246 EFIAPI
    247 XhcGetState (
    248   IN  EFI_USB2_HC_PROTOCOL  *This,
    249   OUT EFI_USB_HC_STATE      *State
    250   )
    251 {
    252   USB_XHCI_INSTANCE  *Xhc;
    253   EFI_TPL            OldTpl;
    254 
    255   if (State == NULL) {
    256     return EFI_INVALID_PARAMETER;
    257   }
    258 
    259   OldTpl = gBS->RaiseTPL (XHC_TPL);
    260 
    261   Xhc    = XHC_FROM_THIS (This);
    262 
    263   if (XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HALT)) {
    264     *State = EfiUsbHcStateHalt;
    265   } else {
    266     *State = EfiUsbHcStateOperational;
    267   }
    268 
    269   DEBUG ((EFI_D_INFO, "XhcGetState: current state %d\n", *State));
    270   gBS->RestoreTPL (OldTpl);
    271 
    272   return EFI_SUCCESS;
    273 }
    274 
    275 /**
    276   Sets the USB host controller to a specific state.
    277 
    278   @param  This                  This EFI_USB2_HC_PROTOCOL instance.
    279   @param  State                 The state of the host controller that will be set.
    280 
    281   @retval EFI_SUCCESS           The USB host controller was successfully placed
    282                                 in the state specified by State.
    283   @retval EFI_INVALID_PARAMETER State is invalid.
    284   @retval EFI_DEVICE_ERROR      Failed to set the state due to device error.
    285 
    286 **/
    287 EFI_STATUS
    288 EFIAPI
    289 XhcSetState (
    290   IN EFI_USB2_HC_PROTOCOL  *This,
    291   IN EFI_USB_HC_STATE      State
    292   )
    293 {
    294   USB_XHCI_INSTANCE   *Xhc;
    295   EFI_STATUS          Status;
    296   EFI_USB_HC_STATE    CurState;
    297   EFI_TPL             OldTpl;
    298 
    299   Status = XhcGetState (This, &CurState);
    300 
    301   if (EFI_ERROR (Status)) {
    302     return EFI_DEVICE_ERROR;
    303   }
    304 
    305   if (CurState == State) {
    306     return EFI_SUCCESS;
    307   }
    308 
    309   OldTpl = gBS->RaiseTPL (XHC_TPL);
    310 
    311   Xhc    = XHC_FROM_THIS (This);
    312 
    313   switch (State) {
    314   case EfiUsbHcStateHalt:
    315     Status = XhcHaltHC (Xhc, XHC_GENERIC_TIMEOUT);
    316     break;
    317 
    318   case EfiUsbHcStateOperational:
    319     if (XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HSE)) {
    320       Status = EFI_DEVICE_ERROR;
    321       break;
    322     }
    323 
    324     //
    325     // Software must not write a one to this field unless the host controller
    326     // is in the Halted state. Doing so will yield undefined results.
    327     // refers to Spec[XHCI1.0-2.3.1]
    328     //
    329     if (!XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HALT)) {
    330       Status = EFI_DEVICE_ERROR;
    331       break;
    332     }
    333 
    334     Status = XhcRunHC (Xhc, XHC_GENERIC_TIMEOUT);
    335     break;
    336 
    337   case EfiUsbHcStateSuspend:
    338     Status = EFI_UNSUPPORTED;
    339     break;
    340 
    341   default:
    342     Status = EFI_INVALID_PARAMETER;
    343   }
    344 
    345   DEBUG ((EFI_D_INFO, "XhcSetState: status %r\n", Status));
    346   gBS->RestoreTPL (OldTpl);
    347 
    348   return Status;
    349 }
    350 
    351 /**
    352   Retrieves the current status of a USB root hub port.
    353 
    354   @param  This                  This EFI_USB2_HC_PROTOCOL instance.
    355   @param  PortNumber            The root hub port to retrieve the state from.
    356                                 This value is zero-based.
    357   @param  PortStatus            Variable to receive the port state.
    358 
    359   @retval EFI_SUCCESS           The status of the USB root hub port specified.
    360                                 by PortNumber was returned in PortStatus.
    361   @retval EFI_INVALID_PARAMETER PortNumber is invalid.
    362   @retval EFI_DEVICE_ERROR      Can't read register.
    363 
    364 **/
    365 EFI_STATUS
    366 EFIAPI
    367 XhcGetRootHubPortStatus (
    368   IN  EFI_USB2_HC_PROTOCOL  *This,
    369   IN  UINT8                 PortNumber,
    370   OUT EFI_USB_PORT_STATUS   *PortStatus
    371   )
    372 {
    373   USB_XHCI_INSTANCE       *Xhc;
    374   UINT32                  Offset;
    375   UINT32                  State;
    376   UINT32                  TotalPort;
    377   UINTN                   Index;
    378   UINTN                   MapSize;
    379   EFI_STATUS              Status;
    380   USB_DEV_ROUTE           ParentRouteChart;
    381   EFI_TPL                 OldTpl;
    382 
    383   if (PortStatus == NULL) {
    384     return EFI_INVALID_PARAMETER;
    385   }
    386 
    387   OldTpl = gBS->RaiseTPL (XHC_TPL);
    388 
    389   Xhc       = XHC_FROM_THIS (This);
    390   Status    = EFI_SUCCESS;
    391 
    392   TotalPort = Xhc->HcSParams1.Data.MaxPorts;
    393 
    394   if (PortNumber >= TotalPort) {
    395     Status = EFI_INVALID_PARAMETER;
    396     goto ON_EXIT;
    397   }
    398 
    399   Offset                       = (UINT32) (XHC_PORTSC_OFFSET + (0x10 * PortNumber));
    400   PortStatus->PortStatus       = 0;
    401   PortStatus->PortChangeStatus = 0;
    402 
    403   State = XhcReadOpReg (Xhc, Offset);
    404 
    405   //
    406   // According to XHCI 1.0 spec, bit 10~13 of the root port status register identifies the speed of the attached device.
    407   //
    408   switch ((State & XHC_PORTSC_PS) >> 10) {
    409   case 2:
    410     PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;
    411     break;
    412 
    413   case 3:
    414     PortStatus->PortStatus |= USB_PORT_STAT_HIGH_SPEED;
    415     break;
    416 
    417   case 4:
    418     PortStatus->PortStatus |= USB_PORT_STAT_SUPER_SPEED;
    419     break;
    420 
    421   default:
    422     break;
    423   }
    424 
    425   //
    426   // Convert the XHCI port/port change state to UEFI status
    427   //
    428   MapSize = sizeof (mUsbPortStateMap) / sizeof (USB_PORT_STATE_MAP);
    429 
    430   for (Index = 0; Index < MapSize; Index++) {
    431     if (XHC_BIT_IS_SET (State, mUsbPortStateMap[Index].HwState)) {
    432       PortStatus->PortStatus = (UINT16) (PortStatus->PortStatus | mUsbPortStateMap[Index].UefiState);
    433     }
    434   }
    435   //
    436   // Bit5~8 reflects its current link state.
    437   //
    438   if ((State & XHC_PORTSC_PLS) >> 5 == 3) {
    439     PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND;
    440   }
    441 
    442   MapSize = sizeof (mUsbPortChangeMap) / sizeof (USB_PORT_STATE_MAP);
    443 
    444   for (Index = 0; Index < MapSize; Index++) {
    445     if (XHC_BIT_IS_SET (State, mUsbPortChangeMap[Index].HwState)) {
    446       PortStatus->PortChangeStatus = (UINT16) (PortStatus->PortChangeStatus | mUsbPortChangeMap[Index].UefiState);
    447     }
    448   }
    449 
    450   MapSize = sizeof (mUsbClearPortChangeMap) / sizeof (USB_CLEAR_PORT_MAP);
    451 
    452   for (Index = 0; Index < MapSize; Index++) {
    453     if (XHC_BIT_IS_SET (State, mUsbClearPortChangeMap[Index].HwState)) {
    454       XhcClearRootHubPortFeature (This, PortNumber, (EFI_USB_PORT_FEATURE)mUsbClearPortChangeMap[Index].Selector);
    455     }
    456   }
    457 
    458   //
    459   // Poll the root port status register to enable/disable corresponding device slot if there is a device attached/detached.
    460   // For those devices behind hub, we get its attach/detach event by hooking Get_Port_Status request at control transfer for those hub.
    461   //
    462   ParentRouteChart.Dword = 0;
    463   XhcPollPortStatusChange (Xhc, ParentRouteChart, PortNumber, PortStatus);
    464 
    465 ON_EXIT:
    466   gBS->RestoreTPL (OldTpl);
    467   return Status;
    468 }
    469 
    470 
    471 /**
    472   Sets a feature for the specified root hub port.
    473 
    474   @param  This                  This EFI_USB2_HC_PROTOCOL instance.
    475   @param  PortNumber            Root hub port to set.
    476   @param  PortFeature           Feature to set.
    477 
    478   @retval EFI_SUCCESS           The feature specified by PortFeature was set.
    479   @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
    480   @retval EFI_DEVICE_ERROR      Can't read register.
    481 
    482 **/
    483 EFI_STATUS
    484 EFIAPI
    485 XhcSetRootHubPortFeature (
    486   IN EFI_USB2_HC_PROTOCOL  *This,
    487   IN UINT8                 PortNumber,
    488   IN EFI_USB_PORT_FEATURE  PortFeature
    489   )
    490 {
    491   USB_XHCI_INSTANCE       *Xhc;
    492   UINT32                  Offset;
    493   UINT32                  State;
    494   UINT32                  TotalPort;
    495   EFI_STATUS              Status;
    496   EFI_TPL                 OldTpl;
    497 
    498   OldTpl = gBS->RaiseTPL (XHC_TPL);
    499 
    500   Xhc    = XHC_FROM_THIS (This);
    501   Status = EFI_SUCCESS;
    502 
    503   TotalPort = (Xhc->HcSParams1.Data.MaxPorts);
    504 
    505   if (PortNumber >= TotalPort) {
    506     Status = EFI_INVALID_PARAMETER;
    507     goto ON_EXIT;
    508   }
    509 
    510   Offset = (UINT32) (XHC_PORTSC_OFFSET + (0x10 * PortNumber));
    511   State  = XhcReadOpReg (Xhc, Offset);
    512 
    513   //
    514   // Mask off the port status change bits, these bits are
    515   // write clean bit
    516   //
    517   State &= ~ (BIT1 | BIT17 | BIT18 | BIT19 | BIT20 | BIT21 | BIT22 | BIT23);
    518 
    519   switch (PortFeature) {
    520   case EfiUsbPortEnable:
    521     //
    522     // Ports may only be enabled by the xHC. Software cannot enable a port by writing a '1' to this flag.
    523     // A port may be disabled by software writing a '1' to this flag.
    524     //
    525     Status = EFI_SUCCESS;
    526     break;
    527 
    528   case EfiUsbPortSuspend:
    529     State |= XHC_PORTSC_LWS;
    530     XhcWriteOpReg (Xhc, Offset, State);
    531     State &= ~XHC_PORTSC_PLS;
    532     State |= (3 << 5) ;
    533     XhcWriteOpReg (Xhc, Offset, State);
    534     break;
    535 
    536   case EfiUsbPortReset:
    537     DEBUG ((EFI_D_INFO, "XhcUsbPortReset!\n"));
    538     //
    539     // Make sure Host Controller not halt before reset it
    540     //
    541     if (XhcIsHalt (Xhc)) {
    542       Status = XhcRunHC (Xhc, XHC_GENERIC_TIMEOUT);
    543 
    544       if (EFI_ERROR (Status)) {
    545         DEBUG ((EFI_D_INFO, "XhcSetRootHubPortFeature :failed to start HC - %r\n", Status));
    546         break;
    547       }
    548     }
    549 
    550     //
    551     // 4.3.1 Resetting a Root Hub Port
    552     // 1) Write the PORTSC register with the Port Reset (PR) bit set to '1'.
    553     //
    554     State |= XHC_PORTSC_RESET;
    555     XhcWriteOpReg (Xhc, Offset, State);
    556     XhcWaitOpRegBit(Xhc, Offset, XHC_PORTSC_PRC, TRUE, XHC_GENERIC_TIMEOUT);
    557     break;
    558 
    559   case EfiUsbPortPower:
    560     //
    561     // Not supported, ignore the operation
    562     //
    563     Status = EFI_SUCCESS;
    564     break;
    565 
    566   case EfiUsbPortOwner:
    567     //
    568     // XHCI root hub port don't has the owner bit, ignore the operation
    569     //
    570     Status = EFI_SUCCESS;
    571     break;
    572 
    573   default:
    574     Status = EFI_INVALID_PARAMETER;
    575   }
    576 
    577 ON_EXIT:
    578   DEBUG ((EFI_D_INFO, "XhcSetRootHubPortFeature: status %r\n", Status));
    579   gBS->RestoreTPL (OldTpl);
    580 
    581   return Status;
    582 }
    583 
    584 
    585 /**
    586   Clears a feature for the specified root hub port.
    587 
    588   @param  This                  A pointer to the EFI_USB2_HC_PROTOCOL instance.
    589   @param  PortNumber            Specifies the root hub port whose feature is
    590                                 requested to be cleared.
    591   @param  PortFeature           Indicates the feature selector associated with the
    592                                 feature clear request.
    593 
    594   @retval EFI_SUCCESS           The feature specified by PortFeature was cleared
    595                                 for the USB root hub port specified by PortNumber.
    596   @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
    597   @retval EFI_DEVICE_ERROR      Can't read register.
    598 
    599 **/
    600 EFI_STATUS
    601 EFIAPI
    602 XhcClearRootHubPortFeature (
    603   IN EFI_USB2_HC_PROTOCOL  *This,
    604   IN UINT8                 PortNumber,
    605   IN EFI_USB_PORT_FEATURE  PortFeature
    606   )
    607 {
    608   USB_XHCI_INSTANCE       *Xhc;
    609   UINT32                  Offset;
    610   UINT32                  State;
    611   UINT32                  TotalPort;
    612   EFI_STATUS              Status;
    613   EFI_TPL                 OldTpl;
    614 
    615   OldTpl = gBS->RaiseTPL (XHC_TPL);
    616 
    617   Xhc       = XHC_FROM_THIS (This);
    618   Status    = EFI_SUCCESS;
    619 
    620   TotalPort = (Xhc->HcSParams1.Data.MaxPorts);
    621 
    622   if (PortNumber >= TotalPort) {
    623     Status = EFI_INVALID_PARAMETER;
    624     goto ON_EXIT;
    625   }
    626 
    627   Offset = XHC_PORTSC_OFFSET + (0x10 * PortNumber);
    628 
    629   //
    630   // Mask off the port status change bits, these bits are
    631   // write clean bit
    632   //
    633   State  = XhcReadOpReg (Xhc, Offset);
    634   State &= ~ (BIT1 | BIT17 | BIT18 | BIT19 | BIT20 | BIT21 | BIT22 | BIT23);
    635 
    636   switch (PortFeature) {
    637   case EfiUsbPortEnable:
    638     //
    639     // Ports may only be enabled by the xHC. Software cannot enable a port by writing a '1' to this flag.
    640     // A port may be disabled by software writing a '1' to this flag.
    641     //
    642     State |= XHC_PORTSC_PED;
    643     State &= ~XHC_PORTSC_RESET;
    644     XhcWriteOpReg (Xhc, Offset, State);
    645     break;
    646 
    647   case EfiUsbPortSuspend:
    648     State |= XHC_PORTSC_LWS;
    649     XhcWriteOpReg (Xhc, Offset, State);
    650     State &= ~XHC_PORTSC_PLS;
    651     XhcWriteOpReg (Xhc, Offset, State);
    652     break;
    653 
    654   case EfiUsbPortReset:
    655     //
    656     // PORTSC_RESET BIT(4) bit is RW1S attribute, which means Write-1-to-set status:
    657     // Register bits indicate status when read, a clear bit may be set by
    658     // writing a '1'. Writing a '0' to RW1S bits has no effect.
    659     //
    660     break;
    661 
    662   case EfiUsbPortOwner:
    663     //
    664     // XHCI root hub port don't has the owner bit, ignore the operation
    665     //
    666     break;
    667 
    668   case EfiUsbPortConnectChange:
    669     //
    670     // Clear connect status change
    671     //
    672     State |= XHC_PORTSC_CSC;
    673     XhcWriteOpReg (Xhc, Offset, State);
    674     break;
    675 
    676   case EfiUsbPortEnableChange:
    677     //
    678     // Clear enable status change
    679     //
    680     State |= XHC_PORTSC_PEC;
    681     XhcWriteOpReg (Xhc, Offset, State);
    682     break;
    683 
    684   case EfiUsbPortOverCurrentChange:
    685     //
    686     // Clear PortOverCurrent change
    687     //
    688     State |= XHC_PORTSC_OCC;
    689     XhcWriteOpReg (Xhc, Offset, State);
    690     break;
    691 
    692   case EfiUsbPortResetChange:
    693     //
    694     // Clear Port Reset change
    695     //
    696     State |= XHC_PORTSC_PRC;
    697     XhcWriteOpReg (Xhc, Offset, State);
    698     break;
    699 
    700   case EfiUsbPortPower:
    701   case EfiUsbPortSuspendChange:
    702     //
    703     // Not supported or not related operation
    704     //
    705     break;
    706 
    707   default:
    708     Status = EFI_INVALID_PARAMETER;
    709     break;
    710   }
    711 
    712 ON_EXIT:
    713   DEBUG ((EFI_D_INFO, "XhcClearRootHubPortFeature: status %r\n", Status));
    714   gBS->RestoreTPL (OldTpl);
    715 
    716   return Status;
    717 }
    718 
    719 
    720 /**
    721   Submits control transfer to a target USB device.
    722 
    723   @param  This                  This EFI_USB2_HC_PROTOCOL instance.
    724   @param  DeviceAddress         The target device address.
    725   @param  DeviceSpeed           Target device speed.
    726   @param  MaximumPacketLength   Maximum packet size the default control transfer
    727                                 endpoint is capable of sending or receiving.
    728   @param  Request               USB device request to send.
    729   @param  TransferDirection     Specifies the data direction for the data stage
    730   @param  Data                  Data buffer to be transmitted or received from USB
    731                                 device.
    732   @param  DataLength            The size (in bytes) of the data buffer.
    733   @param  Timeout               Indicates the maximum timeout, in millisecond.
    734   @param  Translator            Transaction translator to be used by this device.
    735   @param  TransferResult        Return the result of this control transfer.
    736 
    737   @retval EFI_SUCCESS           Transfer was completed successfully.
    738   @retval EFI_OUT_OF_RESOURCES  The transfer failed due to lack of resources.
    739   @retval EFI_INVALID_PARAMETER Some parameters are invalid.
    740   @retval EFI_TIMEOUT           Transfer failed due to timeout.
    741   @retval EFI_DEVICE_ERROR      Transfer failed due to host controller or device error.
    742 
    743 **/
    744 EFI_STATUS
    745 EFIAPI
    746 XhcControlTransfer (
    747   IN     EFI_USB2_HC_PROTOCOL                *This,
    748   IN     UINT8                               DeviceAddress,
    749   IN     UINT8                               DeviceSpeed,
    750   IN     UINTN                               MaximumPacketLength,
    751   IN     EFI_USB_DEVICE_REQUEST              *Request,
    752   IN     EFI_USB_DATA_DIRECTION              TransferDirection,
    753   IN OUT VOID                                *Data,
    754   IN OUT UINTN                               *DataLength,
    755   IN     UINTN                               Timeout,
    756   IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
    757   OUT    UINT32                              *TransferResult
    758   )
    759 {
    760   USB_XHCI_INSTANCE       *Xhc;
    761   URB                     *Urb;
    762   UINT8                   Endpoint;
    763   UINT8                   Index;
    764   UINT8                   DescriptorType;
    765   UINT8                   SlotId;
    766   UINT8                   TTT;
    767   UINT8                   MTT;
    768   UINT32                  MaxPacket0;
    769   EFI_USB_HUB_DESCRIPTOR  *HubDesc;
    770   EFI_TPL                 OldTpl;
    771   EFI_STATUS              Status;
    772   EFI_STATUS              RecoveryStatus;
    773   UINTN                   MapSize;
    774   EFI_USB_PORT_STATUS     PortStatus;
    775   UINT32                  State;
    776   EFI_USB_DEVICE_REQUEST  ClearPortRequest;
    777   UINTN                   Len;
    778 
    779   //
    780   // Validate parameters
    781   //
    782   if ((Request == NULL) || (TransferResult == NULL)) {
    783     return EFI_INVALID_PARAMETER;
    784   }
    785 
    786   if ((TransferDirection != EfiUsbDataIn) &&
    787       (TransferDirection != EfiUsbDataOut) &&
    788       (TransferDirection != EfiUsbNoData)) {
    789     return EFI_INVALID_PARAMETER;
    790   }
    791 
    792   if ((TransferDirection == EfiUsbNoData) &&
    793       ((Data != NULL) || (*DataLength != 0))) {
    794     return EFI_INVALID_PARAMETER;
    795   }
    796 
    797   if ((TransferDirection != EfiUsbNoData) &&
    798      ((Data == NULL) || (*DataLength == 0))) {
    799     return EFI_INVALID_PARAMETER;
    800   }
    801 
    802   if ((MaximumPacketLength != 8)  && (MaximumPacketLength != 16) &&
    803       (MaximumPacketLength != 32) && (MaximumPacketLength != 64) &&
    804       (MaximumPacketLength != 512)
    805       ) {
    806     return EFI_INVALID_PARAMETER;
    807   }
    808 
    809   if ((DeviceSpeed == EFI_USB_SPEED_LOW) && (MaximumPacketLength != 8)) {
    810     return EFI_INVALID_PARAMETER;
    811   }
    812 
    813   if ((DeviceSpeed == EFI_USB_SPEED_SUPER) && (MaximumPacketLength != 512)) {
    814     return EFI_INVALID_PARAMETER;
    815   }
    816 
    817   OldTpl = gBS->RaiseTPL (XHC_TPL);
    818 
    819   Xhc             = XHC_FROM_THIS (This);
    820 
    821   Status          = EFI_DEVICE_ERROR;
    822   *TransferResult = EFI_USB_ERR_SYSTEM;
    823   Len             = 0;
    824 
    825   if (XhcIsHalt (Xhc) || XhcIsSysError (Xhc)) {
    826     DEBUG ((EFI_D_ERROR, "XhcControlTransfer: HC halted at entrance\n"));
    827     goto ON_EXIT;
    828   }
    829 
    830   //
    831   // Check if the device is still enabled before every transaction.
    832   //
    833   SlotId = XhcBusDevAddrToSlotId (Xhc, DeviceAddress);
    834   if (SlotId == 0) {
    835     goto ON_EXIT;
    836   }
    837 
    838   //
    839   // Hook the Set_Address request from UsbBus.
    840   // According to XHCI 1.0 spec, the Set_Address request is replaced by XHCI's Address_Device cmd.
    841   //
    842   if ((Request->Request     == USB_REQ_SET_ADDRESS) &&
    843       (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD, USB_TARGET_DEVICE))) {
    844     //
    845     // Reset the BusDevAddr field of all disabled entries in UsbDevContext array firstly.
    846     // This way is used to clean the history to avoid using wrong device address by XhcAsyncInterruptTransfer().
    847     //
    848     for (Index = 0; Index < 255; Index++) {
    849       if (!Xhc->UsbDevContext[Index + 1].Enabled &&
    850           (Xhc->UsbDevContext[Index + 1].SlotId == 0) &&
    851           (Xhc->UsbDevContext[Index + 1].BusDevAddr == (UINT8)Request->Value)) {
    852         Xhc->UsbDevContext[Index + 1].BusDevAddr = 0;
    853       }
    854     }
    855 
    856     if (Xhc->UsbDevContext[SlotId].XhciDevAddr == 0) {
    857       Status = EFI_DEVICE_ERROR;
    858       goto ON_EXIT;
    859     }
    860     //
    861     // The actual device address has been assigned by XHCI during initializing the device slot.
    862     // So we just need establish the mapping relationship between the device address requested from UsbBus
    863     // and the actual device address assigned by XHCI. The the following invocations through EFI_USB2_HC_PROTOCOL interface
    864     // can find out the actual device address by it.
    865     //
    866     Xhc->UsbDevContext[SlotId].BusDevAddr = (UINT8)Request->Value;
    867     Status = EFI_SUCCESS;
    868     goto ON_EXIT;
    869   }
    870 
    871   //
    872   // Create a new URB, insert it into the asynchronous
    873   // schedule list, then poll the execution status.
    874   // Note that we encode the direction in address although default control
    875   // endpoint is bidirectional. XhcCreateUrb expects this
    876   // combination of Ep addr and its direction.
    877   //
    878   Endpoint = (UINT8) (0 | ((TransferDirection == EfiUsbDataIn) ? 0x80 : 0));
    879   Urb = XhcCreateUrb (
    880           Xhc,
    881           DeviceAddress,
    882           Endpoint,
    883           DeviceSpeed,
    884           MaximumPacketLength,
    885           XHC_CTRL_TRANSFER,
    886           Request,
    887           Data,
    888           *DataLength,
    889           NULL,
    890           NULL
    891           );
    892 
    893   if (Urb == NULL) {
    894     DEBUG ((EFI_D_ERROR, "XhcControlTransfer: failed to create URB"));
    895     Status = EFI_OUT_OF_RESOURCES;
    896     goto ON_EXIT;
    897   }
    898 
    899   Status = XhcExecTransfer (Xhc, FALSE, Urb, Timeout);
    900 
    901   //
    902   // Get the status from URB. The result is updated in XhcCheckUrbResult
    903   // which is called by XhcExecTransfer
    904   //
    905   *TransferResult = Urb->Result;
    906   *DataLength     = Urb->Completed;
    907 
    908   if (Status == EFI_TIMEOUT) {
    909     //
    910     // The transfer timed out. Abort the transfer by dequeueing of the TD.
    911     //
    912     RecoveryStatus = XhcDequeueTrbFromEndpoint(Xhc, Urb);
    913     if (EFI_ERROR(RecoveryStatus)) {
    914       DEBUG((EFI_D_ERROR, "XhcControlTransfer: XhcDequeueTrbFromEndpoint failed\n"));
    915     }
    916     goto FREE_URB;
    917   } else {
    918     if (*TransferResult == EFI_USB_NOERROR) {
    919       Status = EFI_SUCCESS;
    920     } else if (*TransferResult == EFI_USB_ERR_STALL) {
    921       RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);
    922       if (EFI_ERROR (RecoveryStatus)) {
    923         DEBUG ((EFI_D_ERROR, "XhcControlTransfer: XhcRecoverHaltedEndpoint failed\n"));
    924       }
    925       Status = EFI_DEVICE_ERROR;
    926       goto FREE_URB;
    927     } else {
    928       goto FREE_URB;
    929     }
    930   }
    931 
    932   Xhc->PciIo->Flush (Xhc->PciIo);
    933 
    934   if (Urb->DataMap != NULL) {
    935     Status = Xhc->PciIo->Unmap (Xhc->PciIo, Urb->DataMap);
    936     ASSERT_EFI_ERROR (Status);
    937     if (EFI_ERROR (Status)) {
    938       Status = EFI_DEVICE_ERROR;
    939       goto FREE_URB;
    940     }
    941   }
    942 
    943   //
    944   // Hook Get_Descriptor request from UsbBus as we need evaluate context and configure endpoint.
    945   // Hook Get_Status request form UsbBus as we need trace device attach/detach event happened at hub.
    946   // Hook Set_Config request from UsbBus as we need configure device endpoint.
    947   //
    948   if ((Request->Request     == USB_REQ_GET_DESCRIPTOR) &&
    949       ((Request->RequestType == USB_REQUEST_TYPE (EfiUsbDataIn, USB_REQ_TYPE_STANDARD, USB_TARGET_DEVICE)) ||
    950       ((Request->RequestType == USB_REQUEST_TYPE (EfiUsbDataIn, USB_REQ_TYPE_CLASS, USB_TARGET_DEVICE))))) {
    951     DescriptorType = (UINT8)(Request->Value >> 8);
    952     if ((DescriptorType == USB_DESC_TYPE_DEVICE) && ((*DataLength == sizeof (EFI_USB_DEVICE_DESCRIPTOR)) || ((DeviceSpeed == EFI_USB_SPEED_FULL) && (*DataLength == 8)))) {
    953         ASSERT (Data != NULL);
    954         //
    955         // Store a copy of device scriptor as hub device need this info to configure endpoint.
    956         //
    957         CopyMem (&Xhc->UsbDevContext[SlotId].DevDesc, Data, *DataLength);
    958         if (Xhc->UsbDevContext[SlotId].DevDesc.BcdUSB == 0x0300) {
    959           //
    960           // If it's a usb3.0 device, then its max packet size is a 2^n.
    961           //
    962           MaxPacket0 = 1 << Xhc->UsbDevContext[SlotId].DevDesc.MaxPacketSize0;
    963         } else {
    964           MaxPacket0 = Xhc->UsbDevContext[SlotId].DevDesc.MaxPacketSize0;
    965         }
    966         Xhc->UsbDevContext[SlotId].ConfDesc = AllocateZeroPool (Xhc->UsbDevContext[SlotId].DevDesc.NumConfigurations * sizeof (EFI_USB_CONFIG_DESCRIPTOR *));
    967         if (Xhc->HcCParams.Data.Csz == 0) {
    968           Status = XhcEvaluateContext (Xhc, SlotId, MaxPacket0);
    969         } else {
    970           Status = XhcEvaluateContext64 (Xhc, SlotId, MaxPacket0);
    971         }
    972     } else if (DescriptorType == USB_DESC_TYPE_CONFIG) {
    973       ASSERT (Data != NULL);
    974       if (*DataLength == ((UINT16 *)Data)[1]) {
    975         //
    976         // Get configuration value from request, Store the configuration descriptor for Configure_Endpoint cmd.
    977         //
    978         Index = (UINT8)Request->Value;
    979         ASSERT (Index < Xhc->UsbDevContext[SlotId].DevDesc.NumConfigurations);
    980         Xhc->UsbDevContext[SlotId].ConfDesc[Index] = AllocateZeroPool(*DataLength);
    981         CopyMem (Xhc->UsbDevContext[SlotId].ConfDesc[Index], Data, *DataLength);
    982         //
    983         // Default to use AlternateSetting 0 for all interfaces.
    984         //
    985         Xhc->UsbDevContext[SlotId].ActiveAlternateSetting = AllocateZeroPool (Xhc->UsbDevContext[SlotId].ConfDesc[Index]->NumInterfaces * sizeof (UINT8));
    986       }
    987     } else if (((DescriptorType == USB_DESC_TYPE_HUB) ||
    988                (DescriptorType == USB_DESC_TYPE_HUB_SUPER_SPEED)) && (*DataLength > 2)) {
    989       ASSERT (Data != NULL);
    990       HubDesc = (EFI_USB_HUB_DESCRIPTOR *)Data;
    991       ASSERT (HubDesc->NumPorts <= 15);
    992       //
    993       // The bit 5,6 of HubCharacter field of Hub Descriptor is TTT.
    994       //
    995       TTT = (UINT8)((HubDesc->HubCharacter & (BIT5 | BIT6)) >> 5);
    996       if (Xhc->UsbDevContext[SlotId].DevDesc.DeviceProtocol == 2) {
    997         //
    998         // Don't support multi-TT feature for super speed hub now.
    999         //
   1000         MTT = 0;
   1001         DEBUG ((EFI_D_ERROR, "XHCI: Don't support multi-TT feature for Hub now. (force to disable MTT)\n"));
   1002       } else {
   1003         MTT = 0;
   1004       }
   1005 
   1006       if (Xhc->HcCParams.Data.Csz == 0) {
   1007         Status = XhcConfigHubContext (Xhc, SlotId, HubDesc->NumPorts, TTT, MTT);
   1008       } else {
   1009         Status = XhcConfigHubContext64 (Xhc, SlotId, HubDesc->NumPorts, TTT, MTT);
   1010       }
   1011     }
   1012   } else if ((Request->Request     == USB_REQ_SET_CONFIG) &&
   1013              (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD, USB_TARGET_DEVICE))) {
   1014     //
   1015     // Hook Set_Config request from UsbBus as we need configure device endpoint.
   1016     //
   1017     for (Index = 0; Index < Xhc->UsbDevContext[SlotId].DevDesc.NumConfigurations; Index++) {
   1018       if (Xhc->UsbDevContext[SlotId].ConfDesc[Index]->ConfigurationValue == (UINT8)Request->Value) {
   1019         if (Xhc->HcCParams.Data.Csz == 0) {
   1020           Status = XhcSetConfigCmd (Xhc, SlotId, DeviceSpeed, Xhc->UsbDevContext[SlotId].ConfDesc[Index]);
   1021         } else {
   1022           Status = XhcSetConfigCmd64 (Xhc, SlotId, DeviceSpeed, Xhc->UsbDevContext[SlotId].ConfDesc[Index]);
   1023         }
   1024         break;
   1025       }
   1026     }
   1027   } else if ((Request->Request     == USB_REQ_SET_INTERFACE) &&
   1028              (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD, USB_TARGET_INTERFACE))) {
   1029     //
   1030     // Hook Set_Interface request from UsbBus as we need configure interface setting.
   1031     // Request->Value indicates AlterlateSetting to set
   1032     // Request->Index indicates Interface to set
   1033     //
   1034     if (Xhc->UsbDevContext[SlotId].ActiveAlternateSetting[(UINT8) Request->Index] != (UINT8) Request->Value) {
   1035       if (Xhc->HcCParams.Data.Csz == 0) {
   1036         Status = XhcSetInterface (Xhc, SlotId, DeviceSpeed, Xhc->UsbDevContext[SlotId].ConfDesc[Xhc->UsbDevContext[SlotId].ActiveConfiguration - 1], Request);
   1037       } else {
   1038         Status = XhcSetInterface64 (Xhc, SlotId, DeviceSpeed, Xhc->UsbDevContext[SlotId].ConfDesc[Xhc->UsbDevContext[SlotId].ActiveConfiguration - 1], Request);
   1039       }
   1040     }
   1041   } else if ((Request->Request     == USB_REQ_GET_STATUS) &&
   1042              (Request->RequestType == USB_REQUEST_TYPE (EfiUsbDataIn, USB_REQ_TYPE_CLASS, USB_TARGET_OTHER))) {
   1043     ASSERT (Data != NULL);
   1044     //
   1045     // Hook Get_Status request from UsbBus to keep track of the port status change.
   1046     //
   1047     State                       = *(UINT32 *)Data;
   1048     PortStatus.PortStatus       = 0;
   1049     PortStatus.PortChangeStatus = 0;
   1050 
   1051     if (DeviceSpeed == EFI_USB_SPEED_SUPER) {
   1052       //
   1053       // For super speed hub, its bit10~12 presents the attached device speed.
   1054       //
   1055       if ((State & XHC_PORTSC_PS) >> 10 == 0) {
   1056         PortStatus.PortStatus |= USB_PORT_STAT_SUPER_SPEED;
   1057       }
   1058     } else {
   1059       //
   1060       // For high or full/low speed hub, its bit9~10 presents the attached device speed.
   1061       //
   1062       if (XHC_BIT_IS_SET (State, BIT9)) {
   1063         PortStatus.PortStatus |= USB_PORT_STAT_LOW_SPEED;
   1064       } else if (XHC_BIT_IS_SET (State, BIT10)) {
   1065         PortStatus.PortStatus |= USB_PORT_STAT_HIGH_SPEED;
   1066       }
   1067     }
   1068 
   1069     //
   1070     // Convert the XHCI port/port change state to UEFI status
   1071     //
   1072     MapSize = sizeof (mUsbHubPortStateMap) / sizeof (USB_PORT_STATE_MAP);
   1073     for (Index = 0; Index < MapSize; Index++) {
   1074       if (XHC_BIT_IS_SET (State, mUsbHubPortStateMap[Index].HwState)) {
   1075         PortStatus.PortStatus = (UINT16) (PortStatus.PortStatus | mUsbHubPortStateMap[Index].UefiState);
   1076       }
   1077     }
   1078 
   1079     MapSize = sizeof (mUsbHubPortChangeMap) / sizeof (USB_PORT_STATE_MAP);
   1080     for (Index = 0; Index < MapSize; Index++) {
   1081       if (XHC_BIT_IS_SET (State, mUsbHubPortChangeMap[Index].HwState)) {
   1082         PortStatus.PortChangeStatus = (UINT16) (PortStatus.PortChangeStatus | mUsbHubPortChangeMap[Index].UefiState);
   1083       }
   1084     }
   1085 
   1086     MapSize = sizeof (mUsbHubClearPortChangeMap) / sizeof (USB_CLEAR_PORT_MAP);
   1087 
   1088     for (Index = 0; Index < MapSize; Index++) {
   1089       if (XHC_BIT_IS_SET (State, mUsbHubClearPortChangeMap[Index].HwState)) {
   1090         ZeroMem (&ClearPortRequest, sizeof (EFI_USB_DEVICE_REQUEST));
   1091         ClearPortRequest.RequestType  = USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_CLASS, USB_TARGET_OTHER);
   1092         ClearPortRequest.Request      = (UINT8) USB_REQ_CLEAR_FEATURE;
   1093         ClearPortRequest.Value        = mUsbHubClearPortChangeMap[Index].Selector;
   1094         ClearPortRequest.Index        = Request->Index;
   1095         ClearPortRequest.Length       = 0;
   1096 
   1097         XhcControlTransfer (
   1098           This,
   1099           DeviceAddress,
   1100           DeviceSpeed,
   1101           MaximumPacketLength,
   1102           &ClearPortRequest,
   1103           EfiUsbNoData,
   1104           NULL,
   1105           &Len,
   1106           Timeout,
   1107           Translator,
   1108           TransferResult
   1109           );
   1110       }
   1111     }
   1112 
   1113     XhcPollPortStatusChange (Xhc, Xhc->UsbDevContext[SlotId].RouteString, (UINT8)Request->Index, &PortStatus);
   1114 
   1115     *(UINT32 *)Data = *(UINT32*)&PortStatus;
   1116   }
   1117 
   1118 FREE_URB:
   1119   FreePool (Urb);
   1120 
   1121 ON_EXIT:
   1122 
   1123   if (EFI_ERROR (Status)) {
   1124     DEBUG ((EFI_D_ERROR, "XhcControlTransfer: error - %r, transfer - %x\n", Status, *TransferResult));
   1125   }
   1126 
   1127   gBS->RestoreTPL (OldTpl);
   1128 
   1129   return Status;
   1130 }
   1131 
   1132 
   1133 /**
   1134   Submits bulk transfer to a bulk endpoint of a USB device.
   1135 
   1136   @param  This                  This EFI_USB2_HC_PROTOCOL instance.
   1137   @param  DeviceAddress         Target device address.
   1138   @param  EndPointAddress       Endpoint number and its direction in bit 7.
   1139   @param  DeviceSpeed           Device speed, Low speed device doesn't support bulk
   1140                                 transfer.
   1141   @param  MaximumPacketLength   Maximum packet size the endpoint is capable of
   1142                                 sending or receiving.
   1143   @param  DataBuffersNumber     Number of data buffers prepared for the transfer.
   1144   @param  Data                  Array of pointers to the buffers of data to transmit
   1145                                 from or receive into.
   1146   @param  DataLength            The lenght of the data buffer.
   1147   @param  DataToggle            On input, the initial data toggle for the transfer;
   1148                                 On output, it is updated to to next data toggle to
   1149                                 use of the subsequent bulk transfer.
   1150   @param  Timeout               Indicates the maximum time, in millisecond, which
   1151                                 the transfer is allowed to complete.
   1152   @param  Translator            A pointr to the transaction translator data.
   1153   @param  TransferResult        A pointer to the detailed result information of the
   1154                                 bulk transfer.
   1155 
   1156   @retval EFI_SUCCESS           The transfer was completed successfully.
   1157   @retval EFI_OUT_OF_RESOURCES  The transfer failed due to lack of resource.
   1158   @retval EFI_INVALID_PARAMETER Some parameters are invalid.
   1159   @retval EFI_TIMEOUT           The transfer failed due to timeout.
   1160   @retval EFI_DEVICE_ERROR      The transfer failed due to host controller error.
   1161 
   1162 **/
   1163 EFI_STATUS
   1164 EFIAPI
   1165 XhcBulkTransfer (
   1166   IN     EFI_USB2_HC_PROTOCOL                *This,
   1167   IN     UINT8                               DeviceAddress,
   1168   IN     UINT8                               EndPointAddress,
   1169   IN     UINT8                               DeviceSpeed,
   1170   IN     UINTN                               MaximumPacketLength,
   1171   IN     UINT8                               DataBuffersNumber,
   1172   IN OUT VOID                                *Data[EFI_USB_MAX_BULK_BUFFER_NUM],
   1173   IN OUT UINTN                               *DataLength,
   1174   IN OUT UINT8                               *DataToggle,
   1175   IN     UINTN                               Timeout,
   1176   IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
   1177   OUT    UINT32                              *TransferResult
   1178   )
   1179 {
   1180   USB_XHCI_INSTANCE       *Xhc;
   1181   URB                     *Urb;
   1182   UINT8                   SlotId;
   1183   EFI_STATUS              Status;
   1184   EFI_STATUS              RecoveryStatus;
   1185   EFI_TPL                 OldTpl;
   1186 
   1187   //
   1188   // Validate the parameters
   1189   //
   1190   if ((DataLength == NULL) || (*DataLength == 0) ||
   1191       (Data == NULL) || (Data[0] == NULL) || (TransferResult == NULL)) {
   1192     return EFI_INVALID_PARAMETER;
   1193   }
   1194 
   1195   if ((*DataToggle != 0) && (*DataToggle != 1)) {
   1196     return EFI_INVALID_PARAMETER;
   1197   }
   1198 
   1199   if ((DeviceSpeed == EFI_USB_SPEED_LOW) ||
   1200       ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||
   1201       ((EFI_USB_SPEED_HIGH == DeviceSpeed) && (MaximumPacketLength > 512)) ||
   1202       ((EFI_USB_SPEED_SUPER == DeviceSpeed) && (MaximumPacketLength > 1024))) {
   1203     return EFI_INVALID_PARAMETER;
   1204   }
   1205 
   1206   OldTpl = gBS->RaiseTPL (XHC_TPL);
   1207 
   1208   Xhc             = XHC_FROM_THIS (This);
   1209 
   1210   *TransferResult = EFI_USB_ERR_SYSTEM;
   1211   Status          = EFI_DEVICE_ERROR;
   1212 
   1213   if (XhcIsHalt (Xhc) || XhcIsSysError (Xhc)) {
   1214     DEBUG ((EFI_D_ERROR, "XhcBulkTransfer: HC is halted\n"));
   1215     goto ON_EXIT;
   1216   }
   1217 
   1218   //
   1219   // Check if the device is still enabled before every transaction.
   1220   //
   1221   SlotId = XhcBusDevAddrToSlotId (Xhc, DeviceAddress);
   1222   if (SlotId == 0) {
   1223     goto ON_EXIT;
   1224   }
   1225 
   1226   //
   1227   // Create a new URB, insert it into the asynchronous
   1228   // schedule list, then poll the execution status.
   1229   //
   1230   Urb = XhcCreateUrb (
   1231           Xhc,
   1232           DeviceAddress,
   1233           EndPointAddress,
   1234           DeviceSpeed,
   1235           MaximumPacketLength,
   1236           XHC_BULK_TRANSFER,
   1237           NULL,
   1238           Data[0],
   1239           *DataLength,
   1240           NULL,
   1241           NULL
   1242           );
   1243 
   1244   if (Urb == NULL) {
   1245     DEBUG ((EFI_D_ERROR, "XhcBulkTransfer: failed to create URB\n"));
   1246     Status = EFI_OUT_OF_RESOURCES;
   1247     goto ON_EXIT;
   1248   }
   1249 
   1250   Status = XhcExecTransfer (Xhc, FALSE, Urb, Timeout);
   1251 
   1252   *TransferResult = Urb->Result;
   1253   *DataLength     = Urb->Completed;
   1254 
   1255   if (Status == EFI_TIMEOUT) {
   1256     //
   1257     // The transfer timed out. Abort the transfer by dequeueing of the TD.
   1258     //
   1259     RecoveryStatus = XhcDequeueTrbFromEndpoint(Xhc, Urb);
   1260     if (EFI_ERROR(RecoveryStatus)) {
   1261       DEBUG((EFI_D_ERROR, "XhcBulkTransfer: XhcDequeueTrbFromEndpoint failed\n"));
   1262     }
   1263   } else {
   1264     if (*TransferResult == EFI_USB_NOERROR) {
   1265       Status = EFI_SUCCESS;
   1266     } else if (*TransferResult == EFI_USB_ERR_STALL) {
   1267       RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);
   1268       if (EFI_ERROR (RecoveryStatus)) {
   1269         DEBUG ((EFI_D_ERROR, "XhcBulkTransfer: XhcRecoverHaltedEndpoint failed\n"));
   1270       }
   1271       Status = EFI_DEVICE_ERROR;
   1272     }
   1273   }
   1274 
   1275   Xhc->PciIo->Flush (Xhc->PciIo);
   1276   XhcFreeUrb (Xhc, Urb);
   1277 
   1278 ON_EXIT:
   1279 
   1280   if (EFI_ERROR (Status)) {
   1281     DEBUG ((EFI_D_ERROR, "XhcBulkTransfer: error - %r, transfer - %x\n", Status, *TransferResult));
   1282   }
   1283   gBS->RestoreTPL (OldTpl);
   1284 
   1285   return Status;
   1286 }
   1287 
   1288 /**
   1289   Submits an asynchronous interrupt transfer to an
   1290   interrupt endpoint of a USB device.
   1291 
   1292   @param  This                  This EFI_USB2_HC_PROTOCOL instance.
   1293   @param  DeviceAddress         Target device address.
   1294   @param  EndPointAddress       Endpoint number and its direction encoded in bit 7
   1295   @param  DeviceSpeed           Indicates device speed.
   1296   @param  MaximumPacketLength   Maximum packet size the target endpoint is capable
   1297   @param  IsNewTransfer         If TRUE, to submit an new asynchronous interrupt
   1298                                 transfer If FALSE, to remove the specified
   1299                                 asynchronous interrupt.
   1300   @param  DataToggle            On input, the initial data toggle to use; on output,
   1301                                 it is updated to indicate the next data toggle.
   1302   @param  PollingInterval       The he interval, in milliseconds, that the transfer
   1303                                 is polled.
   1304   @param  DataLength            The length of data to receive at the rate specified
   1305                                 by  PollingInterval.
   1306   @param  Translator            Transaction translator to use.
   1307   @param  CallBackFunction      Function to call at the rate specified by
   1308                                 PollingInterval.
   1309   @param  Context               Context to CallBackFunction.
   1310 
   1311   @retval EFI_SUCCESS           The request has been successfully submitted or canceled.
   1312   @retval EFI_INVALID_PARAMETER Some parameters are invalid.
   1313   @retval EFI_OUT_OF_RESOURCES  The request failed due to a lack of resources.
   1314   @retval EFI_DEVICE_ERROR      The transfer failed due to host controller error.
   1315 
   1316 **/
   1317 EFI_STATUS
   1318 EFIAPI
   1319 XhcAsyncInterruptTransfer (
   1320   IN     EFI_USB2_HC_PROTOCOL                *This,
   1321   IN     UINT8                               DeviceAddress,
   1322   IN     UINT8                               EndPointAddress,
   1323   IN     UINT8                               DeviceSpeed,
   1324   IN     UINTN                               MaximumPacketLength,
   1325   IN     BOOLEAN                             IsNewTransfer,
   1326   IN OUT UINT8                               *DataToggle,
   1327   IN     UINTN                               PollingInterval,
   1328   IN     UINTN                               DataLength,
   1329   IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
   1330   IN     EFI_ASYNC_USB_TRANSFER_CALLBACK     CallBackFunction,
   1331   IN     VOID                                *Context OPTIONAL
   1332   )
   1333 {
   1334   USB_XHCI_INSTANCE       *Xhc;
   1335   URB                     *Urb;
   1336   EFI_STATUS              Status;
   1337   UINT8                   SlotId;
   1338   UINT8                   Index;
   1339   UINT8                   *Data;
   1340   EFI_TPL                 OldTpl;
   1341 
   1342   //
   1343   // Validate parameters
   1344   //
   1345   if (!XHCI_IS_DATAIN (EndPointAddress)) {
   1346     return EFI_INVALID_PARAMETER;
   1347   }
   1348 
   1349   if (IsNewTransfer) {
   1350     if (DataLength == 0) {
   1351       return EFI_INVALID_PARAMETER;
   1352     }
   1353 
   1354     if ((*DataToggle != 1) && (*DataToggle != 0)) {
   1355       return EFI_INVALID_PARAMETER;
   1356     }
   1357 
   1358     if ((PollingInterval > 255) || (PollingInterval < 1)) {
   1359       return EFI_INVALID_PARAMETER;
   1360     }
   1361   }
   1362 
   1363   OldTpl = gBS->RaiseTPL (XHC_TPL);
   1364 
   1365   Xhc    = XHC_FROM_THIS (This);
   1366 
   1367   //
   1368   // Delete Async interrupt transfer request.
   1369   //
   1370   if (!IsNewTransfer) {
   1371     //
   1372     // The delete request may happen after device is detached.
   1373     //
   1374     for (Index = 0; Index < 255; Index++) {
   1375       if (Xhc->UsbDevContext[Index + 1].BusDevAddr == DeviceAddress) {
   1376         break;
   1377       }
   1378     }
   1379 
   1380     if (Index == 255) {
   1381       Status = EFI_INVALID_PARAMETER;
   1382       goto ON_EXIT;
   1383     }
   1384 
   1385     Status = XhciDelAsyncIntTransfer (Xhc, DeviceAddress, EndPointAddress);
   1386     DEBUG ((EFI_D_INFO, "XhcAsyncInterruptTransfer: remove old transfer for addr %d, Status = %r\n", DeviceAddress, Status));
   1387     goto ON_EXIT;
   1388   }
   1389 
   1390   Status = EFI_SUCCESS;
   1391 
   1392   if (XhcIsHalt (Xhc) || XhcIsSysError (Xhc)) {
   1393     DEBUG ((EFI_D_ERROR, "XhcAsyncInterruptTransfer: HC is halt\n"));
   1394     Status = EFI_DEVICE_ERROR;
   1395     goto ON_EXIT;
   1396   }
   1397 
   1398   //
   1399   // Check if the device is still enabled before every transaction.
   1400   //
   1401   SlotId = XhcBusDevAddrToSlotId (Xhc, DeviceAddress);
   1402   if (SlotId == 0) {
   1403     goto ON_EXIT;
   1404   }
   1405 
   1406   Data = AllocateZeroPool (DataLength);
   1407 
   1408   if (Data == NULL) {
   1409     DEBUG ((EFI_D_ERROR, "XhcAsyncInterruptTransfer: failed to allocate buffer\n"));
   1410     Status = EFI_OUT_OF_RESOURCES;
   1411     goto ON_EXIT;
   1412   }
   1413 
   1414   Urb = XhcCreateUrb (
   1415           Xhc,
   1416           DeviceAddress,
   1417           EndPointAddress,
   1418           DeviceSpeed,
   1419           MaximumPacketLength,
   1420           XHC_INT_TRANSFER_ASYNC,
   1421           NULL,
   1422           Data,
   1423           DataLength,
   1424           CallBackFunction,
   1425           Context
   1426           );
   1427 
   1428   if (Urb == NULL) {
   1429     DEBUG ((EFI_D_ERROR, "XhcAsyncInterruptTransfer: failed to create URB\n"));
   1430     FreePool (Data);
   1431     Status = EFI_OUT_OF_RESOURCES;
   1432     goto ON_EXIT;
   1433   }
   1434 
   1435   InsertHeadList (&Xhc->AsyncIntTransfers, &Urb->UrbList);
   1436   //
   1437   // Ring the doorbell
   1438   //
   1439   Status = RingIntTransferDoorBell (Xhc, Urb);
   1440 
   1441 ON_EXIT:
   1442   Xhc->PciIo->Flush (Xhc->PciIo);
   1443   gBS->RestoreTPL (OldTpl);
   1444 
   1445   return Status;
   1446 }
   1447 
   1448 
   1449 /**
   1450   Submits synchronous interrupt transfer to an interrupt endpoint
   1451   of a USB device.
   1452 
   1453   @param  This                  This EFI_USB2_HC_PROTOCOL instance.
   1454   @param  DeviceAddress         Target device address.
   1455   @param  EndPointAddress       Endpoint number and its direction encoded in bit 7
   1456   @param  DeviceSpeed           Indicates device speed.
   1457   @param  MaximumPacketLength   Maximum packet size the target endpoint is capable
   1458                                 of sending or receiving.
   1459   @param  Data                  Buffer of data that will be transmitted to  USB
   1460                                 device or received from USB device.
   1461   @param  DataLength            On input, the size, in bytes, of the data buffer; On
   1462                                 output, the number of bytes transferred.
   1463   @param  DataToggle            On input, the initial data toggle to use; on output,
   1464                                 it is updated to indicate the next data toggle.
   1465   @param  Timeout               Maximum time, in second, to complete.
   1466   @param  Translator            Transaction translator to use.
   1467   @param  TransferResult        Variable to receive the transfer result.
   1468 
   1469   @return EFI_SUCCESS           The transfer was completed successfully.
   1470   @return EFI_OUT_OF_RESOURCES  The transfer failed due to lack of resource.
   1471   @return EFI_INVALID_PARAMETER Some parameters are invalid.
   1472   @return EFI_TIMEOUT           The transfer failed due to timeout.
   1473   @return EFI_DEVICE_ERROR      The failed due to host controller or device error
   1474 
   1475 **/
   1476 EFI_STATUS
   1477 EFIAPI
   1478 XhcSyncInterruptTransfer (
   1479   IN     EFI_USB2_HC_PROTOCOL                *This,
   1480   IN     UINT8                               DeviceAddress,
   1481   IN     UINT8                               EndPointAddress,
   1482   IN     UINT8                               DeviceSpeed,
   1483   IN     UINTN                               MaximumPacketLength,
   1484   IN OUT VOID                                *Data,
   1485   IN OUT UINTN                               *DataLength,
   1486   IN OUT UINT8                               *DataToggle,
   1487   IN     UINTN                               Timeout,
   1488   IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
   1489   OUT    UINT32                              *TransferResult
   1490   )
   1491 {
   1492   USB_XHCI_INSTANCE       *Xhc;
   1493   URB                     *Urb;
   1494   UINT8                   SlotId;
   1495   EFI_STATUS              Status;
   1496   EFI_STATUS              RecoveryStatus;
   1497   EFI_TPL                 OldTpl;
   1498 
   1499   //
   1500   // Validates parameters
   1501   //
   1502   if ((DataLength == NULL) || (*DataLength == 0) ||
   1503       (Data == NULL) || (TransferResult == NULL)) {
   1504     return EFI_INVALID_PARAMETER;
   1505   }
   1506 
   1507   if ((*DataToggle != 1) && (*DataToggle != 0)) {
   1508     return EFI_INVALID_PARAMETER;
   1509   }
   1510 
   1511   if (((DeviceSpeed == EFI_USB_SPEED_LOW) && (MaximumPacketLength != 8))  ||
   1512       ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||
   1513       ((DeviceSpeed == EFI_USB_SPEED_HIGH) && (MaximumPacketLength > 3072))) {
   1514     return EFI_INVALID_PARAMETER;
   1515   }
   1516 
   1517   OldTpl = gBS->RaiseTPL (XHC_TPL);
   1518 
   1519   Xhc     = XHC_FROM_THIS (This);
   1520 
   1521   *TransferResult = EFI_USB_ERR_SYSTEM;
   1522   Status          = EFI_DEVICE_ERROR;
   1523 
   1524   if (XhcIsHalt (Xhc) || XhcIsSysError (Xhc)) {
   1525     DEBUG ((EFI_D_ERROR, "EhcSyncInterruptTransfer: HC is halt\n"));
   1526     goto ON_EXIT;
   1527   }
   1528 
   1529   //
   1530   // Check if the device is still enabled before every transaction.
   1531   //
   1532   SlotId = XhcBusDevAddrToSlotId (Xhc, DeviceAddress);
   1533   if (SlotId == 0) {
   1534     goto ON_EXIT;
   1535   }
   1536 
   1537   Urb = XhcCreateUrb (
   1538           Xhc,
   1539           DeviceAddress,
   1540           EndPointAddress,
   1541           DeviceSpeed,
   1542           MaximumPacketLength,
   1543           XHC_INT_TRANSFER_SYNC,
   1544           NULL,
   1545           Data,
   1546           *DataLength,
   1547           NULL,
   1548           NULL
   1549           );
   1550 
   1551   if (Urb == NULL) {
   1552     DEBUG ((EFI_D_ERROR, "XhcSyncInterruptTransfer: failed to create URB\n"));
   1553     Status = EFI_OUT_OF_RESOURCES;
   1554     goto ON_EXIT;
   1555   }
   1556 
   1557   Status = XhcExecTransfer (Xhc, FALSE, Urb, Timeout);
   1558 
   1559   *TransferResult = Urb->Result;
   1560   *DataLength     = Urb->Completed;
   1561 
   1562   if (Status == EFI_TIMEOUT) {
   1563     //
   1564     // The transfer timed out. Abort the transfer by dequeueing of the TD.
   1565     //
   1566     RecoveryStatus = XhcDequeueTrbFromEndpoint(Xhc, Urb);
   1567     if (EFI_ERROR(RecoveryStatus)) {
   1568       DEBUG((EFI_D_ERROR, "XhcSyncInterruptTransfer: XhcDequeueTrbFromEndpoint failed\n"));
   1569     }
   1570   } else {
   1571     if (*TransferResult == EFI_USB_NOERROR) {
   1572       Status = EFI_SUCCESS;
   1573     } else if (*TransferResult == EFI_USB_ERR_STALL) {
   1574       RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);
   1575       if (EFI_ERROR (RecoveryStatus)) {
   1576         DEBUG ((EFI_D_ERROR, "XhcSyncInterruptTransfer: XhcRecoverHaltedEndpoint failed\n"));
   1577       }
   1578       Status = EFI_DEVICE_ERROR;
   1579     }
   1580   }
   1581 
   1582   Xhc->PciIo->Flush (Xhc->PciIo);
   1583   XhcFreeUrb (Xhc, Urb);
   1584 
   1585 ON_EXIT:
   1586   if (EFI_ERROR (Status)) {
   1587     DEBUG ((EFI_D_ERROR, "XhcSyncInterruptTransfer: error - %r, transfer - %x\n", Status, *TransferResult));
   1588   }
   1589   gBS->RestoreTPL (OldTpl);
   1590 
   1591   return Status;
   1592 }
   1593 
   1594 
   1595 /**
   1596   Submits isochronous transfer to a target USB device.
   1597 
   1598   @param  This                 This EFI_USB2_HC_PROTOCOL instance.
   1599   @param  DeviceAddress        Target device address.
   1600   @param  EndPointAddress      End point address with its direction.
   1601   @param  DeviceSpeed          Device speed, Low speed device doesn't support this
   1602                                type.
   1603   @param  MaximumPacketLength  Maximum packet size that the endpoint is capable of
   1604                                sending or receiving.
   1605   @param  DataBuffersNumber    Number of data buffers prepared for the transfer.
   1606   @param  Data                 Array of pointers to the buffers of data that will
   1607                                be transmitted to USB device or received from USB
   1608                                device.
   1609   @param  DataLength           The size, in bytes, of the data buffer.
   1610   @param  Translator           Transaction translator to use.
   1611   @param  TransferResult       Variable to receive the transfer result.
   1612 
   1613   @return EFI_UNSUPPORTED      Isochronous transfer is unsupported.
   1614 
   1615 **/
   1616 EFI_STATUS
   1617 EFIAPI
   1618 XhcIsochronousTransfer (
   1619   IN     EFI_USB2_HC_PROTOCOL                *This,
   1620   IN     UINT8                               DeviceAddress,
   1621   IN     UINT8                               EndPointAddress,
   1622   IN     UINT8                               DeviceSpeed,
   1623   IN     UINTN                               MaximumPacketLength,
   1624   IN     UINT8                               DataBuffersNumber,
   1625   IN OUT VOID                                *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
   1626   IN     UINTN                               DataLength,
   1627   IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
   1628   OUT    UINT32                              *TransferResult
   1629   )
   1630 {
   1631   return EFI_UNSUPPORTED;
   1632 }
   1633 
   1634 
   1635 /**
   1636   Submits Async isochronous transfer to a target USB device.
   1637 
   1638   @param  This                 This EFI_USB2_HC_PROTOCOL instance.
   1639   @param  DeviceAddress        Target device address.
   1640   @param  EndPointAddress      End point address with its direction.
   1641   @param  DeviceSpeed          Device speed, Low speed device doesn't support this
   1642                                type.
   1643   @param  MaximumPacketLength  Maximum packet size that the endpoint is capable of
   1644                                sending or receiving.
   1645   @param  DataBuffersNumber    Number of data buffers prepared for the transfer.
   1646   @param  Data                 Array of pointers to the buffers of data that will
   1647                                be transmitted to USB device or received from USB
   1648                                device.
   1649   @param  DataLength           The size, in bytes, of the data buffer.
   1650   @param  Translator           Transaction translator to use.
   1651   @param  IsochronousCallBack  Function to be called when the transfer complete.
   1652   @param  Context              Context passed to the call back function as
   1653                                parameter.
   1654 
   1655   @return EFI_UNSUPPORTED      Isochronous transfer isn't supported.
   1656 
   1657 **/
   1658 EFI_STATUS
   1659 EFIAPI
   1660 XhcAsyncIsochronousTransfer (
   1661   IN     EFI_USB2_HC_PROTOCOL                *This,
   1662   IN     UINT8                               DeviceAddress,
   1663   IN     UINT8                               EndPointAddress,
   1664   IN     UINT8                               DeviceSpeed,
   1665   IN     UINTN                               MaximumPacketLength,
   1666   IN     UINT8                               DataBuffersNumber,
   1667   IN OUT VOID                                *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
   1668   IN     UINTN                               DataLength,
   1669   IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
   1670   IN     EFI_ASYNC_USB_TRANSFER_CALLBACK     IsochronousCallBack,
   1671   IN     VOID                                *Context
   1672   )
   1673 {
   1674   return EFI_UNSUPPORTED;
   1675 }
   1676 
   1677 /**
   1678   Entry point for EFI drivers.
   1679 
   1680   @param  ImageHandle       EFI_HANDLE.
   1681   @param  SystemTable       EFI_SYSTEM_TABLE.
   1682 
   1683   @retval EFI_SUCCESS       Success.
   1684   @retval Others            Fail.
   1685 
   1686 **/
   1687 EFI_STATUS
   1688 EFIAPI
   1689 XhcDriverEntryPoint (
   1690   IN EFI_HANDLE           ImageHandle,
   1691   IN EFI_SYSTEM_TABLE     *SystemTable
   1692   )
   1693 {
   1694   return EfiLibInstallDriverBindingComponentName2 (
   1695            ImageHandle,
   1696            SystemTable,
   1697            &gXhciDriverBinding,
   1698            ImageHandle,
   1699            &gXhciComponentName,
   1700            &gXhciComponentName2
   1701            );
   1702 }
   1703 
   1704 
   1705 /**
   1706   Test to see if this driver supports ControllerHandle. Any
   1707   ControllerHandle that has Usb2HcProtocol installed will
   1708   be supported.
   1709 
   1710   @param  This                 Protocol instance pointer.
   1711   @param  Controller           Handle of device to test.
   1712   @param  RemainingDevicePath  Not used.
   1713 
   1714   @return EFI_SUCCESS          This driver supports this device.
   1715   @return EFI_UNSUPPORTED      This driver does not support this device.
   1716 
   1717 **/
   1718 EFI_STATUS
   1719 EFIAPI
   1720 XhcDriverBindingSupported (
   1721   IN EFI_DRIVER_BINDING_PROTOCOL *This,
   1722   IN EFI_HANDLE                  Controller,
   1723   IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath
   1724   )
   1725 {
   1726   EFI_STATUS              Status;
   1727   EFI_PCI_IO_PROTOCOL     *PciIo;
   1728   USB_CLASSC              UsbClassCReg;
   1729 
   1730   //
   1731   // Test whether there is PCI IO Protocol attached on the controller handle.
   1732   //
   1733   Status = gBS->OpenProtocol (
   1734                   Controller,
   1735                   &gEfiPciIoProtocolGuid,
   1736                   (VOID **) &PciIo,
   1737                   This->DriverBindingHandle,
   1738                   Controller,
   1739                   EFI_OPEN_PROTOCOL_BY_DRIVER
   1740                   );
   1741 
   1742   if (EFI_ERROR (Status)) {
   1743     return EFI_UNSUPPORTED;
   1744   }
   1745 
   1746   Status = PciIo->Pci.Read (
   1747                         PciIo,
   1748                         EfiPciIoWidthUint8,
   1749                         PCI_CLASSCODE_OFFSET,
   1750                         sizeof (USB_CLASSC) / sizeof (UINT8),
   1751                         &UsbClassCReg
   1752                         );
   1753 
   1754   if (EFI_ERROR (Status)) {
   1755     Status = EFI_UNSUPPORTED;
   1756     goto ON_EXIT;
   1757   }
   1758 
   1759   //
   1760   // Test whether the controller belongs to Xhci type
   1761   //
   1762   if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) ||
   1763       (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) ||
   1764       (UsbClassCReg.ProgInterface != PCI_IF_XHCI)) {
   1765     Status = EFI_UNSUPPORTED;
   1766   }
   1767 
   1768 ON_EXIT:
   1769   gBS->CloseProtocol (
   1770          Controller,
   1771          &gEfiPciIoProtocolGuid,
   1772          This->DriverBindingHandle,
   1773          Controller
   1774          );
   1775 
   1776   return Status;
   1777 }
   1778 
   1779 /**
   1780   Create and initialize a USB_XHCI_INSTANCE structure.
   1781 
   1782   @param  PciIo                  The PciIo on this device.
   1783   @param  DevicePath             The device path of host controller.
   1784   @param  OriginalPciAttributes  Original PCI attributes.
   1785 
   1786   @return The allocated and initialized USB_XHCI_INSTANCE structure if created,
   1787           otherwise NULL.
   1788 
   1789 **/
   1790 USB_XHCI_INSTANCE*
   1791 XhcCreateUsbHc (
   1792   IN EFI_PCI_IO_PROTOCOL       *PciIo,
   1793   IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
   1794   IN UINT64                    OriginalPciAttributes
   1795   )
   1796 {
   1797   USB_XHCI_INSTANCE       *Xhc;
   1798   EFI_STATUS              Status;
   1799   UINT32                  PageSize;
   1800   UINT16                  ExtCapReg;
   1801 
   1802   Xhc = AllocateZeroPool (sizeof (USB_XHCI_INSTANCE));
   1803 
   1804   if (Xhc == NULL) {
   1805     return NULL;
   1806   }
   1807 
   1808   //
   1809   // Initialize private data structure
   1810   //
   1811   Xhc->Signature             = XHCI_INSTANCE_SIG;
   1812   Xhc->PciIo                 = PciIo;
   1813   Xhc->DevicePath            = DevicePath;
   1814   Xhc->OriginalPciAttributes = OriginalPciAttributes;
   1815   CopyMem (&Xhc->Usb2Hc, &gXhciUsb2HcTemplate, sizeof (EFI_USB2_HC_PROTOCOL));
   1816 
   1817   InitializeListHead (&Xhc->AsyncIntTransfers);
   1818 
   1819   //
   1820   // Be caution that the Offset passed to XhcReadCapReg() should be Dword align
   1821   //
   1822   Xhc->CapLength        = XhcReadCapReg8 (Xhc, XHC_CAPLENGTH_OFFSET);
   1823   Xhc->HcSParams1.Dword = XhcReadCapReg (Xhc, XHC_HCSPARAMS1_OFFSET);
   1824   Xhc->HcSParams2.Dword = XhcReadCapReg (Xhc, XHC_HCSPARAMS2_OFFSET);
   1825   Xhc->HcCParams.Dword  = XhcReadCapReg (Xhc, XHC_HCCPARAMS_OFFSET);
   1826   Xhc->DBOff            = XhcReadCapReg (Xhc, XHC_DBOFF_OFFSET);
   1827   Xhc->RTSOff           = XhcReadCapReg (Xhc, XHC_RTSOFF_OFFSET);
   1828 
   1829   //
   1830   // This PageSize field defines the page size supported by the xHC implementation.
   1831   // This xHC supports a page size of 2^(n+12) if bit n is Set. For example,
   1832   // if bit 0 is Set, the xHC supports 4k byte page sizes.
   1833   //
   1834   PageSize      = XhcReadOpReg(Xhc, XHC_PAGESIZE_OFFSET) & XHC_PAGESIZE_MASK;
   1835   Xhc->PageSize = 1 << (HighBitSet32(PageSize) + 12);
   1836 
   1837   ExtCapReg            = (UINT16) (Xhc->HcCParams.Data.ExtCapReg);
   1838   Xhc->ExtCapRegBase   = ExtCapReg << 2;
   1839   Xhc->UsbLegSupOffset = XhcGetCapabilityAddr (Xhc, XHC_CAP_USB_LEGACY);
   1840   Xhc->DebugCapSupOffset = XhcGetCapabilityAddr (Xhc, XHC_CAP_USB_DEBUG);
   1841 
   1842   DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: Capability length 0x%x\n", Xhc->CapLength));
   1843   DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: HcSParams1 0x%x\n", Xhc->HcSParams1));
   1844   DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: HcSParams2 0x%x\n", Xhc->HcSParams2));
   1845   DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: HcCParams 0x%x\n", Xhc->HcCParams));
   1846   DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: DBOff 0x%x\n", Xhc->DBOff));
   1847   DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: RTSOff 0x%x\n", Xhc->RTSOff));
   1848   DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: UsbLegSupOffset 0x%x\n", Xhc->UsbLegSupOffset));
   1849   DEBUG ((EFI_D_INFO, "XhcCreateUsb3Hc: DebugCapSupOffset 0x%x\n", Xhc->DebugCapSupOffset));
   1850 
   1851   //
   1852   // Create AsyncRequest Polling Timer
   1853   //
   1854   Status = gBS->CreateEvent (
   1855                   EVT_TIMER | EVT_NOTIFY_SIGNAL,
   1856                   TPL_NOTIFY,
   1857                   XhcMonitorAsyncRequests,
   1858                   Xhc,
   1859                   &Xhc->PollTimer
   1860                   );
   1861 
   1862   if (EFI_ERROR (Status)) {
   1863     goto ON_ERROR;
   1864   }
   1865 
   1866   return Xhc;
   1867 
   1868 ON_ERROR:
   1869   FreePool (Xhc);
   1870   return NULL;
   1871 }
   1872 
   1873 /**
   1874   One notified function to stop the Host Controller when gBS->ExitBootServices() called.
   1875 
   1876   @param  Event                   Pointer to this event
   1877   @param  Context                 Event handler private data
   1878 
   1879 **/
   1880 VOID
   1881 EFIAPI
   1882 XhcExitBootService (
   1883   EFI_EVENT  Event,
   1884   VOID       *Context
   1885   )
   1886 
   1887 {
   1888   USB_XHCI_INSTANCE    *Xhc;
   1889   EFI_PCI_IO_PROTOCOL  *PciIo;
   1890 
   1891   Xhc = (USB_XHCI_INSTANCE*) Context;
   1892   PciIo = Xhc->PciIo;
   1893 
   1894   //
   1895   // Stop AsyncRequest Polling timer then stop the XHCI driver
   1896   // and uninstall the XHCI protocl.
   1897   //
   1898   gBS->SetTimer (Xhc->PollTimer, TimerCancel, 0);
   1899   XhcHaltHC (Xhc, XHC_GENERIC_TIMEOUT);
   1900 
   1901   if (Xhc->PollTimer != NULL) {
   1902     gBS->CloseEvent (Xhc->PollTimer);
   1903   }
   1904 
   1905   XhcClearBiosOwnership (Xhc);
   1906 
   1907   //
   1908   // Restore original PCI attributes
   1909   //
   1910   PciIo->Attributes (
   1911                   PciIo,
   1912                   EfiPciIoAttributeOperationSet,
   1913                   Xhc->OriginalPciAttributes,
   1914                   NULL
   1915                   );
   1916 }
   1917 
   1918 /**
   1919   Starting the Usb XHCI Driver.
   1920 
   1921   @param  This                 Protocol instance pointer.
   1922   @param  Controller           Handle of device to test.
   1923   @param  RemainingDevicePath  Not used.
   1924 
   1925   @return EFI_SUCCESS          supports this device.
   1926   @return EFI_UNSUPPORTED      do not support this device.
   1927   @return EFI_DEVICE_ERROR     cannot be started due to device Error.
   1928   @return EFI_OUT_OF_RESOURCES cannot allocate resources.
   1929 
   1930 **/
   1931 EFI_STATUS
   1932 EFIAPI
   1933 XhcDriverBindingStart (
   1934   IN EFI_DRIVER_BINDING_PROTOCOL *This,
   1935   IN EFI_HANDLE                  Controller,
   1936   IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath
   1937   )
   1938 {
   1939   EFI_STATUS              Status;
   1940   EFI_PCI_IO_PROTOCOL     *PciIo;
   1941   UINT64                  Supports;
   1942   UINT64                  OriginalPciAttributes;
   1943   BOOLEAN                 PciAttributesSaved;
   1944   USB_XHCI_INSTANCE       *Xhc;
   1945   EFI_DEVICE_PATH_PROTOCOL  *HcDevicePath;
   1946 
   1947   //
   1948   // Open the PciIo Protocol, then enable the USB host controller
   1949   //
   1950   Status = gBS->OpenProtocol (
   1951                   Controller,
   1952                   &gEfiPciIoProtocolGuid,
   1953                   (VOID **) &PciIo,
   1954                   This->DriverBindingHandle,
   1955                   Controller,
   1956                   EFI_OPEN_PROTOCOL_BY_DRIVER
   1957                   );
   1958 
   1959   if (EFI_ERROR (Status)) {
   1960     return Status;
   1961   }
   1962 
   1963   //
   1964   // Open Device Path Protocol for on USB host controller
   1965   //
   1966   HcDevicePath = NULL;
   1967   Status = gBS->OpenProtocol (
   1968                   Controller,
   1969                   &gEfiDevicePathProtocolGuid,
   1970                   (VOID **) &HcDevicePath,
   1971                   This->DriverBindingHandle,
   1972                   Controller,
   1973                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
   1974                   );
   1975 
   1976   PciAttributesSaved = FALSE;
   1977   //
   1978   // Save original PCI attributes
   1979   //
   1980   Status = PciIo->Attributes (
   1981                     PciIo,
   1982                     EfiPciIoAttributeOperationGet,
   1983                     0,
   1984                     &OriginalPciAttributes
   1985                     );
   1986 
   1987   if (EFI_ERROR (Status)) {
   1988     goto CLOSE_PCIIO;
   1989   }
   1990   PciAttributesSaved = TRUE;
   1991 
   1992   Status = PciIo->Attributes (
   1993                     PciIo,
   1994                     EfiPciIoAttributeOperationSupported,
   1995                     0,
   1996                     &Supports
   1997                     );
   1998   if (!EFI_ERROR (Status)) {
   1999     Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
   2000     Status = PciIo->Attributes (
   2001                       PciIo,
   2002                       EfiPciIoAttributeOperationEnable,
   2003                       Supports,
   2004                       NULL
   2005                       );
   2006   }
   2007 
   2008   if (EFI_ERROR (Status)) {
   2009     DEBUG ((EFI_D_ERROR, "XhcDriverBindingStart: failed to enable controller\n"));
   2010     goto CLOSE_PCIIO;
   2011   }
   2012 
   2013   //
   2014   // Create then install USB2_HC_PROTOCOL
   2015   //
   2016   Xhc = XhcCreateUsbHc (PciIo, HcDevicePath, OriginalPciAttributes);
   2017 
   2018   if (Xhc == NULL) {
   2019     DEBUG ((EFI_D_ERROR, "XhcDriverBindingStart: failed to create USB2_HC\n"));
   2020     return EFI_OUT_OF_RESOURCES;
   2021   }
   2022 
   2023   XhcSetBiosOwnership (Xhc);
   2024 
   2025   XhcResetHC (Xhc, XHC_RESET_TIMEOUT);
   2026   ASSERT (XhcIsHalt (Xhc));
   2027 
   2028   //
   2029   // After Chip Hardware Reset wait until the Controller Not Ready (CNR) flag
   2030   // in the USBSTS is '0' before writing any xHC Operational or Runtime registers.
   2031   //
   2032   ASSERT (!(XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_CNR)));
   2033 
   2034   //
   2035   // Initialize the schedule
   2036   //
   2037   XhcInitSched (Xhc);
   2038 
   2039   //
   2040   // Start the Host Controller
   2041   //
   2042   XhcRunHC(Xhc, XHC_GENERIC_TIMEOUT);
   2043 
   2044   //
   2045   // Start the asynchronous interrupt monitor
   2046   //
   2047   Status = gBS->SetTimer (Xhc->PollTimer, TimerPeriodic, XHC_ASYNC_TIMER_INTERVAL);
   2048   if (EFI_ERROR (Status)) {
   2049     DEBUG ((EFI_D_ERROR, "XhcDriverBindingStart: failed to start async interrupt monitor\n"));
   2050     XhcHaltHC (Xhc, XHC_GENERIC_TIMEOUT);
   2051     goto FREE_POOL;
   2052   }
   2053 
   2054   //
   2055   // Create event to stop the HC when exit boot service.
   2056   //
   2057   Status = gBS->CreateEventEx (
   2058                   EVT_NOTIFY_SIGNAL,
   2059                   TPL_NOTIFY,
   2060                   XhcExitBootService,
   2061                   Xhc,
   2062                   &gEfiEventExitBootServicesGuid,
   2063                   &Xhc->ExitBootServiceEvent
   2064                   );
   2065   if (EFI_ERROR (Status)) {
   2066     goto FREE_POOL;
   2067   }
   2068 
   2069   //
   2070   // Install the component name protocol, don't fail the start
   2071   // because of something for display.
   2072   //
   2073   AddUnicodeString2 (
   2074     "eng",
   2075     gXhciComponentName.SupportedLanguages,
   2076     &Xhc->ControllerNameTable,
   2077     L"eXtensible Host Controller (USB 3.0)",
   2078     TRUE
   2079     );
   2080   AddUnicodeString2 (
   2081     "en",
   2082     gXhciComponentName2.SupportedLanguages,
   2083     &Xhc->ControllerNameTable,
   2084     L"eXtensible Host Controller (USB 3.0)",
   2085     FALSE
   2086     );
   2087 
   2088   Status = gBS->InstallProtocolInterface (
   2089                   &Controller,
   2090                   &gEfiUsb2HcProtocolGuid,
   2091                   EFI_NATIVE_INTERFACE,
   2092                   &Xhc->Usb2Hc
   2093                   );
   2094   if (EFI_ERROR (Status)) {
   2095     DEBUG ((EFI_D_ERROR, "XhcDriverBindingStart: failed to install USB2_HC Protocol\n"));
   2096     goto FREE_POOL;
   2097   }
   2098 
   2099   DEBUG ((EFI_D_INFO, "XhcDriverBindingStart: XHCI started for controller @ %x\n", Controller));
   2100   return EFI_SUCCESS;
   2101 
   2102 FREE_POOL:
   2103   gBS->CloseEvent (Xhc->PollTimer);
   2104   XhcFreeSched (Xhc);
   2105   FreePool (Xhc);
   2106 
   2107 CLOSE_PCIIO:
   2108   if (PciAttributesSaved) {
   2109     //
   2110     // Restore original PCI attributes
   2111     //
   2112     PciIo->Attributes (
   2113                     PciIo,
   2114                     EfiPciIoAttributeOperationSet,
   2115                     OriginalPciAttributes,
   2116                     NULL
   2117                     );
   2118   }
   2119 
   2120   gBS->CloseProtocol (
   2121          Controller,
   2122          &gEfiPciIoProtocolGuid,
   2123          This->DriverBindingHandle,
   2124          Controller
   2125          );
   2126 
   2127   return Status;
   2128 }
   2129 
   2130 
   2131 /**
   2132   Stop this driver on ControllerHandle. Support stoping any child handles
   2133   created by this driver.
   2134 
   2135   @param  This                 Protocol instance pointer.
   2136   @param  Controller           Handle of device to stop driver on.
   2137   @param  NumberOfChildren     Number of Children in the ChildHandleBuffer.
   2138   @param  ChildHandleBuffer    List of handles for the children we need to stop.
   2139 
   2140   @return EFI_SUCCESS          Success.
   2141   @return EFI_DEVICE_ERROR     Fail.
   2142 
   2143 **/
   2144 EFI_STATUS
   2145 EFIAPI
   2146 XhcDriverBindingStop (
   2147   IN EFI_DRIVER_BINDING_PROTOCOL *This,
   2148   IN EFI_HANDLE                  Controller,
   2149   IN UINTN                       NumberOfChildren,
   2150   IN EFI_HANDLE                  *ChildHandleBuffer
   2151   )
   2152 {
   2153   EFI_STATUS            Status;
   2154   EFI_USB2_HC_PROTOCOL  *Usb2Hc;
   2155   EFI_PCI_IO_PROTOCOL   *PciIo;
   2156   USB_XHCI_INSTANCE     *Xhc;
   2157   UINT8                 Index;
   2158 
   2159   //
   2160   // Test whether the Controller handler passed in is a valid
   2161   // Usb controller handle that should be supported, if not,
   2162   // return the error status directly
   2163   //
   2164   Status = gBS->OpenProtocol (
   2165                   Controller,
   2166                   &gEfiUsb2HcProtocolGuid,
   2167                   (VOID **) &Usb2Hc,
   2168                   This->DriverBindingHandle,
   2169                   Controller,
   2170                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
   2171                   );
   2172 
   2173   if (EFI_ERROR (Status)) {
   2174     return Status;
   2175   }
   2176 
   2177   Status = gBS->UninstallProtocolInterface (
   2178                   Controller,
   2179                   &gEfiUsb2HcProtocolGuid,
   2180                   Usb2Hc
   2181                   );
   2182 
   2183   if (EFI_ERROR (Status)) {
   2184     return Status;
   2185   }
   2186 
   2187   Xhc   = XHC_FROM_THIS (Usb2Hc);
   2188   PciIo = Xhc->PciIo;
   2189 
   2190   //
   2191   // Stop AsyncRequest Polling timer then stop the XHCI driver
   2192   // and uninstall the XHCI protocl.
   2193   //
   2194   gBS->SetTimer (Xhc->PollTimer, TimerCancel, 0);
   2195 
   2196   //
   2197   // Disable the device slots occupied by these devices on its downstream ports.
   2198   // Entry 0 is reserved.
   2199   //
   2200   for (Index = 0; Index < 255; Index++) {
   2201     if (!Xhc->UsbDevContext[Index + 1].Enabled ||
   2202         (Xhc->UsbDevContext[Index + 1].SlotId == 0)) {
   2203       continue;
   2204     }
   2205     if (Xhc->HcCParams.Data.Csz == 0) {
   2206       XhcDisableSlotCmd (Xhc, Xhc->UsbDevContext[Index + 1].SlotId);
   2207     } else {
   2208       XhcDisableSlotCmd64 (Xhc, Xhc->UsbDevContext[Index + 1].SlotId);
   2209     }
   2210   }
   2211 
   2212   if (Xhc->PollTimer != NULL) {
   2213     gBS->CloseEvent (Xhc->PollTimer);
   2214   }
   2215 
   2216   if (Xhc->ExitBootServiceEvent != NULL) {
   2217     gBS->CloseEvent (Xhc->ExitBootServiceEvent);
   2218   }
   2219 
   2220   XhcHaltHC (Xhc, XHC_GENERIC_TIMEOUT);
   2221   XhcClearBiosOwnership (Xhc);
   2222   XhciDelAllAsyncIntTransfers (Xhc);
   2223   XhcFreeSched (Xhc);
   2224 
   2225   if (Xhc->ControllerNameTable) {
   2226     FreeUnicodeStringTable (Xhc->ControllerNameTable);
   2227   }
   2228 
   2229   //
   2230   // Restore original PCI attributes
   2231   //
   2232   PciIo->Attributes (
   2233            PciIo,
   2234            EfiPciIoAttributeOperationSet,
   2235            Xhc->OriginalPciAttributes,
   2236            NULL
   2237            );
   2238 
   2239   gBS->CloseProtocol (
   2240          Controller,
   2241          &gEfiPciIoProtocolGuid,
   2242          This->DriverBindingHandle,
   2243          Controller
   2244          );
   2245 
   2246   FreePool (Xhc);
   2247 
   2248   return EFI_SUCCESS;
   2249 }
   2250 
   2251