Home | History | Annotate | Download | only in Dxe
      1 /** @file
      2 This file contains the implementation of Usb Hc Protocol.
      3 
      4 Copyright (c) 2013-2016 Intel Corporation.
      5 
      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 
     17 #include "Ohci.h"
     18 
     19 /**
     20   Provides software reset for the USB host controller.
     21 
     22   @param  This                  This EFI_USB_HC_PROTOCOL instance.
     23   @param  Attributes            A bit mask of the reset operation to perform.
     24 
     25   @retval EFI_SUCCESS           The reset operation succeeded.
     26   @retval EFI_INVALID_PARAMETER Attributes is not valid.
     27   @retval EFI_UNSUPPOURTED      The type of reset specified by Attributes is
     28                                 not currently supported by the host controller.
     29   @retval EFI_DEVICE_ERROR      Host controller isn't halted to reset.
     30 
     31 **/
     32 EFI_STATUS
     33 EFIAPI
     34 OhciReset (
     35   IN EFI_USB_HC_PROTOCOL  *This,
     36   IN UINT16               Attributes
     37   )
     38 {
     39   EFI_STATUS              Status;
     40   USB_OHCI_HC_DEV         *Ohc;
     41   UINT8                   Index;
     42   UINT8                   NumOfPorts;
     43   UINT32                  PowerOnGoodTime;
     44   UINT32                  Data32;
     45   BOOLEAN                 Flag = FALSE;
     46 
     47   if ((Attributes & ~(EFI_USB_HC_RESET_GLOBAL | EFI_USB_HC_RESET_HOST_CONTROLLER)) != 0) {
     48     return EFI_INVALID_PARAMETER;
     49   }
     50 
     51   Status = EFI_SUCCESS;
     52   Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
     53 
     54   if ((Attributes & EFI_USB_HC_RESET_HOST_CONTROLLER) != 0) {
     55     gBS->Stall (50 * 1000);
     56     Status = OhciSetHcCommandStatus (Ohc, HC_RESET, HC_RESET);
     57     if (EFI_ERROR (Status)) {
     58       return EFI_DEVICE_ERROR;
     59     }
     60     gBS->Stall (50 * 1000);
     61     //
     62     // Wait for host controller reset.
     63     //
     64     PowerOnGoodTime = 50;
     65     do {
     66       gBS->Stall (1 * 1000);
     67       Data32 = OhciGetOperationalReg (Ohc->PciIo, HC_COMMAND_STATUS );
     68       if (EFI_ERROR (Status)) {
     69         return EFI_DEVICE_ERROR;
     70       }
     71       if ((Data32 & HC_RESET) == 0) {
     72         Flag = TRUE;
     73         break;
     74       }
     75     }while(PowerOnGoodTime--);
     76     if (!Flag){
     77       return EFI_DEVICE_ERROR;
     78     }
     79   }
     80   OhciFreeIntTransferMemory (Ohc);
     81   Status = OhciInitializeInterruptList (Ohc);
     82   OhciSetFrameInterval (Ohc, FRAME_INTERVAL, 0x2edf);
     83   if ((Attributes &  EFI_USB_HC_RESET_GLOBAL) != 0) {
     84     Status = OhciSetHcControl (Ohc, HC_FUNCTIONAL_STATE, HC_STATE_RESET);
     85     if (EFI_ERROR (Status)) {
     86       return EFI_DEVICE_ERROR;
     87     }
     88     gBS->Stall (50 * 1000);
     89   }
     90   //
     91   // Initialize host controller operational registers
     92   //
     93   OhciSetFrameInterval (Ohc, FS_LARGEST_DATA_PACKET, 0x2778);
     94   OhciSetFrameInterval (Ohc, FRAME_INTERVAL, 0x2edf);
     95   OhciSetPeriodicStart (Ohc, 0x2a2f);
     96   OhciSetHcControl (Ohc, CONTROL_BULK_RATIO, 0x3);
     97   OhciSetHcCommandStatus (Ohc, CONTROL_LIST_FILLED | BULK_LIST_FILLED, 0);
     98   OhciSetRootHubDescriptor (Ohc, RH_PSWITCH_MODE, 0);
     99   OhciSetRootHubDescriptor (Ohc, RH_NO_PSWITCH | RH_NOC_PROT, 1);
    100   //OhciSetRootHubDescriptor (Hc, RH_PSWITCH_MODE | RH_NO_PSWITCH, 0);
    101   //OhciSetRootHubDescriptor (Hc, RH_PSWITCH_MODE | RH_NOC_PROT, 1);
    102 
    103   OhciSetRootHubDescriptor (Ohc, RH_DEV_REMOVABLE, 0);
    104   OhciSetRootHubDescriptor (Ohc, RH_PORT_PWR_CTRL_MASK, 0xffff);
    105   OhciSetRootHubStatus (Ohc, RH_LOCAL_PSTAT_CHANGE);
    106   OhciSetRootHubPortStatus (Ohc, 0, RH_SET_PORT_POWER);
    107   OhciGetRootHubNumOfPorts (This, &NumOfPorts);
    108   for (Index = 0; Index < NumOfPorts; Index++) {
    109     if (!EFI_ERROR (OhciSetRootHubPortFeature (This, Index, EfiUsbPortReset))) {
    110       gBS->Stall (200 * 1000);
    111       OhciClearRootHubPortFeature (This, Index, EfiUsbPortReset);
    112       gBS->Stall (1000);
    113       OhciSetRootHubPortFeature (This, Index, EfiUsbPortEnable);
    114       gBS->Stall (1000);
    115     }
    116   }
    117   OhciSetMemoryPointer (Ohc, HC_HCCA, Ohc->HccaMemoryBlock);
    118   OhciSetMemoryPointer (Ohc, HC_CONTROL_HEAD, NULL);
    119   OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, NULL);
    120   OhciSetHcControl (Ohc, PERIODIC_ENABLE | CONTROL_ENABLE | BULK_ENABLE, 1); /*ISOCHRONOUS_ENABLE*/
    121   OhciSetHcControl (Ohc, HC_FUNCTIONAL_STATE, HC_STATE_OPERATIONAL);
    122   gBS->Stall (50*1000);
    123   //
    124   // Wait till first SOF occurs, and then clear it
    125   //
    126   while (OhciGetHcInterruptStatus (Ohc, START_OF_FRAME) == 0);
    127   OhciClearInterruptStatus (Ohc, START_OF_FRAME);
    128   gBS->Stall (1000);
    129 
    130   return Status;
    131 }
    132 
    133 /**
    134   Retrieve the current state of the USB host controller.
    135 
    136   @param  This                  This EFI_USB_HC_PROTOCOL instance.
    137   @param  State                 Variable to return the current host controller
    138                                 state.
    139 
    140   @retval EFI_SUCCESS           Host controller state was returned in State.
    141   @retval EFI_INVALID_PARAMETER State is NULL.
    142   @retval EFI_DEVICE_ERROR      An error was encountered while attempting to
    143                                 retrieve the host controller's current state.
    144 
    145 **/
    146 
    147 EFI_STATUS
    148 EFIAPI
    149 OhciGetState (
    150   IN  EFI_USB_HC_PROTOCOL  *This,
    151   OUT EFI_USB_HC_STATE     *State
    152   )
    153 {
    154   USB_OHCI_HC_DEV         *Ohc;
    155   UINT32                  FuncState;
    156 
    157   if (State == NULL) {
    158     return EFI_INVALID_PARAMETER;
    159   }
    160 
    161   Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
    162 
    163   FuncState = OhciGetHcControl (Ohc, HC_FUNCTIONAL_STATE);
    164 
    165   switch (FuncState) {
    166     case HC_STATE_RESET:
    167     case HC_STATE_RESUME:
    168       *State = EfiUsbHcStateHalt;
    169       break;
    170 
    171     case HC_STATE_OPERATIONAL:
    172       *State = EfiUsbHcStateOperational;
    173       break;
    174 
    175     case HC_STATE_SUSPEND:
    176       *State = EfiUsbHcStateSuspend;
    177       break;
    178 
    179     default:
    180       ASSERT (FALSE);
    181   }
    182   return EFI_SUCCESS;
    183 }
    184 
    185 /**
    186   Sets the USB host controller to a specific state.
    187 
    188   @param  This                  This EFI_USB_HC_PROTOCOL instance.
    189   @param  State                 The state of the host controller that will be set.
    190 
    191   @retval EFI_SUCCESS           The USB host controller was successfully placed
    192                                 in the state specified by State.
    193   @retval EFI_INVALID_PARAMETER State is invalid.
    194   @retval EFI_DEVICE_ERROR      Failed to set the state due to device error.
    195 
    196 **/
    197 
    198 EFI_STATUS
    199 EFIAPI
    200 OhciSetState(
    201   IN EFI_USB_HC_PROTOCOL  *This,
    202   IN EFI_USB_HC_STATE     State
    203   )
    204 {
    205   EFI_STATUS              Status;
    206   USB_OHCI_HC_DEV         *Ohc;
    207 
    208   Ohc = USB_OHCI_HC_DEV_FROM_THIS(This);
    209 
    210   switch (State) {
    211     case EfiUsbHcStateHalt:
    212       Status = OhciSetHcControl (Ohc, HC_FUNCTIONAL_STATE, HC_STATE_RESET);
    213       break;
    214 
    215     case EfiUsbHcStateOperational:
    216       Status = OhciSetHcControl (Ohc, HC_FUNCTIONAL_STATE, HC_STATE_OPERATIONAL);
    217       break;
    218 
    219     case EfiUsbHcStateSuspend:
    220       Status = OhciSetHcControl (Ohc, HC_FUNCTIONAL_STATE, HC_STATE_SUSPEND);
    221       break;
    222 
    223     default:
    224       Status = EFI_INVALID_PARAMETER;
    225   }
    226 
    227   gBS->Stall (1000);
    228 
    229   return Status;
    230 }
    231 
    232 /**
    233 
    234   Submits control transfer to a target USB device.
    235 
    236   @param  This                  A pointer to the EFI_USB_HC_PROTOCOL instance.
    237   @param  DeviceAddress         Represents the address of the target device on the USB,
    238                                 which is assigned during USB enumeration.
    239   @param  IsSlowDevice          Indicates whether the target device is slow device
    240                                 or full-speed device.
    241   @param  MaxPaketLength        Indicates the maximum packet size that the
    242                                 default control transfer endpoint is capable of
    243                                 sending or receiving.
    244   @param  Request               A pointer to the USB device request that will be sent
    245                                 to the USB device.
    246   @param  TransferDirection     Specifies the data direction for the transfer.
    247                                 There are three values available, DataIn, DataOut
    248                                 and NoData.
    249   @param  Data                  A pointer to the buffer of data that will be transmitted
    250                                 to USB device or received from USB device.
    251   @param  DataLength            Indicates the size, in bytes, of the data buffer
    252                                 specified by Data.
    253   @param  TimeOut               Indicates the maximum time, in microseconds,
    254                                 which the transfer is allowed to complete.
    255   @param  TransferResult        A pointer to the detailed result information generated
    256                                 by this control transfer.
    257 
    258   @retval EFI_SUCCESS           The control transfer was completed successfully.
    259   @retval EFI_OUT_OF_RESOURCES  The control transfer could not be completed due to a lack of resources.
    260   @retval EFI_INVALID_PARAMETER Some parameters are invalid.
    261   @retval EFI_TIMEOUT           The control transfer failed due to timeout.
    262   @retval EFI_DEVICE_ERROR      The control transfer failed due to host controller or device error.
    263                                 Caller should check TranferResult for detailed error information.
    264 
    265 --*/
    266 
    267 
    268 EFI_STATUS
    269 EFIAPI
    270 OhciControlTransfer (
    271   IN     EFI_USB_HC_PROTOCOL     *This,
    272   IN     UINT8                   DeviceAddress,
    273   IN     BOOLEAN                 IsSlowDevice,
    274   IN     UINT8                   MaxPacketLength,
    275   IN     EFI_USB_DEVICE_REQUEST  *Request,
    276   IN     EFI_USB_DATA_DIRECTION  TransferDirection,
    277   IN OUT VOID                    *Data                 OPTIONAL,
    278   IN OUT UINTN                   *DataLength           OPTIONAL,
    279   IN     UINTN                   TimeOut,
    280   OUT    UINT32                  *TransferResult
    281   )
    282 {
    283   USB_OHCI_HC_DEV                *Ohc;
    284   ED_DESCRIPTOR                  *HeadEd;
    285   ED_DESCRIPTOR                  *Ed;
    286   TD_DESCRIPTOR                  *HeadTd;
    287   TD_DESCRIPTOR                  *SetupTd;
    288   TD_DESCRIPTOR                  *DataTd;
    289   TD_DESCRIPTOR                  *StatusTd;
    290   TD_DESCRIPTOR                  *EmptyTd;
    291   EFI_STATUS                     Status;
    292   UINT32                         DataPidDir;
    293   UINT32                         StatusPidDir;
    294   UINTN                          TimeCount;
    295   OHCI_ED_RESULT                 EdResult;
    296 
    297   EFI_PCI_IO_PROTOCOL_OPERATION  MapOp;
    298 
    299   UINTN                          ActualSendLength;
    300   UINTN                          LeftLength;
    301   UINT8                          DataToggle;
    302 
    303   VOID                           *ReqMapping = NULL;
    304   UINTN                          ReqMapLength = 0;
    305   EFI_PHYSICAL_ADDRESS           ReqMapPhyAddr = 0;
    306 
    307   VOID                           *DataMapping = NULL;
    308   UINTN                          DataMapLength = 0;
    309   EFI_PHYSICAL_ADDRESS           DataMapPhyAddr = 0;
    310 
    311   HeadTd = NULL;
    312   DataTd = NULL;
    313 
    314   if ((TransferDirection != EfiUsbDataOut && TransferDirection != EfiUsbDataIn &&
    315        TransferDirection != EfiUsbNoData) ||
    316       Request == NULL || DataLength == NULL || TransferResult == NULL ||
    317       (TransferDirection == EfiUsbNoData && (*DataLength != 0 || Data != NULL)) ||
    318       (TransferDirection != EfiUsbNoData && (*DataLength == 0 || Data == NULL)) ||
    319       (IsSlowDevice && MaxPacketLength != 8) ||
    320       (MaxPacketLength != 8 && MaxPacketLength != 16 &&
    321        MaxPacketLength != 32 && MaxPacketLength != 64)) {
    322     return EFI_INVALID_PARAMETER;
    323   }
    324 
    325   if (*DataLength > MAX_BYTES_PER_TD) {
    326     DEBUG ((EFI_D_ERROR, "OhciControlTransfer: Request data size is too large\r\n"));
    327     return EFI_INVALID_PARAMETER;
    328   }
    329 
    330   Ohc = USB_OHCI_HC_DEV_FROM_THIS(This);
    331 
    332   if (TransferDirection == EfiUsbDataIn) {
    333     DataPidDir = TD_IN_PID;
    334     StatusPidDir = TD_OUT_PID;
    335   } else {
    336     DataPidDir = TD_OUT_PID;
    337     StatusPidDir = TD_IN_PID;
    338   }
    339 
    340   Status = OhciSetHcControl (Ohc, CONTROL_ENABLE, 0);
    341   if (EFI_ERROR(Status)) {
    342     DEBUG ((EFI_D_INFO, "OhciControlTransfer: fail to disable CONTROL_ENABLE\r\n"));
    343     *TransferResult = EFI_USB_ERR_SYSTEM;
    344     return EFI_DEVICE_ERROR;
    345   }
    346   Status = OhciSetHcCommandStatus (Ohc, CONTROL_LIST_FILLED, 0);
    347   if (EFI_ERROR(Status)) {
    348     DEBUG ((EFI_D_INFO, "OhciControlTransfer: fail to disable CONTROL_LIST_FILLED\r\n"));
    349     *TransferResult = EFI_USB_ERR_SYSTEM;
    350     return EFI_DEVICE_ERROR;
    351   }
    352   gBS->Stall(20 * 1000);
    353 
    354   OhciSetMemoryPointer (Ohc, HC_CONTROL_HEAD, NULL);
    355   Ed = OhciCreateED (Ohc);
    356   if (Ed == NULL) {
    357     Status = EFI_OUT_OF_RESOURCES;
    358     DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate ED buffer\r\n"));
    359     goto CTRL_EXIT;
    360   }
    361   OhciSetEDField (Ed, ED_SKIP, 1);
    362   OhciSetEDField (Ed, ED_FUNC_ADD, DeviceAddress);
    363   OhciSetEDField (Ed, ED_ENDPT_NUM, 0);
    364   OhciSetEDField (Ed, ED_DIR, ED_FROM_TD_DIR);
    365   OhciSetEDField (Ed, ED_SPEED, IsSlowDevice);
    366   OhciSetEDField (Ed, ED_FORMAT | ED_HALTED | ED_DTTOGGLE, 0);
    367   OhciSetEDField (Ed, ED_MAX_PACKET, MaxPacketLength);
    368   OhciSetEDField (Ed, ED_PDATA, 0);
    369   OhciSetEDField (Ed, ED_ZERO, 0);
    370   OhciSetEDField (Ed, ED_TDHEAD_PTR, 0);
    371   OhciSetEDField (Ed, ED_TDTAIL_PTR, 0);
    372   OhciSetEDField (Ed, ED_NEXT_EDPTR, 0);
    373   HeadEd = OhciAttachEDToList (Ohc, CONTROL_LIST, Ed, NULL);
    374   //
    375   // Setup Stage
    376   //
    377   if(Request != NULL) {
    378     ReqMapLength = sizeof(EFI_USB_DEVICE_REQUEST);
    379     MapOp = EfiPciIoOperationBusMasterRead;
    380     Status = Ohc->PciIo->Map (Ohc->PciIo, MapOp, (UINT8 *)Request, &ReqMapLength, &ReqMapPhyAddr, &ReqMapping);
    381     if (EFI_ERROR(Status)) {
    382       DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to Map Request Buffer\r\n"));
    383       goto FREE_ED_BUFF;
    384     }
    385   }
    386   SetupTd = OhciCreateTD (Ohc);
    387   if (SetupTd == NULL) {
    388     Status = EFI_OUT_OF_RESOURCES;
    389     DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate Setup TD buffer\r\n"));
    390     goto UNMAP_SETUP_BUFF;
    391   }
    392   HeadTd = SetupTd;
    393   OhciSetTDField (SetupTd, TD_PDATA, 0);
    394   OhciSetTDField (SetupTd, TD_BUFFER_ROUND, 1);
    395   OhciSetTDField (SetupTd, TD_DIR_PID, TD_SETUP_PID);
    396   OhciSetTDField (SetupTd, TD_DELAY_INT, TD_NO_DELAY);
    397   OhciSetTDField (SetupTd, TD_DT_TOGGLE, 2);
    398   OhciSetTDField (SetupTd, TD_ERROR_CNT, 0);
    399   OhciSetTDField (SetupTd, TD_COND_CODE, TD_TOBE_PROCESSED);
    400   OhciSetTDField (SetupTd, TD_CURR_BUFFER_PTR, (UINT32)ReqMapPhyAddr);
    401   OhciSetTDField (SetupTd, TD_NEXT_PTR, 0);
    402   OhciSetTDField (SetupTd, TD_BUFFER_END_PTR, (UINT32)(ReqMapPhyAddr + sizeof (EFI_USB_DEVICE_REQUEST) - 1));
    403   SetupTd->ActualSendLength = sizeof (EFI_USB_DEVICE_REQUEST);
    404   SetupTd->DataBuffer = (UINT32)ReqMapPhyAddr;
    405   SetupTd->NextTDPointer = 0;
    406 
    407   if (TransferDirection == EfiUsbDataIn) {
    408     MapOp = EfiPciIoOperationBusMasterWrite;
    409   } else {
    410     MapOp = EfiPciIoOperationBusMasterRead;
    411   }
    412   DataMapLength = *DataLength;
    413   if ((Data != NULL) && (DataMapLength != 0)) {
    414     Status = Ohc->PciIo->Map (Ohc->PciIo, MapOp, Data, &DataMapLength, &DataMapPhyAddr, &DataMapping);
    415     if (EFI_ERROR(Status)) {
    416       DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail To Map Data Buffer\r\n"));
    417       goto FREE_TD_BUFF;
    418     }
    419   }
    420   //
    421   //Data Stage
    422   //
    423   LeftLength = DataMapLength;
    424   ActualSendLength = DataMapLength;
    425   DataToggle = 1;
    426   while (LeftLength > 0) {
    427     ActualSendLength = LeftLength;
    428     if (LeftLength > MaxPacketLength) {
    429       ActualSendLength = MaxPacketLength;
    430     }
    431     DataTd = OhciCreateTD (Ohc);
    432     if (DataTd == NULL) {
    433       DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate buffer for Data Stage TD\r\n"));
    434       Status = EFI_OUT_OF_RESOURCES;
    435       goto UNMAP_DATA_BUFF;
    436     }
    437     OhciSetTDField (DataTd, TD_PDATA, 0);
    438     OhciSetTDField (DataTd, TD_BUFFER_ROUND, 1);
    439     OhciSetTDField (DataTd, TD_DIR_PID, DataPidDir);
    440     OhciSetTDField (DataTd, TD_DELAY_INT, TD_NO_DELAY);
    441     OhciSetTDField (DataTd, TD_DT_TOGGLE, DataToggle);
    442     OhciSetTDField (DataTd, TD_ERROR_CNT, 0);
    443     OhciSetTDField (DataTd, TD_COND_CODE, TD_TOBE_PROCESSED);
    444     OhciSetTDField (DataTd, TD_CURR_BUFFER_PTR, (UINT32) DataMapPhyAddr);
    445     OhciSetTDField (DataTd, TD_BUFFER_END_PTR, (UINT32)(DataMapPhyAddr + ActualSendLength - 1));
    446     OhciSetTDField (DataTd, TD_NEXT_PTR, 0);
    447     DataTd->ActualSendLength = (UINT32)ActualSendLength;
    448     DataTd->DataBuffer = (UINT32)DataMapPhyAddr;
    449     DataTd->NextTDPointer = 0;
    450     OhciLinkTD (HeadTd, DataTd);
    451     DataToggle ^= 1;
    452     DataMapPhyAddr += ActualSendLength;
    453     LeftLength -= ActualSendLength;
    454   }
    455   //
    456   // Status Stage
    457   //
    458   StatusTd = OhciCreateTD (Ohc);
    459   if (StatusTd == NULL) {
    460     DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate buffer for Status Stage TD\r\n"));
    461     Status = EFI_OUT_OF_RESOURCES;
    462     goto UNMAP_DATA_BUFF;
    463   }
    464   OhciSetTDField (StatusTd, TD_PDATA, 0);
    465   OhciSetTDField (StatusTd, TD_BUFFER_ROUND, 1);
    466   OhciSetTDField (StatusTd, TD_DIR_PID, StatusPidDir);
    467   OhciSetTDField (StatusTd, TD_DELAY_INT, 7);
    468   OhciSetTDField (StatusTd, TD_DT_TOGGLE, 3);
    469   OhciSetTDField (StatusTd, TD_ERROR_CNT, 0);
    470   OhciSetTDField (StatusTd, TD_COND_CODE, TD_TOBE_PROCESSED);
    471   OhciSetTDField (StatusTd, TD_CURR_BUFFER_PTR, 0);
    472   OhciSetTDField (StatusTd, TD_NEXT_PTR, 0);
    473   OhciSetTDField (StatusTd, TD_BUFFER_END_PTR, 0);
    474   StatusTd->ActualSendLength = 0;
    475   StatusTd->DataBuffer = 0;
    476   StatusTd->NextTDPointer = 0;
    477   OhciLinkTD (HeadTd, StatusTd);
    478   //
    479   // Empty Stage
    480   //
    481   EmptyTd = OhciCreateTD (Ohc);
    482   if (EmptyTd == NULL) {
    483     Status = EFI_OUT_OF_RESOURCES;
    484     goto UNMAP_DATA_BUFF;
    485   }
    486   OhciSetTDField (EmptyTd, TD_PDATA, 0);
    487   OhciSetTDField (EmptyTd, TD_BUFFER_ROUND, 0);
    488   OhciSetTDField (EmptyTd, TD_DIR_PID, 0);
    489   OhciSetTDField (EmptyTd, TD_DELAY_INT, 0);
    490   //OhciSetTDField (EmptyTd, TD_DT_TOGGLE, CurrentToggle);
    491   EmptyTd->Word0.DataToggle = 0;
    492   OhciSetTDField (EmptyTd, TD_ERROR_CNT, 0);
    493   OhciSetTDField (EmptyTd, TD_COND_CODE, 0);
    494   OhciSetTDField (EmptyTd, TD_CURR_BUFFER_PTR, 0);
    495   OhciSetTDField (EmptyTd, TD_BUFFER_END_PTR, 0);
    496   OhciSetTDField (EmptyTd, TD_NEXT_PTR, 0);
    497   EmptyTd->ActualSendLength = 0;
    498   EmptyTd->DataBuffer = 0;
    499   EmptyTd->NextTDPointer = 0;
    500   OhciLinkTD (HeadTd, EmptyTd);
    501   Ed->TdTailPointer = (UINT32)(UINTN)EmptyTd;
    502   OhciAttachTDListToED (Ed, HeadTd);
    503   //
    504   // For debugging,  dump ED & TD buffer befor transferring
    505   //
    506   //
    507   //OhciDumpEdTdInfo (Ohc, Ed, HeadTd, TRUE);
    508   //
    509   OhciSetEDField (Ed, ED_SKIP, 0);
    510   Status = OhciSetHcControl (Ohc, CONTROL_ENABLE, 1);
    511   if (EFI_ERROR(Status)) {
    512     DEBUG ((EFI_D_INFO, "OhciControlTransfer: fail to enable CONTROL_ENABLE\r\n"));
    513     *TransferResult = EFI_USB_ERR_SYSTEM;
    514     Status = EFI_DEVICE_ERROR;
    515     goto UNMAP_DATA_BUFF;
    516   }
    517   Status = OhciSetHcCommandStatus (Ohc, CONTROL_LIST_FILLED, 1);
    518   if (EFI_ERROR(Status)) {
    519     DEBUG ((EFI_D_INFO, "OhciControlTransfer: fail to enable CONTROL_LIST_FILLED\r\n"));
    520     *TransferResult = EFI_USB_ERR_SYSTEM;
    521     Status = EFI_DEVICE_ERROR;
    522     goto UNMAP_DATA_BUFF;
    523   }
    524   gBS->Stall(20 * 1000);
    525 
    526 
    527   TimeCount = 0;
    528   Status = CheckIfDone (Ohc, CONTROL_LIST, Ed, HeadTd, &EdResult);
    529 
    530   while (Status == EFI_NOT_READY && TimeCount <= TimeOut) {
    531     gBS->Stall (1000);
    532     TimeCount++;
    533     Status = CheckIfDone (Ohc, CONTROL_LIST, Ed, HeadTd, &EdResult);
    534   }
    535   //
    536   // For debugging, dump ED & TD buffer after transferring
    537   //
    538   //OhciDumpEdTdInfo (Ohc, Ed, HeadTd, FALSE);
    539   //
    540   *TransferResult = ConvertErrorCode (EdResult.ErrorCode);
    541 
    542   if (EdResult.ErrorCode != TD_NO_ERROR) {
    543     if (EdResult.ErrorCode == TD_TOBE_PROCESSED) {
    544       DEBUG ((EFI_D_INFO, "Control pipe timeout, > %d mS\r\n", TimeOut));
    545     } else {
    546       DEBUG ((EFI_D_INFO, "Control pipe broken\r\n"));
    547     }
    548     *DataLength = 0;
    549   } else {
    550     DEBUG ((EFI_D_INFO, "Control transfer successed\r\n"));
    551   }
    552 
    553 UNMAP_DATA_BUFF:
    554   OhciSetEDField (Ed, ED_SKIP, 1);
    555   if (HeadEd == Ed) {
    556     OhciSetMemoryPointer (Ohc, HC_CONTROL_HEAD, NULL);
    557   } else {
    558     HeadEd->NextED = Ed->NextED;
    559   }
    560   if(DataMapping != NULL) {
    561     Ohc->PciIo->Unmap(Ohc->PciIo, DataMapping);
    562   }
    563 
    564 FREE_TD_BUFF:
    565   while (HeadTd) {
    566     DataTd = HeadTd;
    567     HeadTd = (TD_DESCRIPTOR *)(UINTN)(HeadTd->NextTDPointer);
    568     UsbHcFreeMem(Ohc->MemPool, DataTd, sizeof(TD_DESCRIPTOR));
    569   }
    570 
    571 UNMAP_SETUP_BUFF:
    572   if(ReqMapping != NULL) {
    573     Ohc->PciIo->Unmap(Ohc->PciIo, ReqMapping);
    574   }
    575 
    576 FREE_ED_BUFF:
    577   UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));
    578 
    579 CTRL_EXIT:
    580   return Status;
    581 }
    582 
    583 /**
    584 
    585   Submits bulk transfer to a bulk endpoint of a USB device.
    586 
    587   @param  This                  A pointer to the EFI_USB_HC_PROTOCOL instance.
    588   @param  DeviceAddress         Represents the address of the target device on the USB,
    589                                 which is assigned during USB enumeration.
    590   @param  EndPointAddress       The combination of an endpoint number and an
    591                                 endpoint direction of the target USB device.
    592                                 Each endpoint address supports data transfer in
    593                                 one direction except the control endpoint
    594                                 (whose default endpoint address is 0).
    595                                 It is the caller's responsibility to make sure that
    596                                 the EndPointAddress represents a bulk endpoint.
    597   @param  MaximumPacketLength   Indicates the maximum packet size the target endpoint
    598                                 is capable of sending or receiving.
    599   @param  Data                  A pointer to the buffer of data that will be transmitted
    600                                 to USB device or received from USB device.
    601   @param  DataLength            When input, indicates the size, in bytes, of the data buffer
    602                                 specified by Data. When output, indicates the actually
    603                                 transferred data size.
    604   @param  DataToggle            A pointer to the data toggle value. On input, it indicates
    605                                 the initial data toggle value the bulk transfer should adopt;
    606                                 on output, it is updated to indicate the data toggle value
    607                                 of the subsequent bulk transfer.
    608   @param  TimeOut               Indicates the maximum time, in microseconds, which the
    609                                 transfer is allowed to complete.
    610   TransferResult                A pointer to the detailed result information of the
    611                                 bulk transfer.
    612 
    613   @retval EFI_SUCCESS           The bulk transfer was completed successfully.
    614   @retval EFI_OUT_OF_RESOURCES  The bulk transfer could not be submitted due to lack of resource.
    615   @retval EFI_INVALID_PARAMETER Some parameters are invalid.
    616   @retval EFI_TIMEOUT           The bulk transfer failed due to timeout.
    617   @retval EFI_DEVICE_ERROR      The bulk transfer failed due to host controller or device error.
    618                                 Caller should check TranferResult for detailed error information.
    619 
    620 **/
    621 
    622 
    623 EFI_STATUS
    624 EFIAPI
    625 OhciBulkTransfer(
    626   IN     EFI_USB_HC_PROTOCOL  *This,
    627   IN     UINT8                DeviceAddress,
    628   IN     UINT8                EndPointAddress,
    629   IN     UINT8                MaxPacketLength,
    630   IN OUT VOID                 *Data,
    631   IN OUT UINTN                *DataLength,
    632   IN OUT UINT8                *DataToggle,
    633   IN     UINTN                TimeOut,
    634   OUT    UINT32               *TransferResult
    635   )
    636 {
    637   USB_OHCI_HC_DEV                *Ohc;
    638   ED_DESCRIPTOR                  *HeadEd;
    639   ED_DESCRIPTOR                  *Ed;
    640   UINT32                         DataPidDir;
    641   TD_DESCRIPTOR                  *HeadTd;
    642   TD_DESCRIPTOR                  *DataTd;
    643   TD_DESCRIPTOR                  *EmptyTd;
    644   EFI_STATUS                     Status;
    645   UINT8                          EndPointNum;
    646   UINTN                          TimeCount;
    647   OHCI_ED_RESULT                 EdResult;
    648 
    649   EFI_PCI_IO_PROTOCOL_OPERATION  MapOp;
    650   VOID                           *Mapping;
    651   UINTN                          MapLength;
    652   EFI_PHYSICAL_ADDRESS           MapPyhAddr;
    653   UINTN                          LeftLength;
    654   UINTN                          ActualSendLength;
    655   BOOLEAN                        FirstTD;
    656 
    657   Mapping = NULL;
    658   MapLength = 0;
    659   MapPyhAddr = 0;
    660   LeftLength = 0;
    661   Status = EFI_SUCCESS;
    662 
    663   if (Data == NULL || DataLength == NULL || DataToggle == NULL || TransferResult == NULL ||
    664       *DataLength == 0 || (*DataToggle != 0 && *DataToggle != 1) ||
    665       (MaxPacketLength != 8 && MaxPacketLength != 16 &&
    666        MaxPacketLength != 32 && MaxPacketLength != 64)) {
    667     return EFI_INVALID_PARAMETER;
    668   }
    669 
    670   Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
    671 
    672   if ((EndPointAddress & 0x80) != 0) {
    673     DataPidDir = TD_IN_PID;
    674     MapOp = EfiPciIoOperationBusMasterWrite;
    675   } else {
    676     DataPidDir = TD_OUT_PID;
    677     MapOp = EfiPciIoOperationBusMasterRead;
    678   }
    679 
    680   EndPointNum = (EndPointAddress & 0xF);
    681   EdResult.NextToggle = *DataToggle;
    682 
    683   Status = OhciSetHcControl (Ohc, BULK_ENABLE, 0);
    684   if (EFI_ERROR(Status)) {
    685     DEBUG ((EFI_D_INFO, "OhciControlTransfer: fail to disable BULK_ENABLE\r\n"));
    686     *TransferResult = EFI_USB_ERR_SYSTEM;
    687     return EFI_DEVICE_ERROR;
    688   }
    689   Status = OhciSetHcCommandStatus (Ohc, BULK_LIST_FILLED, 0);
    690   if (EFI_ERROR(Status)) {
    691     DEBUG ((EFI_D_INFO, "OhciControlTransfer: fail to disable BULK_LIST_FILLED\r\n"));
    692     *TransferResult = EFI_USB_ERR_SYSTEM;
    693     return EFI_DEVICE_ERROR;
    694   }
    695   gBS->Stall(20 * 1000);
    696 
    697   OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, NULL);
    698 
    699   Ed = OhciCreateED (Ohc);
    700   if (Ed == NULL) {
    701     return EFI_OUT_OF_RESOURCES;
    702   }
    703   OhciSetEDField (Ed, ED_SKIP, 1);
    704   OhciSetEDField (Ed, ED_FUNC_ADD, DeviceAddress);
    705   OhciSetEDField (Ed, ED_ENDPT_NUM, EndPointNum);
    706   OhciSetEDField (Ed, ED_DIR, ED_FROM_TD_DIR);
    707   OhciSetEDField (Ed, ED_SPEED, HI_SPEED);
    708   OhciSetEDField (Ed, ED_FORMAT | ED_HALTED | ED_DTTOGGLE, 0);
    709   OhciSetEDField (Ed, ED_MAX_PACKET, MaxPacketLength);
    710   OhciSetEDField (Ed, ED_PDATA, 0);
    711   OhciSetEDField (Ed, ED_ZERO, 0);
    712   OhciSetEDField (Ed, ED_TDHEAD_PTR, 0);
    713   OhciSetEDField (Ed, ED_TDTAIL_PTR, 0);
    714   OhciSetEDField (Ed, ED_NEXT_EDPTR, 0);
    715   HeadEd = OhciAttachEDToList (Ohc, BULK_LIST, Ed, NULL);
    716 
    717   if(Data != NULL) {
    718     MapLength = *DataLength;
    719     Status = Ohc->PciIo->Map (Ohc->PciIo, MapOp, (UINT8 *)Data, &MapLength, &MapPyhAddr, &Mapping);
    720     if (EFI_ERROR(Status)) {
    721       DEBUG ((EFI_D_INFO, "OhciBulkTransfer: Fail to Map Data Buffer for Bulk\r\n"));
    722       goto FREE_ED_BUFF;
    723     }
    724   }
    725   //
    726   //Data Stage
    727   //
    728   LeftLength = MapLength;
    729   ActualSendLength = MapLength;
    730   HeadTd = NULL;
    731   FirstTD = TRUE;
    732   while (LeftLength > 0) {
    733     ActualSendLength = LeftLength;
    734     if (LeftLength > MaxPacketLength) {
    735       ActualSendLength = MaxPacketLength;
    736     }
    737     DataTd = OhciCreateTD (Ohc);
    738     if (DataTd == NULL) {
    739       DEBUG ((EFI_D_INFO, "OhciBulkTransfer: Fail to allocate buffer for Data Stage TD\r\n"));
    740       Status = EFI_OUT_OF_RESOURCES;
    741       goto FREE_OHCI_TDBUFF;
    742     }
    743     OhciSetTDField (DataTd, TD_PDATA, 0);
    744     OhciSetTDField (DataTd, TD_BUFFER_ROUND, 1);
    745     OhciSetTDField (DataTd, TD_DIR_PID, DataPidDir);
    746     OhciSetTDField (DataTd, TD_DELAY_INT, TD_NO_DELAY);
    747     OhciSetTDField (DataTd, TD_DT_TOGGLE, *DataToggle);
    748     OhciSetTDField (DataTd, TD_ERROR_CNT, 0);
    749     OhciSetTDField (DataTd, TD_COND_CODE, TD_TOBE_PROCESSED);
    750     OhciSetTDField (DataTd, TD_CURR_BUFFER_PTR, (UINT32) MapPyhAddr);
    751     OhciSetTDField (DataTd, TD_BUFFER_END_PTR, (UINT32)(MapPyhAddr + ActualSendLength - 1));
    752     OhciSetTDField (DataTd, TD_NEXT_PTR, 0);
    753     DataTd->ActualSendLength = (UINT32)ActualSendLength;
    754     DataTd->DataBuffer = (UINT32)MapPyhAddr;
    755     DataTd->NextTDPointer = 0;
    756     if (FirstTD) {
    757       HeadTd = DataTd;
    758       FirstTD = FALSE;
    759     } else {
    760       OhciLinkTD (HeadTd, DataTd);
    761     }
    762     *DataToggle ^= 1;
    763     MapPyhAddr += ActualSendLength;
    764     LeftLength -= ActualSendLength;
    765   }
    766   //
    767   // Empty Stage
    768   //
    769   EmptyTd = OhciCreateTD (Ohc);
    770   if (EmptyTd == NULL) {
    771     Status = EFI_OUT_OF_RESOURCES;
    772     DEBUG ((EFI_D_INFO, "OhciBulkTransfer: Fail to allocate buffer for Empty TD\r\n"));
    773     goto FREE_OHCI_TDBUFF;
    774   }
    775   OhciSetTDField (EmptyTd, TD_PDATA, 0);
    776   OhciSetTDField (EmptyTd, TD_BUFFER_ROUND, 0);
    777   OhciSetTDField (EmptyTd, TD_DIR_PID, 0);
    778   OhciSetTDField (EmptyTd, TD_DELAY_INT, 0);
    779   //OhciSetTDField (EmptyTd, TD_DT_TOGGLE, CurrentToggle);
    780   EmptyTd->Word0.DataToggle = 0;
    781   OhciSetTDField (EmptyTd, TD_ERROR_CNT, 0);
    782   OhciSetTDField (EmptyTd, TD_COND_CODE, 0);
    783   OhciSetTDField (EmptyTd, TD_CURR_BUFFER_PTR, 0);
    784   OhciSetTDField (EmptyTd, TD_BUFFER_END_PTR, 0);
    785   OhciSetTDField (EmptyTd, TD_NEXT_PTR, 0);
    786   EmptyTd->ActualSendLength = 0;
    787   EmptyTd->DataBuffer = 0;
    788   EmptyTd->NextTDPointer = 0;
    789   OhciLinkTD (HeadTd, EmptyTd);
    790   Ed->TdTailPointer = (UINT32)(UINTN)EmptyTd;
    791   OhciAttachTDListToED (Ed, HeadTd);
    792 
    793   OhciSetEDField (Ed, ED_SKIP, 0);
    794   Status = OhciSetHcCommandStatus (Ohc, BULK_LIST_FILLED, 1);
    795   if (EFI_ERROR(Status)) {
    796     *TransferResult = EFI_USB_ERR_SYSTEM;
    797     Status = EFI_DEVICE_ERROR;
    798     DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to enable BULK_LIST_FILLED\r\n"));
    799     goto FREE_OHCI_TDBUFF;
    800   }
    801   Status = OhciSetHcControl (Ohc, BULK_ENABLE, 1);
    802   if (EFI_ERROR(Status)) {
    803     *TransferResult = EFI_USB_ERR_SYSTEM;
    804     Status = EFI_DEVICE_ERROR;
    805     DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to enable BULK_ENABLE\r\n"));
    806     goto FREE_OHCI_TDBUFF;
    807   }
    808   gBS->Stall(20 * 1000);
    809 
    810   TimeCount = 0;
    811   Status = CheckIfDone (Ohc, BULK_LIST, Ed, HeadTd, &EdResult);
    812   while (Status == EFI_NOT_READY && TimeCount <= TimeOut) {
    813     gBS->Stall (1000);
    814     TimeCount++;
    815     Status = CheckIfDone (Ohc, BULK_LIST, Ed, HeadTd, &EdResult);
    816   }
    817 
    818   *TransferResult = ConvertErrorCode (EdResult.ErrorCode);
    819 
    820   if (EdResult.ErrorCode != TD_NO_ERROR) {
    821     if (EdResult.ErrorCode == TD_TOBE_PROCESSED) {
    822       DEBUG ((EFI_D_INFO, "Bulk pipe timeout, > %d mS\r\n", TimeOut));
    823     } else {
    824       DEBUG ((EFI_D_INFO, "Bulk pipe broken\r\n"));
    825       *DataToggle = EdResult.NextToggle;
    826     }
    827     *DataLength = 0;
    828   } else {
    829     DEBUG ((EFI_D_INFO, "Bulk transfer successed\r\n"));
    830   }
    831   //*DataToggle = (UINT8) OhciGetEDField (Ed, ED_DTTOGGLE);
    832 
    833 FREE_OHCI_TDBUFF:
    834   OhciSetEDField (Ed, ED_SKIP, 1);
    835   if (HeadEd == Ed) {
    836     OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, NULL);
    837   }else {
    838     HeadEd->NextED = Ed->NextED;
    839   }
    840   while (HeadTd) {
    841     DataTd = HeadTd;
    842     HeadTd = (TD_DESCRIPTOR *)(UINTN)(HeadTd->NextTDPointer);
    843     UsbHcFreeMem(Ohc->MemPool, DataTd, sizeof(TD_DESCRIPTOR));
    844   }
    845 
    846   if(Mapping != NULL) {
    847     Ohc->PciIo->Unmap(Ohc->PciIo, Mapping);
    848   }
    849 
    850 FREE_ED_BUFF:
    851   UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));
    852 
    853   return Status;
    854 }
    855 /**
    856 
    857   Submits an interrupt transfer to an interrupt endpoint of a USB device.
    858 
    859   @param  Ohc                   Device private data
    860   @param  DeviceAddress         Represents the address of the target device on the USB,
    861                                 which is assigned during USB enumeration.
    862   @param  EndPointAddress       The combination of an endpoint number and an endpoint
    863                                 direction of the target USB device. Each endpoint address
    864                                 supports data transfer in one direction except the
    865                                 control endpoint (whose default endpoint address is 0).
    866                                 It is the caller's responsibility to make sure that
    867                                 the EndPointAddress represents an interrupt endpoint.
    868   @param  IsSlowDevice          Indicates whether the target device is slow device
    869                                 or full-speed device.
    870   @param  MaxPacketLength       Indicates the maximum packet size the target endpoint
    871                                 is capable of sending or receiving.
    872   @param  IsNewTransfer         If TRUE, an asynchronous interrupt pipe is built between
    873                                 the host and the target interrupt endpoint.
    874                                 If FALSE, the specified asynchronous interrupt pipe
    875                                 is canceled.
    876   @param  DataToggle            A pointer to the data toggle value.  On input, it is valid
    877                                 when IsNewTransfer is TRUE, and it indicates the initial
    878                                 data toggle value the asynchronous interrupt transfer
    879                                 should adopt.
    880                                 On output, it is valid when IsNewTransfer is FALSE,
    881                                 and it is updated to indicate the data toggle value of
    882                                 the subsequent asynchronous interrupt transfer.
    883   @param  PollingInterval       Indicates the interval, in milliseconds, that the
    884                                 asynchronous interrupt transfer is polled.
    885                                 This parameter is required when IsNewTransfer is TRUE.
    886   @param  UCBuffer              Uncacheable buffer
    887   @param  DataLength            Indicates the length of data to be received at the
    888                                 rate specified by PollingInterval from the target
    889                                 asynchronous interrupt endpoint.  This parameter
    890                                 is only required when IsNewTransfer is TRUE.
    891   @param  CallBackFunction      The Callback function.This function is called at the
    892                                 rate specified by PollingInterval.This parameter is
    893                                 only required when IsNewTransfer is TRUE.
    894   @param  Context               The context that is passed to the CallBackFunction.
    895                                 This is an optional parameter and may be NULL.
    896   @param  IsPeriodic            Periodic interrupt or not
    897   @param  OutputED              The correspoding ED carried out
    898   @param  OutputTD              The correspoding TD carried out
    899 
    900 
    901   @retval EFI_SUCCESS           The asynchronous interrupt transfer request has been successfully
    902                                 submitted or canceled.
    903   @retval EFI_INVALID_PARAMETER Some parameters are invalid.
    904   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
    905 
    906 **/
    907 
    908 EFI_STATUS
    909 OhciInterruptTransfer (
    910   IN     USB_OHCI_HC_DEV                  *Ohc,
    911   IN     UINT8                            DeviceAddress,
    912   IN     UINT8                            EndPointAddress,
    913   IN     BOOLEAN                          IsSlowDevice,
    914   IN     UINT8                            MaxPacketLength,
    915   IN     BOOLEAN                          IsNewTransfer,
    916   IN OUT UINT8                            *DataToggle        OPTIONAL,
    917   IN     UINTN                            PollingInterval    OPTIONAL,
    918   IN     VOID                             *UCBuffer          OPTIONAL,
    919   IN     UINTN                            DataLength         OPTIONAL,
    920   IN     EFI_ASYNC_USB_TRANSFER_CALLBACK  CallBackFunction   OPTIONAL,
    921   IN     VOID                             *Context           OPTIONAL,
    922   IN     BOOLEAN                          IsPeriodic         OPTIONAL,
    923   OUT    ED_DESCRIPTOR                    **OutputED         OPTIONAL,
    924   OUT    TD_DESCRIPTOR                    **OutputTD         OPTIONAL
    925   )
    926 {
    927   ED_DESCRIPTOR            *Ed;
    928   UINT8                    EdDir;
    929   ED_DESCRIPTOR            *HeadEd;
    930   TD_DESCRIPTOR            *HeadTd;
    931   TD_DESCRIPTOR            *DataTd;
    932   TD_DESCRIPTOR            *EmptTd;
    933   UINTN                    Depth;
    934   UINTN                    Index;
    935   EFI_STATUS               Status;
    936   UINT8                    EndPointNum;
    937   UINT32                   DataPidDir;
    938   INTERRUPT_CONTEXT_ENTRY  *Entry;
    939   EFI_TPL                  OldTpl;
    940   BOOLEAN                  FirstTD;
    941 
    942  VOID                      *Mapping;
    943  UINTN                     MapLength;
    944  EFI_PHYSICAL_ADDRESS      MapPyhAddr;
    945  UINTN                     LeftLength;
    946  UINTN                     ActualSendLength;
    947 
    948 
    949   if (DataLength > MAX_BYTES_PER_TD) {
    950     DEBUG ((EFI_D_ERROR, "OhciInterruptTransfer: Error param\r\n"));
    951     return EFI_INVALID_PARAMETER;
    952   }
    953 
    954   if ((EndPointAddress & 0x80) != 0) {
    955     EdDir = ED_IN_DIR;
    956     DataPidDir = TD_IN_PID;
    957   } else {
    958     EdDir = ED_OUT_DIR;
    959     DataPidDir = TD_OUT_PID;
    960   }
    961 
    962   EndPointNum = (EndPointAddress & 0xF);
    963 
    964   if (!IsNewTransfer) {
    965     OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
    966     OhciSetHcControl (Ohc, PERIODIC_ENABLE, 0);
    967     OhciFreeInterruptContext (Ohc, DeviceAddress, EndPointAddress, DataToggle);
    968     Status = OhciFreeInterruptEdByAddr (Ohc, DeviceAddress, EndPointNum);
    969     OhciSetHcControl (Ohc, PERIODIC_ENABLE, 1);
    970     gBS->RestoreTPL (OldTpl);
    971     return Status;
    972   }
    973   MapLength = DataLength;
    974   Status = Ohc->PciIo->Map(
    975                          Ohc->PciIo,
    976                          EfiPciIoOperationBusMasterWrite,
    977                          UCBuffer,
    978                          &MapLength,
    979                          &MapPyhAddr,
    980                          &Mapping
    981                          );
    982   if (EFI_ERROR (Status)) {
    983     DEBUG ((EFI_D_ERROR, "OhciInterruptTransfer: Failt to PciIo->Map buffer \r\n"));
    984     goto EXIT;
    985   }
    986   Depth = 5;
    987   Index = 1;
    988   while (PollingInterval >= Index * 2 && Depth > 0) {
    989     Index *= 2;
    990     Depth--;
    991   }
    992   //
    993   //ED Stage
    994   //
    995   HeadEd = OhciFindMinInterruptEDList (Ohc, (UINT32)Depth);
    996   if ((Ed = OhciFindWorkingEd (HeadEd, DeviceAddress, EndPointNum, EdDir)) != NULL) {
    997     OhciSetEDField (Ed, ED_SKIP, 1);
    998   } else {
    999     Ed = OhciCreateED (Ohc);
   1000     if (Ed == NULL) {
   1001       Status = EFI_OUT_OF_RESOURCES;
   1002       DEBUG ((EFI_D_ERROR, "OhciInterruptTransfer: Fail to allocate buffer for ED\r\n"));
   1003       goto UNMAP_OHCI_XBUFF;
   1004     }
   1005     OhciSetEDField (Ed, ED_SKIP, 1);
   1006     OhciSetEDField (Ed, ED_FUNC_ADD, DeviceAddress);
   1007     OhciSetEDField (Ed, ED_ENDPT_NUM, EndPointNum);
   1008     OhciSetEDField (Ed, ED_DIR, ED_FROM_TD_DIR);
   1009     OhciSetEDField (Ed, ED_SPEED, IsSlowDevice);
   1010     OhciSetEDField (Ed, ED_FORMAT, 0);
   1011     OhciSetEDField (Ed, ED_MAX_PACKET, MaxPacketLength);
   1012     OhciSetEDField (Ed, ED_PDATA | ED_ZERO | ED_HALTED | ED_DTTOGGLE, 0);
   1013     OhciSetEDField (Ed, ED_TDHEAD_PTR, 0);
   1014     OhciSetEDField (Ed, ED_TDTAIL_PTR, 0);
   1015     OhciSetEDField (Ed, ED_NEXT_EDPTR, 0);
   1016     OhciAttachEDToList (Ohc, INTERRUPT_LIST, Ed, HeadEd);
   1017   }
   1018   //
   1019   //Data Stage
   1020   //
   1021   LeftLength = MapLength;
   1022   ActualSendLength = MapLength;
   1023   HeadTd = NULL;
   1024   FirstTD = TRUE;
   1025   while (LeftLength > 0) {
   1026     ActualSendLength = LeftLength;
   1027     if (LeftLength > MaxPacketLength) {
   1028       ActualSendLength = MaxPacketLength;
   1029     }
   1030     DataTd = OhciCreateTD (Ohc);
   1031     if (DataTd == NULL) {
   1032       Status = EFI_OUT_OF_RESOURCES;
   1033       DEBUG ((EFI_D_ERROR, "OhciInterruptTransfer: Fail to allocate buffer for Data Stage TD\r\n"));
   1034       goto FREE_OHCI_TDBUFF;
   1035     }
   1036     OhciSetTDField (DataTd, TD_PDATA, 0);
   1037     OhciSetTDField (DataTd, TD_BUFFER_ROUND, 1);
   1038     OhciSetTDField (DataTd, TD_DIR_PID, DataPidDir);
   1039     OhciSetTDField (DataTd, TD_DELAY_INT, TD_NO_DELAY);
   1040     OhciSetTDField (DataTd, TD_DT_TOGGLE, *DataToggle);
   1041     OhciSetTDField (DataTd, TD_ERROR_CNT, 0);
   1042     OhciSetTDField (DataTd, TD_COND_CODE, TD_TOBE_PROCESSED);
   1043     OhciSetTDField (DataTd, TD_CURR_BUFFER_PTR, (UINT32) MapPyhAddr);
   1044     OhciSetTDField (DataTd, TD_BUFFER_END_PTR, (UINT32)(MapPyhAddr + ActualSendLength - 1));
   1045     OhciSetTDField (DataTd, TD_NEXT_PTR, 0);
   1046     DataTd->ActualSendLength = (UINT32)ActualSendLength;
   1047     DataTd->DataBuffer = (UINT32)MapPyhAddr;
   1048     DataTd->NextTDPointer = 0;
   1049     if (FirstTD) {
   1050       HeadTd = DataTd;
   1051       FirstTD = FALSE;
   1052     } else {
   1053       OhciLinkTD (HeadTd, DataTd);
   1054     }
   1055     *DataToggle ^= 1;
   1056     MapPyhAddr += ActualSendLength;
   1057     LeftLength -= ActualSendLength;
   1058   }
   1059 
   1060   EmptTd = OhciCreateTD (Ohc);
   1061   if (EmptTd == NULL) {
   1062     Status = EFI_OUT_OF_RESOURCES;
   1063     DEBUG ((EFI_D_ERROR, "OhciInterruptTransfer: Fail to allocate buffer for Empty Stage TD\r\n"));
   1064     goto FREE_OHCI_TDBUFF;
   1065   }
   1066   OhciSetTDField (EmptTd, TD_PDATA, 0);
   1067   OhciSetTDField (EmptTd, TD_BUFFER_ROUND, 0);
   1068   OhciSetTDField (EmptTd, TD_DIR_PID, 0);
   1069   OhciSetTDField (EmptTd, TD_DELAY_INT, 0);
   1070   //OhciSetTDField (EmptTd, TD_DT_TOGGLE, CurrentToggle);
   1071   EmptTd->Word0.DataToggle = 0;
   1072   OhciSetTDField (EmptTd, TD_ERROR_CNT, 0);
   1073   OhciSetTDField (EmptTd, TD_COND_CODE, 0);
   1074   OhciSetTDField (EmptTd, TD_CURR_BUFFER_PTR, 0);
   1075   OhciSetTDField (EmptTd, TD_BUFFER_END_PTR, 0);
   1076   OhciSetTDField (EmptTd, TD_NEXT_PTR, 0);
   1077   EmptTd->ActualSendLength = 0;
   1078   EmptTd->DataBuffer = 0;
   1079   EmptTd->NextTDPointer = 0;
   1080   OhciLinkTD (HeadTd, EmptTd);
   1081   Ed->TdTailPointer = (UINT32)(UINTN)EmptTd;
   1082   OhciAttachTDListToED (Ed, HeadTd);
   1083 
   1084   if (OutputED != NULL) {
   1085     *OutputED = Ed;
   1086   }
   1087   if (OutputTD != NULL) {
   1088     *OutputTD = HeadTd;
   1089   }
   1090 
   1091   if (CallBackFunction != NULL) {
   1092     Entry = AllocatePool (sizeof (INTERRUPT_CONTEXT_ENTRY));
   1093     if (Entry == NULL) {
   1094       goto FREE_OHCI_TDBUFF;
   1095     }
   1096 
   1097     Entry->DeviceAddress = DeviceAddress;
   1098     Entry->EndPointAddress = EndPointAddress;
   1099     Entry->Ed = Ed;
   1100     Entry->DataTd = HeadTd;
   1101     Entry->IsSlowDevice = IsSlowDevice;
   1102     Entry->MaxPacketLength = MaxPacketLength;
   1103     Entry->PollingInterval = PollingInterval;
   1104     Entry->CallBackFunction = CallBackFunction;
   1105     Entry->Context = Context;
   1106     Entry->IsPeriodic = IsPeriodic;
   1107     Entry->UCBuffer = UCBuffer;
   1108     Entry->UCBufferMapping = Mapping;
   1109     Entry->DataLength = DataLength;
   1110     Entry->Toggle = DataToggle;
   1111     Entry->NextEntry = NULL;
   1112     OhciAddInterruptContextEntry (Ohc, Entry);
   1113   }
   1114   OhciSetEDField (Ed, ED_SKIP, 0);
   1115 
   1116   if (OhciGetHcControl (Ohc, PERIODIC_ENABLE) == 0) {
   1117     Status = OhciSetHcControl (Ohc, PERIODIC_ENABLE, 1);
   1118     gBS->Stall (1000);
   1119   }
   1120 
   1121   return EFI_SUCCESS;
   1122 
   1123 FREE_OHCI_TDBUFF:
   1124   while (HeadTd) {
   1125     DataTd = HeadTd;
   1126     HeadTd = (TD_DESCRIPTOR *)(UINTN)(HeadTd->NextTDPointer);
   1127     UsbHcFreeMem(Ohc->MemPool, DataTd, sizeof(TD_DESCRIPTOR));
   1128   }
   1129 
   1130 //FREE_OHCI_EDBUFF:
   1131   if ((HeadEd != Ed) && HeadEd && Ed) {
   1132     while(HeadEd->NextED != (UINT32)(UINTN)Ed) {
   1133       HeadEd = (ED_DESCRIPTOR *)(UINTN)(HeadEd->NextED);
   1134     }
   1135   HeadEd->NextED = Ed->NextED;
   1136     UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));
   1137   }
   1138 
   1139 UNMAP_OHCI_XBUFF:
   1140   Ohc->PciIo->Unmap(Ohc->PciIo, Mapping);
   1141 
   1142 EXIT:
   1143   return Status;
   1144 }
   1145 
   1146 /**
   1147 
   1148   Submits an asynchronous interrupt transfer to an interrupt endpoint of a USB device.
   1149 
   1150   @param  This                  A pointer to the EFI_USB_HC_PROTOCOL instance.
   1151   @param  DeviceAddress         Represents the address of the target device on the USB,
   1152                                 which is assigned during USB enumeration.
   1153   @param  EndPointAddress       The combination of an endpoint number and an endpoint
   1154                                 direction of the target USB device. Each endpoint address
   1155                                 supports data transfer in one direction except the
   1156                                 control endpoint (whose default endpoint address is 0).
   1157                                 It is the caller's responsibility to make sure that
   1158                                 the EndPointAddress represents an interrupt endpoint.
   1159   @param  IsSlowDevice          Indicates whether the target device is slow device
   1160                                 or full-speed device.
   1161   @param  MaxiumPacketLength    Indicates the maximum packet size the target endpoint
   1162                                 is capable of sending or receiving.
   1163   @param  IsNewTransfer         If TRUE, an asynchronous interrupt pipe is built between
   1164                                 the host and the target interrupt endpoint.
   1165                                 If FALSE, the specified asynchronous interrupt pipe
   1166                                 is canceled.
   1167   @param  DataToggle            A pointer to the data toggle value.  On input, it is valid
   1168                                 when IsNewTransfer is TRUE, and it indicates the initial
   1169                                 data toggle value the asynchronous interrupt transfer
   1170                                 should adopt.
   1171                                 On output, it is valid when IsNewTransfer is FALSE,
   1172                                 and it is updated to indicate the data toggle value of
   1173                                 the subsequent asynchronous interrupt transfer.
   1174   @param  PollingInterval       Indicates the interval, in milliseconds, that the
   1175                                 asynchronous interrupt transfer is polled.
   1176                                 This parameter is required when IsNewTransfer is TRUE.
   1177   @param  DataLength            Indicates the length of data to be received at the
   1178                                 rate specified by PollingInterval from the target
   1179                                 asynchronous interrupt endpoint.  This parameter
   1180                                 is only required when IsNewTransfer is TRUE.
   1181   @param  CallBackFunction      The Callback function.This function is called at the
   1182                                 rate specified by PollingInterval.This parameter is
   1183                                 only required when IsNewTransfer is TRUE.
   1184   @param  Context               The context that is passed to the CallBackFunction.
   1185                                 This is an optional parameter and may be NULL.
   1186 
   1187   @retval EFI_SUCCESS           The asynchronous interrupt transfer request has been successfully
   1188                                 submitted or canceled.
   1189   @retval EFI_INVALID_PARAMETER Some parameters are invalid.
   1190   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
   1191 
   1192 **/
   1193 
   1194 
   1195 EFI_STATUS
   1196 EFIAPI
   1197 OhciAsyncInterruptTransfer (
   1198   IN     EFI_USB_HC_PROTOCOL              *This,
   1199   IN     UINT8                            DeviceAddress,
   1200   IN     UINT8                            EndPointAddress,
   1201   IN     BOOLEAN                          IsSlowDevice,
   1202   IN     UINT8                            MaxPacketLength,
   1203   IN     BOOLEAN                          IsNewTransfer,
   1204   IN OUT UINT8                            *DataToggle        OPTIONAL,
   1205   IN     UINTN                            PollingInterval    OPTIONAL,
   1206   IN     UINTN                            DataLength         OPTIONAL,
   1207   IN     EFI_ASYNC_USB_TRANSFER_CALLBACK  CallBackFunction   OPTIONAL,
   1208   IN     VOID                             *Context           OPTIONAL
   1209   )
   1210 {
   1211   EFI_STATUS              Status;
   1212   USB_OHCI_HC_DEV         *Ohc;
   1213   VOID                    *UCBuffer;
   1214 
   1215   if (DataToggle == NULL || (EndPointAddress & 0x80) == 0 ||
   1216     (IsNewTransfer && (DataLength == 0 ||
   1217     (*DataToggle != 0 && *DataToggle != 1) || (PollingInterval < 1 || PollingInterval > 255)))) {
   1218     return EFI_INVALID_PARAMETER;
   1219   }
   1220 
   1221   Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
   1222   if ( IsNewTransfer ) {
   1223     UCBuffer = AllocatePool(DataLength);
   1224     if (UCBuffer == NULL) {
   1225       return EFI_OUT_OF_RESOURCES;
   1226     }
   1227   } else {
   1228     UCBuffer = NULL;
   1229   }
   1230   Status = OhciInterruptTransfer (
   1231              Ohc,
   1232              DeviceAddress,
   1233              EndPointAddress,
   1234              IsSlowDevice,
   1235              MaxPacketLength,
   1236              IsNewTransfer,
   1237              DataToggle,
   1238              PollingInterval,
   1239              UCBuffer,
   1240              DataLength,
   1241              CallBackFunction,
   1242              Context,
   1243              TRUE,
   1244              NULL,
   1245              NULL
   1246              );
   1247   if ( IsNewTransfer ) {
   1248     if (EFI_ERROR(Status)) {
   1249       gBS->FreePool (UCBuffer);
   1250     }
   1251   }
   1252   return Status;
   1253 }
   1254 
   1255 
   1256 /**
   1257 
   1258   Submits synchronous interrupt transfer to an interrupt endpoint
   1259   of a USB device.
   1260 
   1261   @param  This                  A pointer to the EFI_USB_HC_PROTOCOL instance.
   1262   @param  DeviceAddress         Represents the address of the target device on the USB,
   1263                                 which is assigned during USB enumeration.
   1264   @param  EndPointAddress       The combination of an endpoint number and an endpoint
   1265                                 direction of the target USB device. Each endpoint
   1266                                 address supports data transfer in one direction
   1267                                 except the control endpoint (whose default
   1268                                 endpoint address is 0). It is the caller's responsibility
   1269                                 to make sure that the EndPointAddress represents
   1270                                 an interrupt endpoint.
   1271   @param  IsSlowDevice          Indicates whether the target device is slow device
   1272                                 or full-speed device.
   1273   @param  MaxPacketLength       Indicates the maximum packet size the target endpoint
   1274                                 is capable of sending or receiving.
   1275   @param  Data                  A pointer to the buffer of data that will be transmitted
   1276                                 to USB device or received from USB device.
   1277   @param  DataLength            On input, the size, in bytes, of the data buffer specified
   1278                                 by Data. On output, the number of bytes transferred.
   1279   @param  DataToggle            A pointer to the data toggle value. On input, it indicates
   1280                                 the initial data toggle value the synchronous interrupt
   1281                                 transfer should adopt;
   1282                                 on output, it is updated to indicate the data toggle value
   1283                                 of the subsequent synchronous interrupt transfer.
   1284   @param  TimeOut               Indicates the maximum time, in microseconds, which the
   1285                                 transfer is allowed to complete.
   1286   @param  TransferResult        A pointer to the detailed result information from
   1287                                 the synchronous interrupt transfer.
   1288 
   1289   @retval EFI_UNSUPPORTED       This interface not available.
   1290   @retval EFI_INVALID_PARAMETER Parameters not follow spec
   1291 
   1292 **/
   1293 
   1294 
   1295 EFI_STATUS
   1296 EFIAPI
   1297 OhciSyncInterruptTransfer (
   1298   IN     EFI_USB_HC_PROTOCOL  *This,
   1299   IN     UINT8                DeviceAddress,
   1300   IN     UINT8                EndPointAddress,
   1301   IN     BOOLEAN              IsSlowDevice,
   1302   IN     UINT8                MaxPacketLength,
   1303   IN OUT VOID                 *Data,
   1304   IN OUT UINTN                *DataLength,
   1305   IN OUT UINT8                *DataToggle,
   1306   IN     UINTN                TimeOut,
   1307   OUT    UINT32               *TransferResult
   1308   )
   1309 {
   1310   USB_OHCI_HC_DEV         *Ohc;
   1311   EFI_STATUS              Status;
   1312   ED_DESCRIPTOR           *Ed;
   1313   TD_DESCRIPTOR           *HeadTd;
   1314   OHCI_ED_RESULT          EdResult;
   1315   VOID                    *UCBuffer;
   1316 
   1317   if ((EndPointAddress & 0x80) == 0 || Data == NULL || DataLength == NULL || *DataLength == 0 ||
   1318       (IsSlowDevice && MaxPacketLength > 8) || (!IsSlowDevice && MaxPacketLength > 64) ||
   1319       DataToggle == NULL || (*DataToggle != 0 && *DataToggle != 1) || TransferResult == NULL) {
   1320     return EFI_INVALID_PARAMETER;
   1321   }
   1322 
   1323   Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
   1324   UCBuffer = AllocatePool (*DataLength);
   1325   if (UCBuffer == NULL) {
   1326     return EFI_OUT_OF_RESOURCES;
   1327   }
   1328   Status = OhciInterruptTransfer (
   1329              Ohc,
   1330              DeviceAddress,
   1331              EndPointAddress,
   1332              IsSlowDevice,
   1333              MaxPacketLength,
   1334              TRUE,
   1335              DataToggle,
   1336              1,
   1337              UCBuffer,
   1338              *DataLength,
   1339              NULL,
   1340              NULL,
   1341              FALSE,
   1342              &Ed,
   1343              &HeadTd
   1344              );
   1345 
   1346   if (!EFI_ERROR (Status)) {
   1347     Status = CheckIfDone (Ohc, INTERRUPT_LIST, Ed, HeadTd, &EdResult);
   1348     while (Status == EFI_NOT_READY && TimeOut > 0) {
   1349       gBS->Stall (1000);
   1350       TimeOut--;
   1351       Status = CheckIfDone (Ohc, INTERRUPT_LIST, Ed, HeadTd, &EdResult);
   1352     }
   1353 
   1354     *TransferResult = ConvertErrorCode (EdResult.ErrorCode);
   1355   }
   1356   CopyMem(Data, UCBuffer, *DataLength);
   1357   Status = OhciInterruptTransfer (
   1358              Ohc,
   1359              DeviceAddress,
   1360              EndPointAddress,
   1361              IsSlowDevice,
   1362              MaxPacketLength,
   1363              FALSE,
   1364              DataToggle,
   1365              0,
   1366              NULL,
   1367              0,
   1368              NULL,
   1369              NULL,
   1370              FALSE,
   1371              NULL,
   1372              NULL
   1373              );
   1374 
   1375   return Status;
   1376 }
   1377 /**
   1378 
   1379   Submits isochronous transfer to a target USB device.
   1380 
   1381   @param  This                  A pointer to the EFI_USB_HC_PROTOCOL instance.
   1382   @param  DeviceAddress         Represents the address of the target device on the USB,
   1383                                 which is assigned during USB enumeration.
   1384   @param  EndPointAddress       End point address
   1385   @param  MaximumPacketLength   Indicates the maximum packet size that the
   1386                                 default control transfer endpoint is capable of
   1387                                 sending or receiving.
   1388   @param  Data                  A pointer to the buffer of data that will be transmitted
   1389                                 to USB device or received from USB device.
   1390   @param  DataLength            Indicates the size, in bytes, of the data buffer
   1391                                 specified by Data.
   1392   @param  TransferResult        A pointer to the detailed result information generated
   1393                                 by this control transfer.
   1394 
   1395   @retval EFI_UNSUPPORTED       This interface not available
   1396   @retval EFI_INVALID_PARAMETER Data is NULL or DataLength is 0 or TransferResult is NULL
   1397 
   1398 **/
   1399 
   1400 
   1401 EFI_STATUS
   1402 EFIAPI
   1403 OhciIsochronousTransfer (
   1404   IN     EFI_USB_HC_PROTOCOL  *This,
   1405   IN     UINT8                DeviceAddress,
   1406   IN     UINT8                EndPointAddress,
   1407   IN     UINT8                MaximumPacketLength,
   1408   IN OUT VOID                 *Data,
   1409   IN OUT UINTN                DataLength,
   1410   OUT    UINT32               *TransferResult
   1411   )
   1412 {
   1413   if (Data == NULL || DataLength == 0 || TransferResult == NULL) {
   1414     return EFI_INVALID_PARAMETER;
   1415   }
   1416 
   1417   return EFI_UNSUPPORTED;
   1418 }
   1419 
   1420 /**
   1421 
   1422   Submits Async isochronous transfer to a target USB device.
   1423 
   1424   @param  his                   A pointer to the EFI_USB_HC_PROTOCOL instance.
   1425   @param  DeviceAddress         Represents the address of the target device on the USB,
   1426                                 which is assigned during USB enumeration.
   1427   @param  EndPointAddress       End point address
   1428   @param  MaximumPacketLength   Indicates the maximum packet size that the
   1429                                 default control transfer endpoint is capable of
   1430                                 sending or receiving.
   1431   @param  Data                  A pointer to the buffer of data that will be transmitted
   1432                                 to USB device or received from USB device.
   1433   @param  IsochronousCallBack   When the transfer complete, the call back function will be called
   1434   @param  Context               Pass to the call back function as parameter
   1435 
   1436   @retval EFI_UNSUPPORTED       This interface not available
   1437   @retval EFI_INVALID_PARAMETER Data is NULL or Datalength is 0
   1438 
   1439 **/
   1440 
   1441 EFI_STATUS
   1442 EFIAPI
   1443 OhciAsyncIsochronousTransfer (
   1444   IN     EFI_USB_HC_PROTOCOL                *This,
   1445   IN     UINT8                              DeviceAddress,
   1446   IN     UINT8                              EndPointAddress,
   1447   IN     UINT8                              MaximumPacketLength,
   1448   IN OUT VOID                               *Data,
   1449   IN OUT UINTN                              DataLength,
   1450   IN     EFI_ASYNC_USB_TRANSFER_CALLBACK    IsochronousCallBack,
   1451   IN     VOID                               *Context OPTIONAL
   1452   )
   1453 {
   1454 
   1455   if (Data == NULL || DataLength == 0) {
   1456     return EFI_INVALID_PARAMETER;
   1457   }
   1458 
   1459   return EFI_UNSUPPORTED;
   1460 }
   1461 
   1462 /**
   1463 
   1464   Retrieves the number of root hub ports.
   1465 
   1466   @param  This                  A pointer to the EFI_USB_HC_PROTOCOL instance.
   1467   @param  NumOfPorts            A pointer to the number of the root hub ports.
   1468 
   1469   @retval EFI_SUCCESS           The port number was retrieved successfully.
   1470 **/
   1471 EFI_STATUS
   1472 EFIAPI
   1473 OhciGetRootHubNumOfPorts (
   1474   IN  EFI_USB_HC_PROTOCOL  *This,
   1475   OUT UINT8                *NumOfPorts
   1476   )
   1477 {
   1478   USB_OHCI_HC_DEV  *Ohc;
   1479   Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
   1480 
   1481   if (NumOfPorts == NULL) {
   1482     return EFI_INVALID_PARAMETER;
   1483   }
   1484 
   1485   *NumOfPorts = (UINT8)OhciGetRootHubDescriptor(Ohc, RH_NUM_DS_PORTS);
   1486 
   1487   return EFI_SUCCESS;
   1488 }
   1489 /**
   1490 
   1491   Retrieves the current status of a USB root hub port.
   1492 
   1493   @param  This                  A pointer to the EFI_USB_HC_PROTOCOL.
   1494   @param  PortNumber            Specifies the root hub port from which the status
   1495                                 is to be retrieved.  This value is zero-based. For example,
   1496                                 if a root hub has two ports, then the first port is numbered 0,
   1497                                 and the second port is numbered 1.
   1498   @param  PortStatus            A pointer to the current port status bits and
   1499                                 port status change bits.
   1500 
   1501   @retval EFI_SUCCESS           The status of the USB root hub port specified by PortNumber
   1502                                 was returned in PortStatus.
   1503   @retval EFI_INVALID_PARAMETER Port number not valid
   1504 **/
   1505 
   1506 
   1507 EFI_STATUS
   1508 EFIAPI
   1509 OhciGetRootHubPortStatus (
   1510   IN  EFI_USB_HC_PROTOCOL  *This,
   1511   IN  UINT8                PortNumber,
   1512   OUT EFI_USB_PORT_STATUS  *PortStatus
   1513   )
   1514 {
   1515   USB_OHCI_HC_DEV  *Ohc;
   1516   UINT8            NumOfPorts;
   1517 
   1518   Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
   1519 
   1520   OhciGetRootHubNumOfPorts (This, &NumOfPorts);
   1521   if (PortNumber >= NumOfPorts) {
   1522     return EFI_INVALID_PARAMETER;
   1523   }
   1524   PortStatus->PortStatus = 0;
   1525   PortStatus->PortChangeStatus = 0;
   1526 
   1527   if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_CURR_CONNECT_STAT)) {
   1528     PortStatus->PortStatus |= USB_PORT_STAT_CONNECTION;
   1529   }
   1530   if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_ENABLE_STAT)) {
   1531     PortStatus->PortStatus |= USB_PORT_STAT_ENABLE;
   1532   }
   1533   if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_SUSPEND_STAT)) {
   1534     PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND;
   1535   }
   1536   if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_OC_INDICATOR)) {
   1537     PortStatus->PortStatus |= USB_PORT_STAT_OVERCURRENT;
   1538   }
   1539   if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_RESET_STAT)) {
   1540     PortStatus->PortStatus |= USB_PORT_STAT_RESET;
   1541   }
   1542   if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_POWER_STAT)) {
   1543     PortStatus->PortStatus |= USB_PORT_STAT_POWER;
   1544   }
   1545   if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_LSDEVICE_ATTACHED)) {
   1546     PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;
   1547   }
   1548   if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE)) {
   1549     PortStatus->PortChangeStatus |= USB_PORT_STAT_C_ENABLE;
   1550   }
   1551   if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE)) {
   1552     PortStatus->PortChangeStatus |= USB_PORT_STAT_C_CONNECTION;
   1553   }
   1554   if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE)) {
   1555     PortStatus->PortChangeStatus |= USB_PORT_STAT_C_SUSPEND;
   1556   }
   1557   if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE)) {
   1558     PortStatus->PortChangeStatus |= USB_PORT_STAT_C_OVERCURRENT;
   1559   }
   1560   if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE)) {
   1561     PortStatus->PortChangeStatus |= USB_PORT_STAT_C_RESET;
   1562   }
   1563 
   1564   return EFI_SUCCESS;
   1565 }
   1566 /**
   1567 
   1568   Sets a feature for the specified root hub port.
   1569 
   1570   @param  This                  A pointer to the EFI_USB_HC_PROTOCOL.
   1571   @param  PortNumber            Specifies the root hub port whose feature
   1572                                 is requested to be set.
   1573   @param  PortFeature           Indicates the feature selector associated
   1574                                 with the feature set request.
   1575 
   1576   @retval EFI_SUCCESS           The feature specified by PortFeature was set for the
   1577                                 USB root hub port specified by PortNumber.
   1578   @retval EFI_DEVICE_ERROR      Set feature failed because of hardware issue
   1579   @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
   1580 **/
   1581 EFI_STATUS
   1582 EFIAPI
   1583 OhciSetRootHubPortFeature (
   1584   IN EFI_USB_HC_PROTOCOL   *This,
   1585   IN UINT8                 PortNumber,
   1586   IN EFI_USB_PORT_FEATURE  PortFeature
   1587   )
   1588 {
   1589   USB_OHCI_HC_DEV         *Ohc;
   1590   EFI_STATUS              Status;
   1591   UINT8                   NumOfPorts;
   1592   UINTN                   RetryTimes;
   1593 
   1594   OhciGetRootHubNumOfPorts (This, &NumOfPorts);
   1595   if (PortNumber >= NumOfPorts) {
   1596     return EFI_INVALID_PARAMETER;
   1597   }
   1598 
   1599   Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
   1600 
   1601   Status = EFI_SUCCESS;
   1602 
   1603 
   1604   switch (PortFeature) {
   1605     case EfiUsbPortPower:
   1606       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_POWER);
   1607 
   1608       //
   1609       // Verify the state
   1610       //
   1611       RetryTimes = 0;
   1612       do {
   1613         gBS->Stall (1000);
   1614         RetryTimes++;
   1615       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_POWER_STAT) == 0 &&
   1616                RetryTimes < MAX_RETRY_TIMES);
   1617 
   1618       if (RetryTimes >= MAX_RETRY_TIMES) {
   1619         return EFI_DEVICE_ERROR;
   1620       }
   1621       break;
   1622 
   1623     case EfiUsbPortReset:
   1624       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_RESET);
   1625 
   1626       //
   1627       // Verify the state
   1628       //
   1629       RetryTimes = 0;
   1630       do {
   1631         gBS->Stall (1000);
   1632         RetryTimes++;
   1633       } while ((OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE) == 0 ||
   1634                 OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT) == 1) &&
   1635                RetryTimes < MAX_RETRY_TIMES);
   1636 
   1637       if (RetryTimes >= MAX_RETRY_TIMES) {
   1638         return EFI_DEVICE_ERROR;
   1639       }
   1640 
   1641       OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE);
   1642       break;
   1643 
   1644     case EfiUsbPortEnable:
   1645       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_ENABLE);
   1646 
   1647       //
   1648       // Verify the state
   1649       //
   1650       RetryTimes = 0;
   1651       do {
   1652         gBS->Stall (1000);
   1653         RetryTimes++;
   1654       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT) == 0 &&
   1655                RetryTimes < MAX_RETRY_TIMES);
   1656 
   1657       if (RetryTimes >= MAX_RETRY_TIMES) {
   1658         return EFI_DEVICE_ERROR;
   1659       }
   1660       break;
   1661 
   1662 
   1663     case EfiUsbPortSuspend:
   1664       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_SUSPEND);
   1665 
   1666       //
   1667       // Verify the state
   1668       //
   1669       RetryTimes = 0;
   1670       do {
   1671         gBS->Stall (1000);
   1672         RetryTimes++;
   1673       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT) == 0 &&
   1674                RetryTimes < MAX_RETRY_TIMES);
   1675 
   1676       if (RetryTimes >= MAX_RETRY_TIMES) {
   1677         return EFI_DEVICE_ERROR;
   1678       }
   1679       break;
   1680 
   1681     default:
   1682       return EFI_INVALID_PARAMETER;
   1683   }
   1684 
   1685   return Status;
   1686 }
   1687 
   1688 /**
   1689 
   1690   Clears a feature for the specified root hub port.
   1691 
   1692   @param  This                  A pointer to the EFI_USB_HC_PROTOCOL instance.
   1693   @param  PortNumber            Specifies the root hub port whose feature
   1694                                 is requested to be cleared.
   1695   @param  PortFeature           Indicates the feature selector associated with the
   1696                                 feature clear request.
   1697 
   1698   @retval EFI_SUCCESS           The feature specified by PortFeature was cleared for the
   1699                                 USB root hub port specified by PortNumber.
   1700   @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
   1701   @retval EFI_DEVICE_ERROR      Some error happened when clearing feature
   1702 **/
   1703 EFI_STATUS
   1704 EFIAPI
   1705 OhciClearRootHubPortFeature (
   1706   IN EFI_USB_HC_PROTOCOL   *This,
   1707   IN UINT8                 PortNumber,
   1708   IN EFI_USB_PORT_FEATURE  PortFeature
   1709   )
   1710 {
   1711   USB_OHCI_HC_DEV         *Ohc;
   1712   EFI_STATUS              Status;
   1713   UINT8                   NumOfPorts;
   1714   UINTN                   RetryTimes;
   1715 
   1716 
   1717   OhciGetRootHubNumOfPorts (This, &NumOfPorts);
   1718   if (PortNumber >= NumOfPorts) {
   1719     return EFI_INVALID_PARAMETER;
   1720   }
   1721 
   1722   Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
   1723 
   1724   Status = EFI_SUCCESS;
   1725 
   1726   switch (PortFeature) {
   1727     case EfiUsbPortEnable:
   1728       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_PORT_ENABLE);
   1729 
   1730       //
   1731       // Verify the state
   1732       //
   1733       RetryTimes = 0;
   1734       do {
   1735         gBS->Stall (1000);
   1736         RetryTimes++;
   1737       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT) == 1 &&
   1738                RetryTimes < MAX_RETRY_TIMES);
   1739 
   1740       if (RetryTimes >= MAX_RETRY_TIMES) {
   1741         return EFI_DEVICE_ERROR;
   1742       }
   1743       break;
   1744 
   1745     case EfiUsbPortSuspend:
   1746       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_SUSPEND_STATUS);
   1747 
   1748       //
   1749       // Verify the state
   1750       //
   1751       RetryTimes = 0;
   1752       do {
   1753         gBS->Stall (1000);
   1754         RetryTimes++;
   1755       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT) == 1 &&
   1756                RetryTimes < MAX_RETRY_TIMES);
   1757 
   1758       if (RetryTimes >= MAX_RETRY_TIMES) {
   1759         return EFI_DEVICE_ERROR;
   1760       }
   1761       break;
   1762 
   1763     case EfiUsbPortReset:
   1764       break;
   1765 
   1766     case EfiUsbPortPower:
   1767       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_PORT_POWER);
   1768 
   1769       //
   1770       // Verify the state
   1771       //
   1772       RetryTimes = 0;
   1773       do {
   1774         gBS->Stall (1000);
   1775         RetryTimes++;
   1776       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_POWER_STAT) == 1 &&
   1777                RetryTimes < MAX_RETRY_TIMES);
   1778 
   1779       if (RetryTimes >= MAX_RETRY_TIMES) {
   1780         return EFI_DEVICE_ERROR;
   1781       }
   1782       break;
   1783 
   1784     case EfiUsbPortConnectChange:
   1785       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE);
   1786 
   1787       //
   1788       // Verify the state
   1789       //
   1790       RetryTimes = 0;
   1791       do {
   1792         gBS->Stall (1000);
   1793         RetryTimes++;
   1794       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE) == 1 &&
   1795                RetryTimes < MAX_RETRY_TIMES);
   1796 
   1797       if (RetryTimes >= MAX_RETRY_TIMES) {
   1798         return EFI_DEVICE_ERROR;
   1799       }
   1800       break;
   1801 
   1802     case EfiUsbPortResetChange:
   1803       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE);
   1804 
   1805       //
   1806       // Verify the state
   1807       //
   1808       RetryTimes = 0;
   1809       do {
   1810         gBS->Stall (1000);
   1811         RetryTimes++;
   1812       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE) == 1 &&
   1813                RetryTimes < MAX_RETRY_TIMES);
   1814 
   1815       if (RetryTimes >= MAX_RETRY_TIMES) {
   1816         return EFI_DEVICE_ERROR;
   1817       }
   1818       break;
   1819 
   1820 
   1821     case EfiUsbPortEnableChange:
   1822       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE);
   1823 
   1824       //
   1825       // Verify the state
   1826       //
   1827       RetryTimes = 0;
   1828       do {
   1829         gBS->Stall (1000);
   1830         RetryTimes++;
   1831       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE) == 1 &&
   1832                RetryTimes < MAX_RETRY_TIMES);
   1833 
   1834       if (RetryTimes >= MAX_RETRY_TIMES) {
   1835         return EFI_DEVICE_ERROR;
   1836       }
   1837       break;
   1838 
   1839     case EfiUsbPortSuspendChange:
   1840       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE);
   1841 
   1842       //
   1843       // Verify the state
   1844       //
   1845       RetryTimes = 0;
   1846       do {
   1847         gBS->Stall (1000);
   1848         RetryTimes++;
   1849       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE) == 1 &&
   1850                RetryTimes < MAX_RETRY_TIMES);
   1851 
   1852       if (RetryTimes >= MAX_RETRY_TIMES) {
   1853         return EFI_DEVICE_ERROR;
   1854       }
   1855       break;
   1856 
   1857     case EfiUsbPortOverCurrentChange:
   1858       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE);
   1859 
   1860       //
   1861       // Verify the state
   1862       //
   1863       RetryTimes = 0;
   1864       do {
   1865         gBS->Stall (1000);
   1866         RetryTimes++;
   1867       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE) == 1 &&
   1868                RetryTimes < MAX_RETRY_TIMES);
   1869 
   1870       if (RetryTimes >= MAX_RETRY_TIMES) {
   1871         return EFI_DEVICE_ERROR;
   1872       }
   1873       break;
   1874 
   1875     default:
   1876       return EFI_INVALID_PARAMETER;
   1877   }
   1878 
   1879   return Status;
   1880 }
   1881 
   1882 EFI_DRIVER_BINDING_PROTOCOL gOhciDriverBinding = {
   1883   OHCIDriverBindingSupported,
   1884   OHCIDriverBindingStart,
   1885   OHCIDriverBindingStop,
   1886   0x10,
   1887   NULL,
   1888   NULL
   1889 };
   1890 
   1891 
   1892 /**
   1893   Entry point for EFI drivers.
   1894 
   1895   @param  ImageHandle           EFI_HANDLE.
   1896   @param  SystemTable           EFI_SYSTEM_TABLE.
   1897 
   1898   @retval EFI_SUCCESS           Driver is successfully loaded.
   1899   @return Others                Failed.
   1900 
   1901 **/
   1902 EFI_STATUS
   1903 EFIAPI
   1904 OHCIDriverEntryPoint (
   1905   IN EFI_HANDLE          ImageHandle,
   1906   IN EFI_SYSTEM_TABLE    *SystemTable
   1907   )
   1908 {
   1909   return EfiLibInstallDriverBindingComponentName2 (
   1910            ImageHandle,
   1911            SystemTable,
   1912            &gOhciDriverBinding,
   1913            ImageHandle,
   1914            &gOhciComponentName,
   1915            &gOhciComponentName2
   1916            );
   1917 }
   1918 
   1919 
   1920 /**
   1921   Test to see if this driver supports ControllerHandle. Any
   1922   ControllerHandle that has UsbHcProtocol installed will be supported.
   1923 
   1924   @param  This                 Protocol instance pointer.
   1925   @param  Controller           Handle of device to test.
   1926   @param  RemainingDevicePath  Not used.
   1927 
   1928   @return EFI_SUCCESS          This driver supports this device.
   1929   @return EFI_UNSUPPORTED      This driver does not support this device.
   1930 
   1931 **/
   1932 EFI_STATUS
   1933 EFIAPI
   1934 OHCIDriverBindingSupported (
   1935   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
   1936   IN EFI_HANDLE                   Controller,
   1937   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
   1938   )
   1939 {
   1940   EFI_STATUS              Status;
   1941   EFI_PCI_IO_PROTOCOL     *PciIo;
   1942   USB_CLASSC              UsbClassCReg;
   1943   //
   1944   // Test whether there is PCI IO Protocol attached on the controller handle.
   1945   //
   1946   Status = gBS->OpenProtocol (
   1947                   Controller,
   1948                   &gEfiPciIoProtocolGuid,
   1949                   (VOID **) &PciIo,
   1950                   This->DriverBindingHandle,
   1951                   Controller,
   1952                   EFI_OPEN_PROTOCOL_BY_DRIVER
   1953                   );
   1954 
   1955   if (EFI_ERROR (Status)) {
   1956     return EFI_UNSUPPORTED;
   1957   }
   1958 
   1959   Status = PciIo->Pci.Read (
   1960                         PciIo,
   1961                         EfiPciIoWidthUint8,
   1962                         PCI_CLASSCODE_OFFSET,
   1963                         sizeof (USB_CLASSC) / sizeof (UINT8),
   1964                         &UsbClassCReg
   1965                         );
   1966 
   1967   if (EFI_ERROR (Status)) {
   1968     Status = EFI_UNSUPPORTED;
   1969     goto ON_EXIT;
   1970   }
   1971   //
   1972   // Test whether the controller belongs to OHCI type
   1973   //
   1974   if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) ||
   1975       (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) ||
   1976       (UsbClassCReg.ProgInterface != PCI_IF_OHCI)
   1977       ) {
   1978 
   1979     Status = EFI_UNSUPPORTED;
   1980   }
   1981 ON_EXIT:
   1982   gBS->CloseProtocol (
   1983          Controller,
   1984          &gEfiPciIoProtocolGuid,
   1985          This->DriverBindingHandle,
   1986          Controller
   1987          );
   1988 
   1989   return Status;
   1990 
   1991 }
   1992 
   1993 /**
   1994 
   1995   Allocate and initialize the empty OHCI device.
   1996 
   1997   @param  PciIo                  The PCIIO to use.
   1998   @param  OriginalPciAttributes  The original PCI attributes.
   1999 
   2000   @return Allocated OHCI device  If err, return NULL.
   2001 
   2002 **/
   2003 
   2004 USB_OHCI_HC_DEV *
   2005 OhciAllocateDev (
   2006   IN EFI_PCI_IO_PROTOCOL  *PciIo,
   2007   IN UINT64               OriginalPciAttributes
   2008   )
   2009 {
   2010   USB_OHCI_HC_DEV         *Ohc;
   2011   EFI_STATUS              Status;
   2012   VOID                    *Buf;
   2013   EFI_PHYSICAL_ADDRESS    PhyAddr;
   2014   VOID                    *Map;
   2015   UINTN                   Pages;
   2016   UINTN                   Bytes;
   2017 
   2018   Ohc = AllocateZeroPool (sizeof (USB_OHCI_HC_DEV));
   2019   if (Ohc == NULL) {
   2020     return NULL;
   2021   }
   2022 
   2023   Ohc->Signature                      = USB_OHCI_HC_DEV_SIGNATURE;
   2024   Ohc->PciIo                          = PciIo;
   2025 
   2026   Ohc->UsbHc.Reset                    = OhciReset;
   2027   Ohc->UsbHc.GetState                 = OhciGetState;
   2028   Ohc->UsbHc.SetState                 = OhciSetState;
   2029   Ohc->UsbHc.ControlTransfer          = OhciControlTransfer;
   2030   Ohc->UsbHc.BulkTransfer             = OhciBulkTransfer;
   2031   Ohc->UsbHc.AsyncInterruptTransfer   = OhciAsyncInterruptTransfer;
   2032   Ohc->UsbHc.SyncInterruptTransfer    = OhciSyncInterruptTransfer;
   2033   Ohc->UsbHc.IsochronousTransfer      = OhciIsochronousTransfer;
   2034   Ohc->UsbHc.AsyncIsochronousTransfer = OhciAsyncIsochronousTransfer;
   2035   Ohc->UsbHc.GetRootHubPortNumber     = OhciGetRootHubNumOfPorts;
   2036   Ohc->UsbHc.GetRootHubPortStatus     = OhciGetRootHubPortStatus;
   2037   Ohc->UsbHc.SetRootHubPortFeature    = OhciSetRootHubPortFeature;
   2038   Ohc->UsbHc.ClearRootHubPortFeature  = OhciClearRootHubPortFeature;
   2039   Ohc->UsbHc.MajorRevision            = 0x1;
   2040   Ohc->UsbHc.MinorRevision            = 0x1;
   2041 
   2042   Ohc->OriginalPciAttributes = OriginalPciAttributes;
   2043 
   2044   Ohc->HccaMemoryBlock = NULL;
   2045   Ohc->HccaMemoryMapping   = NULL;
   2046   Ohc->HccaMemoryBuf = NULL;
   2047   Ohc->HccaMemoryPages = 0;
   2048   Ohc->InterruptContextList = NULL;
   2049   Ohc->ControllerNameTable = NULL;
   2050   Ohc->HouseKeeperTimer = NULL;
   2051 
   2052   Ohc->MemPool = UsbHcInitMemPool(PciIo, TRUE, 0);
   2053   if(Ohc->MemPool == NULL) {
   2054     goto FREE_DEV_BUFFER;
   2055   }
   2056 
   2057   Bytes = 4096;
   2058   Pages = EFI_SIZE_TO_PAGES (Bytes);
   2059 
   2060   Status = PciIo->AllocateBuffer (
   2061                     PciIo,
   2062                     AllocateAnyPages,
   2063                     EfiBootServicesData,
   2064                     Pages,
   2065                     &Buf,
   2066                     0
   2067                     );
   2068 
   2069   if (EFI_ERROR (Status)) {
   2070     goto FREE_MEM_POOL;
   2071   }
   2072 
   2073   Status = PciIo->Map (
   2074                     PciIo,
   2075                     EfiPciIoOperationBusMasterCommonBuffer,
   2076                     Buf,
   2077                     &Bytes,
   2078                     &PhyAddr,
   2079                     &Map
   2080                     );
   2081 
   2082   if (EFI_ERROR (Status) || (Bytes != 4096)) {
   2083     goto FREE_MEM_PAGE;
   2084   }
   2085 
   2086   Ohc->HccaMemoryBlock = (HCCA_MEMORY_BLOCK *)(UINTN)PhyAddr;
   2087   Ohc->HccaMemoryMapping = Map;
   2088   Ohc->HccaMemoryBuf = (VOID *)(UINTN)Buf;
   2089   Ohc->HccaMemoryPages = Pages;
   2090 
   2091   return Ohc;
   2092 
   2093 FREE_MEM_PAGE:
   2094   PciIo->FreeBuffer (PciIo, Pages, Buf);
   2095 FREE_MEM_POOL:
   2096   UsbHcFreeMemPool (Ohc->MemPool);
   2097 FREE_DEV_BUFFER:
   2098   FreePool(Ohc);
   2099 
   2100   return NULL;
   2101 }
   2102 /**
   2103 
   2104   Free the OHCI device and release its associated resources.
   2105 
   2106   @param  Ohc                   The OHCI device to release.
   2107 
   2108 **/
   2109 VOID
   2110 OhciFreeDev (
   2111   IN USB_OHCI_HC_DEV      *Ohc
   2112   )
   2113 {
   2114   OhciFreeFixedIntMemory (Ohc);
   2115 
   2116   if (Ohc->HouseKeeperTimer != NULL) {
   2117     gBS->CloseEvent (Ohc->HouseKeeperTimer);
   2118   }
   2119 
   2120   if (Ohc->ExitBootServiceEvent != NULL) {
   2121     gBS->CloseEvent (Ohc->ExitBootServiceEvent);
   2122   }
   2123 
   2124   if (Ohc->MemPool != NULL) {
   2125     UsbHcFreeMemPool (Ohc->MemPool);
   2126   }
   2127 
   2128   if (Ohc->HccaMemoryMapping != NULL ) {
   2129     Ohc->PciIo->FreeBuffer (Ohc->PciIo, Ohc->HccaMemoryPages, Ohc->HccaMemoryBuf);
   2130   }
   2131 
   2132   if (Ohc->ControllerNameTable != NULL) {
   2133     FreeUnicodeStringTable (Ohc->ControllerNameTable);
   2134   }
   2135 
   2136   FreePool (Ohc);
   2137 }
   2138 /**
   2139 
   2140   Uninstall all Ohci Interface.
   2141 
   2142   @param  Controller            Controller handle.
   2143   @param  This                  Protocol instance pointer.
   2144 
   2145 **/
   2146 VOID
   2147 OhciCleanDevUp (
   2148   IN  EFI_HANDLE           Controller,
   2149   IN  EFI_USB_HC_PROTOCOL  *This
   2150   )
   2151 {
   2152   USB_OHCI_HC_DEV  *Ohc;
   2153 
   2154   //
   2155   // Retrieve private context structure
   2156   //
   2157   Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
   2158 
   2159   //
   2160   // Uninstall the USB_HC and USB_HC2 protocol
   2161   //
   2162   gBS->UninstallProtocolInterface (
   2163          Controller,
   2164          &gEfiUsbHcProtocolGuid,
   2165          &Ohc->UsbHc
   2166          );
   2167 
   2168   //
   2169   // Cancel the timer event
   2170   //
   2171   gBS->SetTimer (Ohc->HouseKeeperTimer, TimerCancel, 0);
   2172 
   2173   //
   2174   // Stop the host controller
   2175   //
   2176   OhciSetHcControl (Ohc, PERIODIC_ENABLE | CONTROL_ENABLE | ISOCHRONOUS_ENABLE | BULK_ENABLE, 0);
   2177   This->Reset (This, EFI_USB_HC_RESET_GLOBAL);
   2178   This->SetState (This, EfiUsbHcStateHalt);
   2179 
   2180   //
   2181   // Free resources
   2182   //
   2183   OhciFreeDynamicIntMemory (Ohc);
   2184 
   2185   //
   2186   // Restore original PCI attributes
   2187   //
   2188   Ohc->PciIo->Attributes (
   2189                 Ohc->PciIo,
   2190                 EfiPciIoAttributeOperationSet,
   2191                 Ohc->OriginalPciAttributes,
   2192                 NULL
   2193                 );
   2194 
   2195   //
   2196   // Free the private context structure
   2197   //
   2198   OhciFreeDev (Ohc);
   2199 }
   2200 
   2201 /**
   2202 
   2203   One notified function to stop the Host Controller when gBS->ExitBootServices() called.
   2204 
   2205   @param  Event                 Pointer to this event
   2206   @param  Context               Event handler private data
   2207 **/
   2208 VOID
   2209 EFIAPI
   2210 OhcExitBootService (
   2211   EFI_EVENT                      Event,
   2212   VOID                           *Context
   2213   )
   2214 {
   2215   USB_OHCI_HC_DEV           *Ohc;
   2216   EFI_USB_HC_PROTOCOL       *UsbHc;
   2217   Ohc = (USB_OHCI_HC_DEV *) Context;
   2218 
   2219   UsbHc = &Ohc->UsbHc;
   2220   //
   2221   // Stop the Host Controller
   2222   //
   2223   //OhciStopHc (Ohc, OHC_GENERIC_TIMEOUT);
   2224   OhciSetHcControl (Ohc, PERIODIC_ENABLE | CONTROL_ENABLE | ISOCHRONOUS_ENABLE | BULK_ENABLE, 0);
   2225   UsbHc->Reset (UsbHc, EFI_USB_HC_RESET_GLOBAL);
   2226   UsbHc->SetState (UsbHc, EfiUsbHcStateHalt);
   2227 
   2228   return;
   2229 }
   2230 
   2231 
   2232 /**
   2233   Starting the Usb OHCI Driver.
   2234 
   2235   @param  This                  Protocol instance pointer.
   2236   @param  Controller            Handle of device to test.
   2237   @param  RemainingDevicePath   Not used.
   2238 
   2239   @retval EFI_SUCCESS           This driver supports this device.
   2240   @retval EFI_UNSUPPORTED       This driver does not support this device.
   2241   @retval EFI_DEVICE_ERROR      This driver cannot be started due to device Error.
   2242                                 EFI_OUT_OF_RESOURCES- Failed due to resource shortage.
   2243 
   2244 **/
   2245 EFI_STATUS
   2246 EFIAPI
   2247 OHCIDriverBindingStart (
   2248   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
   2249   IN EFI_HANDLE                   Controller,
   2250   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
   2251   )
   2252 {
   2253   EFI_STATUS              Status;
   2254   EFI_PCI_IO_PROTOCOL     *PciIo;
   2255   USB_OHCI_HC_DEV         *Ohc;
   2256   UINT64                  Supports;
   2257   UINT64                  OriginalPciAttributes;
   2258   BOOLEAN                 PciAttributesSaved;
   2259 
   2260   //
   2261   // Open PCIIO, then enable the HC device and turn off emulation
   2262   //
   2263   Ohc = NULL;
   2264   Status = gBS->OpenProtocol (
   2265                   Controller,
   2266                   &gEfiPciIoProtocolGuid,
   2267                   (VOID **) &PciIo,
   2268                   This->DriverBindingHandle,
   2269                   Controller,
   2270                   EFI_OPEN_PROTOCOL_BY_DRIVER
   2271                   );
   2272 
   2273   if (EFI_ERROR (Status)) {
   2274     return Status;
   2275   }
   2276 
   2277   PciAttributesSaved = FALSE;
   2278   //
   2279   // Save original PCI attributes
   2280   //
   2281   Status = PciIo->Attributes (
   2282                     PciIo,
   2283                     EfiPciIoAttributeOperationGet,
   2284                     0,
   2285                     &OriginalPciAttributes
   2286                     );
   2287 
   2288   if (EFI_ERROR (Status)) {
   2289     goto CLOSE_PCIIO;
   2290   }
   2291   PciAttributesSaved = TRUE;
   2292 
   2293   //
   2294   // Robustnesss improvement such as for UoL
   2295   // Default is not required.
   2296   //
   2297   //if (FeaturePcdGet (PcdTurnOffUsbLegacySupport)) {
   2298   //  OhciTurnOffUsbEmulation (PciIo);
   2299   //}
   2300 
   2301   Status = PciIo->Attributes (
   2302                     PciIo,
   2303                     EfiPciIoAttributeOperationSupported,
   2304                     0,
   2305                     &Supports
   2306                     );
   2307   if (!EFI_ERROR (Status)) {
   2308     Supports &= EFI_PCI_DEVICE_ENABLE;
   2309     Status = PciIo->Attributes (
   2310                       PciIo,
   2311                       EfiPciIoAttributeOperationEnable,
   2312                       Supports,
   2313                       NULL
   2314                       );
   2315   }
   2316 
   2317   if (EFI_ERROR (Status)) {
   2318     goto CLOSE_PCIIO;
   2319   }
   2320   //
   2321   //Allocate memory for OHC private data structure
   2322   //
   2323   Ohc = OhciAllocateDev(PciIo, OriginalPciAttributes);
   2324   if (Ohc == NULL){
   2325     Status = EFI_OUT_OF_RESOURCES;
   2326     goto CLOSE_PCIIO;
   2327   }
   2328 
   2329   //Status = OhciInitializeInterruptList ( Uhc );
   2330   //if (EFI_ERROR (Status)) {
   2331   //  goto FREE_OHC;
   2332   //}
   2333 
   2334   //
   2335   // Set 0.01 s timer
   2336   //
   2337   Status = gBS->CreateEvent (
   2338                   EVT_TIMER | EVT_NOTIFY_SIGNAL,
   2339                   TPL_NOTIFY,
   2340                   OhciHouseKeeper,
   2341                   Ohc,
   2342                   &Ohc->HouseKeeperTimer
   2343                   );
   2344   if (EFI_ERROR (Status)) {
   2345     goto FREE_OHC;
   2346   }
   2347 
   2348   Status = gBS->SetTimer (Ohc->HouseKeeperTimer, TimerPeriodic, 10 * 1000 * 10);
   2349   if (EFI_ERROR (Status)) {
   2350     goto FREE_OHC;
   2351   }
   2352 
   2353   //
   2354   //Install Host Controller Protocol
   2355   //
   2356   Status = gBS->InstallProtocolInterface (
   2357                   &Controller,
   2358                   &gEfiUsbHcProtocolGuid,
   2359                   EFI_NATIVE_INTERFACE,
   2360                   &Ohc->UsbHc
   2361                   );
   2362   if (EFI_ERROR (Status)) {
   2363     DEBUG ((EFI_D_INFO, "Install protocol error"));
   2364     goto FREE_OHC;
   2365   }
   2366   //
   2367   // Create event to stop the HC when exit boot service.
   2368   //
   2369   Status = gBS->CreateEventEx (
   2370                   EVT_NOTIFY_SIGNAL,
   2371                   TPL_NOTIFY,
   2372                   OhcExitBootService,
   2373                   Ohc,
   2374                   &gEfiEventExitBootServicesGuid,
   2375                   &Ohc->ExitBootServiceEvent
   2376                   );
   2377   if (EFI_ERROR (Status)) {
   2378     DEBUG ((EFI_D_INFO, "Create exit boot event error"));
   2379     goto UNINSTALL_USBHC;
   2380   }
   2381   AddUnicodeString2 (
   2382     "eng",
   2383     gOhciComponentName.SupportedLanguages,
   2384     &Ohc->ControllerNameTable,
   2385     L"Usb Universal Host Controller",
   2386     TRUE
   2387     );
   2388   AddUnicodeString2 (
   2389     "en",
   2390     gOhciComponentName2.SupportedLanguages,
   2391     &Ohc->ControllerNameTable,
   2392     L"Usb Universal Host Controller",
   2393     FALSE
   2394     );
   2395 
   2396   return EFI_SUCCESS;
   2397 
   2398 UNINSTALL_USBHC:
   2399   gBS->UninstallMultipleProtocolInterfaces (
   2400          Controller,
   2401          &gEfiUsbHcProtocolGuid,
   2402          &Ohc->UsbHc,
   2403          NULL
   2404          );
   2405 
   2406 FREE_OHC:
   2407   OhciFreeDev (Ohc);
   2408 
   2409 CLOSE_PCIIO:
   2410   if (PciAttributesSaved) {
   2411   //
   2412   // Restore original PCI attributes
   2413   //
   2414     PciIo->Attributes (
   2415              PciIo,
   2416              EfiPciIoAttributeOperationSet,
   2417              OriginalPciAttributes,
   2418              NULL
   2419              );
   2420   }
   2421 
   2422   gBS->CloseProtocol (
   2423          Controller,
   2424          &gEfiPciIoProtocolGuid,
   2425          This->DriverBindingHandle,
   2426          Controller
   2427          );
   2428   return Status;
   2429 }
   2430 
   2431 /**
   2432   Stop this driver on ControllerHandle. Support stopping any child handles
   2433   created by this driver.
   2434 
   2435   @param  This                  Protocol instance pointer.
   2436   @param  Controller            Handle of device to stop driver on.
   2437   @param  NumberOfChildren      Number of Children in the ChildHandleBuffer.
   2438   @param  ChildHandleBuffer     List of handles for the children we need to stop.
   2439 
   2440   @return EFI_SUCCESS
   2441   @return others
   2442 
   2443 **/
   2444 EFI_STATUS
   2445 EFIAPI
   2446 OHCIDriverBindingStop (
   2447   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
   2448   IN EFI_HANDLE                   Controller,
   2449   IN UINTN                        NumberOfChildren,
   2450   IN EFI_HANDLE                   *ChildHandleBuffer
   2451   )
   2452 {
   2453   EFI_STATUS           Status;
   2454   EFI_USB_HC_PROTOCOL  *UsbHc;
   2455 
   2456   Status = gBS->OpenProtocol (
   2457                   Controller,
   2458                   &gEfiUsbHcProtocolGuid,
   2459                   (VOID **)&UsbHc,
   2460                   This->DriverBindingHandle,
   2461                   Controller,
   2462                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
   2463                   );
   2464   if (EFI_ERROR (Status)) {
   2465     return Status;
   2466   }
   2467 
   2468   OhciCleanDevUp(Controller, UsbHc);
   2469 
   2470   gBS->CloseProtocol (
   2471          Controller,
   2472          &gEfiPciIoProtocolGuid,
   2473          This->DriverBindingHandle,
   2474          Controller
   2475          );
   2476   return EFI_SUCCESS;
   2477 }
   2478 
   2479 
   2480