Home | History | Annotate | Download | only in Dxe
      1 /** @file
      2 This file contains the implementation of Usb Hc Protocol.
      3 
      4 Copyright (c) 2013-2015 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   UINT8                          EdDir;
    641   UINT32                         DataPidDir;
    642   TD_DESCRIPTOR                  *HeadTd;
    643   TD_DESCRIPTOR                  *DataTd;
    644   TD_DESCRIPTOR                  *EmptyTd;
    645   EFI_STATUS                     Status;
    646   EFI_USB_DATA_DIRECTION         TransferDirection;
    647   UINT8                          EndPointNum;
    648   UINTN                          TimeCount;
    649   OHCI_ED_RESULT                 EdResult;
    650 
    651   EFI_PCI_IO_PROTOCOL_OPERATION  MapOp;
    652   VOID                           *Mapping;
    653   UINTN                          MapLength;
    654   EFI_PHYSICAL_ADDRESS           MapPyhAddr;
    655   UINTN                          LeftLength;
    656   UINTN                          ActualSendLength;
    657   BOOLEAN                        FirstTD;
    658 
    659   Mapping = NULL;
    660   MapLength = 0;
    661   MapPyhAddr = 0;
    662   LeftLength = 0;
    663   Status = EFI_SUCCESS;
    664 
    665   if (Data == NULL || DataLength == NULL || DataToggle == NULL || TransferResult == NULL ||
    666       *DataLength == 0 || (*DataToggle != 0 && *DataToggle != 1) ||
    667       (MaxPacketLength != 8 && MaxPacketLength != 16 &&
    668        MaxPacketLength != 32 && MaxPacketLength != 64)) {
    669     return EFI_INVALID_PARAMETER;
    670   }
    671 
    672   Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
    673 
    674   if ((EndPointAddress & 0x80) != 0) {
    675     TransferDirection = EfiUsbDataIn;
    676     EdDir = ED_IN_DIR;
    677     DataPidDir = TD_IN_PID;
    678     MapOp = EfiPciIoOperationBusMasterWrite;
    679   } else {
    680     TransferDirection = EfiUsbDataOut;
    681     EdDir = ED_OUT_DIR;
    682     DataPidDir = TD_OUT_PID;
    683     MapOp = EfiPciIoOperationBusMasterRead;
    684   }
    685 
    686   EndPointNum = (EndPointAddress & 0xF);
    687   EdResult.NextToggle = *DataToggle;
    688 
    689   Status = OhciSetHcControl (Ohc, BULK_ENABLE, 0);
    690   if (EFI_ERROR(Status)) {
    691     DEBUG ((EFI_D_INFO, "OhciControlTransfer: fail to disable BULK_ENABLE\r\n"));
    692     *TransferResult = EFI_USB_ERR_SYSTEM;
    693     return EFI_DEVICE_ERROR;
    694   }
    695   Status = OhciSetHcCommandStatus (Ohc, BULK_LIST_FILLED, 0);
    696   if (EFI_ERROR(Status)) {
    697     DEBUG ((EFI_D_INFO, "OhciControlTransfer: fail to disable BULK_LIST_FILLED\r\n"));
    698     *TransferResult = EFI_USB_ERR_SYSTEM;
    699     return EFI_DEVICE_ERROR;
    700   }
    701   gBS->Stall(20 * 1000);
    702 
    703   OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, NULL);
    704 
    705   Ed = OhciCreateED (Ohc);
    706   if (Ed == NULL) {
    707     return EFI_OUT_OF_RESOURCES;
    708   }
    709   OhciSetEDField (Ed, ED_SKIP, 1);
    710   OhciSetEDField (Ed, ED_FUNC_ADD, DeviceAddress);
    711   OhciSetEDField (Ed, ED_ENDPT_NUM, EndPointNum);
    712   OhciSetEDField (Ed, ED_DIR, ED_FROM_TD_DIR);
    713   OhciSetEDField (Ed, ED_SPEED, HI_SPEED);
    714   OhciSetEDField (Ed, ED_FORMAT | ED_HALTED | ED_DTTOGGLE, 0);
    715   OhciSetEDField (Ed, ED_MAX_PACKET, MaxPacketLength);
    716   OhciSetEDField (Ed, ED_PDATA, 0);
    717   OhciSetEDField (Ed, ED_ZERO, 0);
    718   OhciSetEDField (Ed, ED_TDHEAD_PTR, 0);
    719   OhciSetEDField (Ed, ED_TDTAIL_PTR, 0);
    720   OhciSetEDField (Ed, ED_NEXT_EDPTR, 0);
    721   HeadEd = OhciAttachEDToList (Ohc, BULK_LIST, Ed, NULL);
    722 
    723   if(Data != NULL) {
    724     MapLength = *DataLength;
    725     Status = Ohc->PciIo->Map (Ohc->PciIo, MapOp, (UINT8 *)Data, &MapLength, &MapPyhAddr, &Mapping);
    726     if (EFI_ERROR(Status)) {
    727       DEBUG ((EFI_D_INFO, "OhciBulkTransfer: Fail to Map Data Buffer for Bulk\r\n"));
    728       goto FREE_ED_BUFF;
    729     }
    730   }
    731   //
    732   //Data Stage
    733   //
    734   LeftLength = MapLength;
    735   ActualSendLength = MapLength;
    736   HeadTd = NULL;
    737   FirstTD = TRUE;
    738   while (LeftLength > 0) {
    739     ActualSendLength = LeftLength;
    740     if (LeftLength > MaxPacketLength) {
    741       ActualSendLength = MaxPacketLength;
    742     }
    743     DataTd = OhciCreateTD (Ohc);
    744     if (DataTd == NULL) {
    745       DEBUG ((EFI_D_INFO, "OhciBulkTransfer: Fail to allocate buffer for Data Stage TD\r\n"));
    746       Status = EFI_OUT_OF_RESOURCES;
    747       goto FREE_OHCI_TDBUFF;
    748     }
    749     OhciSetTDField (DataTd, TD_PDATA, 0);
    750     OhciSetTDField (DataTd, TD_BUFFER_ROUND, 1);
    751     OhciSetTDField (DataTd, TD_DIR_PID, DataPidDir);
    752     OhciSetTDField (DataTd, TD_DELAY_INT, TD_NO_DELAY);
    753     OhciSetTDField (DataTd, TD_DT_TOGGLE, *DataToggle);
    754     OhciSetTDField (DataTd, TD_ERROR_CNT, 0);
    755     OhciSetTDField (DataTd, TD_COND_CODE, TD_TOBE_PROCESSED);
    756     OhciSetTDField (DataTd, TD_CURR_BUFFER_PTR, (UINT32) MapPyhAddr);
    757     OhciSetTDField (DataTd, TD_BUFFER_END_PTR, (UINT32)(MapPyhAddr + ActualSendLength - 1));
    758     OhciSetTDField (DataTd, TD_NEXT_PTR, 0);
    759     DataTd->ActualSendLength = (UINT32)ActualSendLength;
    760     DataTd->DataBuffer = (UINT32)MapPyhAddr;
    761     DataTd->NextTDPointer = 0;
    762     if (FirstTD) {
    763       HeadTd = DataTd;
    764       FirstTD = FALSE;
    765     } else {
    766       OhciLinkTD (HeadTd, DataTd);
    767     }
    768     *DataToggle ^= 1;
    769     MapPyhAddr += ActualSendLength;
    770     LeftLength -= ActualSendLength;
    771   }
    772   //
    773   // Empty Stage
    774   //
    775   EmptyTd = OhciCreateTD (Ohc);
    776   if (EmptyTd == NULL) {
    777     Status = EFI_OUT_OF_RESOURCES;
    778     DEBUG ((EFI_D_INFO, "OhciBulkTransfer: Fail to allocate buffer for Empty TD\r\n"));
    779     goto FREE_OHCI_TDBUFF;
    780   }
    781   OhciSetTDField (EmptyTd, TD_PDATA, 0);
    782   OhciSetTDField (EmptyTd, TD_BUFFER_ROUND, 0);
    783   OhciSetTDField (EmptyTd, TD_DIR_PID, 0);
    784   OhciSetTDField (EmptyTd, TD_DELAY_INT, 0);
    785   //OhciSetTDField (EmptyTd, TD_DT_TOGGLE, CurrentToggle);
    786   EmptyTd->Word0.DataToggle = 0;
    787   OhciSetTDField (EmptyTd, TD_ERROR_CNT, 0);
    788   OhciSetTDField (EmptyTd, TD_COND_CODE, 0);
    789   OhciSetTDField (EmptyTd, TD_CURR_BUFFER_PTR, 0);
    790   OhciSetTDField (EmptyTd, TD_BUFFER_END_PTR, 0);
    791   OhciSetTDField (EmptyTd, TD_NEXT_PTR, 0);
    792   EmptyTd->ActualSendLength = 0;
    793   EmptyTd->DataBuffer = 0;
    794   EmptyTd->NextTDPointer = 0;
    795   OhciLinkTD (HeadTd, EmptyTd);
    796   Ed->TdTailPointer = (UINT32)(UINTN)EmptyTd;
    797   OhciAttachTDListToED (Ed, HeadTd);
    798 
    799   OhciSetEDField (Ed, ED_SKIP, 0);
    800   Status = OhciSetHcCommandStatus (Ohc, BULK_LIST_FILLED, 1);
    801   if (EFI_ERROR(Status)) {
    802     *TransferResult = EFI_USB_ERR_SYSTEM;
    803     Status = EFI_DEVICE_ERROR;
    804     DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to enable BULK_LIST_FILLED\r\n"));
    805     goto FREE_OHCI_TDBUFF;
    806   }
    807   Status = OhciSetHcControl (Ohc, BULK_ENABLE, 1);
    808   if (EFI_ERROR(Status)) {
    809     *TransferResult = EFI_USB_ERR_SYSTEM;
    810     Status = EFI_DEVICE_ERROR;
    811     DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to enable BULK_ENABLE\r\n"));
    812     goto FREE_OHCI_TDBUFF;
    813   }
    814   gBS->Stall(20 * 1000);
    815 
    816   TimeCount = 0;
    817   Status = CheckIfDone (Ohc, BULK_LIST, Ed, HeadTd, &EdResult);
    818   while (Status == EFI_NOT_READY && TimeCount <= TimeOut) {
    819     gBS->Stall (1000);
    820     TimeCount++;
    821     Status = CheckIfDone (Ohc, BULK_LIST, Ed, HeadTd, &EdResult);
    822   }
    823 
    824   *TransferResult = ConvertErrorCode (EdResult.ErrorCode);
    825 
    826   if (EdResult.ErrorCode != TD_NO_ERROR) {
    827     if (EdResult.ErrorCode == TD_TOBE_PROCESSED) {
    828       DEBUG ((EFI_D_INFO, "Bulk pipe timeout, > %d mS\r\n", TimeOut));
    829     } else {
    830       DEBUG ((EFI_D_INFO, "Bulk pipe broken\r\n"));
    831       *DataToggle = EdResult.NextToggle;
    832     }
    833     *DataLength = 0;
    834   } else {
    835     DEBUG ((EFI_D_INFO, "Bulk transfer successed\r\n"));
    836   }
    837   //*DataToggle = (UINT8) OhciGetEDField (Ed, ED_DTTOGGLE);
    838 
    839 FREE_OHCI_TDBUFF:
    840   OhciSetEDField (Ed, ED_SKIP, 1);
    841   if (HeadEd == Ed) {
    842     OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, NULL);
    843   }else {
    844     HeadEd->NextED = Ed->NextED;
    845   }
    846   while (HeadTd) {
    847     DataTd = HeadTd;
    848     HeadTd = (TD_DESCRIPTOR *)(UINTN)(HeadTd->NextTDPointer);
    849     UsbHcFreeMem(Ohc->MemPool, DataTd, sizeof(TD_DESCRIPTOR));
    850   }
    851 
    852   if(Mapping != NULL) {
    853     Ohc->PciIo->Unmap(Ohc->PciIo, Mapping);
    854   }
    855 
    856 FREE_ED_BUFF:
    857   UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));
    858 
    859   return Status;
    860 }
    861 /**
    862 
    863   Submits an interrupt transfer to an interrupt endpoint of a USB device.
    864 
    865   @param  Ohc                   Device private data
    866   @param  DeviceAddress         Represents the address of the target device on the USB,
    867                                 which is assigned during USB enumeration.
    868   @param  EndPointAddress       The combination of an endpoint number and an endpoint
    869                                 direction of the target USB device. Each endpoint address
    870                                 supports data transfer in one direction except the
    871                                 control endpoint (whose default endpoint address is 0).
    872                                 It is the caller's responsibility to make sure that
    873                                 the EndPointAddress represents an interrupt endpoint.
    874   @param  IsSlowDevice          Indicates whether the target device is slow device
    875                                 or full-speed device.
    876   @param  MaxPacketLength       Indicates the maximum packet size the target endpoint
    877                                 is capable of sending or receiving.
    878   @param  IsNewTransfer         If TRUE, an asynchronous interrupt pipe is built between
    879                                 the host and the target interrupt endpoint.
    880                                 If FALSE, the specified asynchronous interrupt pipe
    881                                 is canceled.
    882   @param  DataToggle            A pointer to the data toggle value.  On input, it is valid
    883                                 when IsNewTransfer is TRUE, and it indicates the initial
    884                                 data toggle value the asynchronous interrupt transfer
    885                                 should adopt.
    886                                 On output, it is valid when IsNewTransfer is FALSE,
    887                                 and it is updated to indicate the data toggle value of
    888                                 the subsequent asynchronous interrupt transfer.
    889   @param  PollingInterval       Indicates the interval, in milliseconds, that the
    890                                 asynchronous interrupt transfer is polled.
    891                                 This parameter is required when IsNewTransfer is TRUE.
    892   @param  UCBuffer              Uncacheable buffer
    893   @param  DataLength            Indicates the length of data to be received at the
    894                                 rate specified by PollingInterval from the target
    895                                 asynchronous interrupt endpoint.  This parameter
    896                                 is only required when IsNewTransfer is TRUE.
    897   @param  CallBackFunction      The Callback function.This function is called at the
    898                                 rate specified by PollingInterval.This parameter is
    899                                 only required when IsNewTransfer is TRUE.
    900   @param  Context               The context that is passed to the CallBackFunction.
    901                                 This is an optional parameter and may be NULL.
    902   @param  IsPeriodic            Periodic interrupt or not
    903   @param  OutputED              The correspoding ED carried out
    904   @param  OutputTD              The correspoding TD carried out
    905 
    906 
    907   @retval EFI_SUCCESS           The asynchronous interrupt transfer request has been successfully
    908                                 submitted or canceled.
    909   @retval EFI_INVALID_PARAMETER Some parameters are invalid.
    910   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
    911 
    912 **/
    913 
    914 EFI_STATUS
    915 OhciInterruptTransfer (
    916   IN     USB_OHCI_HC_DEV                  *Ohc,
    917   IN     UINT8                            DeviceAddress,
    918   IN     UINT8                            EndPointAddress,
    919   IN     BOOLEAN                          IsSlowDevice,
    920   IN     UINT8                            MaxPacketLength,
    921   IN     BOOLEAN                          IsNewTransfer,
    922   IN OUT UINT8                            *DataToggle        OPTIONAL,
    923   IN     UINTN                            PollingInterval    OPTIONAL,
    924   IN     VOID                             *UCBuffer          OPTIONAL,
    925   IN     UINTN                            DataLength         OPTIONAL,
    926   IN     EFI_ASYNC_USB_TRANSFER_CALLBACK  CallBackFunction   OPTIONAL,
    927   IN     VOID                             *Context           OPTIONAL,
    928   IN     BOOLEAN                          IsPeriodic         OPTIONAL,
    929   OUT    ED_DESCRIPTOR                    **OutputED         OPTIONAL,
    930   OUT    TD_DESCRIPTOR                    **OutputTD         OPTIONAL
    931   )
    932 {
    933   ED_DESCRIPTOR            *Ed;
    934   UINT8                    EdDir;
    935   ED_DESCRIPTOR            *HeadEd;
    936   TD_DESCRIPTOR            *HeadTd;
    937   TD_DESCRIPTOR            *DataTd;
    938   TD_DESCRIPTOR            *EmptTd;
    939   UINTN                    Depth;
    940   UINTN                    Index;
    941   EFI_STATUS               Status;
    942   UINT8                    EndPointNum;
    943   UINT32                   DataPidDir;
    944   EFI_USB_DATA_DIRECTION   TransferDirection;
    945   INTERRUPT_CONTEXT_ENTRY  *Entry;
    946   EFI_TPL                  OldTpl;
    947   BOOLEAN                  FirstTD;
    948 
    949  VOID                      *Mapping;
    950  UINTN                     MapLength;
    951  EFI_PHYSICAL_ADDRESS      MapPyhAddr;
    952  UINTN                     LeftLength;
    953  UINTN                     ActualSendLength;
    954 
    955 
    956   if (DataLength > MAX_BYTES_PER_TD) {
    957     DEBUG ((EFI_D_ERROR, "OhciInterruptTransfer: Error param\r\n"));
    958     return EFI_INVALID_PARAMETER;
    959   }
    960 
    961   if ((EndPointAddress & 0x80) != 0) {
    962     TransferDirection = EfiUsbDataIn;
    963     EdDir = ED_IN_DIR;
    964     DataPidDir = TD_IN_PID;
    965   } else {
    966     TransferDirection = EfiUsbDataOut;
    967     EdDir = ED_OUT_DIR;
    968     DataPidDir = TD_OUT_PID;
    969   }
    970 
    971   EndPointNum = (EndPointAddress & 0xF);
    972 
    973   if (!IsNewTransfer) {
    974     OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
    975     OhciSetHcControl (Ohc, PERIODIC_ENABLE, 0);
    976     OhciFreeInterruptContext (Ohc, DeviceAddress, EndPointAddress, DataToggle);
    977     Status = OhciFreeInterruptEdByAddr (Ohc, DeviceAddress, EndPointNum);
    978     OhciSetHcControl (Ohc, PERIODIC_ENABLE, 1);
    979     gBS->RestoreTPL (OldTpl);
    980     return Status;
    981   }
    982   MapLength = DataLength;
    983   Status = Ohc->PciIo->Map(
    984                          Ohc->PciIo,
    985                          EfiPciIoOperationBusMasterWrite,
    986                          UCBuffer,
    987                          &MapLength,
    988                          &MapPyhAddr,
    989                          &Mapping
    990                          );
    991   if (EFI_ERROR (Status)) {
    992     DEBUG ((EFI_D_ERROR, "OhciInterruptTransfer: Failt to PciIo->Map buffer \r\n"));
    993     goto EXIT;
    994   }
    995   Depth = 5;
    996   Index = 1;
    997   while (PollingInterval >= Index * 2 && Depth > 0) {
    998     Index *= 2;
    999     Depth--;
   1000   }
   1001   //
   1002   //ED Stage
   1003   //
   1004   HeadEd = OhciFindMinInterruptEDList (Ohc, (UINT32)Depth);
   1005   if ((Ed = OhciFindWorkingEd (HeadEd, DeviceAddress, EndPointNum, EdDir)) != NULL) {
   1006     OhciSetEDField (Ed, ED_SKIP, 1);
   1007   } else {
   1008     Ed = OhciCreateED (Ohc);
   1009     if (Ed == NULL) {
   1010       Status = EFI_OUT_OF_RESOURCES;
   1011       DEBUG ((EFI_D_ERROR, "OhciInterruptTransfer: Fail to allocate buffer for ED\r\n"));
   1012       goto UNMAP_OHCI_XBUFF;
   1013     }
   1014     OhciSetEDField (Ed, ED_SKIP, 1);
   1015     OhciSetEDField (Ed, ED_FUNC_ADD, DeviceAddress);
   1016     OhciSetEDField (Ed, ED_ENDPT_NUM, EndPointNum);
   1017     OhciSetEDField (Ed, ED_DIR, ED_FROM_TD_DIR);
   1018     OhciSetEDField (Ed, ED_SPEED, IsSlowDevice);
   1019     OhciSetEDField (Ed, ED_FORMAT, 0);
   1020     OhciSetEDField (Ed, ED_MAX_PACKET, MaxPacketLength);
   1021     OhciSetEDField (Ed, ED_PDATA | ED_ZERO | ED_HALTED | ED_DTTOGGLE, 0);
   1022     OhciSetEDField (Ed, ED_TDHEAD_PTR, 0);
   1023     OhciSetEDField (Ed, ED_TDTAIL_PTR, 0);
   1024     OhciSetEDField (Ed, ED_NEXT_EDPTR, 0);
   1025     OhciAttachEDToList (Ohc, INTERRUPT_LIST, Ed, HeadEd);
   1026   }
   1027   //
   1028   //Data Stage
   1029   //
   1030   LeftLength = MapLength;
   1031   ActualSendLength = MapLength;
   1032   HeadTd = NULL;
   1033   FirstTD = TRUE;
   1034   while (LeftLength > 0) {
   1035     ActualSendLength = LeftLength;
   1036     if (LeftLength > MaxPacketLength) {
   1037       ActualSendLength = MaxPacketLength;
   1038     }
   1039     DataTd = OhciCreateTD (Ohc);
   1040     if (DataTd == NULL) {
   1041       Status = EFI_OUT_OF_RESOURCES;
   1042       DEBUG ((EFI_D_ERROR, "OhciInterruptTransfer: Fail to allocate buffer for Data Stage TD\r\n"));
   1043       goto FREE_OHCI_TDBUFF;
   1044     }
   1045     OhciSetTDField (DataTd, TD_PDATA, 0);
   1046     OhciSetTDField (DataTd, TD_BUFFER_ROUND, 1);
   1047     OhciSetTDField (DataTd, TD_DIR_PID, DataPidDir);
   1048     OhciSetTDField (DataTd, TD_DELAY_INT, TD_NO_DELAY);
   1049     OhciSetTDField (DataTd, TD_DT_TOGGLE, *DataToggle);
   1050     OhciSetTDField (DataTd, TD_ERROR_CNT, 0);
   1051     OhciSetTDField (DataTd, TD_COND_CODE, TD_TOBE_PROCESSED);
   1052     OhciSetTDField (DataTd, TD_CURR_BUFFER_PTR, (UINT32) MapPyhAddr);
   1053     OhciSetTDField (DataTd, TD_BUFFER_END_PTR, (UINT32)(MapPyhAddr + ActualSendLength - 1));
   1054     OhciSetTDField (DataTd, TD_NEXT_PTR, 0);
   1055     DataTd->ActualSendLength = (UINT32)ActualSendLength;
   1056     DataTd->DataBuffer = (UINT32)MapPyhAddr;
   1057     DataTd->NextTDPointer = 0;
   1058     if (FirstTD) {
   1059       HeadTd = DataTd;
   1060       FirstTD = FALSE;
   1061     } else {
   1062       OhciLinkTD (HeadTd, DataTd);
   1063     }
   1064     *DataToggle ^= 1;
   1065     MapPyhAddr += ActualSendLength;
   1066     LeftLength -= ActualSendLength;
   1067   }
   1068 
   1069   EmptTd = OhciCreateTD (Ohc);
   1070   if (EmptTd == NULL) {
   1071     Status = EFI_OUT_OF_RESOURCES;
   1072     DEBUG ((EFI_D_ERROR, "OhciInterruptTransfer: Fail to allocate buffer for Empty Stage TD\r\n"));
   1073     goto FREE_OHCI_TDBUFF;
   1074   }
   1075   OhciSetTDField (EmptTd, TD_PDATA, 0);
   1076   OhciSetTDField (EmptTd, TD_BUFFER_ROUND, 0);
   1077   OhciSetTDField (EmptTd, TD_DIR_PID, 0);
   1078   OhciSetTDField (EmptTd, TD_DELAY_INT, 0);
   1079   //OhciSetTDField (EmptTd, TD_DT_TOGGLE, CurrentToggle);
   1080   EmptTd->Word0.DataToggle = 0;
   1081   OhciSetTDField (EmptTd, TD_ERROR_CNT, 0);
   1082   OhciSetTDField (EmptTd, TD_COND_CODE, 0);
   1083   OhciSetTDField (EmptTd, TD_CURR_BUFFER_PTR, 0);
   1084   OhciSetTDField (EmptTd, TD_BUFFER_END_PTR, 0);
   1085   OhciSetTDField (EmptTd, TD_NEXT_PTR, 0);
   1086   EmptTd->ActualSendLength = 0;
   1087   EmptTd->DataBuffer = 0;
   1088   EmptTd->NextTDPointer = 0;
   1089   OhciLinkTD (HeadTd, EmptTd);
   1090   Ed->TdTailPointer = (UINT32)(UINTN)EmptTd;
   1091   OhciAttachTDListToED (Ed, HeadTd);
   1092 
   1093   if (OutputED != NULL) {
   1094     *OutputED = Ed;
   1095   }
   1096   if (OutputTD != NULL) {
   1097     *OutputTD = HeadTd;
   1098   }
   1099 
   1100   if (CallBackFunction != NULL) {
   1101     Entry = AllocatePool (sizeof (INTERRUPT_CONTEXT_ENTRY));
   1102     if (Entry == NULL) {
   1103       goto FREE_OHCI_TDBUFF;
   1104     }
   1105 
   1106     Entry->DeviceAddress = DeviceAddress;
   1107     Entry->EndPointAddress = EndPointAddress;
   1108     Entry->Ed = Ed;
   1109     Entry->DataTd = HeadTd;
   1110     Entry->IsSlowDevice = IsSlowDevice;
   1111     Entry->MaxPacketLength = MaxPacketLength;
   1112     Entry->PollingInterval = PollingInterval;
   1113     Entry->CallBackFunction = CallBackFunction;
   1114     Entry->Context = Context;
   1115     Entry->IsPeriodic = IsPeriodic;
   1116     Entry->UCBuffer = UCBuffer;
   1117     Entry->UCBufferMapping = Mapping;
   1118     Entry->DataLength = DataLength;
   1119     Entry->Toggle = DataToggle;
   1120     Entry->NextEntry = NULL;
   1121     OhciAddInterruptContextEntry (Ohc, Entry);
   1122   }
   1123   OhciSetEDField (Ed, ED_SKIP, 0);
   1124 
   1125   if (OhciGetHcControl (Ohc, PERIODIC_ENABLE) == 0) {
   1126     Status = OhciSetHcControl (Ohc, PERIODIC_ENABLE, 1);
   1127     gBS->Stall (1000);
   1128   }
   1129 
   1130   return EFI_SUCCESS;
   1131 
   1132 FREE_OHCI_TDBUFF:
   1133   while (HeadTd) {
   1134     DataTd = HeadTd;
   1135     HeadTd = (TD_DESCRIPTOR *)(UINTN)(HeadTd->NextTDPointer);
   1136     UsbHcFreeMem(Ohc->MemPool, DataTd, sizeof(TD_DESCRIPTOR));
   1137   }
   1138 
   1139 //FREE_OHCI_EDBUFF:
   1140   if ((HeadEd != Ed) && HeadEd && Ed) {
   1141     while(HeadEd->NextED != (UINT32)(UINTN)Ed) {
   1142       HeadEd = (ED_DESCRIPTOR *)(UINTN)(HeadEd->NextED);
   1143     }
   1144   HeadEd->NextED = Ed->NextED;
   1145     UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));
   1146   }
   1147 
   1148 UNMAP_OHCI_XBUFF:
   1149   Ohc->PciIo->Unmap(Ohc->PciIo, Mapping);
   1150 
   1151 EXIT:
   1152   return Status;
   1153 }
   1154 
   1155 /**
   1156 
   1157   Submits an asynchronous interrupt transfer to an interrupt endpoint of a USB device.
   1158 
   1159   @param  This                  A pointer to the EFI_USB_HC_PROTOCOL instance.
   1160   @param  DeviceAddress         Represents the address of the target device on the USB,
   1161                                 which is assigned during USB enumeration.
   1162   @param  EndPointAddress       The combination of an endpoint number and an endpoint
   1163                                 direction of the target USB device. Each endpoint address
   1164                                 supports data transfer in one direction except the
   1165                                 control endpoint (whose default endpoint address is 0).
   1166                                 It is the caller's responsibility to make sure that
   1167                                 the EndPointAddress represents an interrupt endpoint.
   1168   @param  IsSlowDevice          Indicates whether the target device is slow device
   1169                                 or full-speed device.
   1170   @param  MaxiumPacketLength    Indicates the maximum packet size the target endpoint
   1171                                 is capable of sending or receiving.
   1172   @param  IsNewTransfer         If TRUE, an asynchronous interrupt pipe is built between
   1173                                 the host and the target interrupt endpoint.
   1174                                 If FALSE, the specified asynchronous interrupt pipe
   1175                                 is canceled.
   1176   @param  DataToggle            A pointer to the data toggle value.  On input, it is valid
   1177                                 when IsNewTransfer is TRUE, and it indicates the initial
   1178                                 data toggle value the asynchronous interrupt transfer
   1179                                 should adopt.
   1180                                 On output, it is valid when IsNewTransfer is FALSE,
   1181                                 and it is updated to indicate the data toggle value of
   1182                                 the subsequent asynchronous interrupt transfer.
   1183   @param  PollingInterval       Indicates the interval, in milliseconds, that the
   1184                                 asynchronous interrupt transfer is polled.
   1185                                 This parameter is required when IsNewTransfer is TRUE.
   1186   @param  DataLength            Indicates the length of data to be received at the
   1187                                 rate specified by PollingInterval from the target
   1188                                 asynchronous interrupt endpoint.  This parameter
   1189                                 is only required when IsNewTransfer is TRUE.
   1190   @param  CallBackFunction      The Callback function.This function is called at the
   1191                                 rate specified by PollingInterval.This parameter is
   1192                                 only required when IsNewTransfer is TRUE.
   1193   @param  Context               The context that is passed to the CallBackFunction.
   1194                                 This is an optional parameter and may be NULL.
   1195 
   1196   @retval EFI_SUCCESS           The asynchronous interrupt transfer request has been successfully
   1197                                 submitted or canceled.
   1198   @retval EFI_INVALID_PARAMETER Some parameters are invalid.
   1199   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
   1200 
   1201 **/
   1202 
   1203 
   1204 EFI_STATUS
   1205 EFIAPI
   1206 OhciAsyncInterruptTransfer (
   1207   IN     EFI_USB_HC_PROTOCOL              *This,
   1208   IN     UINT8                            DeviceAddress,
   1209   IN     UINT8                            EndPointAddress,
   1210   IN     BOOLEAN                          IsSlowDevice,
   1211   IN     UINT8                            MaxPacketLength,
   1212   IN     BOOLEAN                          IsNewTransfer,
   1213   IN OUT UINT8                            *DataToggle        OPTIONAL,
   1214   IN     UINTN                            PollingInterval    OPTIONAL,
   1215   IN     UINTN                            DataLength         OPTIONAL,
   1216   IN     EFI_ASYNC_USB_TRANSFER_CALLBACK  CallBackFunction   OPTIONAL,
   1217   IN     VOID                             *Context           OPTIONAL
   1218   )
   1219 {
   1220   EFI_STATUS              Status;
   1221   USB_OHCI_HC_DEV         *Ohc;
   1222   VOID                    *UCBuffer;
   1223 
   1224   if (DataToggle == NULL || (EndPointAddress & 0x80) == 0 ||
   1225     (IsNewTransfer && (DataLength == 0 ||
   1226     (*DataToggle != 0 && *DataToggle != 1) || (PollingInterval < 1 || PollingInterval > 255)))) {
   1227     return EFI_INVALID_PARAMETER;
   1228   }
   1229 
   1230   Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
   1231   if ( IsNewTransfer ) {
   1232     UCBuffer = AllocatePool(DataLength);
   1233     if (UCBuffer == NULL) {
   1234       return EFI_OUT_OF_RESOURCES;
   1235     }
   1236   } else {
   1237     UCBuffer = NULL;
   1238   }
   1239   Status = OhciInterruptTransfer (
   1240              Ohc,
   1241              DeviceAddress,
   1242              EndPointAddress,
   1243              IsSlowDevice,
   1244              MaxPacketLength,
   1245              IsNewTransfer,
   1246              DataToggle,
   1247              PollingInterval,
   1248              UCBuffer,
   1249              DataLength,
   1250              CallBackFunction,
   1251              Context,
   1252              TRUE,
   1253              NULL,
   1254              NULL
   1255              );
   1256   if ( IsNewTransfer ) {
   1257     if (EFI_ERROR(Status)) {
   1258       gBS->FreePool (UCBuffer);
   1259     }
   1260   }
   1261   return Status;
   1262 }
   1263 
   1264 
   1265 /**
   1266 
   1267   Submits synchronous interrupt transfer to an interrupt endpoint
   1268   of a USB device.
   1269 
   1270   @param  This                  A pointer to the EFI_USB_HC_PROTOCOL instance.
   1271   @param  DeviceAddress         Represents the address of the target device on the USB,
   1272                                 which is assigned during USB enumeration.
   1273   @param  EndPointAddress       The combination of an endpoint number and an endpoint
   1274                                 direction of the target USB device. Each endpoint
   1275                                 address supports data transfer in one direction
   1276                                 except the control endpoint (whose default
   1277                                 endpoint address is 0). It is the caller's responsibility
   1278                                 to make sure that the EndPointAddress represents
   1279                                 an interrupt endpoint.
   1280   @param  IsSlowDevice          Indicates whether the target device is slow device
   1281                                 or full-speed device.
   1282   @param  MaxPacketLength       Indicates the maximum packet size the target endpoint
   1283                                 is capable of sending or receiving.
   1284   @param  Data                  A pointer to the buffer of data that will be transmitted
   1285                                 to USB device or received from USB device.
   1286   @param  DataLength            On input, the size, in bytes, of the data buffer specified
   1287                                 by Data. On output, the number of bytes transferred.
   1288   @param  DataToggle            A pointer to the data toggle value. On input, it indicates
   1289                                 the initial data toggle value the synchronous interrupt
   1290                                 transfer should adopt;
   1291                                 on output, it is updated to indicate the data toggle value
   1292                                 of the subsequent synchronous interrupt transfer.
   1293   @param  TimeOut               Indicates the maximum time, in microseconds, which the
   1294                                 transfer is allowed to complete.
   1295   @param  TransferResult        A pointer to the detailed result information from
   1296                                 the synchronous interrupt transfer.
   1297 
   1298   @retval EFI_UNSUPPORTED       This interface not available.
   1299   @retval EFI_INVALID_PARAMETER Parameters not follow spec
   1300 
   1301 **/
   1302 
   1303 
   1304 EFI_STATUS
   1305 EFIAPI
   1306 OhciSyncInterruptTransfer (
   1307   IN     EFI_USB_HC_PROTOCOL  *This,
   1308   IN     UINT8                DeviceAddress,
   1309   IN     UINT8                EndPointAddress,
   1310   IN     BOOLEAN              IsSlowDevice,
   1311   IN     UINT8                MaxPacketLength,
   1312   IN OUT VOID                 *Data,
   1313   IN OUT UINTN                *DataLength,
   1314   IN OUT UINT8                *DataToggle,
   1315   IN     UINTN                TimeOut,
   1316   OUT    UINT32               *TransferResult
   1317   )
   1318 {
   1319   USB_OHCI_HC_DEV         *Ohc;
   1320   EFI_STATUS              Status;
   1321   ED_DESCRIPTOR           *Ed;
   1322   TD_DESCRIPTOR           *HeadTd;
   1323   OHCI_ED_RESULT          EdResult;
   1324   VOID                    *UCBuffer;
   1325 
   1326   if ((EndPointAddress & 0x80) == 0 || Data == NULL || DataLength == NULL || *DataLength == 0 ||
   1327       (IsSlowDevice && MaxPacketLength > 8) || (!IsSlowDevice && MaxPacketLength > 64) ||
   1328       DataToggle == NULL || (*DataToggle != 0 && *DataToggle != 1) || TransferResult == NULL) {
   1329     return EFI_INVALID_PARAMETER;
   1330   }
   1331 
   1332   Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
   1333   UCBuffer = AllocatePool (*DataLength);
   1334   if (UCBuffer == NULL) {
   1335     return EFI_OUT_OF_RESOURCES;
   1336   }
   1337   Status = OhciInterruptTransfer (
   1338              Ohc,
   1339              DeviceAddress,
   1340              EndPointAddress,
   1341              IsSlowDevice,
   1342              MaxPacketLength,
   1343              TRUE,
   1344              DataToggle,
   1345              1,
   1346              UCBuffer,
   1347              *DataLength,
   1348              NULL,
   1349              NULL,
   1350              FALSE,
   1351              &Ed,
   1352              &HeadTd
   1353              );
   1354 
   1355   if (!EFI_ERROR (Status)) {
   1356     Status = CheckIfDone (Ohc, INTERRUPT_LIST, Ed, HeadTd, &EdResult);
   1357     while (Status == EFI_NOT_READY && TimeOut > 0) {
   1358       gBS->Stall (1000);
   1359       TimeOut--;
   1360       Status = CheckIfDone (Ohc, INTERRUPT_LIST, Ed, HeadTd, &EdResult);
   1361     }
   1362 
   1363     *TransferResult = ConvertErrorCode (EdResult.ErrorCode);
   1364   }
   1365   CopyMem(Data, UCBuffer, *DataLength);
   1366   Status = OhciInterruptTransfer (
   1367              Ohc,
   1368              DeviceAddress,
   1369              EndPointAddress,
   1370              IsSlowDevice,
   1371              MaxPacketLength,
   1372              FALSE,
   1373              DataToggle,
   1374              0,
   1375              NULL,
   1376              0,
   1377              NULL,
   1378              NULL,
   1379              FALSE,
   1380              NULL,
   1381              NULL
   1382              );
   1383 
   1384   return Status;
   1385 }
   1386 /**
   1387 
   1388   Submits isochronous transfer to a target USB device.
   1389 
   1390   @param  This                  A pointer to the EFI_USB_HC_PROTOCOL instance.
   1391   @param  DeviceAddress         Represents the address of the target device on the USB,
   1392                                 which is assigned during USB enumeration.
   1393   @param  EndPointAddress       End point address
   1394   @param  MaximumPacketLength   Indicates the maximum packet size that the
   1395                                 default control transfer endpoint is capable of
   1396                                 sending or receiving.
   1397   @param  Data                  A pointer to the buffer of data that will be transmitted
   1398                                 to USB device or received from USB device.
   1399   @param  DataLength            Indicates the size, in bytes, of the data buffer
   1400                                 specified by Data.
   1401   @param  TransferResult        A pointer to the detailed result information generated
   1402                                 by this control transfer.
   1403 
   1404   @retval EFI_UNSUPPORTED       This interface not available
   1405   @retval EFI_INVALID_PARAMETER Data is NULL or DataLength is 0 or TransferResult is NULL
   1406 
   1407 **/
   1408 
   1409 
   1410 EFI_STATUS
   1411 EFIAPI
   1412 OhciIsochronousTransfer (
   1413   IN     EFI_USB_HC_PROTOCOL  *This,
   1414   IN     UINT8                DeviceAddress,
   1415   IN     UINT8                EndPointAddress,
   1416   IN     UINT8                MaximumPacketLength,
   1417   IN OUT VOID                 *Data,
   1418   IN OUT UINTN                DataLength,
   1419   OUT    UINT32               *TransferResult
   1420   )
   1421 {
   1422   if (Data == NULL || DataLength == 0 || TransferResult == NULL) {
   1423     return EFI_INVALID_PARAMETER;
   1424   }
   1425 
   1426   return EFI_UNSUPPORTED;
   1427 }
   1428 
   1429 /**
   1430 
   1431   Submits Async isochronous transfer to a target USB device.
   1432 
   1433   @param  his                   A pointer to the EFI_USB_HC_PROTOCOL instance.
   1434   @param  DeviceAddress         Represents the address of the target device on the USB,
   1435                                 which is assigned during USB enumeration.
   1436   @param  EndPointAddress       End point address
   1437   @param  MaximumPacketLength   Indicates the maximum packet size that the
   1438                                 default control transfer endpoint is capable of
   1439                                 sending or receiving.
   1440   @param  Data                  A pointer to the buffer of data that will be transmitted
   1441                                 to USB device or received from USB device.
   1442   @param  IsochronousCallBack   When the transfer complete, the call back function will be called
   1443   @param  Context               Pass to the call back function as parameter
   1444 
   1445   @retval EFI_UNSUPPORTED       This interface not available
   1446   @retval EFI_INVALID_PARAMETER Data is NULL or Datalength is 0
   1447 
   1448 **/
   1449 
   1450 EFI_STATUS
   1451 EFIAPI
   1452 OhciAsyncIsochronousTransfer (
   1453   IN     EFI_USB_HC_PROTOCOL                *This,
   1454   IN     UINT8                              DeviceAddress,
   1455   IN     UINT8                              EndPointAddress,
   1456   IN     UINT8                              MaximumPacketLength,
   1457   IN OUT VOID                               *Data,
   1458   IN OUT UINTN                              DataLength,
   1459   IN     EFI_ASYNC_USB_TRANSFER_CALLBACK    IsochronousCallBack,
   1460   IN     VOID                               *Context OPTIONAL
   1461   )
   1462 {
   1463 
   1464   if (Data == NULL || DataLength == 0) {
   1465     return EFI_INVALID_PARAMETER;
   1466   }
   1467 
   1468   return EFI_UNSUPPORTED;
   1469 }
   1470 
   1471 /**
   1472 
   1473   Retrieves the number of root hub ports.
   1474 
   1475   @param  This                  A pointer to the EFI_USB_HC_PROTOCOL instance.
   1476   @param  NumOfPorts            A pointer to the number of the root hub ports.
   1477 
   1478   @retval EFI_SUCCESS           The port number was retrieved successfully.
   1479 **/
   1480 EFI_STATUS
   1481 EFIAPI
   1482 OhciGetRootHubNumOfPorts (
   1483   IN  EFI_USB_HC_PROTOCOL  *This,
   1484   OUT UINT8                *NumOfPorts
   1485   )
   1486 {
   1487   USB_OHCI_HC_DEV  *Ohc;
   1488   Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
   1489 
   1490   if (NumOfPorts == NULL) {
   1491     return EFI_INVALID_PARAMETER;
   1492   }
   1493 
   1494   *NumOfPorts = (UINT8)OhciGetRootHubDescriptor(Ohc, RH_NUM_DS_PORTS);
   1495 
   1496   return EFI_SUCCESS;
   1497 }
   1498 /**
   1499 
   1500   Retrieves the current status of a USB root hub port.
   1501 
   1502   @param  This                  A pointer to the EFI_USB_HC_PROTOCOL.
   1503   @param  PortNumber            Specifies the root hub port from which the status
   1504                                 is to be retrieved.  This value is zero-based. For example,
   1505                                 if a root hub has two ports, then the first port is numbered 0,
   1506                                 and the second port is numbered 1.
   1507   @param  PortStatus            A pointer to the current port status bits and
   1508                                 port status change bits.
   1509 
   1510   @retval EFI_SUCCESS           The status of the USB root hub port specified by PortNumber
   1511                                 was returned in PortStatus.
   1512   @retval EFI_INVALID_PARAMETER Port number not valid
   1513 **/
   1514 
   1515 
   1516 EFI_STATUS
   1517 EFIAPI
   1518 OhciGetRootHubPortStatus (
   1519   IN  EFI_USB_HC_PROTOCOL  *This,
   1520   IN  UINT8                PortNumber,
   1521   OUT EFI_USB_PORT_STATUS  *PortStatus
   1522   )
   1523 {
   1524   USB_OHCI_HC_DEV  *Ohc;
   1525   UINT8            NumOfPorts;
   1526 
   1527   Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
   1528 
   1529   OhciGetRootHubNumOfPorts (This, &NumOfPorts);
   1530   if (PortNumber >= NumOfPorts) {
   1531     return EFI_INVALID_PARAMETER;
   1532   }
   1533   PortStatus->PortStatus = 0;
   1534   PortStatus->PortChangeStatus = 0;
   1535 
   1536   if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_CURR_CONNECT_STAT)) {
   1537     PortStatus->PortStatus |= USB_PORT_STAT_CONNECTION;
   1538   }
   1539   if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_ENABLE_STAT)) {
   1540     PortStatus->PortStatus |= USB_PORT_STAT_ENABLE;
   1541   }
   1542   if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_SUSPEND_STAT)) {
   1543     PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND;
   1544   }
   1545   if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_OC_INDICATOR)) {
   1546     PortStatus->PortStatus |= USB_PORT_STAT_OVERCURRENT;
   1547   }
   1548   if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_RESET_STAT)) {
   1549     PortStatus->PortStatus |= USB_PORT_STAT_RESET;
   1550   }
   1551   if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_POWER_STAT)) {
   1552     PortStatus->PortStatus |= USB_PORT_STAT_POWER;
   1553   }
   1554   if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_LSDEVICE_ATTACHED)) {
   1555     PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;
   1556   }
   1557   if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE)) {
   1558     PortStatus->PortChangeStatus |= USB_PORT_STAT_C_ENABLE;
   1559   }
   1560   if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE)) {
   1561     PortStatus->PortChangeStatus |= USB_PORT_STAT_C_CONNECTION;
   1562   }
   1563   if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE)) {
   1564     PortStatus->PortChangeStatus |= USB_PORT_STAT_C_SUSPEND;
   1565   }
   1566   if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE)) {
   1567     PortStatus->PortChangeStatus |= USB_PORT_STAT_C_OVERCURRENT;
   1568   }
   1569   if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE)) {
   1570     PortStatus->PortChangeStatus |= USB_PORT_STAT_C_RESET;
   1571   }
   1572 
   1573   return EFI_SUCCESS;
   1574 }
   1575 /**
   1576 
   1577   Sets a feature for the specified root hub port.
   1578 
   1579   @param  This                  A pointer to the EFI_USB_HC_PROTOCOL.
   1580   @param  PortNumber            Specifies the root hub port whose feature
   1581                                 is requested to be set.
   1582   @param  PortFeature           Indicates the feature selector associated
   1583                                 with the feature set request.
   1584 
   1585   @retval EFI_SUCCESS           The feature specified by PortFeature was set for the
   1586                                 USB root hub port specified by PortNumber.
   1587   @retval EFI_DEVICE_ERROR      Set feature failed because of hardware issue
   1588   @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
   1589 **/
   1590 EFI_STATUS
   1591 EFIAPI
   1592 OhciSetRootHubPortFeature (
   1593   IN EFI_USB_HC_PROTOCOL   *This,
   1594   IN UINT8                 PortNumber,
   1595   IN EFI_USB_PORT_FEATURE  PortFeature
   1596   )
   1597 {
   1598   USB_OHCI_HC_DEV         *Ohc;
   1599   EFI_STATUS              Status;
   1600   UINT8                   NumOfPorts;
   1601   UINTN                   RetryTimes;
   1602 
   1603   OhciGetRootHubNumOfPorts (This, &NumOfPorts);
   1604   if (PortNumber >= NumOfPorts) {
   1605     return EFI_INVALID_PARAMETER;
   1606   }
   1607 
   1608   Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
   1609 
   1610   Status = EFI_SUCCESS;
   1611 
   1612 
   1613   switch (PortFeature) {
   1614     case EfiUsbPortPower:
   1615       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_POWER);
   1616 
   1617       //
   1618       // Verify the state
   1619       //
   1620       RetryTimes = 0;
   1621       do {
   1622         gBS->Stall (1000);
   1623         RetryTimes++;
   1624       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_POWER_STAT) == 0 &&
   1625                RetryTimes < MAX_RETRY_TIMES);
   1626 
   1627       if (RetryTimes >= MAX_RETRY_TIMES) {
   1628         return EFI_DEVICE_ERROR;
   1629       }
   1630       break;
   1631 
   1632     case EfiUsbPortReset:
   1633       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_RESET);
   1634 
   1635       //
   1636       // Verify the state
   1637       //
   1638       RetryTimes = 0;
   1639       do {
   1640         gBS->Stall (1000);
   1641         RetryTimes++;
   1642       } while ((OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE) == 0 ||
   1643                 OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT) == 1) &&
   1644                RetryTimes < MAX_RETRY_TIMES);
   1645 
   1646       if (RetryTimes >= MAX_RETRY_TIMES) {
   1647         return EFI_DEVICE_ERROR;
   1648       }
   1649 
   1650       OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE);
   1651       break;
   1652 
   1653     case EfiUsbPortEnable:
   1654       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_ENABLE);
   1655 
   1656       //
   1657       // Verify the state
   1658       //
   1659       RetryTimes = 0;
   1660       do {
   1661         gBS->Stall (1000);
   1662         RetryTimes++;
   1663       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT) == 0 &&
   1664                RetryTimes < MAX_RETRY_TIMES);
   1665 
   1666       if (RetryTimes >= MAX_RETRY_TIMES) {
   1667         return EFI_DEVICE_ERROR;
   1668       }
   1669       break;
   1670 
   1671 
   1672     case EfiUsbPortSuspend:
   1673       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_SUSPEND);
   1674 
   1675       //
   1676       // Verify the state
   1677       //
   1678       RetryTimes = 0;
   1679       do {
   1680         gBS->Stall (1000);
   1681         RetryTimes++;
   1682       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT) == 0 &&
   1683                RetryTimes < MAX_RETRY_TIMES);
   1684 
   1685       if (RetryTimes >= MAX_RETRY_TIMES) {
   1686         return EFI_DEVICE_ERROR;
   1687       }
   1688       break;
   1689 
   1690     default:
   1691       return EFI_INVALID_PARAMETER;
   1692   }
   1693 
   1694   return Status;
   1695 }
   1696 
   1697 /**
   1698 
   1699   Clears a feature for the specified root hub port.
   1700 
   1701   @param  This                  A pointer to the EFI_USB_HC_PROTOCOL instance.
   1702   @param  PortNumber            Specifies the root hub port whose feature
   1703                                 is requested to be cleared.
   1704   @param  PortFeature           Indicates the feature selector associated with the
   1705                                 feature clear request.
   1706 
   1707   @retval EFI_SUCCESS           The feature specified by PortFeature was cleared for the
   1708                                 USB root hub port specified by PortNumber.
   1709   @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
   1710   @retval EFI_DEVICE_ERROR      Some error happened when clearing feature
   1711 **/
   1712 EFI_STATUS
   1713 EFIAPI
   1714 OhciClearRootHubPortFeature (
   1715   IN EFI_USB_HC_PROTOCOL   *This,
   1716   IN UINT8                 PortNumber,
   1717   IN EFI_USB_PORT_FEATURE  PortFeature
   1718   )
   1719 {
   1720   USB_OHCI_HC_DEV         *Ohc;
   1721   EFI_STATUS              Status;
   1722   UINT8                   NumOfPorts;
   1723   UINTN                   RetryTimes;
   1724 
   1725 
   1726   OhciGetRootHubNumOfPorts (This, &NumOfPorts);
   1727   if (PortNumber >= NumOfPorts) {
   1728     return EFI_INVALID_PARAMETER;
   1729   }
   1730 
   1731   Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
   1732 
   1733   Status = EFI_SUCCESS;
   1734 
   1735   switch (PortFeature) {
   1736     case EfiUsbPortEnable:
   1737       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_PORT_ENABLE);
   1738 
   1739       //
   1740       // Verify the state
   1741       //
   1742       RetryTimes = 0;
   1743       do {
   1744         gBS->Stall (1000);
   1745         RetryTimes++;
   1746       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT) == 1 &&
   1747                RetryTimes < MAX_RETRY_TIMES);
   1748 
   1749       if (RetryTimes >= MAX_RETRY_TIMES) {
   1750         return EFI_DEVICE_ERROR;
   1751       }
   1752       break;
   1753 
   1754     case EfiUsbPortSuspend:
   1755       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_SUSPEND_STATUS);
   1756 
   1757       //
   1758       // Verify the state
   1759       //
   1760       RetryTimes = 0;
   1761       do {
   1762         gBS->Stall (1000);
   1763         RetryTimes++;
   1764       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT) == 1 &&
   1765                RetryTimes < MAX_RETRY_TIMES);
   1766 
   1767       if (RetryTimes >= MAX_RETRY_TIMES) {
   1768         return EFI_DEVICE_ERROR;
   1769       }
   1770       break;
   1771 
   1772     case EfiUsbPortReset:
   1773       break;
   1774 
   1775     case EfiUsbPortPower:
   1776       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_PORT_POWER);
   1777 
   1778       //
   1779       // Verify the state
   1780       //
   1781       RetryTimes = 0;
   1782       do {
   1783         gBS->Stall (1000);
   1784         RetryTimes++;
   1785       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_POWER_STAT) == 1 &&
   1786                RetryTimes < MAX_RETRY_TIMES);
   1787 
   1788       if (RetryTimes >= MAX_RETRY_TIMES) {
   1789         return EFI_DEVICE_ERROR;
   1790       }
   1791       break;
   1792 
   1793     case EfiUsbPortConnectChange:
   1794       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE);
   1795 
   1796       //
   1797       // Verify the state
   1798       //
   1799       RetryTimes = 0;
   1800       do {
   1801         gBS->Stall (1000);
   1802         RetryTimes++;
   1803       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE) == 1 &&
   1804                RetryTimes < MAX_RETRY_TIMES);
   1805 
   1806       if (RetryTimes >= MAX_RETRY_TIMES) {
   1807         return EFI_DEVICE_ERROR;
   1808       }
   1809       break;
   1810 
   1811     case EfiUsbPortResetChange:
   1812       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE);
   1813 
   1814       //
   1815       // Verify the state
   1816       //
   1817       RetryTimes = 0;
   1818       do {
   1819         gBS->Stall (1000);
   1820         RetryTimes++;
   1821       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE) == 1 &&
   1822                RetryTimes < MAX_RETRY_TIMES);
   1823 
   1824       if (RetryTimes >= MAX_RETRY_TIMES) {
   1825         return EFI_DEVICE_ERROR;
   1826       }
   1827       break;
   1828 
   1829 
   1830     case EfiUsbPortEnableChange:
   1831       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE);
   1832 
   1833       //
   1834       // Verify the state
   1835       //
   1836       RetryTimes = 0;
   1837       do {
   1838         gBS->Stall (1000);
   1839         RetryTimes++;
   1840       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE) == 1 &&
   1841                RetryTimes < MAX_RETRY_TIMES);
   1842 
   1843       if (RetryTimes >= MAX_RETRY_TIMES) {
   1844         return EFI_DEVICE_ERROR;
   1845       }
   1846       break;
   1847 
   1848     case EfiUsbPortSuspendChange:
   1849       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE);
   1850 
   1851       //
   1852       // Verify the state
   1853       //
   1854       RetryTimes = 0;
   1855       do {
   1856         gBS->Stall (1000);
   1857         RetryTimes++;
   1858       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE) == 1 &&
   1859                RetryTimes < MAX_RETRY_TIMES);
   1860 
   1861       if (RetryTimes >= MAX_RETRY_TIMES) {
   1862         return EFI_DEVICE_ERROR;
   1863       }
   1864       break;
   1865 
   1866     case EfiUsbPortOverCurrentChange:
   1867       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE);
   1868 
   1869       //
   1870       // Verify the state
   1871       //
   1872       RetryTimes = 0;
   1873       do {
   1874         gBS->Stall (1000);
   1875         RetryTimes++;
   1876       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE) == 1 &&
   1877                RetryTimes < MAX_RETRY_TIMES);
   1878 
   1879       if (RetryTimes >= MAX_RETRY_TIMES) {
   1880         return EFI_DEVICE_ERROR;
   1881       }
   1882       break;
   1883 
   1884     default:
   1885       return EFI_INVALID_PARAMETER;
   1886   }
   1887 
   1888   return Status;
   1889 }
   1890 
   1891 EFI_DRIVER_BINDING_PROTOCOL gOhciDriverBinding = {
   1892   OHCIDriverBindingSupported,
   1893   OHCIDriverBindingStart,
   1894   OHCIDriverBindingStop,
   1895   0x10,
   1896   NULL,
   1897   NULL
   1898 };
   1899 
   1900 
   1901 /**
   1902   Entry point for EFI drivers.
   1903 
   1904   @param  ImageHandle           EFI_HANDLE.
   1905   @param  SystemTable           EFI_SYSTEM_TABLE.
   1906 
   1907   @retval EFI_SUCCESS           Driver is successfully loaded.
   1908   @return Others                Failed.
   1909 
   1910 **/
   1911 EFI_STATUS
   1912 EFIAPI
   1913 OHCIDriverEntryPoint (
   1914   IN EFI_HANDLE          ImageHandle,
   1915   IN EFI_SYSTEM_TABLE    *SystemTable
   1916   )
   1917 {
   1918   return EfiLibInstallDriverBindingComponentName2 (
   1919            ImageHandle,
   1920            SystemTable,
   1921            &gOhciDriverBinding,
   1922            ImageHandle,
   1923            &gOhciComponentName,
   1924            &gOhciComponentName2
   1925            );
   1926 }
   1927 
   1928 
   1929 /**
   1930   Test to see if this driver supports ControllerHandle. Any
   1931   ControllerHandle that has UsbHcProtocol installed will be supported.
   1932 
   1933   @param  This                 Protocol instance pointer.
   1934   @param  Controller           Handle of device to test.
   1935   @param  RemainingDevicePath  Not used.
   1936 
   1937   @return EFI_SUCCESS          This driver supports this device.
   1938   @return EFI_UNSUPPORTED      This driver does not support this device.
   1939 
   1940 **/
   1941 EFI_STATUS
   1942 EFIAPI
   1943 OHCIDriverBindingSupported (
   1944   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
   1945   IN EFI_HANDLE                   Controller,
   1946   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
   1947   )
   1948 {
   1949   EFI_STATUS              Status;
   1950   EFI_PCI_IO_PROTOCOL     *PciIo;
   1951   USB_CLASSC              UsbClassCReg;
   1952   //
   1953   // Test whether there is PCI IO Protocol attached on the controller handle.
   1954   //
   1955   Status = gBS->OpenProtocol (
   1956                   Controller,
   1957                   &gEfiPciIoProtocolGuid,
   1958                   (VOID **) &PciIo,
   1959                   This->DriverBindingHandle,
   1960                   Controller,
   1961                   EFI_OPEN_PROTOCOL_BY_DRIVER
   1962                   );
   1963 
   1964   if (EFI_ERROR (Status)) {
   1965     return EFI_UNSUPPORTED;
   1966   }
   1967 
   1968   Status = PciIo->Pci.Read (
   1969                         PciIo,
   1970                         EfiPciIoWidthUint8,
   1971                         PCI_CLASSCODE_OFFSET,
   1972                         sizeof (USB_CLASSC) / sizeof (UINT8),
   1973                         &UsbClassCReg
   1974                         );
   1975 
   1976   if (EFI_ERROR (Status)) {
   1977     Status = EFI_UNSUPPORTED;
   1978     goto ON_EXIT;
   1979   }
   1980   //
   1981   // Test whether the controller belongs to OHCI type
   1982   //
   1983   if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) ||
   1984       (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) ||
   1985       (UsbClassCReg.ProgInterface != PCI_IF_OHCI)
   1986       ) {
   1987 
   1988     Status = EFI_UNSUPPORTED;
   1989   }
   1990 ON_EXIT:
   1991   gBS->CloseProtocol (
   1992          Controller,
   1993          &gEfiPciIoProtocolGuid,
   1994          This->DriverBindingHandle,
   1995          Controller
   1996          );
   1997 
   1998   return Status;
   1999 
   2000 }
   2001 
   2002 /**
   2003 
   2004   Allocate and initialize the empty OHCI device.
   2005 
   2006   @param  PciIo                  The PCIIO to use.
   2007   @param  OriginalPciAttributes  The original PCI attributes.
   2008 
   2009   @return Allocated OHCI device  If err, return NULL.
   2010 
   2011 **/
   2012 
   2013 USB_OHCI_HC_DEV *
   2014 OhciAllocateDev (
   2015   IN EFI_PCI_IO_PROTOCOL  *PciIo,
   2016   IN UINT64               OriginalPciAttributes
   2017   )
   2018 {
   2019   USB_OHCI_HC_DEV         *Ohc;
   2020   EFI_STATUS              Status;
   2021   VOID                    *Buf;
   2022   EFI_PHYSICAL_ADDRESS    PhyAddr;
   2023   VOID                    *Map;
   2024   UINTN                   Pages;
   2025   UINTN                   Bytes;
   2026 
   2027   Ohc = AllocateZeroPool (sizeof (USB_OHCI_HC_DEV));
   2028   if (Ohc == NULL) {
   2029     return NULL;
   2030   }
   2031 
   2032   Ohc->Signature                      = USB_OHCI_HC_DEV_SIGNATURE;
   2033   Ohc->PciIo                          = PciIo;
   2034 
   2035   Ohc->UsbHc.Reset                    = OhciReset;
   2036   Ohc->UsbHc.GetState                 = OhciGetState;
   2037   Ohc->UsbHc.SetState                 = OhciSetState;
   2038   Ohc->UsbHc.ControlTransfer          = OhciControlTransfer;
   2039   Ohc->UsbHc.BulkTransfer             = OhciBulkTransfer;
   2040   Ohc->UsbHc.AsyncInterruptTransfer   = OhciAsyncInterruptTransfer;
   2041   Ohc->UsbHc.SyncInterruptTransfer    = OhciSyncInterruptTransfer;
   2042   Ohc->UsbHc.IsochronousTransfer      = OhciIsochronousTransfer;
   2043   Ohc->UsbHc.AsyncIsochronousTransfer = OhciAsyncIsochronousTransfer;
   2044   Ohc->UsbHc.GetRootHubPortNumber     = OhciGetRootHubNumOfPorts;
   2045   Ohc->UsbHc.GetRootHubPortStatus     = OhciGetRootHubPortStatus;
   2046   Ohc->UsbHc.SetRootHubPortFeature    = OhciSetRootHubPortFeature;
   2047   Ohc->UsbHc.ClearRootHubPortFeature  = OhciClearRootHubPortFeature;
   2048   Ohc->UsbHc.MajorRevision            = 0x1;
   2049   Ohc->UsbHc.MinorRevision            = 0x1;
   2050 
   2051   Ohc->OriginalPciAttributes = OriginalPciAttributes;
   2052 
   2053   Ohc->HccaMemoryBlock = NULL;
   2054   Ohc->HccaMemoryMapping   = NULL;
   2055   Ohc->HccaMemoryBuf = NULL;
   2056   Ohc->HccaMemoryPages = 0;
   2057   Ohc->InterruptContextList = NULL;
   2058   Ohc->ControllerNameTable = NULL;
   2059   Ohc->HouseKeeperTimer = NULL;
   2060 
   2061   Ohc->MemPool = UsbHcInitMemPool(PciIo, TRUE, 0);
   2062   if(Ohc->MemPool == NULL) {
   2063     goto FREE_DEV_BUFFER;
   2064   }
   2065 
   2066   Bytes = 4096;
   2067   Pages = EFI_SIZE_TO_PAGES (Bytes);
   2068 
   2069   Status = PciIo->AllocateBuffer (
   2070                     PciIo,
   2071                     AllocateAnyPages,
   2072                     EfiBootServicesData,
   2073                     Pages,
   2074                     &Buf,
   2075                     0
   2076                     );
   2077 
   2078   if (EFI_ERROR (Status)) {
   2079     goto FREE_MEM_POOL;
   2080   }
   2081 
   2082   Status = PciIo->Map (
   2083                     PciIo,
   2084                     EfiPciIoOperationBusMasterCommonBuffer,
   2085                     Buf,
   2086                     &Bytes,
   2087                     &PhyAddr,
   2088                     &Map
   2089                     );
   2090 
   2091   if (EFI_ERROR (Status) || (Bytes != 4096)) {
   2092     goto FREE_MEM_PAGE;
   2093   }
   2094 
   2095   Ohc->HccaMemoryBlock = (HCCA_MEMORY_BLOCK *)(UINTN)PhyAddr;
   2096   Ohc->HccaMemoryMapping = Map;
   2097   Ohc->HccaMemoryBuf = (VOID *)(UINTN)Buf;
   2098   Ohc->HccaMemoryPages = Pages;
   2099 
   2100   return Ohc;
   2101 
   2102 FREE_MEM_PAGE:
   2103   PciIo->FreeBuffer (PciIo, Pages, Buf);
   2104 FREE_MEM_POOL:
   2105   UsbHcFreeMemPool (Ohc->MemPool);
   2106 FREE_DEV_BUFFER:
   2107   FreePool(Ohc);
   2108 
   2109   return NULL;
   2110 }
   2111 /**
   2112 
   2113   Free the OHCI device and release its associated resources.
   2114 
   2115   @param  Ohc                   The OHCI device to release.
   2116 
   2117 **/
   2118 VOID
   2119 OhciFreeDev (
   2120   IN USB_OHCI_HC_DEV      *Ohc
   2121   )
   2122 {
   2123   OhciFreeFixedIntMemory (Ohc);
   2124 
   2125   if (Ohc->HouseKeeperTimer != NULL) {
   2126     gBS->CloseEvent (Ohc->HouseKeeperTimer);
   2127   }
   2128 
   2129   if (Ohc->ExitBootServiceEvent != NULL) {
   2130     gBS->CloseEvent (Ohc->ExitBootServiceEvent);
   2131   }
   2132 
   2133   if (Ohc->MemPool != NULL) {
   2134     UsbHcFreeMemPool (Ohc->MemPool);
   2135   }
   2136 
   2137   if (Ohc->HccaMemoryMapping != NULL ) {
   2138     Ohc->PciIo->FreeBuffer (Ohc->PciIo, Ohc->HccaMemoryPages, Ohc->HccaMemoryBuf);
   2139   }
   2140 
   2141   if (Ohc->ControllerNameTable != NULL) {
   2142     FreeUnicodeStringTable (Ohc->ControllerNameTable);
   2143   }
   2144 
   2145   FreePool (Ohc);
   2146 }
   2147 /**
   2148 
   2149   Uninstall all Ohci Interface.
   2150 
   2151   @param  Controller            Controller handle.
   2152   @param  This                  Protocol instance pointer.
   2153 
   2154 **/
   2155 VOID
   2156 OhciCleanDevUp (
   2157   IN  EFI_HANDLE           Controller,
   2158   IN  EFI_USB_HC_PROTOCOL  *This
   2159   )
   2160 {
   2161   USB_OHCI_HC_DEV  *Ohc;
   2162 
   2163   //
   2164   // Retrieve private context structure
   2165   //
   2166   Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
   2167 
   2168   //
   2169   // Uninstall the USB_HC and USB_HC2 protocol
   2170   //
   2171   gBS->UninstallProtocolInterface (
   2172          Controller,
   2173          &gEfiUsbHcProtocolGuid,
   2174          &Ohc->UsbHc
   2175          );
   2176 
   2177   //
   2178   // Cancel the timer event
   2179   //
   2180   gBS->SetTimer (Ohc->HouseKeeperTimer, TimerCancel, 0);
   2181 
   2182   //
   2183   // Stop the host controller
   2184   //
   2185   OhciSetHcControl (Ohc, PERIODIC_ENABLE | CONTROL_ENABLE | ISOCHRONOUS_ENABLE | BULK_ENABLE, 0);
   2186   This->Reset (This, EFI_USB_HC_RESET_GLOBAL);
   2187   This->SetState (This, EfiUsbHcStateHalt);
   2188 
   2189   //
   2190   // Free resources
   2191   //
   2192   OhciFreeDynamicIntMemory (Ohc);
   2193 
   2194   //
   2195   // Restore original PCI attributes
   2196   //
   2197   Ohc->PciIo->Attributes (
   2198                 Ohc->PciIo,
   2199                 EfiPciIoAttributeOperationSet,
   2200                 Ohc->OriginalPciAttributes,
   2201                 NULL
   2202                 );
   2203 
   2204   //
   2205   // Free the private context structure
   2206   //
   2207   OhciFreeDev (Ohc);
   2208 }
   2209 
   2210 /**
   2211 
   2212   One notified function to stop the Host Controller when gBS->ExitBootServices() called.
   2213 
   2214   @param  Event                 Pointer to this event
   2215   @param  Context               Event hanlder private data
   2216 **/
   2217 VOID
   2218 EFIAPI
   2219 OhcExitBootService (
   2220   EFI_EVENT                      Event,
   2221   VOID                           *Context
   2222   )
   2223 {
   2224   USB_OHCI_HC_DEV           *Ohc;
   2225   EFI_USB_HC_PROTOCOL       *UsbHc;
   2226   Ohc = (USB_OHCI_HC_DEV *) Context;
   2227 
   2228   UsbHc = &Ohc->UsbHc;
   2229   //
   2230   // Stop the Host Controller
   2231   //
   2232   //OhciStopHc (Ohc, OHC_GENERIC_TIMEOUT);
   2233   OhciSetHcControl (Ohc, PERIODIC_ENABLE | CONTROL_ENABLE | ISOCHRONOUS_ENABLE | BULK_ENABLE, 0);
   2234   UsbHc->Reset (UsbHc, EFI_USB_HC_RESET_GLOBAL);
   2235   UsbHc->SetState (UsbHc, EfiUsbHcStateHalt);
   2236 
   2237   return;
   2238 }
   2239 
   2240 
   2241 /**
   2242   Starting the Usb OHCI Driver.
   2243 
   2244   @param  This                  Protocol instance pointer.
   2245   @param  Controller            Handle of device to test.
   2246   @param  RemainingDevicePath   Not used.
   2247 
   2248   @retval EFI_SUCCESS           This driver supports this device.
   2249   @retval EFI_UNSUPPORTED       This driver does not support this device.
   2250   @retval EFI_DEVICE_ERROR      This driver cannot be started due to device Error.
   2251                                 EFI_OUT_OF_RESOURCES- Failed due to resource shortage.
   2252 
   2253 **/
   2254 EFI_STATUS
   2255 EFIAPI
   2256 OHCIDriverBindingStart (
   2257   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
   2258   IN EFI_HANDLE                   Controller,
   2259   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
   2260   )
   2261 {
   2262   EFI_STATUS              Status;
   2263   EFI_PCI_IO_PROTOCOL     *PciIo;
   2264   USB_OHCI_HC_DEV         *Ohc;
   2265   UINT64                  Supports;
   2266   UINT64                  OriginalPciAttributes;
   2267   BOOLEAN                 PciAttributesSaved;
   2268 
   2269   //
   2270   // Open PCIIO, then enable the HC device and turn off emulation
   2271   //
   2272   Ohc = NULL;
   2273   Status = gBS->OpenProtocol (
   2274                   Controller,
   2275                   &gEfiPciIoProtocolGuid,
   2276                   (VOID **) &PciIo,
   2277                   This->DriverBindingHandle,
   2278                   Controller,
   2279                   EFI_OPEN_PROTOCOL_BY_DRIVER
   2280                   );
   2281 
   2282   if (EFI_ERROR (Status)) {
   2283     return Status;
   2284   }
   2285 
   2286   PciAttributesSaved = FALSE;
   2287   //
   2288   // Save original PCI attributes
   2289   //
   2290   Status = PciIo->Attributes (
   2291                     PciIo,
   2292                     EfiPciIoAttributeOperationGet,
   2293                     0,
   2294                     &OriginalPciAttributes
   2295                     );
   2296 
   2297   if (EFI_ERROR (Status)) {
   2298     goto CLOSE_PCIIO;
   2299   }
   2300   PciAttributesSaved = TRUE;
   2301 
   2302   //
   2303   // Robustnesss improvement such as for UoL
   2304   // Default is not required.
   2305   //
   2306   //if (FeaturePcdGet (PcdTurnOffUsbLegacySupport)) {
   2307   //  OhciTurnOffUsbEmulation (PciIo);
   2308   //}
   2309 
   2310   Status = PciIo->Attributes (
   2311                     PciIo,
   2312                     EfiPciIoAttributeOperationSupported,
   2313                     0,
   2314                     &Supports
   2315                     );
   2316   if (!EFI_ERROR (Status)) {
   2317     Supports &= EFI_PCI_DEVICE_ENABLE;
   2318     Status = PciIo->Attributes (
   2319                       PciIo,
   2320                       EfiPciIoAttributeOperationEnable,
   2321                       Supports,
   2322                       NULL
   2323                       );
   2324   }
   2325 
   2326   if (EFI_ERROR (Status)) {
   2327     goto CLOSE_PCIIO;
   2328   }
   2329   //
   2330   //Allocate memory for OHC private data structure
   2331   //
   2332   Ohc = OhciAllocateDev(PciIo, OriginalPciAttributes);
   2333   if (Ohc == NULL){
   2334     Status = EFI_OUT_OF_RESOURCES;
   2335     goto CLOSE_PCIIO;
   2336   }
   2337 
   2338   //Status = OhciInitializeInterruptList ( Uhc );
   2339   //if (EFI_ERROR (Status)) {
   2340   //  goto FREE_OHC;
   2341   //}
   2342 
   2343   //
   2344   // Set 0.01 s timer
   2345   //
   2346   Status = gBS->CreateEvent (
   2347                   EVT_TIMER | EVT_NOTIFY_SIGNAL,
   2348                   TPL_NOTIFY,
   2349                   OhciHouseKeeper,
   2350                   Ohc,
   2351                   &Ohc->HouseKeeperTimer
   2352                   );
   2353   if (EFI_ERROR (Status)) {
   2354     goto FREE_OHC;
   2355   }
   2356 
   2357   Status = gBS->SetTimer (Ohc->HouseKeeperTimer, TimerPeriodic, 10 * 1000 * 10);
   2358   if (EFI_ERROR (Status)) {
   2359     goto FREE_OHC;
   2360   }
   2361 
   2362   //
   2363   //Install Host Controller Protocol
   2364   //
   2365   Status = gBS->InstallProtocolInterface (
   2366                   &Controller,
   2367                   &gEfiUsbHcProtocolGuid,
   2368                   EFI_NATIVE_INTERFACE,
   2369                   &Ohc->UsbHc
   2370                   );
   2371   if (EFI_ERROR (Status)) {
   2372     DEBUG ((EFI_D_INFO, "Install protocol error"));
   2373     goto FREE_OHC;
   2374   }
   2375   //
   2376   // Create event to stop the HC when exit boot service.
   2377   //
   2378   Status = gBS->CreateEventEx (
   2379                   EVT_NOTIFY_SIGNAL,
   2380                   TPL_NOTIFY,
   2381                   OhcExitBootService,
   2382                   Ohc,
   2383                   &gEfiEventExitBootServicesGuid,
   2384                   &Ohc->ExitBootServiceEvent
   2385                   );
   2386   if (EFI_ERROR (Status)) {
   2387     DEBUG ((EFI_D_INFO, "Create exit boot event error"));
   2388     goto UNINSTALL_USBHC;
   2389   }
   2390   AddUnicodeString2 (
   2391     "eng",
   2392     gOhciComponentName.SupportedLanguages,
   2393     &Ohc->ControllerNameTable,
   2394     L"Usb Universal Host Controller",
   2395     TRUE
   2396     );
   2397   AddUnicodeString2 (
   2398     "en",
   2399     gOhciComponentName2.SupportedLanguages,
   2400     &Ohc->ControllerNameTable,
   2401     L"Usb Universal Host Controller",
   2402     FALSE
   2403     );
   2404 
   2405   return EFI_SUCCESS;
   2406 
   2407 UNINSTALL_USBHC:
   2408   gBS->UninstallMultipleProtocolInterfaces (
   2409          Controller,
   2410          &gEfiUsbHcProtocolGuid,
   2411          &Ohc->UsbHc,
   2412          NULL
   2413          );
   2414 
   2415 FREE_OHC:
   2416   OhciFreeDev (Ohc);
   2417 
   2418 CLOSE_PCIIO:
   2419   if (PciAttributesSaved) {
   2420   //
   2421   // Restore original PCI attributes
   2422   //
   2423     PciIo->Attributes (
   2424              PciIo,
   2425              EfiPciIoAttributeOperationSet,
   2426              OriginalPciAttributes,
   2427              NULL
   2428              );
   2429   }
   2430 
   2431   gBS->CloseProtocol (
   2432          Controller,
   2433          &gEfiPciIoProtocolGuid,
   2434          This->DriverBindingHandle,
   2435          Controller
   2436          );
   2437   return Status;
   2438 }
   2439 
   2440 /**
   2441   Stop this driver on ControllerHandle. Support stoping any child handles
   2442   created by this driver.
   2443 
   2444   @param  This                  Protocol instance pointer.
   2445   @param  Controller            Handle of device to stop driver on.
   2446   @param  NumberOfChildren      Number of Children in the ChildHandleBuffer.
   2447   @param  ChildHandleBuffer     List of handles for the children we need to stop.
   2448 
   2449   @return EFI_SUCCESS
   2450   @return others
   2451 
   2452 **/
   2453 EFI_STATUS
   2454 EFIAPI
   2455 OHCIDriverBindingStop (
   2456   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
   2457   IN EFI_HANDLE                   Controller,
   2458   IN UINTN                        NumberOfChildren,
   2459   IN EFI_HANDLE                   *ChildHandleBuffer
   2460   )
   2461 {
   2462   EFI_STATUS           Status;
   2463   EFI_USB_HC_PROTOCOL  *UsbHc;
   2464 
   2465   Status = gBS->OpenProtocol (
   2466                   Controller,
   2467                   &gEfiUsbHcProtocolGuid,
   2468                   (VOID **)&UsbHc,
   2469                   This->DriverBindingHandle,
   2470                   Controller,
   2471                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
   2472                   );
   2473   if (EFI_ERROR (Status)) {
   2474     return Status;
   2475   }
   2476 
   2477   OhciCleanDevUp(Controller, UsbHc);
   2478 
   2479   gBS->CloseProtocol (
   2480          Controller,
   2481          &gEfiPciIoProtocolGuid,
   2482          This->DriverBindingHandle,
   2483          Controller
   2484          );
   2485   return EFI_SUCCESS;
   2486 }
   2487 
   2488 
   2489