Home | History | Annotate | Download | only in UhciDxe
      1 /** @file
      2 
      3   The UHCI driver model and HC protocol routines.
      4 
      5 Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>
      6 This program and the accompanying materials
      7 are licensed and made available under the terms and conditions of the BSD License
      8 which accompanies this distribution.  The full text of the license may be found at
      9 http://opensource.org/licenses/bsd-license.php
     10 
     11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include "Uhci.h"
     17 
     18 
     19 EFI_DRIVER_BINDING_PROTOCOL gUhciDriverBinding = {
     20   UhciDriverBindingSupported,
     21   UhciDriverBindingStart,
     22   UhciDriverBindingStop,
     23   0x20,
     24   NULL,
     25   NULL
     26 };
     27 
     28 /**
     29   Provides software reset for the USB host controller according to UEFI 2.0 spec.
     30 
     31   @param  This                   A pointer to the EFI_USB2_HC_PROTOCOL instance.
     32   @param  Attributes             A bit mask of the reset operation to perform.  See
     33                                  below for a list of the supported bit mask values.
     34 
     35   @return EFI_SUCCESS            The reset operation succeeded.
     36   @return EFI_INVALID_PARAMETER  Attributes is not valid.
     37   @return EFI_UNSUPPORTED        This type of reset is not currently supported.
     38   @return EFI_DEVICE_ERROR       Other errors.
     39 
     40 **/
     41 EFI_STATUS
     42 EFIAPI
     43 Uhci2Reset (
     44   IN EFI_USB2_HC_PROTOCOL   *This,
     45   IN UINT16                 Attributes
     46   )
     47 {
     48   USB_HC_DEV          *Uhc;
     49   EFI_TPL             OldTpl;
     50 
     51   if ((Attributes == EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG) ||
     52       (Attributes == EFI_USB_HC_RESET_HOST_WITH_DEBUG)) {
     53     return EFI_UNSUPPORTED;
     54   }
     55 
     56   Uhc = UHC_FROM_USB2_HC_PROTO (This);
     57 
     58   if (Uhc->DevicePath != NULL) {
     59     //
     60     // Report Status Code to indicate reset happens
     61     //
     62     REPORT_STATUS_CODE_WITH_DEVICE_PATH (
     63       EFI_PROGRESS_CODE,
     64       (EFI_IO_BUS_USB | EFI_IOB_PC_RESET),
     65       Uhc->DevicePath
     66       );
     67   }
     68 
     69   OldTpl  = gBS->RaiseTPL (UHCI_TPL);
     70 
     71   switch (Attributes) {
     72   case EFI_USB_HC_RESET_GLOBAL:
     73     //
     74     // Stop schedule and set the Global Reset bit in the command register
     75     //
     76     UhciStopHc (Uhc, UHC_GENERIC_TIMEOUT);
     77     UhciSetRegBit (Uhc->PciIo, USBCMD_OFFSET, USBCMD_GRESET);
     78 
     79     gBS->Stall (UHC_ROOT_PORT_RESET_STALL);
     80 
     81     //
     82     // Clear the Global Reset bit to zero.
     83     //
     84     UhciClearRegBit (Uhc->PciIo, USBCMD_OFFSET, USBCMD_GRESET);
     85 
     86     gBS->Stall (UHC_ROOT_PORT_RECOVERY_STALL);
     87     break;
     88 
     89   case EFI_USB_HC_RESET_HOST_CONTROLLER:
     90     //
     91     // Stop schedule and set Host Controller Reset bit to 1
     92     //
     93     UhciStopHc (Uhc, UHC_GENERIC_TIMEOUT);
     94     UhciSetRegBit (Uhc->PciIo, USBCMD_OFFSET, USBCMD_HCRESET);
     95 
     96     gBS->Stall (UHC_ROOT_PORT_RECOVERY_STALL);
     97     break;
     98 
     99   default:
    100     goto ON_INVAILD_PARAMETER;
    101   }
    102 
    103   //
    104   // Delete all old transactions on the USB bus, then
    105   // reinitialize the frame list
    106   //
    107   UhciFreeAllAsyncReq (Uhc);
    108   UhciDestoryFrameList (Uhc);
    109   UhciInitFrameList (Uhc);
    110 
    111   gBS->RestoreTPL (OldTpl);
    112 
    113   return EFI_SUCCESS;
    114 
    115 ON_INVAILD_PARAMETER:
    116 
    117   gBS->RestoreTPL (OldTpl);
    118 
    119   return EFI_INVALID_PARAMETER;
    120 }
    121 
    122 
    123 /**
    124   Retrieves current state of the USB host controller according to UEFI 2.0 spec.
    125 
    126   @param  This                   A pointer to the EFI_USB2_HC_PROTOCOL instance.
    127   @param  State                  Variable to receive current device state.
    128 
    129   @return EFI_SUCCESS            The state is returned.
    130   @return EFI_INVALID_PARAMETER  State is not valid.
    131   @return EFI_DEVICE_ERROR       Other errors.
    132 
    133 **/
    134 EFI_STATUS
    135 EFIAPI
    136 Uhci2GetState (
    137   IN   EFI_USB2_HC_PROTOCOL   *This,
    138   OUT  EFI_USB_HC_STATE       *State
    139   )
    140 {
    141   USB_HC_DEV          *Uhc;
    142   UINT16              UsbSts;
    143   UINT16              UsbCmd;
    144 
    145   if (State == NULL) {
    146     return EFI_INVALID_PARAMETER;
    147   }
    148 
    149   Uhc     = UHC_FROM_USB2_HC_PROTO (This);
    150 
    151   UsbCmd  = UhciReadReg (Uhc->PciIo, USBCMD_OFFSET);
    152   UsbSts  = UhciReadReg (Uhc->PciIo, USBSTS_OFFSET);
    153 
    154   if ((UsbCmd & USBCMD_EGSM) !=0 ) {
    155     *State = EfiUsbHcStateSuspend;
    156 
    157   } else if ((UsbSts & USBSTS_HCH) != 0) {
    158     *State = EfiUsbHcStateHalt;
    159 
    160   } else {
    161     *State = EfiUsbHcStateOperational;
    162   }
    163 
    164   return EFI_SUCCESS;
    165 }
    166 
    167 
    168 /**
    169   Sets the USB host controller to a specific state according to UEFI 2.0 spec.
    170 
    171   @param  This                   A pointer to the EFI_USB2_HC_PROTOCOL instance.
    172   @param  State                  Indicates the state of the host controller that will
    173                                  be set.
    174 
    175   @return EFI_SUCCESS            Host controller was successfully placed in the state.
    176   @return EFI_INVALID_PARAMETER  State is invalid.
    177   @return EFI_DEVICE_ERROR       Failed to set the state.
    178 
    179 **/
    180 EFI_STATUS
    181 EFIAPI
    182 Uhci2SetState (
    183   IN EFI_USB2_HC_PROTOCOL    *This,
    184   IN EFI_USB_HC_STATE        State
    185   )
    186 {
    187   EFI_USB_HC_STATE    CurState;
    188   USB_HC_DEV          *Uhc;
    189   EFI_TPL             OldTpl;
    190   EFI_STATUS          Status;
    191   UINT16              UsbCmd;
    192 
    193   Uhc     = UHC_FROM_USB2_HC_PROTO (This);
    194   Status  = Uhci2GetState (This, &CurState);
    195 
    196   if (EFI_ERROR (Status)) {
    197     return EFI_DEVICE_ERROR;
    198   }
    199 
    200   if (CurState == State) {
    201     return EFI_SUCCESS;
    202   }
    203 
    204   Status  = EFI_SUCCESS;
    205   OldTpl  = gBS->RaiseTPL (UHCI_TPL);
    206 
    207   switch (State) {
    208   case EfiUsbHcStateHalt:
    209     Status = UhciStopHc (Uhc, UHC_GENERIC_TIMEOUT);
    210     break;
    211 
    212   case EfiUsbHcStateOperational:
    213     UsbCmd = UhciReadReg (Uhc->PciIo, USBCMD_OFFSET);
    214 
    215     if (CurState == EfiUsbHcStateHalt) {
    216       //
    217       // Set Run/Stop bit to 1, also set the bandwidht reclamation
    218       // point to 64 bytes
    219       //
    220       UsbCmd |= USBCMD_RS | USBCMD_MAXP;
    221       UhciWriteReg (Uhc->PciIo, USBCMD_OFFSET, UsbCmd);
    222 
    223     } else if (CurState == EfiUsbHcStateSuspend) {
    224       //
    225       // If FGR(Force Global Resume) bit is 0, set it
    226       //
    227       if ((UsbCmd & USBCMD_FGR) == 0) {
    228         UsbCmd |= USBCMD_FGR;
    229         UhciWriteReg (Uhc->PciIo, USBCMD_OFFSET, UsbCmd);
    230       }
    231 
    232       //
    233       // wait 20ms to let resume complete (20ms is specified by UHCI spec)
    234       //
    235       gBS->Stall (UHC_FORCE_GLOBAL_RESUME_STALL);
    236 
    237       //
    238       // Write FGR bit to 0 and EGSM(Enter Global Suspend Mode) bit to 0
    239       //
    240       UsbCmd &= ~USBCMD_FGR;
    241       UsbCmd &= ~USBCMD_EGSM;
    242       UsbCmd |= USBCMD_RS;
    243       UhciWriteReg (Uhc->PciIo, USBCMD_OFFSET, UsbCmd);
    244     }
    245 
    246     break;
    247 
    248   case EfiUsbHcStateSuspend:
    249     Status = Uhci2SetState (This, EfiUsbHcStateHalt);
    250 
    251     if (EFI_ERROR (Status)) {
    252       Status = EFI_DEVICE_ERROR;
    253       goto ON_EXIT;
    254     }
    255 
    256     //
    257     // Set Enter Global Suspend Mode bit to 1.
    258     //
    259     UsbCmd = UhciReadReg (Uhc->PciIo, USBCMD_OFFSET);
    260     UsbCmd |= USBCMD_EGSM;
    261     UhciWriteReg (Uhc->PciIo, USBCMD_OFFSET, UsbCmd);
    262     break;
    263 
    264   default:
    265     Status = EFI_INVALID_PARAMETER;
    266     break;
    267   }
    268 
    269 ON_EXIT:
    270   gBS->RestoreTPL (OldTpl);
    271   return Status;
    272 }
    273 
    274 /**
    275   Retrieves capabilities of USB host controller according to UEFI 2.0 spec.
    276 
    277   @param  This                   A pointer to the EFI_USB2_HC_PROTOCOL instance.
    278   @param  MaxSpeed               A pointer to the max speed USB host controller
    279                                  supports.
    280   @param  PortNumber             A pointer to the number of root hub ports.
    281   @param  Is64BitCapable         A pointer to an integer to show whether USB host
    282                                  controller supports 64-bit memory addressing.
    283 
    284   @return EFI_SUCCESS            capabilities were retrieved successfully.
    285   @return EFI_INVALID_PARAMETER  MaxSpeed or PortNumber or Is64BitCapable is NULL.
    286   @return EFI_DEVICE_ERROR       An error was encountered.
    287 
    288 **/
    289 EFI_STATUS
    290 EFIAPI
    291 Uhci2GetCapability (
    292   IN  EFI_USB2_HC_PROTOCOL  *This,
    293   OUT UINT8                 *MaxSpeed,
    294   OUT UINT8                 *PortNumber,
    295   OUT UINT8                 *Is64BitCapable
    296   )
    297 {
    298   USB_HC_DEV          *Uhc;
    299   UINT32              Offset;
    300   UINT16              PortSC;
    301   UINT32              Index;
    302 
    303   Uhc = UHC_FROM_USB2_HC_PROTO (This);
    304 
    305   if ((NULL == MaxSpeed) || (NULL == PortNumber) || (NULL == Is64BitCapable)) {
    306     return EFI_INVALID_PARAMETER;
    307   }
    308 
    309   *MaxSpeed       = EFI_USB_SPEED_FULL;
    310   *Is64BitCapable = (UINT8) FALSE;
    311 
    312   *PortNumber = 0;
    313 
    314   for (Index = 0; Index < USB_MAX_ROOTHUB_PORT; Index++) {
    315     Offset  = USBPORTSC_OFFSET + Index * 2;
    316     PortSC  = UhciReadReg (Uhc->PciIo, Offset);
    317 
    318     //
    319     // Port status's bit 7 is reserved and always returns 1 if
    320     // the port number is valid. Intel's UHCI (in EHCI controller)
    321     // returns 0 in this bit if port number is invalid. Also, if
    322     // PciIo IoRead returns error, 0xFFFF is returned to caller.
    323     //
    324     if (((PortSC & 0x80) == 0) || (PortSC == 0xFFFF)) {
    325       break;
    326     }
    327     (*PortNumber)++;
    328   }
    329 
    330   Uhc->RootPorts = *PortNumber;
    331 
    332   DEBUG ((EFI_D_INFO, "Uhci2GetCapability: %d ports\n", (UINT32)Uhc->RootPorts));
    333   return EFI_SUCCESS;
    334 }
    335 
    336 
    337 /**
    338   Retrieves the current status of a USB root hub port according to UEFI 2.0 spec.
    339 
    340   @param  This                    A pointer to the EFI_USB2_HC_PROTOCOL.
    341   @param  PortNumber              The port to get status.
    342   @param  PortStatus              A pointer to the current port status bits and  port
    343                                   status change bits.
    344 
    345   @return EFI_SUCCESS             status of the USB root hub port was returned in PortStatus.
    346   @return EFI_INVALID_PARAMETER   PortNumber is invalid.
    347   @return EFI_DEVICE_ERROR        Can't read register.
    348 
    349 **/
    350 EFI_STATUS
    351 EFIAPI
    352 Uhci2GetRootHubPortStatus (
    353   IN   EFI_USB2_HC_PROTOCOL   *This,
    354   IN   UINT8                  PortNumber,
    355   OUT  EFI_USB_PORT_STATUS    *PortStatus
    356   )
    357 {
    358   USB_HC_DEV          *Uhc;
    359   UINT32              Offset;
    360   UINT16              PortSC;
    361 
    362   Uhc = UHC_FROM_USB2_HC_PROTO (This);
    363 
    364   if (PortStatus == NULL) {
    365     return EFI_INVALID_PARAMETER;
    366   }
    367 
    368   if (PortNumber >= Uhc->RootPorts) {
    369     return EFI_INVALID_PARAMETER;
    370   }
    371 
    372   Offset                        = USBPORTSC_OFFSET + PortNumber * 2;
    373   PortStatus->PortStatus        = 0;
    374   PortStatus->PortChangeStatus  = 0;
    375 
    376   PortSC                        = UhciReadReg (Uhc->PciIo, Offset);
    377 
    378   if ((PortSC & USBPORTSC_CCS) != 0) {
    379     PortStatus->PortStatus |= USB_PORT_STAT_CONNECTION;
    380   }
    381 
    382   if ((PortSC & USBPORTSC_PED) != 0) {
    383     PortStatus->PortStatus |= USB_PORT_STAT_ENABLE;
    384   }
    385 
    386   if ((PortSC & USBPORTSC_SUSP) != 0) {
    387     DEBUG ((EFI_D_INFO, "Uhci2GetRootHubPortStatus: port %d is suspended\n", PortNumber));
    388     PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND;
    389   }
    390 
    391   if ((PortSC & USBPORTSC_PR) != 0) {
    392     PortStatus->PortStatus |= USB_PORT_STAT_RESET;
    393   }
    394 
    395   if ((PortSC & USBPORTSC_LSDA) != 0) {
    396     PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;
    397   }
    398 
    399   //
    400   // CHC will always return one in port owner bit
    401   //
    402   PortStatus->PortStatus |= USB_PORT_STAT_OWNER;
    403 
    404   if ((PortSC & USBPORTSC_CSC) != 0) {
    405     PortStatus->PortChangeStatus |= USB_PORT_STAT_C_CONNECTION;
    406   }
    407 
    408   if ((PortSC & USBPORTSC_PEDC) != 0) {
    409     PortStatus->PortChangeStatus |= USB_PORT_STAT_C_ENABLE;
    410   }
    411 
    412   return EFI_SUCCESS;
    413 }
    414 
    415 
    416 /**
    417   Sets a feature for the specified root hub port according to UEFI 2.0 spec.
    418 
    419   @param  This                   A pointer to the EFI_USB2_HC_PROTOCOL.
    420   @param  PortNumber             Specifies the root hub port whose feature  is
    421                                  requested to be set.
    422   @param  PortFeature            Indicates the feature selector associated  with the
    423                                  feature set request.
    424 
    425   @return EFI_SUCCESS            PortFeature was set for the root port.
    426   @return EFI_INVALID_PARAMETER  PortNumber is invalid or PortFeature is invalid.
    427   @return EFI_DEVICE_ERROR       Can't read register.
    428 
    429 **/
    430 EFI_STATUS
    431 EFIAPI
    432 Uhci2SetRootHubPortFeature (
    433   IN EFI_USB2_HC_PROTOCOL    *This,
    434   IN UINT8                   PortNumber,
    435   IN EFI_USB_PORT_FEATURE    PortFeature
    436   )
    437 {
    438   USB_HC_DEV          *Uhc;
    439   EFI_TPL             OldTpl;
    440   UINT32              Offset;
    441   UINT16              PortSC;
    442   UINT16              Command;
    443 
    444   Uhc = UHC_FROM_USB2_HC_PROTO (This);
    445 
    446   if (PortNumber >= Uhc->RootPorts) {
    447     return EFI_INVALID_PARAMETER;
    448   }
    449 
    450   Offset  = USBPORTSC_OFFSET + PortNumber * 2;
    451 
    452   OldTpl  = gBS->RaiseTPL (UHCI_TPL);
    453   PortSC  = UhciReadReg (Uhc->PciIo, Offset);
    454 
    455   switch (PortFeature) {
    456   case EfiUsbPortSuspend:
    457     Command = UhciReadReg (Uhc->PciIo, USBCMD_OFFSET);
    458     if ((Command & USBCMD_EGSM) == 0) {
    459       //
    460       // if global suspend is not active, can set port suspend
    461       //
    462       PortSC &= 0xfff5;
    463       PortSC |= USBPORTSC_SUSP;
    464     }
    465     break;
    466 
    467   case EfiUsbPortReset:
    468     PortSC &= 0xfff5;
    469     PortSC |= USBPORTSC_PR;
    470     break;
    471 
    472   case EfiUsbPortPower:
    473     //
    474     // No action
    475     //
    476     break;
    477 
    478   case EfiUsbPortEnable:
    479     PortSC &= 0xfff5;
    480     PortSC |= USBPORTSC_PED;
    481     break;
    482 
    483   default:
    484     gBS->RestoreTPL (OldTpl);
    485     return EFI_INVALID_PARAMETER;
    486   }
    487 
    488   UhciWriteReg (Uhc->PciIo, Offset, PortSC);
    489   gBS->RestoreTPL (OldTpl);
    490 
    491   return EFI_SUCCESS;
    492 }
    493 
    494 
    495 /**
    496   Clears a feature for the specified root hub port according to Uefi 2.0 spec.
    497 
    498   @param  This                   A pointer to the EFI_USB2_HC_PROTOCOL instance.
    499   @param  PortNumber             Specifies the root hub port whose feature  is
    500                                  requested to be cleared.
    501   @param  PortFeature            Indicates the feature selector associated with the
    502                                  feature clear request.
    503 
    504   @return EFI_SUCCESS            PortFeature was cleared for the USB root hub port.
    505   @return EFI_INVALID_PARAMETER  PortNumber is invalid or PortFeature is invalid.
    506   @return EFI_DEVICE_ERROR       Can't read register.
    507 
    508 **/
    509 EFI_STATUS
    510 EFIAPI
    511 Uhci2ClearRootHubPortFeature (
    512   IN EFI_USB2_HC_PROTOCOL    *This,
    513   IN UINT8                   PortNumber,
    514   IN EFI_USB_PORT_FEATURE    PortFeature
    515   )
    516 {
    517   USB_HC_DEV          *Uhc;
    518   EFI_TPL             OldTpl;
    519   UINT32              Offset;
    520   UINT16              PortSC;
    521 
    522   Uhc = UHC_FROM_USB2_HC_PROTO (This);
    523 
    524   if (PortNumber >= Uhc->RootPorts) {
    525     return EFI_INVALID_PARAMETER;
    526   }
    527 
    528   Offset  = USBPORTSC_OFFSET + PortNumber * 2;
    529 
    530   OldTpl  = gBS->RaiseTPL (UHCI_TPL);
    531   PortSC  = UhciReadReg (Uhc->PciIo, Offset);
    532 
    533   switch (PortFeature) {
    534   case EfiUsbPortEnable:
    535     PortSC &= 0xfff5;
    536     PortSC &= ~USBPORTSC_PED;
    537     break;
    538 
    539   case EfiUsbPortSuspend:
    540     //
    541     // Cause a resume on the specified port if in suspend mode.
    542     //
    543     PortSC &= 0xfff5;
    544     PortSC &= ~USBPORTSC_SUSP;
    545     break;
    546 
    547   case EfiUsbPortPower:
    548     //
    549     // No action
    550     //
    551     break;
    552 
    553   case EfiUsbPortReset:
    554     PortSC &= 0xfff5;
    555     PortSC &= ~USBPORTSC_PR;
    556     break;
    557 
    558   case EfiUsbPortConnectChange:
    559     PortSC &= 0xfff5;
    560     PortSC |= USBPORTSC_CSC;
    561     break;
    562 
    563   case EfiUsbPortEnableChange:
    564     PortSC &= 0xfff5;
    565     PortSC |= USBPORTSC_PEDC;
    566     break;
    567 
    568   case EfiUsbPortSuspendChange:
    569     //
    570     // Root hub does not support this
    571     //
    572     break;
    573 
    574   case EfiUsbPortOverCurrentChange:
    575     //
    576     // Root hub does not support this
    577     //
    578     break;
    579 
    580   case EfiUsbPortResetChange:
    581     //
    582     // Root hub does not support this
    583     //
    584     break;
    585 
    586   default:
    587     gBS->RestoreTPL (OldTpl);
    588     return EFI_INVALID_PARAMETER;
    589   }
    590 
    591   UhciWriteReg (Uhc->PciIo, Offset, PortSC);
    592   gBS->RestoreTPL (OldTpl);
    593 
    594   return EFI_SUCCESS;
    595 }
    596 
    597 
    598 /**
    599   Submits control transfer to a target USB device according to UEFI 2.0 spec.
    600 
    601   @param  This                   A pointer to the EFI_USB2_HC_PROTOCOL instance.
    602   @param  DeviceAddress          Target device address.
    603   @param  DeviceSpeed            Device speed.
    604   @param  MaximumPacketLength    Maximum packet size of the target endpoint.
    605   @param  Request                USB device request to send.
    606   @param  TransferDirection      Data direction of the Data stage in control transfer.
    607   @param  Data                   Data to transmit/receive in data stage.
    608   @param  DataLength             Length of the data.
    609   @param  TimeOut                Maximum time, in microseconds, for transfer to complete.
    610   @param  Translator             Transaction translator to be used by this device.
    611   @param  TransferResult         Variable to receive the transfer result.
    612 
    613   @return EFI_SUCCESS            The control transfer was completed successfully.
    614   @return EFI_OUT_OF_RESOURCES   Failed due to lack of resource.
    615   @return EFI_INVALID_PARAMETER  Some parameters are invalid.
    616   @return EFI_TIMEOUT            Failed due to timeout.
    617   @return EFI_DEVICE_ERROR       Failed due to host controller or device error.
    618 
    619 **/
    620 EFI_STATUS
    621 EFIAPI
    622 Uhci2ControlTransfer (
    623   IN     EFI_USB2_HC_PROTOCOL                 *This,
    624   IN     UINT8                                DeviceAddress,
    625   IN     UINT8                                DeviceSpeed,
    626   IN     UINTN                                MaximumPacketLength,
    627   IN     EFI_USB_DEVICE_REQUEST               *Request,
    628   IN     EFI_USB_DATA_DIRECTION               TransferDirection,
    629   IN OUT VOID                                 *Data,
    630   IN OUT UINTN                                *DataLength,
    631   IN     UINTN                                TimeOut,
    632   IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR   *Translator,
    633   OUT    UINT32                               *TransferResult
    634   )
    635 {
    636   USB_HC_DEV              *Uhc;
    637   UHCI_TD_SW              *TDs;
    638   EFI_TPL                 OldTpl;
    639   EFI_STATUS              Status;
    640   UHCI_QH_RESULT          QhResult;
    641   UINT8                   PktId;
    642   UINT8                   *RequestPhy;
    643   VOID                    *RequestMap;
    644   UINT8                   *DataPhy;
    645   VOID                    *DataMap;
    646   BOOLEAN                 IsSlowDevice;
    647   UINTN                   TransferDataLength;
    648 
    649   Uhc         = UHC_FROM_USB2_HC_PROTO (This);
    650   TDs         = NULL;
    651   DataPhy     = NULL;
    652   DataMap     = NULL;
    653   RequestPhy  = NULL;
    654   RequestMap  = NULL;
    655 
    656   IsSlowDevice  = (BOOLEAN) ((EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE);
    657 
    658   //
    659   // Parameters Checking
    660   //
    661   if (Request == NULL || TransferResult == NULL) {
    662     return EFI_INVALID_PARAMETER;
    663   }
    664 
    665   if (IsSlowDevice && (MaximumPacketLength != 8)) {
    666     return EFI_INVALID_PARAMETER;
    667   }
    668 
    669   if ((MaximumPacketLength != 8) &&  (MaximumPacketLength != 16) &&
    670       (MaximumPacketLength != 32) && (MaximumPacketLength != 64)) {
    671 
    672     return EFI_INVALID_PARAMETER;
    673   }
    674 
    675   if ((TransferDirection != EfiUsbNoData) && (Data == NULL || DataLength == NULL)) {
    676     return EFI_INVALID_PARAMETER;
    677   }
    678 
    679   if (TransferDirection == EfiUsbNoData) {
    680     TransferDataLength = 0;
    681   } else {
    682     TransferDataLength = *DataLength;
    683   }
    684 
    685   *TransferResult = EFI_USB_ERR_SYSTEM;
    686   Status          = EFI_DEVICE_ERROR;
    687 
    688   //
    689   // If errors exist that cause host controller halt,
    690   // clear status then return EFI_DEVICE_ERROR.
    691   //
    692   UhciAckAllInterrupt (Uhc);
    693 
    694   if (!UhciIsHcWorking (Uhc->PciIo)) {
    695     return EFI_DEVICE_ERROR;
    696   }
    697 
    698   OldTpl = gBS->RaiseTPL (UHCI_TPL);
    699 
    700   //
    701   // Map the Request and data for bus master access,
    702   // then create a list of TD for this transfer
    703   //
    704   Status = UhciMapUserRequest (Uhc, Request, &RequestPhy, &RequestMap);
    705 
    706   if (EFI_ERROR (Status)) {
    707     goto ON_EXIT;
    708   }
    709 
    710   Status = UhciMapUserData (Uhc, TransferDirection, Data, DataLength, &PktId, &DataPhy, &DataMap);
    711 
    712   if (EFI_ERROR (Status)) {
    713     Uhc->PciIo->Unmap (Uhc->PciIo, RequestMap);
    714     goto ON_EXIT;
    715   }
    716 
    717   TDs = UhciCreateCtrlTds (
    718           Uhc,
    719           DeviceAddress,
    720           PktId,
    721           (UINT8*)Request,
    722           RequestPhy,
    723           (UINT8*)Data,
    724           DataPhy,
    725           TransferDataLength,
    726           (UINT8) MaximumPacketLength,
    727           IsSlowDevice
    728           );
    729 
    730   if (TDs == NULL) {
    731     Status = EFI_OUT_OF_RESOURCES;
    732     goto UNMAP_DATA;
    733   }
    734 
    735   //
    736   // According to the speed of the end point, link
    737   // the TD to corrosponding queue head, then check
    738   // the execution result
    739   //
    740   UhciLinkTdToQh (Uhc, Uhc->CtrlQh, TDs);
    741   Status = UhciExecuteTransfer (Uhc, Uhc->CtrlQh, TDs, TimeOut, IsSlowDevice, &QhResult);
    742   UhciUnlinkTdFromQh (Uhc->CtrlQh, TDs);
    743 
    744   Uhc->PciIo->Flush (Uhc->PciIo);
    745 
    746   *TransferResult = QhResult.Result;
    747 
    748   if (DataLength != NULL) {
    749     *DataLength = QhResult.Complete;
    750   }
    751 
    752   UhciDestoryTds (Uhc, TDs);
    753 
    754 UNMAP_DATA:
    755   Uhc->PciIo->Unmap (Uhc->PciIo, DataMap);
    756   Uhc->PciIo->Unmap (Uhc->PciIo, RequestMap);
    757 
    758 ON_EXIT:
    759   gBS->RestoreTPL (OldTpl);
    760   return Status;
    761 }
    762 
    763 
    764 /**
    765   Submits bulk transfer to a bulk endpoint of a USB device.
    766 
    767   @param  This                   A pointer to the EFI_USB2_HC_PROTOCOL instance.
    768   @param  DeviceAddress          Target device address.
    769   @param  EndPointAddress        Endpoint number and direction.
    770   @param  DeviceSpeed            Device speed.
    771   @param  MaximumPacketLength    Maximum packet size of the target endpoint.
    772   @param  DataBuffersNumber      Number of data buffers prepared for the transfer.
    773   @param  Data                   Array of pointers to the buffers of data.
    774   @param  DataLength             On input, size of the data buffer, On output,
    775                                  actually transferred data size.
    776   @param  DataToggle             On input, data toggle to use; On output, next data toggle.
    777   @param  TimeOut                Maximum time out, in microseconds.
    778   @param  Translator             A pointr to the transaction translator data.
    779   @param  TransferResult         Variable to receive transfer result.
    780 
    781   @return EFI_SUCCESS            The bulk transfer was completed successfully.
    782   @return EFI_OUT_OF_RESOURCES   Failed due to lack of resource.
    783   @return EFI_INVALID_PARAMETER  Some parameters are invalid.
    784   @return EFI_TIMEOUT            Failed due to timeout.
    785   @return EFI_DEVICE_ERROR       Failed due to host controller or device error.
    786 
    787 **/
    788 EFI_STATUS
    789 EFIAPI
    790 Uhci2BulkTransfer (
    791   IN     EFI_USB2_HC_PROTOCOL               *This,
    792   IN     UINT8                              DeviceAddress,
    793   IN     UINT8                              EndPointAddress,
    794   IN     UINT8                              DeviceSpeed,
    795   IN     UINTN                              MaximumPacketLength,
    796   IN     UINT8                              DataBuffersNumber,
    797   IN OUT VOID                               *Data[EFI_USB_MAX_BULK_BUFFER_NUM],
    798   IN OUT UINTN                              *DataLength,
    799   IN OUT UINT8                              *DataToggle,
    800   IN     UINTN                              TimeOut,
    801   IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
    802   OUT    UINT32                             *TransferResult
    803   )
    804 {
    805   EFI_USB_DATA_DIRECTION  Direction;
    806   EFI_TPL                 OldTpl;
    807   USB_HC_DEV              *Uhc;
    808   UHCI_TD_SW              *TDs;
    809   UHCI_QH_SW              *BulkQh;
    810   UHCI_QH_RESULT          QhResult;
    811   EFI_STATUS              Status;
    812   UINT8                   PktId;
    813   UINT8                   *DataPhy;
    814   VOID                    *DataMap;
    815 
    816   Uhc     = UHC_FROM_USB2_HC_PROTO (This);
    817   DataPhy = NULL;
    818   DataMap = NULL;
    819 
    820   if (DeviceSpeed == EFI_USB_SPEED_LOW) {
    821     return EFI_INVALID_PARAMETER;
    822   }
    823 
    824   if ((DataLength == NULL) || (*DataLength == 0) || (Data == NULL) || (TransferResult == NULL)) {
    825     return EFI_INVALID_PARAMETER;
    826   }
    827 
    828   if ((*DataToggle != 1) && (*DataToggle != 0)) {
    829     return EFI_INVALID_PARAMETER;
    830   }
    831 
    832   if ((MaximumPacketLength != 8) && (MaximumPacketLength != 16) &&
    833       (MaximumPacketLength != 32) && (MaximumPacketLength != 64)) {
    834     return EFI_INVALID_PARAMETER;
    835   }
    836 
    837   *TransferResult = EFI_USB_ERR_SYSTEM;
    838   Status          = EFI_OUT_OF_RESOURCES;
    839 
    840   //
    841   // If has errors that cause host controller halt,
    842   // then return EFI_DEVICE_ERROR directly.
    843   //
    844   UhciAckAllInterrupt (Uhc);
    845 
    846   if (!UhciIsHcWorking (Uhc->PciIo)) {
    847     return EFI_DEVICE_ERROR;
    848   }
    849 
    850   OldTpl = gBS->RaiseTPL (UHCI_TPL);
    851 
    852   //
    853   // Map the source data buffer for bus master access,
    854   // then create a list of TDs
    855   //
    856   if ((EndPointAddress & 0x80) != 0) {
    857     Direction = EfiUsbDataIn;
    858   } else {
    859     Direction = EfiUsbDataOut;
    860   }
    861 
    862   Status = UhciMapUserData (Uhc, Direction, *Data, DataLength, &PktId, &DataPhy, &DataMap);
    863 
    864   if (EFI_ERROR (Status)) {
    865     goto ON_EXIT;
    866   }
    867 
    868   Status = EFI_OUT_OF_RESOURCES;
    869   TDs    = UhciCreateBulkOrIntTds (
    870              Uhc,
    871              DeviceAddress,
    872              EndPointAddress,
    873              PktId,
    874              (UINT8 *)*Data,
    875              DataPhy,
    876              *DataLength,
    877              DataToggle,
    878              (UINT8) MaximumPacketLength,
    879              FALSE
    880              );
    881 
    882   if (TDs == NULL) {
    883     Uhc->PciIo->Unmap (Uhc->PciIo, DataMap);
    884     goto ON_EXIT;
    885   }
    886 
    887 
    888   //
    889   // Link the TDs to bulk queue head. According to the platfore
    890   // defintion of UHCI_NO_BW_RECLAMATION, BulkQh is either configured
    891   // to do full speed bandwidth reclamation or not.
    892   //
    893   BulkQh = Uhc->BulkQh;
    894 
    895   UhciLinkTdToQh (Uhc, BulkQh, TDs);
    896   Status = UhciExecuteTransfer (Uhc, BulkQh, TDs, TimeOut, FALSE, &QhResult);
    897   UhciUnlinkTdFromQh (BulkQh, TDs);
    898 
    899   Uhc->PciIo->Flush (Uhc->PciIo);
    900 
    901   *TransferResult = QhResult.Result;
    902   *DataToggle     = QhResult.NextToggle;
    903   *DataLength     = QhResult.Complete;
    904 
    905   UhciDestoryTds (Uhc, TDs);
    906   Uhc->PciIo->Unmap (Uhc->PciIo, DataMap);
    907 
    908 ON_EXIT:
    909   gBS->RestoreTPL (OldTpl);
    910   return Status;
    911 }
    912 
    913 
    914 /**
    915   Submits an asynchronous interrupt transfer to an
    916   interrupt endpoint of a USB device according to UEFI 2.0 spec.
    917 
    918   @param  This                   A pointer to the EFI_USB2_HC_PROTOCOL instance.
    919   @param  DeviceAddress          Target device address.
    920   @param  EndPointAddress        Endpoint number and direction.
    921   @param  DeviceSpeed            Device speed.
    922   @param  MaximumPacketLength    Maximum packet size of the target endpoint.
    923   @param  IsNewTransfer          If TRUE, submit a new transfer, if FALSE cancel old transfer.
    924   @param  DataToggle             On input, data toggle to use; On output, next data toggle.
    925   @param  PollingInterval        Interrupt poll rate in milliseconds.
    926   @param  DataLength             On input, size of the data buffer, On output,
    927                                  actually transferred data size.
    928   @param  Translator             A pointr to the transaction translator data.
    929   @param  CallBackFunction       Function to call periodically.
    930   @param  Context                User context.
    931 
    932   @return EFI_SUCCESS            Transfer was submitted.
    933   @return EFI_INVALID_PARAMETER  Some parameters are invalid.
    934   @return EFI_OUT_OF_RESOURCES   Failed due to a lack of resources.
    935   @return EFI_DEVICE_ERROR       Can't read register.
    936 
    937 **/
    938 EFI_STATUS
    939 EFIAPI
    940 Uhci2AsyncInterruptTransfer (
    941   IN     EFI_USB2_HC_PROTOCOL               *This,
    942   IN     UINT8                              DeviceAddress,
    943   IN     UINT8                              EndPointAddress,
    944   IN     UINT8                              DeviceSpeed,
    945   IN     UINTN                              MaximumPacketLength,
    946   IN     BOOLEAN                            IsNewTransfer,
    947   IN OUT UINT8                              *DataToggle,
    948   IN     UINTN                              PollingInterval,
    949   IN     UINTN                              DataLength,
    950   IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
    951   IN     EFI_ASYNC_USB_TRANSFER_CALLBACK    CallBackFunction,
    952   IN     VOID                               *Context
    953   )
    954 {
    955   USB_HC_DEV          *Uhc;
    956   BOOLEAN             IsSlowDevice;
    957   UHCI_QH_SW          *Qh;
    958   UHCI_TD_SW          *IntTds;
    959   EFI_TPL             OldTpl;
    960   EFI_STATUS          Status;
    961   UINT8               *DataPtr;
    962   UINT8               *DataPhy;
    963   UINT8               PktId;
    964 
    965   Uhc       = UHC_FROM_USB2_HC_PROTO (This);
    966   Qh        = NULL;
    967   IntTds    = NULL;
    968   DataPtr   = NULL;
    969   DataPhy   = NULL;
    970 
    971   IsSlowDevice  = (BOOLEAN) ((EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE);
    972 
    973   if ((EndPointAddress & 0x80) == 0) {
    974     return EFI_INVALID_PARAMETER;
    975   }
    976 
    977   //
    978   // Delete Async interrupt transfer request
    979   //
    980   if (!IsNewTransfer) {
    981     OldTpl = gBS->RaiseTPL (UHCI_TPL);
    982     Status = UhciRemoveAsyncReq (Uhc, DeviceAddress, EndPointAddress, DataToggle);
    983 
    984     gBS->RestoreTPL (OldTpl);
    985     return Status;
    986   }
    987 
    988   if (PollingInterval < 1 || PollingInterval > 255) {
    989     return EFI_INVALID_PARAMETER;
    990   }
    991 
    992   if (DataLength == 0) {
    993     return EFI_INVALID_PARAMETER;
    994   }
    995 
    996   if ((*DataToggle != 1) && (*DataToggle != 0)) {
    997     return EFI_INVALID_PARAMETER;
    998   }
    999 
   1000   //
   1001   // If has errors that cause host controller halt,
   1002   // then return EFI_DEVICE_ERROR directly.
   1003   //
   1004   UhciAckAllInterrupt (Uhc);
   1005 
   1006   if (!UhciIsHcWorking (Uhc->PciIo)) {
   1007     return EFI_DEVICE_ERROR;
   1008   }
   1009 
   1010   if ((EndPointAddress & 0x80) == 0) {
   1011     PktId = OUTPUT_PACKET_ID;
   1012   } else {
   1013     PktId = INPUT_PACKET_ID;
   1014   }
   1015 
   1016   //
   1017   // Allocate and map source data buffer for bus master access.
   1018   //
   1019   DataPtr = UsbHcAllocateMem (Uhc->MemPool, DataLength);
   1020 
   1021   if (DataPtr == NULL) {
   1022     return EFI_OUT_OF_RESOURCES;
   1023   }
   1024 
   1025   DataPhy = (UINT8 *) (UINTN) UsbHcGetPciAddressForHostMem (Uhc->MemPool, DataPtr, DataLength);
   1026 
   1027   OldTpl = gBS->RaiseTPL (UHCI_TPL);
   1028 
   1029   Qh = UhciCreateQh (Uhc, PollingInterval);
   1030 
   1031   if (Qh == NULL) {
   1032     Status = EFI_OUT_OF_RESOURCES;
   1033     goto FREE_DATA;
   1034   }
   1035 
   1036   IntTds = UhciCreateBulkOrIntTds (
   1037              Uhc,
   1038              DeviceAddress,
   1039              EndPointAddress,
   1040              PktId,
   1041              DataPtr,
   1042              DataPhy,
   1043              DataLength,
   1044              DataToggle,
   1045              (UINT8) MaximumPacketLength,
   1046              IsSlowDevice
   1047              );
   1048 
   1049   if (IntTds == NULL) {
   1050     Status = EFI_OUT_OF_RESOURCES;
   1051     goto DESTORY_QH;
   1052   }
   1053 
   1054   UhciLinkTdToQh (Uhc, Qh, IntTds);
   1055 
   1056   //
   1057   // Save QH-TD structures to async Interrupt transfer list,
   1058   // for monitor interrupt transfer execution routine use.
   1059   //
   1060   Status = UhciCreateAsyncReq (
   1061              Uhc,
   1062              Qh,
   1063              IntTds,
   1064              DeviceAddress,
   1065              EndPointAddress,
   1066              DataLength,
   1067              PollingInterval,
   1068              DataPtr,
   1069              CallBackFunction,
   1070              Context,
   1071              IsSlowDevice
   1072              );
   1073 
   1074   if (EFI_ERROR (Status)) {
   1075     goto DESTORY_QH;
   1076   }
   1077 
   1078   UhciLinkQhToFrameList (Uhc, Qh);
   1079 
   1080   gBS->RestoreTPL (OldTpl);
   1081   return EFI_SUCCESS;
   1082 
   1083 DESTORY_QH:
   1084   UsbHcFreeMem (Uhc->MemPool, Qh, sizeof (UHCI_QH_SW));
   1085 
   1086 FREE_DATA:
   1087   UsbHcFreeMem (Uhc->MemPool, DataPtr, DataLength);
   1088   Uhc->PciIo->Flush (Uhc->PciIo);
   1089 
   1090   gBS->RestoreTPL (OldTpl);
   1091   return Status;
   1092 }
   1093 
   1094 /**
   1095   Submits synchronous interrupt transfer to an interrupt endpoint
   1096   of a USB device according to UEFI 2.0 spec.
   1097 
   1098 
   1099   @param  This                   A pointer to the EFI_USB2_HC_PROTOCOL instance.
   1100   @param  DeviceAddress          Target device address.
   1101   @param  EndPointAddress        Endpoint number and direction.
   1102   @param  DeviceSpeed            Device speed.
   1103   @param  MaximumPacketLength    Maximum packet size of the target endpoint.
   1104   @param  Data                   Array of pointers to the buffers of data.
   1105   @param  DataLength             On input, size of the data buffer, On output,
   1106                                  actually transferred data size.
   1107   @param  DataToggle             On input, data toggle to use; On output, next data toggle.
   1108   @param  TimeOut                Maximum time out, in microseconds.
   1109   @param  Translator             A pointr to the transaction translator data.
   1110   @param  TransferResult         Variable to receive transfer result.
   1111 
   1112   @return EFI_SUCCESS            The transfer was completed successfully.
   1113   @return EFI_OUT_OF_RESOURCES   Failed due to lack of resource.
   1114   @return EFI_INVALID_PARAMETER  Some parameters are invalid.
   1115   @return EFI_TIMEOUT            Failed due to timeout.
   1116   @return EFI_DEVICE_ERROR       Failed due to host controller or device error.
   1117 
   1118 **/
   1119 EFI_STATUS
   1120 EFIAPI
   1121 Uhci2SyncInterruptTransfer (
   1122   IN     EFI_USB2_HC_PROTOCOL                      *This,
   1123   IN     UINT8                                     DeviceAddress,
   1124   IN     UINT8                                     EndPointAddress,
   1125   IN     UINT8                                     DeviceSpeed,
   1126   IN     UINTN                                     MaximumPacketLength,
   1127   IN OUT VOID                                      *Data,
   1128   IN OUT UINTN                                     *DataLength,
   1129   IN OUT UINT8                                     *DataToggle,
   1130   IN     UINTN                                     TimeOut,
   1131   IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR        *Translator,
   1132   OUT    UINT32                                    *TransferResult
   1133   )
   1134 {
   1135   EFI_STATUS          Status;
   1136   USB_HC_DEV          *Uhc;
   1137   UHCI_TD_SW          *TDs;
   1138   UHCI_QH_RESULT      QhResult;
   1139   EFI_TPL             OldTpl;
   1140   UINT8               *DataPhy;
   1141   VOID                *DataMap;
   1142   UINT8               PktId;
   1143   BOOLEAN             IsSlowDevice;
   1144 
   1145   Uhc     = UHC_FROM_USB2_HC_PROTO (This);
   1146   DataPhy = NULL;
   1147   DataMap = NULL;
   1148   TDs     = NULL;
   1149 
   1150   if (DeviceSpeed == EFI_USB_SPEED_HIGH) {
   1151     return EFI_INVALID_PARAMETER;
   1152   }
   1153 
   1154   IsSlowDevice  = (BOOLEAN) ((EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE);
   1155 
   1156   if ((DataLength == NULL) || (Data == NULL) || (TransferResult == NULL)) {
   1157     return EFI_INVALID_PARAMETER;
   1158   }
   1159 
   1160   if ((*DataToggle != 1) && (*DataToggle != 0)) {
   1161     return EFI_INVALID_PARAMETER;
   1162   }
   1163 
   1164   if ((*DataLength == 0) || (MaximumPacketLength > 64)) {
   1165     return EFI_INVALID_PARAMETER;
   1166   }
   1167 
   1168   if (IsSlowDevice && (MaximumPacketLength > 8)) {
   1169     return EFI_INVALID_PARAMETER;
   1170   }
   1171 
   1172   *TransferResult = EFI_USB_ERR_SYSTEM;
   1173   Status          = EFI_DEVICE_ERROR;
   1174 
   1175 
   1176   UhciAckAllInterrupt (Uhc);
   1177 
   1178   if (!UhciIsHcWorking (Uhc->PciIo)) {
   1179     return Status;
   1180   }
   1181 
   1182   OldTpl = gBS->RaiseTPL (UHCI_TPL);
   1183 
   1184   //
   1185   // Map the source data buffer for bus master access.
   1186   // Create Tds list, then link it to the UHC's interrupt list
   1187   //
   1188   Status = UhciMapUserData (
   1189              Uhc,
   1190              EfiUsbDataIn,
   1191              Data,
   1192              DataLength,
   1193              &PktId,
   1194              &DataPhy,
   1195              &DataMap
   1196              );
   1197 
   1198   if (EFI_ERROR (Status)) {
   1199     goto ON_EXIT;
   1200   }
   1201 
   1202   TDs = UhciCreateBulkOrIntTds (
   1203           Uhc,
   1204           DeviceAddress,
   1205           EndPointAddress,
   1206           PktId,
   1207           (UINT8 *)Data,
   1208           DataPhy,
   1209           *DataLength,
   1210           DataToggle,
   1211           (UINT8) MaximumPacketLength,
   1212           IsSlowDevice
   1213           );
   1214 
   1215   if (TDs == NULL) {
   1216     Uhc->PciIo->Unmap (Uhc->PciIo, DataMap);
   1217 
   1218     Status = EFI_OUT_OF_RESOURCES;
   1219     goto ON_EXIT;
   1220   }
   1221 
   1222 
   1223   UhciLinkTdToQh (Uhc, Uhc->SyncIntQh, TDs);
   1224 
   1225   Status = UhciExecuteTransfer (Uhc, Uhc->SyncIntQh, TDs, TimeOut, IsSlowDevice, &QhResult);
   1226 
   1227   UhciUnlinkTdFromQh (Uhc->SyncIntQh, TDs);
   1228   Uhc->PciIo->Flush (Uhc->PciIo);
   1229 
   1230   *TransferResult = QhResult.Result;
   1231   *DataToggle     = QhResult.NextToggle;
   1232   *DataLength     = QhResult.Complete;
   1233 
   1234   UhciDestoryTds (Uhc, TDs);
   1235   Uhc->PciIo->Unmap (Uhc->PciIo, DataMap);
   1236 
   1237 ON_EXIT:
   1238   gBS->RestoreTPL (OldTpl);
   1239   return Status;
   1240 }
   1241 
   1242 
   1243 /**
   1244   Submits isochronous transfer to a target USB device according to UEFI 2.0 spec.
   1245 
   1246   @param  This                  A pointer to the EFI_USB2_HC_PROTOCOL instance.
   1247   @param  DeviceAddress         Target device address.
   1248   @param  EndPointAddress       Endpoint number and direction.
   1249   @param  DeviceSpeed           Device speed.
   1250   @param  MaximumPacketLength   Maximum packet size of the target endpoint.
   1251   @param  DataBuffersNumber     Number of data buffers prepared for the transfer.
   1252   @param  Data                  Array of pointers to the buffers of data.
   1253   @param  DataLength            On input, size of the data buffer, On output,
   1254                                 actually transferred data size.
   1255   @param  Translator            A pointr to the transaction translator data.
   1256   @param  TransferResult        Variable to receive transfer result.
   1257 
   1258   @return EFI_UNSUPPORTED
   1259 
   1260 **/
   1261 EFI_STATUS
   1262 EFIAPI
   1263 Uhci2IsochronousTransfer (
   1264   IN     EFI_USB2_HC_PROTOCOL               *This,
   1265   IN     UINT8                              DeviceAddress,
   1266   IN     UINT8                              EndPointAddress,
   1267   IN     UINT8                              DeviceSpeed,
   1268   IN     UINTN                              MaximumPacketLength,
   1269   IN     UINT8                              DataBuffersNumber,
   1270   IN OUT VOID                               *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
   1271   IN     UINTN                              DataLength,
   1272   IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
   1273   OUT    UINT32                             *TransferResult
   1274   )
   1275 {
   1276   return EFI_UNSUPPORTED;
   1277 }
   1278 
   1279 
   1280 /**
   1281   Submits Async isochronous transfer to a target USB device according to UEFI 2.0 spec.
   1282 
   1283   @param  This                  A pointer to the EFI_USB2_HC_PROTOCOL instance.
   1284   @param  DeviceAddress         Target device address.
   1285   @param  EndPointAddress       Endpoint number and direction.
   1286   @param  DeviceSpeed           Device speed.
   1287   @param  MaximumPacketLength   Maximum packet size of the target endpoint.
   1288   @param  DataBuffersNumber     Number of data buffers prepared for the transfer.
   1289   @param  Data                  Array of pointers to the buffers of data.
   1290   @param  DataLength            On input, size of the data buffer, On output,
   1291                                 actually transferred data size.
   1292   @param  Translator            A pointr to the transaction translator data.
   1293   @param  IsochronousCallBack   Function to call when the transfer complete.
   1294   @param  Context               Pass to the call back function as parameter.
   1295 
   1296   @return EFI_UNSUPPORTED
   1297 
   1298 **/
   1299 EFI_STATUS
   1300 EFIAPI
   1301 Uhci2AsyncIsochronousTransfer (
   1302   IN     EFI_USB2_HC_PROTOCOL                *This,
   1303   IN     UINT8                               DeviceAddress,
   1304   IN     UINT8                               EndPointAddress,
   1305   IN     UINT8                               DeviceSpeed,
   1306   IN     UINTN                               MaximumPacketLength,
   1307   IN     UINT8                               DataBuffersNumber,
   1308   IN OUT VOID                                *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
   1309   IN     UINTN                               DataLength,
   1310   IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
   1311   IN     EFI_ASYNC_USB_TRANSFER_CALLBACK     IsochronousCallBack,
   1312   IN     VOID                                *Context
   1313   )
   1314 {
   1315   return EFI_UNSUPPORTED;
   1316 }
   1317 
   1318 /**
   1319   Entry point for EFI drivers.
   1320 
   1321   @param  ImageHandle      EFI_HANDLE.
   1322   @param  SystemTable      EFI_SYSTEM_TABLE.
   1323 
   1324   @retval EFI_SUCCESS      Driver is successfully loaded.
   1325   @return Others           Failed.
   1326 
   1327 **/
   1328 EFI_STATUS
   1329 EFIAPI
   1330 UhciDriverEntryPoint (
   1331   IN EFI_HANDLE           ImageHandle,
   1332   IN EFI_SYSTEM_TABLE     *SystemTable
   1333   )
   1334 {
   1335   return EfiLibInstallDriverBindingComponentName2 (
   1336            ImageHandle,
   1337            SystemTable,
   1338            &gUhciDriverBinding,
   1339            ImageHandle,
   1340            &gUhciComponentName,
   1341            &gUhciComponentName2
   1342            );
   1343 }
   1344 
   1345 
   1346 /**
   1347   Test to see if this driver supports ControllerHandle. Any
   1348   ControllerHandle that has UsbHcProtocol installed will be supported.
   1349 
   1350   @param  This                 Protocol instance pointer.
   1351   @param  Controller           Handle of device to test.
   1352   @param  RemainingDevicePath  Not used.
   1353 
   1354   @return EFI_SUCCESS          This driver supports this device.
   1355   @return EFI_UNSUPPORTED      This driver does not support this device.
   1356 
   1357 **/
   1358 EFI_STATUS
   1359 EFIAPI
   1360 UhciDriverBindingSupported (
   1361   IN EFI_DRIVER_BINDING_PROTOCOL     *This,
   1362   IN EFI_HANDLE                      Controller,
   1363   IN EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath
   1364   )
   1365 {
   1366   EFI_STATUS            OpenStatus;
   1367   EFI_STATUS            Status;
   1368   EFI_PCI_IO_PROTOCOL   *PciIo;
   1369   USB_CLASSC            UsbClassCReg;
   1370 
   1371   //
   1372   // Test whether there is PCI IO Protocol attached on the controller handle.
   1373   //
   1374   OpenStatus = gBS->OpenProtocol (
   1375                       Controller,
   1376                       &gEfiPciIoProtocolGuid,
   1377                       (VOID **) &PciIo,
   1378                       This->DriverBindingHandle,
   1379                       Controller,
   1380                       EFI_OPEN_PROTOCOL_BY_DRIVER
   1381                       );
   1382 
   1383   if (EFI_ERROR (OpenStatus)) {
   1384     return OpenStatus;
   1385   }
   1386 
   1387   Status = PciIo->Pci.Read (
   1388                         PciIo,
   1389                         EfiPciIoWidthUint8,
   1390                         PCI_CLASSCODE_OFFSET,
   1391                         sizeof (USB_CLASSC) / sizeof (UINT8),
   1392                         &UsbClassCReg
   1393                         );
   1394 
   1395   if (EFI_ERROR (Status)) {
   1396     Status = EFI_UNSUPPORTED;
   1397     goto ON_EXIT;
   1398   }
   1399 
   1400   //
   1401   // Test whether the controller belongs to UHCI type
   1402   //
   1403   if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) ||
   1404       (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) ||
   1405       (UsbClassCReg.ProgInterface != PCI_IF_UHCI)
   1406       ) {
   1407 
   1408     Status = EFI_UNSUPPORTED;
   1409   }
   1410 
   1411 ON_EXIT:
   1412   gBS->CloseProtocol (
   1413          Controller,
   1414          &gEfiPciIoProtocolGuid,
   1415          This->DriverBindingHandle,
   1416          Controller
   1417          );
   1418 
   1419   return Status;
   1420 
   1421 }
   1422 
   1423 
   1424 /**
   1425   Allocate and initialize the empty UHCI device.
   1426 
   1427   @param  PciIo                  The PCIIO to use.
   1428   @param  DevicePath             The device path of host controller.
   1429   @param  OriginalPciAttributes  The original PCI attributes.
   1430 
   1431   @return Allocated UHCI device. If err, return NULL.
   1432 
   1433 **/
   1434 USB_HC_DEV *
   1435 UhciAllocateDev (
   1436   IN EFI_PCI_IO_PROTOCOL       *PciIo,
   1437   IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
   1438   IN UINT64                    OriginalPciAttributes
   1439   )
   1440 {
   1441   USB_HC_DEV  *Uhc;
   1442   EFI_STATUS  Status;
   1443 
   1444   Uhc = AllocateZeroPool (sizeof (USB_HC_DEV));
   1445 
   1446   if (Uhc == NULL) {
   1447     return NULL;
   1448   }
   1449 
   1450   //
   1451   // This driver supports both USB_HC_PROTOCOL and USB2_HC_PROTOCOL.
   1452   // USB_HC_PROTOCOL is for EFI 1.1 backward compability.
   1453   //
   1454   Uhc->Signature                        = USB_HC_DEV_SIGNATURE;
   1455   Uhc->Usb2Hc.GetCapability             = Uhci2GetCapability;
   1456   Uhc->Usb2Hc.Reset                     = Uhci2Reset;
   1457   Uhc->Usb2Hc.GetState                  = Uhci2GetState;
   1458   Uhc->Usb2Hc.SetState                  = Uhci2SetState;
   1459   Uhc->Usb2Hc.ControlTransfer           = Uhci2ControlTransfer;
   1460   Uhc->Usb2Hc.BulkTransfer              = Uhci2BulkTransfer;
   1461   Uhc->Usb2Hc.AsyncInterruptTransfer    = Uhci2AsyncInterruptTransfer;
   1462   Uhc->Usb2Hc.SyncInterruptTransfer     = Uhci2SyncInterruptTransfer;
   1463   Uhc->Usb2Hc.IsochronousTransfer       = Uhci2IsochronousTransfer;
   1464   Uhc->Usb2Hc.AsyncIsochronousTransfer  = Uhci2AsyncIsochronousTransfer;
   1465   Uhc->Usb2Hc.GetRootHubPortStatus      = Uhci2GetRootHubPortStatus;
   1466   Uhc->Usb2Hc.SetRootHubPortFeature     = Uhci2SetRootHubPortFeature;
   1467   Uhc->Usb2Hc.ClearRootHubPortFeature   = Uhci2ClearRootHubPortFeature;
   1468   Uhc->Usb2Hc.MajorRevision             = 0x1;
   1469   Uhc->Usb2Hc.MinorRevision             = 0x1;
   1470 
   1471   Uhc->PciIo                 = PciIo;
   1472   Uhc->DevicePath            = DevicePath;
   1473   Uhc->OriginalPciAttributes = OriginalPciAttributes;
   1474   Uhc->MemPool               = UsbHcInitMemPool (PciIo, TRUE, 0);
   1475 
   1476   if (Uhc->MemPool == NULL) {
   1477     Status = EFI_OUT_OF_RESOURCES;
   1478     goto ON_ERROR;
   1479   }
   1480 
   1481   InitializeListHead (&Uhc->AsyncIntList);
   1482 
   1483   Status = gBS->CreateEvent (
   1484                   EVT_TIMER | EVT_NOTIFY_SIGNAL,
   1485                   TPL_NOTIFY,
   1486                   UhciMonitorAsyncReqList,
   1487                   Uhc,
   1488                   &Uhc->AsyncIntMonitor
   1489                   );
   1490 
   1491   if (EFI_ERROR (Status)) {
   1492     UsbHcFreeMemPool (Uhc->MemPool);
   1493     goto ON_ERROR;
   1494   }
   1495 
   1496   return Uhc;
   1497 
   1498 ON_ERROR:
   1499   FreePool (Uhc);
   1500   return NULL;
   1501 }
   1502 
   1503 
   1504 /**
   1505   Free the UHCI device and release its associated resources.
   1506 
   1507   @param  Uhc     The UHCI device to release.
   1508 
   1509 **/
   1510 VOID
   1511 UhciFreeDev (
   1512   IN USB_HC_DEV           *Uhc
   1513   )
   1514 {
   1515   if (Uhc->AsyncIntMonitor != NULL) {
   1516     gBS->CloseEvent (Uhc->AsyncIntMonitor);
   1517   }
   1518 
   1519   if (Uhc->ExitBootServiceEvent != NULL) {
   1520     gBS->CloseEvent (Uhc->ExitBootServiceEvent);
   1521   }
   1522 
   1523   if (Uhc->MemPool != NULL) {
   1524     UsbHcFreeMemPool (Uhc->MemPool);
   1525   }
   1526 
   1527   if (Uhc->CtrlNameTable != NULL) {
   1528     FreeUnicodeStringTable (Uhc->CtrlNameTable);
   1529   }
   1530 
   1531   FreePool (Uhc);
   1532 }
   1533 
   1534 
   1535 /**
   1536   Uninstall all Uhci Interface.
   1537 
   1538   @param  Controller           Controller handle.
   1539   @param  This                 Protocol instance pointer.
   1540 
   1541 **/
   1542 VOID
   1543 UhciCleanDevUp (
   1544   IN  EFI_HANDLE           Controller,
   1545   IN  EFI_USB2_HC_PROTOCOL *This
   1546   )
   1547 {
   1548   USB_HC_DEV          *Uhc;
   1549   EFI_STATUS          Status;
   1550 
   1551   //
   1552   // Uninstall the USB_HC and USB_HC2 protocol, then disable the controller
   1553   //
   1554   Uhc = UHC_FROM_USB2_HC_PROTO (This);
   1555 
   1556 
   1557   Status = gBS->UninstallProtocolInterface (
   1558                   Controller,
   1559                   &gEfiUsb2HcProtocolGuid,
   1560                   &Uhc->Usb2Hc
   1561                   );
   1562   if (EFI_ERROR (Status)) {
   1563     return ;
   1564   }
   1565 
   1566   UhciStopHc (Uhc, UHC_GENERIC_TIMEOUT);
   1567   UhciFreeAllAsyncReq (Uhc);
   1568   UhciDestoryFrameList (Uhc);
   1569 
   1570   //
   1571   // Restore original PCI attributes
   1572   //
   1573   Uhc->PciIo->Attributes (
   1574                   Uhc->PciIo,
   1575                   EfiPciIoAttributeOperationSet,
   1576                   Uhc->OriginalPciAttributes,
   1577                   NULL
   1578                   );
   1579 
   1580   UhciFreeDev (Uhc);
   1581 }
   1582 
   1583 /**
   1584   One notified function to stop the Host Controller when gBS->ExitBootServices() called.
   1585 
   1586   @param  Event                   Pointer to this event
   1587   @param  Context                 Event handler private data
   1588 
   1589 **/
   1590 VOID
   1591 EFIAPI
   1592 UhcExitBootService (
   1593   EFI_EVENT                      Event,
   1594   VOID                           *Context
   1595   )
   1596 {
   1597   USB_HC_DEV   *Uhc;
   1598 
   1599   Uhc = (USB_HC_DEV *) Context;
   1600 
   1601   //
   1602   // Stop the Host Controller
   1603   //
   1604   UhciStopHc (Uhc, UHC_GENERIC_TIMEOUT);
   1605 
   1606   //
   1607   // Reset the Host Controller
   1608   //
   1609   UhciSetRegBit (Uhc->PciIo, USBCMD_OFFSET, USBCMD_HCRESET);
   1610   gBS->Stall (UHC_ROOT_PORT_RECOVERY_STALL);
   1611 }
   1612 
   1613 /**
   1614   Starting the Usb UHCI Driver.
   1615 
   1616   @param  This                 Protocol instance pointer.
   1617   @param  Controller           Handle of device to test.
   1618   @param  RemainingDevicePath  Not used.
   1619 
   1620   @retval EFI_SUCCESS          This driver supports this device.
   1621   @retval EFI_UNSUPPORTED      This driver does not support this device.
   1622   @retval EFI_DEVICE_ERROR     This driver cannot be started due to device Error.
   1623                                EFI_OUT_OF_RESOURCES- Failed due to resource shortage.
   1624 
   1625 **/
   1626 EFI_STATUS
   1627 EFIAPI
   1628 UhciDriverBindingStart (
   1629   IN EFI_DRIVER_BINDING_PROTOCOL     *This,
   1630   IN EFI_HANDLE                      Controller,
   1631   IN EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath
   1632   )
   1633 {
   1634   EFI_STATUS          Status;
   1635   EFI_PCI_IO_PROTOCOL *PciIo;
   1636   USB_HC_DEV          *Uhc;
   1637   UINT64              Supports;
   1638   UINT64              OriginalPciAttributes;
   1639   BOOLEAN             PciAttributesSaved;
   1640   EFI_DEVICE_PATH_PROTOCOL  *HcDevicePath;
   1641 
   1642   //
   1643   // Open PCIIO, then enable the EHC device and turn off emulation
   1644   //
   1645   Uhc = NULL;
   1646   Status = gBS->OpenProtocol (
   1647                   Controller,
   1648                   &gEfiPciIoProtocolGuid,
   1649                   (VOID **) &PciIo,
   1650                   This->DriverBindingHandle,
   1651                   Controller,
   1652                   EFI_OPEN_PROTOCOL_BY_DRIVER
   1653                   );
   1654 
   1655   if (EFI_ERROR (Status)) {
   1656     return Status;
   1657   }
   1658 
   1659   //
   1660   // Open Device Path Protocol for on USB host controller
   1661   //
   1662   HcDevicePath = NULL;
   1663   Status = gBS->OpenProtocol (
   1664                   Controller,
   1665                   &gEfiDevicePathProtocolGuid,
   1666                   (VOID **) &HcDevicePath,
   1667                   This->DriverBindingHandle,
   1668                   Controller,
   1669                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
   1670                   );
   1671 
   1672   PciAttributesSaved = FALSE;
   1673   //
   1674   // Save original PCI attributes
   1675   //
   1676   Status = PciIo->Attributes (
   1677                     PciIo,
   1678                     EfiPciIoAttributeOperationGet,
   1679                     0,
   1680                     &OriginalPciAttributes
   1681                     );
   1682 
   1683   if (EFI_ERROR (Status)) {
   1684     goto CLOSE_PCIIO;
   1685   }
   1686   PciAttributesSaved = TRUE;
   1687 
   1688   //
   1689   // Robustnesss improvement such as for UoL
   1690   // Default is not required.
   1691   //
   1692   if (FeaturePcdGet (PcdTurnOffUsbLegacySupport)) {
   1693     UhciTurnOffUsbEmulation (PciIo);
   1694   }
   1695 
   1696   Status = PciIo->Attributes (
   1697                     PciIo,
   1698                     EfiPciIoAttributeOperationSupported,
   1699                     0,
   1700                     &Supports
   1701                     );
   1702   if (!EFI_ERROR (Status)) {
   1703     Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
   1704     Status = PciIo->Attributes (
   1705                       PciIo,
   1706                       EfiPciIoAttributeOperationEnable,
   1707                       Supports,
   1708                       NULL
   1709                       );
   1710   }
   1711 
   1712   if (EFI_ERROR (Status)) {
   1713     goto CLOSE_PCIIO;
   1714   }
   1715 
   1716   Uhc = UhciAllocateDev (PciIo, HcDevicePath, OriginalPciAttributes);
   1717 
   1718   if (Uhc == NULL) {
   1719     Status = EFI_OUT_OF_RESOURCES;
   1720     goto CLOSE_PCIIO;
   1721   }
   1722 
   1723   //
   1724   // Allocate and Init Host Controller's Frame List Entry
   1725   //
   1726   Status = UhciInitFrameList (Uhc);
   1727 
   1728   if (EFI_ERROR (Status)) {
   1729     Status = EFI_OUT_OF_RESOURCES;
   1730     goto FREE_UHC;
   1731   }
   1732 
   1733   Status = gBS->SetTimer (
   1734                   Uhc->AsyncIntMonitor,
   1735                   TimerPeriodic,
   1736                   UHC_ASYNC_POLL_INTERVAL
   1737                   );
   1738 
   1739   if (EFI_ERROR (Status)) {
   1740     goto FREE_UHC;
   1741   }
   1742 
   1743   //
   1744   // Install USB2_HC_PROTOCOL
   1745   //
   1746   Status = gBS->InstallMultipleProtocolInterfaces (
   1747                   &Controller,
   1748                   &gEfiUsb2HcProtocolGuid,
   1749                   &Uhc->Usb2Hc,
   1750                   NULL
   1751                   );
   1752 
   1753   if (EFI_ERROR (Status)) {
   1754     goto FREE_UHC;
   1755   }
   1756 
   1757   //
   1758   // Create event to stop the HC when exit boot service.
   1759   //
   1760   Status = gBS->CreateEventEx (
   1761                   EVT_NOTIFY_SIGNAL,
   1762                   TPL_NOTIFY,
   1763                   UhcExitBootService,
   1764                   Uhc,
   1765                   &gEfiEventExitBootServicesGuid,
   1766                   &Uhc->ExitBootServiceEvent
   1767                   );
   1768   if (EFI_ERROR (Status)) {
   1769     goto UNINSTALL_USBHC;
   1770   }
   1771 
   1772   //
   1773   // Install the component name protocol
   1774   //
   1775   Uhc->CtrlNameTable = NULL;
   1776 
   1777   AddUnicodeString2 (
   1778     "eng",
   1779     gUhciComponentName.SupportedLanguages,
   1780     &Uhc->CtrlNameTable,
   1781     L"Usb Universal Host Controller",
   1782     TRUE
   1783     );
   1784   AddUnicodeString2 (
   1785     "en",
   1786     gUhciComponentName2.SupportedLanguages,
   1787     &Uhc->CtrlNameTable,
   1788     L"Usb Universal Host Controller",
   1789     FALSE
   1790     );
   1791 
   1792 
   1793   //
   1794   // Start the UHCI hardware, also set its reclamation point to 64 bytes
   1795   //
   1796   UhciWriteReg (Uhc->PciIo, USBCMD_OFFSET, USBCMD_RS | USBCMD_MAXP);
   1797 
   1798   return EFI_SUCCESS;
   1799 
   1800 UNINSTALL_USBHC:
   1801   gBS->UninstallMultipleProtocolInterfaces (
   1802          Controller,
   1803          &gEfiUsb2HcProtocolGuid,
   1804          &Uhc->Usb2Hc,
   1805          NULL
   1806          );
   1807 
   1808 FREE_UHC:
   1809   UhciFreeDev (Uhc);
   1810 
   1811 CLOSE_PCIIO:
   1812   if (PciAttributesSaved) {
   1813     //
   1814     // Restore original PCI attributes
   1815     //
   1816     PciIo->Attributes (
   1817                     PciIo,
   1818                     EfiPciIoAttributeOperationSet,
   1819                     OriginalPciAttributes,
   1820                     NULL
   1821                     );
   1822   }
   1823 
   1824   gBS->CloseProtocol (
   1825         Controller,
   1826         &gEfiPciIoProtocolGuid,
   1827         This->DriverBindingHandle,
   1828         Controller
   1829         );
   1830 
   1831   return Status;
   1832 }
   1833 
   1834 
   1835 /**
   1836   Stop this driver on ControllerHandle. Support stopping any child handles
   1837   created by this driver.
   1838 
   1839   @param  This                 Protocol instance pointer.
   1840   @param  Controller           Handle of device to stop driver on.
   1841   @param  NumberOfChildren     Number of Children in the ChildHandleBuffer.
   1842   @param  ChildHandleBuffer    List of handles for the children we need to stop.
   1843 
   1844   @return EFI_SUCCESS
   1845   @return others
   1846 
   1847 **/
   1848 EFI_STATUS
   1849 EFIAPI
   1850 UhciDriverBindingStop (
   1851   IN EFI_DRIVER_BINDING_PROTOCOL     *This,
   1852   IN EFI_HANDLE                      Controller,
   1853   IN UINTN                           NumberOfChildren,
   1854   IN EFI_HANDLE                      *ChildHandleBuffer
   1855   )
   1856 {
   1857   EFI_USB2_HC_PROTOCOL  *Usb2Hc;
   1858   EFI_STATUS            Status;
   1859 
   1860    Status = gBS->OpenProtocol (
   1861                   Controller,
   1862                   &gEfiUsb2HcProtocolGuid,
   1863                   (VOID **) &Usb2Hc,
   1864                   This->DriverBindingHandle,
   1865                   Controller,
   1866                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
   1867                   );
   1868 
   1869   //
   1870   // Test whether the Controller handler passed in is a valid
   1871   // Usb controller handle that should be supported, if not,
   1872   // return the error status directly
   1873   //
   1874   if (EFI_ERROR (Status)) {
   1875     return Status;
   1876   }
   1877 
   1878   UhciCleanDevUp (Controller, Usb2Hc);
   1879 
   1880   gBS->CloseProtocol (
   1881         Controller,
   1882         &gEfiPciIoProtocolGuid,
   1883         This->DriverBindingHandle,
   1884         Controller
   1885         );
   1886 
   1887   return EFI_SUCCESS;
   1888 }
   1889 
   1890