1/** @file
2This file contains the implementation of Usb Hc Protocol.
3
4Copyright (c) 2013-2015 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  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
839FREE_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
856FREE_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
914EFI_STATUS
915OhciInterruptTransfer (
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
1132FREE_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
1148UNMAP_OHCI_XBUFF:
1149  Ohc->PciIo->Unmap(Ohc->PciIo, Mapping);
1150
1151EXIT:
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
1204EFI_STATUS
1205EFIAPI
1206OhciAsyncInterruptTransfer (
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
1304EFI_STATUS
1305EFIAPI
1306OhciSyncInterruptTransfer (
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
1410EFI_STATUS
1411EFIAPI
1412OhciIsochronousTransfer (
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
1450EFI_STATUS
1451EFIAPI
1452OhciAsyncIsochronousTransfer (
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**/
1480EFI_STATUS
1481EFIAPI
1482OhciGetRootHubNumOfPorts (
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
1516EFI_STATUS
1517EFIAPI
1518OhciGetRootHubPortStatus (
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**/
1590EFI_STATUS
1591EFIAPI
1592OhciSetRootHubPortFeature (
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**/
1712EFI_STATUS
1713EFIAPI
1714OhciClearRootHubPortFeature (
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
1891EFI_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**/
1911EFI_STATUS
1912EFIAPI
1913OHCIDriverEntryPoint (
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**/
1941EFI_STATUS
1942EFIAPI
1943OHCIDriverBindingSupported (
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  }
1990ON_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
2013USB_OHCI_HC_DEV *
2014OhciAllocateDev (
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
2102FREE_MEM_PAGE:
2103  PciIo->FreeBuffer (PciIo, Pages, Buf);
2104FREE_MEM_POOL:
2105  UsbHcFreeMemPool (Ohc->MemPool);
2106FREE_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**/
2118VOID
2119OhciFreeDev (
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**/
2155VOID
2156OhciCleanDevUp (
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**/
2217VOID
2218EFIAPI
2219OhcExitBootService (
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**/
2254EFI_STATUS
2255EFIAPI
2256OHCIDriverBindingStart (
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
2407UNINSTALL_USBHC:
2408  gBS->UninstallMultipleProtocolInterfaces (
2409         Controller,
2410         &gEfiUsbHcProtocolGuid,
2411         &Ohc->UsbHc,
2412         NULL
2413         );
2414
2415FREE_OHC:
2416  OhciFreeDev (Ohc);
2417
2418CLOSE_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**/
2453EFI_STATUS
2454EFIAPI
2455OHCIDriverBindingStop (
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