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