1 /** @file
2   The Ehci controller driver.
3 
4   EhciDxe driver is responsible for managing the behavior of EHCI controller.
5   It implements the interfaces of monitoring the status of all ports and transferring
6   Control, Bulk, Interrupt and Isochronous requests to Usb2.0 device.
7 
8   Note that EhciDxe driver is enhanced to guarantee that the EHCI controller get attached
9   to the EHCI controller before a UHCI or OHCI driver attaches to the companion UHCI or
10   OHCI controller.  This way avoids the control transfer on a shared port between EHCI
11   and companion host controller when UHCI or OHCI gets attached earlier than EHCI and a
12   USB 2.0 device inserts.
13 
14 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
15 SPDX-License-Identifier: BSD-2-Clause-Patent
16 
17 **/
18 
19 
20 #include "Ehci.h"
21 
22 //
23 // Two arrays used to translate the EHCI port state (change)
24 // to the UEFI protocol's port state (change).
25 //
26 USB_PORT_STATE_MAP  mUsbPortStateMap[] = {
27   {PORTSC_CONN,     USB_PORT_STAT_CONNECTION},
28   {PORTSC_ENABLED,  USB_PORT_STAT_ENABLE},
29   {PORTSC_SUSPEND,  USB_PORT_STAT_SUSPEND},
30   {PORTSC_OVERCUR,  USB_PORT_STAT_OVERCURRENT},
31   {PORTSC_RESET,    USB_PORT_STAT_RESET},
32   {PORTSC_POWER,    USB_PORT_STAT_POWER},
33   {PORTSC_OWNER,    USB_PORT_STAT_OWNER}
34 };
35 
36 USB_PORT_STATE_MAP  mUsbPortChangeMap[] = {
37   {PORTSC_CONN_CHANGE,    USB_PORT_STAT_C_CONNECTION},
38   {PORTSC_ENABLE_CHANGE,  USB_PORT_STAT_C_ENABLE},
39   {PORTSC_OVERCUR_CHANGE, USB_PORT_STAT_C_OVERCURRENT}
40 };
41 
42 EFI_DRIVER_BINDING_PROTOCOL
43 gEhciDriverBinding = {
44   EhcDriverBindingSupported,
45   EhcDriverBindingStart,
46   EhcDriverBindingStop,
47   0x30,
48   NULL,
49   NULL
50 };
51 
52 /**
53   Retrieves the capability of root hub ports.
54 
55   @param  This                  This EFI_USB_HC_PROTOCOL instance.
56   @param  MaxSpeed              Max speed supported by the controller.
57   @param  PortNumber            Number of the root hub ports.
58   @param  Is64BitCapable        Whether the controller supports 64-bit memory
59                                 addressing.
60 
61   @retval EFI_SUCCESS           Host controller capability were retrieved successfully.
62   @retval EFI_INVALID_PARAMETER Either of the three capability pointer is NULL.
63 
64 **/
65 EFI_STATUS
66 EFIAPI
EhcGetCapability(IN EFI_USB2_HC_PROTOCOL * This,OUT UINT8 * MaxSpeed,OUT UINT8 * PortNumber,OUT UINT8 * Is64BitCapable)67 EhcGetCapability (
68   IN  EFI_USB2_HC_PROTOCOL  *This,
69   OUT UINT8                 *MaxSpeed,
70   OUT UINT8                 *PortNumber,
71   OUT UINT8                 *Is64BitCapable
72   )
73 {
74   USB2_HC_DEV             *Ehc;
75   EFI_TPL                 OldTpl;
76 
77   if ((MaxSpeed == NULL) || (PortNumber == NULL) || (Is64BitCapable == NULL)) {
78     return EFI_INVALID_PARAMETER;
79   }
80 
81   OldTpl          = gBS->RaiseTPL (EHC_TPL);
82   Ehc             = EHC_FROM_THIS (This);
83 
84   *MaxSpeed       = EFI_USB_SPEED_HIGH;
85   *PortNumber     = (UINT8) (Ehc->HcStructParams & HCSP_NPORTS);
86   *Is64BitCapable = (UINT8) Ehc->Support64BitDma;
87 
88   DEBUG ((EFI_D_INFO, "EhcGetCapability: %d ports, 64 bit %d\n", *PortNumber, *Is64BitCapable));
89 
90   gBS->RestoreTPL (OldTpl);
91   return EFI_SUCCESS;
92 }
93 
94 
95 /**
96   Provides software reset for the USB host controller.
97 
98   @param  This                  This EFI_USB2_HC_PROTOCOL instance.
99   @param  Attributes            A bit mask of the reset operation to perform.
100 
101   @retval EFI_SUCCESS           The reset operation succeeded.
102   @retval EFI_INVALID_PARAMETER Attributes is not valid.
103   @retval EFI_UNSUPPOURTED      The type of reset specified by Attributes is
104                                 not currently supported by the host controller.
105   @retval EFI_DEVICE_ERROR      Host controller isn't halted to reset.
106 
107 **/
108 EFI_STATUS
109 EFIAPI
EhcReset(IN EFI_USB2_HC_PROTOCOL * This,IN UINT16 Attributes)110 EhcReset (
111   IN EFI_USB2_HC_PROTOCOL *This,
112   IN UINT16               Attributes
113   )
114 {
115   USB2_HC_DEV             *Ehc;
116   EFI_TPL                 OldTpl;
117   EFI_STATUS              Status;
118 
119   Ehc = EHC_FROM_THIS (This);
120 
121   if (Ehc->DevicePath != NULL) {
122     //
123     // Report Status Code to indicate reset happens
124     //
125     REPORT_STATUS_CODE_WITH_DEVICE_PATH (
126       EFI_PROGRESS_CODE,
127       (EFI_IO_BUS_USB | EFI_IOB_PC_RESET),
128       Ehc->DevicePath
129       );
130   }
131 
132   OldTpl  = gBS->RaiseTPL (EHC_TPL);
133 
134   switch (Attributes) {
135   case EFI_USB_HC_RESET_GLOBAL:
136   //
137   // Flow through, same behavior as Host Controller Reset
138   //
139   case EFI_USB_HC_RESET_HOST_CONTROLLER:
140     //
141     // Host Controller must be Halt when Reset it
142     //
143     if (EhcIsDebugPortInUse (Ehc, NULL)) {
144       Status = EFI_SUCCESS;
145       goto ON_EXIT;
146     }
147 
148     if (!EhcIsHalt (Ehc)) {
149       Status = EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);
150 
151       if (EFI_ERROR (Status)) {
152         Status = EFI_DEVICE_ERROR;
153         goto ON_EXIT;
154       }
155     }
156 
157     //
158     // Clean up the asynchronous transfers, currently only
159     // interrupt supports asynchronous operation.
160     //
161     EhciDelAllAsyncIntTransfers (Ehc);
162     EhcAckAllInterrupt (Ehc);
163     EhcFreeSched (Ehc);
164 
165     Status = EhcResetHC (Ehc, EHC_RESET_TIMEOUT);
166 
167     if (EFI_ERROR (Status)) {
168       goto ON_EXIT;
169     }
170 
171     Status = EhcInitHC (Ehc);
172     break;
173 
174   case EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG:
175   case EFI_USB_HC_RESET_HOST_WITH_DEBUG:
176     Status = EFI_UNSUPPORTED;
177     break;
178 
179   default:
180     Status = EFI_INVALID_PARAMETER;
181   }
182 
183 ON_EXIT:
184   DEBUG ((EFI_D_INFO, "EhcReset: exit status %r\n", Status));
185   gBS->RestoreTPL (OldTpl);
186   return Status;
187 }
188 
189 
190 /**
191   Retrieve the current state of the USB host controller.
192 
193   @param  This                   This EFI_USB2_HC_PROTOCOL instance.
194   @param  State                  Variable to return the current host controller
195                                  state.
196 
197   @retval EFI_SUCCESS            Host controller state was returned in State.
198   @retval EFI_INVALID_PARAMETER  State is NULL.
199   @retval EFI_DEVICE_ERROR       An error was encountered while attempting to
200                                  retrieve the host controller's current state.
201 
202 **/
203 EFI_STATUS
204 EFIAPI
EhcGetState(IN EFI_USB2_HC_PROTOCOL * This,OUT EFI_USB_HC_STATE * State)205 EhcGetState (
206   IN   EFI_USB2_HC_PROTOCOL  *This,
207   OUT  EFI_USB_HC_STATE      *State
208   )
209 {
210   EFI_TPL                 OldTpl;
211   USB2_HC_DEV             *Ehc;
212 
213   if (State == NULL) {
214     return EFI_INVALID_PARAMETER;
215   }
216 
217   OldTpl  = gBS->RaiseTPL (EHC_TPL);
218   Ehc     = EHC_FROM_THIS (This);
219 
220   if (EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT)) {
221     *State = EfiUsbHcStateHalt;
222   } else {
223     *State = EfiUsbHcStateOperational;
224   }
225 
226   gBS->RestoreTPL (OldTpl);
227 
228   DEBUG ((EFI_D_INFO, "EhcGetState: current state %d\n", *State));
229   return EFI_SUCCESS;
230 }
231 
232 
233 /**
234   Sets the USB host controller to a specific state.
235 
236   @param  This                  This EFI_USB2_HC_PROTOCOL instance.
237   @param  State                 The state of the host controller that will be set.
238 
239   @retval EFI_SUCCESS           The USB host controller was successfully placed
240                                 in the state specified by State.
241   @retval EFI_INVALID_PARAMETER State is invalid.
242   @retval EFI_DEVICE_ERROR      Failed to set the state due to device error.
243 
244 **/
245 EFI_STATUS
246 EFIAPI
EhcSetState(IN EFI_USB2_HC_PROTOCOL * This,IN EFI_USB_HC_STATE State)247 EhcSetState (
248   IN EFI_USB2_HC_PROTOCOL *This,
249   IN EFI_USB_HC_STATE     State
250   )
251 {
252   USB2_HC_DEV             *Ehc;
253   EFI_TPL                 OldTpl;
254   EFI_STATUS              Status;
255   EFI_USB_HC_STATE        CurState;
256 
257   Status = EhcGetState (This, &CurState);
258 
259   if (EFI_ERROR (Status)) {
260     return EFI_DEVICE_ERROR;
261   }
262 
263   if (CurState == State) {
264     return EFI_SUCCESS;
265   }
266 
267   OldTpl  = gBS->RaiseTPL (EHC_TPL);
268   Ehc     = EHC_FROM_THIS (This);
269 
270   switch (State) {
271   case EfiUsbHcStateHalt:
272     Status = EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);
273     break;
274 
275   case EfiUsbHcStateOperational:
276     if (EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_SYS_ERROR)) {
277       Status = EFI_DEVICE_ERROR;
278       break;
279     }
280 
281     //
282     // Software must not write a one to this field unless the host controller
283     // is in the Halted state. Doing so will yield undefined results.
284     // refers to Spec[EHCI1.0-2.3.1]
285     //
286     if (!EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT)) {
287       Status = EFI_DEVICE_ERROR;
288       break;
289     }
290 
291     Status = EhcRunHC (Ehc, EHC_GENERIC_TIMEOUT);
292     break;
293 
294   case EfiUsbHcStateSuspend:
295     Status = EFI_UNSUPPORTED;
296     break;
297 
298   default:
299     Status = EFI_INVALID_PARAMETER;
300   }
301 
302   DEBUG ((EFI_D_INFO, "EhcSetState: exit status %r\n", Status));
303   gBS->RestoreTPL (OldTpl);
304   return Status;
305 }
306 
307 
308 /**
309   Retrieves the current status of a USB root hub port.
310 
311   @param  This                  This EFI_USB2_HC_PROTOCOL instance.
312   @param  PortNumber            The root hub port to retrieve the state from.
313                                 This value is zero-based.
314   @param  PortStatus            Variable to receive the port state.
315 
316   @retval EFI_SUCCESS           The status of the USB root hub port specified.
317                                 by PortNumber was returned in PortStatus.
318   @retval EFI_INVALID_PARAMETER PortNumber is invalid.
319   @retval EFI_DEVICE_ERROR      Can't read register.
320 
321 **/
322 EFI_STATUS
323 EFIAPI
EhcGetRootHubPortStatus(IN EFI_USB2_HC_PROTOCOL * This,IN UINT8 PortNumber,OUT EFI_USB_PORT_STATUS * PortStatus)324 EhcGetRootHubPortStatus (
325   IN   EFI_USB2_HC_PROTOCOL  *This,
326   IN   UINT8                 PortNumber,
327   OUT  EFI_USB_PORT_STATUS   *PortStatus
328   )
329 {
330   USB2_HC_DEV             *Ehc;
331   EFI_TPL                 OldTpl;
332   UINT32                  Offset;
333   UINT32                  State;
334   UINT32                  TotalPort;
335   UINTN                   Index;
336   UINTN                   MapSize;
337   EFI_STATUS              Status;
338 
339   if (PortStatus == NULL) {
340     return EFI_INVALID_PARAMETER;
341   }
342 
343   OldTpl    = gBS->RaiseTPL (EHC_TPL);
344 
345   Ehc       = EHC_FROM_THIS (This);
346   Status    = EFI_SUCCESS;
347 
348   TotalPort = (Ehc->HcStructParams & HCSP_NPORTS);
349 
350   if (PortNumber >= TotalPort) {
351     Status = EFI_INVALID_PARAMETER;
352     goto ON_EXIT;
353   }
354 
355   Offset                        = (UINT32) (EHC_PORT_STAT_OFFSET + (4 * PortNumber));
356   PortStatus->PortStatus        = 0;
357   PortStatus->PortChangeStatus  = 0;
358 
359   if (EhcIsDebugPortInUse (Ehc, &PortNumber)) {
360     goto ON_EXIT;
361   }
362 
363   State                         = EhcReadOpReg (Ehc, Offset);
364 
365   //
366   // Identify device speed. If in K state, it is low speed.
367   // If the port is enabled after reset, the device is of
368   // high speed. The USB bus driver should retrieve the actual
369   // port speed after reset.
370   //
371   if (EHC_BIT_IS_SET (State, PORTSC_LINESTATE_K)) {
372     PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;
373 
374   } else if (EHC_BIT_IS_SET (State, PORTSC_ENABLED)) {
375     PortStatus->PortStatus |= USB_PORT_STAT_HIGH_SPEED;
376   }
377 
378   //
379   // Convert the EHCI port/port change state to UEFI status
380   //
381   MapSize = sizeof (mUsbPortStateMap) / sizeof (USB_PORT_STATE_MAP);
382 
383   for (Index = 0; Index < MapSize; Index++) {
384     if (EHC_BIT_IS_SET (State, mUsbPortStateMap[Index].HwState)) {
385       PortStatus->PortStatus = (UINT16) (PortStatus->PortStatus | mUsbPortStateMap[Index].UefiState);
386     }
387   }
388 
389   MapSize = sizeof (mUsbPortChangeMap) / sizeof (USB_PORT_STATE_MAP);
390 
391   for (Index = 0; Index < MapSize; Index++) {
392     if (EHC_BIT_IS_SET (State, mUsbPortChangeMap[Index].HwState)) {
393       PortStatus->PortChangeStatus = (UINT16) (PortStatus->PortChangeStatus | mUsbPortChangeMap[Index].UefiState);
394     }
395   }
396 
397 ON_EXIT:
398   gBS->RestoreTPL (OldTpl);
399   return Status;
400 }
401 
402 
403 /**
404   Sets a feature for the specified root hub port.
405 
406   @param  This                  This EFI_USB2_HC_PROTOCOL instance.
407   @param  PortNumber            Root hub port to set.
408   @param  PortFeature           Feature to set.
409 
410   @retval EFI_SUCCESS           The feature specified by PortFeature was set.
411   @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
412   @retval EFI_DEVICE_ERROR      Can't read register.
413 
414 **/
415 EFI_STATUS
416 EFIAPI
EhcSetRootHubPortFeature(IN EFI_USB2_HC_PROTOCOL * This,IN UINT8 PortNumber,IN EFI_USB_PORT_FEATURE PortFeature)417 EhcSetRootHubPortFeature (
418   IN  EFI_USB2_HC_PROTOCOL  *This,
419   IN  UINT8                 PortNumber,
420   IN  EFI_USB_PORT_FEATURE  PortFeature
421   )
422 {
423   USB2_HC_DEV             *Ehc;
424   EFI_TPL                 OldTpl;
425   UINT32                  Offset;
426   UINT32                  State;
427   UINT32                  TotalPort;
428   EFI_STATUS              Status;
429 
430   OldTpl    = gBS->RaiseTPL (EHC_TPL);
431   Ehc       = EHC_FROM_THIS (This);
432   Status    = EFI_SUCCESS;
433 
434   TotalPort = (Ehc->HcStructParams & HCSP_NPORTS);
435 
436   if (PortNumber >= TotalPort) {
437     Status = EFI_INVALID_PARAMETER;
438     goto ON_EXIT;
439   }
440 
441   Offset  = (UINT32) (EHC_PORT_STAT_OFFSET + (4 * PortNumber));
442   State   = EhcReadOpReg (Ehc, Offset);
443 
444   //
445   // Mask off the port status change bits, these bits are
446   // write clean bit
447   //
448   State &= ~PORTSC_CHANGE_MASK;
449 
450   switch (PortFeature) {
451   case EfiUsbPortEnable:
452     //
453     // Sofeware can't set this bit, Port can only be enable by
454     // EHCI as a part of the reset and enable
455     //
456     State |= PORTSC_ENABLED;
457     EhcWriteOpReg (Ehc, Offset, State);
458     break;
459 
460   case EfiUsbPortSuspend:
461     State |= PORTSC_SUSPEND;
462     EhcWriteOpReg (Ehc, Offset, State);
463     break;
464 
465   case EfiUsbPortReset:
466     //
467     // Make sure Host Controller not halt before reset it
468     //
469     if (EhcIsHalt (Ehc)) {
470       Status = EhcRunHC (Ehc, EHC_GENERIC_TIMEOUT);
471 
472       if (EFI_ERROR (Status)) {
473         DEBUG ((EFI_D_INFO, "EhcSetRootHubPortFeature :failed to start HC - %r\n", Status));
474         break;
475       }
476     }
477 
478     //
479     // Set one to PortReset bit must also set zero to PortEnable bit
480     //
481     State |= PORTSC_RESET;
482     State &= ~PORTSC_ENABLED;
483     EhcWriteOpReg (Ehc, Offset, State);
484     break;
485 
486   case EfiUsbPortPower:
487     //
488     // Set port power bit when PPC is 1
489     //
490     if ((Ehc->HcCapParams & HCSP_PPC) == HCSP_PPC) {
491       State |= PORTSC_POWER;
492       EhcWriteOpReg (Ehc, Offset, State);
493     }
494     break;
495 
496   case EfiUsbPortOwner:
497     State |= PORTSC_OWNER;
498     EhcWriteOpReg (Ehc, Offset, State);
499     break;
500 
501   default:
502     Status = EFI_INVALID_PARAMETER;
503   }
504 
505 ON_EXIT:
506   DEBUG ((EFI_D_INFO, "EhcSetRootHubPortFeature: exit status %r\n", Status));
507 
508   gBS->RestoreTPL (OldTpl);
509   return Status;
510 }
511 
512 
513 /**
514   Clears a feature for the specified root hub port.
515 
516   @param  This                  A pointer to the EFI_USB2_HC_PROTOCOL instance.
517   @param  PortNumber            Specifies the root hub port whose feature is
518                                 requested to be cleared.
519   @param  PortFeature           Indicates the feature selector associated with the
520                                 feature clear request.
521 
522   @retval EFI_SUCCESS           The feature specified by PortFeature was cleared
523                                 for the USB root hub port specified by PortNumber.
524   @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
525   @retval EFI_DEVICE_ERROR      Can't read register.
526 
527 **/
528 EFI_STATUS
529 EFIAPI
EhcClearRootHubPortFeature(IN EFI_USB2_HC_PROTOCOL * This,IN UINT8 PortNumber,IN EFI_USB_PORT_FEATURE PortFeature)530 EhcClearRootHubPortFeature (
531   IN  EFI_USB2_HC_PROTOCOL  *This,
532   IN  UINT8                 PortNumber,
533   IN  EFI_USB_PORT_FEATURE  PortFeature
534   )
535 {
536   USB2_HC_DEV             *Ehc;
537   EFI_TPL                 OldTpl;
538   UINT32                  Offset;
539   UINT32                  State;
540   UINT32                  TotalPort;
541   EFI_STATUS              Status;
542 
543   OldTpl    = gBS->RaiseTPL (EHC_TPL);
544   Ehc       = EHC_FROM_THIS (This);
545   Status    = EFI_SUCCESS;
546 
547   TotalPort = (Ehc->HcStructParams & HCSP_NPORTS);
548 
549   if (PortNumber >= TotalPort) {
550     Status = EFI_INVALID_PARAMETER;
551     goto ON_EXIT;
552   }
553 
554   Offset  = EHC_PORT_STAT_OFFSET + (4 * PortNumber);
555   State   = EhcReadOpReg (Ehc, Offset);
556   State &= ~PORTSC_CHANGE_MASK;
557 
558   switch (PortFeature) {
559   case EfiUsbPortEnable:
560     //
561     // Clear PORT_ENABLE feature means disable port.
562     //
563     State &= ~PORTSC_ENABLED;
564     EhcWriteOpReg (Ehc, Offset, State);
565     break;
566 
567   case EfiUsbPortSuspend:
568     //
569     // A write of zero to this bit is ignored by the host
570     // controller. The host controller will unconditionally
571     // set this bit to a zero when:
572     //   1. software sets the Forct Port Resume bit to a zero from a one.
573     //   2. software sets the Port Reset bit to a one frome a zero.
574     //
575     State &= ~PORSTSC_RESUME;
576     EhcWriteOpReg (Ehc, Offset, State);
577     break;
578 
579   case EfiUsbPortReset:
580     //
581     // Clear PORT_RESET means clear the reset signal.
582     //
583     State &= ~PORTSC_RESET;
584     EhcWriteOpReg (Ehc, Offset, State);
585     break;
586 
587   case EfiUsbPortOwner:
588     //
589     // Clear port owner means this port owned by EHC
590     //
591     State &= ~PORTSC_OWNER;
592     EhcWriteOpReg (Ehc, Offset, State);
593     break;
594 
595   case EfiUsbPortConnectChange:
596     //
597     // Clear connect status change
598     //
599     State |= PORTSC_CONN_CHANGE;
600     EhcWriteOpReg (Ehc, Offset, State);
601     break;
602 
603   case EfiUsbPortEnableChange:
604     //
605     // Clear enable status change
606     //
607     State |= PORTSC_ENABLE_CHANGE;
608     EhcWriteOpReg (Ehc, Offset, State);
609     break;
610 
611   case EfiUsbPortOverCurrentChange:
612     //
613     // Clear PortOverCurrent change
614     //
615     State |= PORTSC_OVERCUR_CHANGE;
616     EhcWriteOpReg (Ehc, Offset, State);
617     break;
618 
619   case EfiUsbPortPower:
620     //
621     // Clear port power bit when PPC is 1
622     //
623     if ((Ehc->HcCapParams & HCSP_PPC) == HCSP_PPC) {
624       State &= ~PORTSC_POWER;
625       EhcWriteOpReg (Ehc, Offset, State);
626     }
627     break;
628   case EfiUsbPortSuspendChange:
629   case EfiUsbPortResetChange:
630     //
631     // Not supported or not related operation
632     //
633     break;
634 
635   default:
636     Status = EFI_INVALID_PARAMETER;
637     break;
638   }
639 
640 ON_EXIT:
641   DEBUG ((EFI_D_INFO, "EhcClearRootHubPortFeature: exit status %r\n", Status));
642   gBS->RestoreTPL (OldTpl);
643   return Status;
644 }
645 
646 
647 /**
648   Submits control transfer to a target USB device.
649 
650   @param  This                  This EFI_USB2_HC_PROTOCOL instance.
651   @param  DeviceAddress         The target device address.
652   @param  DeviceSpeed           Target device speed.
653   @param  MaximumPacketLength   Maximum packet size the default control transfer
654                                 endpoint is capable of sending or receiving.
655   @param  Request               USB device request to send.
656   @param  TransferDirection     Specifies the data direction for the data stage
657   @param  Data                  Data buffer to be transmitted or received from USB
658                                 device.
659   @param  DataLength            The size (in bytes) of the data buffer.
660   @param  TimeOut               Indicates the maximum timeout, in millisecond.
661   @param  Translator            Transaction translator to be used by this device.
662   @param  TransferResult        Return the result of this control transfer.
663 
664   @retval EFI_SUCCESS           Transfer was completed successfully.
665   @retval EFI_OUT_OF_RESOURCES  The transfer failed due to lack of resources.
666   @retval EFI_INVALID_PARAMETER Some parameters are invalid.
667   @retval EFI_TIMEOUT           Transfer failed due to timeout.
668   @retval EFI_DEVICE_ERROR      Transfer failed due to host controller or device error.
669 
670 **/
671 EFI_STATUS
672 EFIAPI
EhcControlTransfer(IN EFI_USB2_HC_PROTOCOL * This,IN UINT8 DeviceAddress,IN UINT8 DeviceSpeed,IN UINTN MaximumPacketLength,IN EFI_USB_DEVICE_REQUEST * Request,IN EFI_USB_DATA_DIRECTION TransferDirection,IN OUT VOID * Data,IN OUT UINTN * DataLength,IN UINTN TimeOut,IN EFI_USB2_HC_TRANSACTION_TRANSLATOR * Translator,OUT UINT32 * TransferResult)673 EhcControlTransfer (
674   IN  EFI_USB2_HC_PROTOCOL                *This,
675   IN  UINT8                               DeviceAddress,
676   IN  UINT8                               DeviceSpeed,
677   IN  UINTN                               MaximumPacketLength,
678   IN  EFI_USB_DEVICE_REQUEST              *Request,
679   IN  EFI_USB_DATA_DIRECTION              TransferDirection,
680   IN  OUT VOID                            *Data,
681   IN  OUT UINTN                           *DataLength,
682   IN  UINTN                               TimeOut,
683   IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
684   OUT UINT32                              *TransferResult
685   )
686 {
687   USB2_HC_DEV             *Ehc;
688   URB                     *Urb;
689   EFI_TPL                 OldTpl;
690   UINT8                   Endpoint;
691   EFI_STATUS              Status;
692 
693   //
694   // Validate parameters
695   //
696   if ((Request == NULL) || (TransferResult == NULL)) {
697     return EFI_INVALID_PARAMETER;
698   }
699 
700   if ((TransferDirection != EfiUsbDataIn) &&
701       (TransferDirection != EfiUsbDataOut) &&
702       (TransferDirection != EfiUsbNoData)) {
703     return EFI_INVALID_PARAMETER;
704   }
705 
706   if ((TransferDirection == EfiUsbNoData) &&
707       ((Data != NULL) || (*DataLength != 0))) {
708     return EFI_INVALID_PARAMETER;
709   }
710 
711   if ((TransferDirection != EfiUsbNoData) &&
712      ((Data == NULL) || (*DataLength == 0))) {
713     return EFI_INVALID_PARAMETER;
714   }
715 
716   if ((MaximumPacketLength != 8)  && (MaximumPacketLength != 16) &&
717       (MaximumPacketLength != 32) && (MaximumPacketLength != 64)) {
718     return EFI_INVALID_PARAMETER;
719   }
720 
721   if ((DeviceSpeed == EFI_USB_SPEED_LOW) && (MaximumPacketLength != 8)) {
722     return EFI_INVALID_PARAMETER;
723   }
724 
725   OldTpl          = gBS->RaiseTPL (EHC_TPL);
726   Ehc             = EHC_FROM_THIS (This);
727 
728   Status          = EFI_DEVICE_ERROR;
729   *TransferResult = EFI_USB_ERR_SYSTEM;
730 
731   if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {
732     DEBUG ((EFI_D_ERROR, "EhcControlTransfer: HC halted at entrance\n"));
733 
734     EhcAckAllInterrupt (Ehc);
735     goto ON_EXIT;
736   }
737 
738   EhcAckAllInterrupt (Ehc);
739 
740   //
741   // Create a new URB, insert it into the asynchronous
742   // schedule list, then poll the execution status.
743   //
744   //
745   // Encode the direction in address, although default control
746   // endpoint is bidirectional. EhcCreateUrb expects this
747   // combination of Ep addr and its direction.
748   //
749   Endpoint = (UINT8) (0 | ((TransferDirection == EfiUsbDataIn) ? 0x80 : 0));
750   Urb = EhcCreateUrb (
751           Ehc,
752           DeviceAddress,
753           Endpoint,
754           DeviceSpeed,
755           0,
756           MaximumPacketLength,
757           Translator,
758           EHC_CTRL_TRANSFER,
759           Request,
760           Data,
761           *DataLength,
762           NULL,
763           NULL,
764           1
765           );
766 
767   if (Urb == NULL) {
768     DEBUG ((EFI_D_ERROR, "EhcControlTransfer: failed to create URB"));
769 
770     Status = EFI_OUT_OF_RESOURCES;
771     goto ON_EXIT;
772   }
773 
774   EhcLinkQhToAsync (Ehc, Urb->Qh);
775   Status = EhcExecTransfer (Ehc, Urb, TimeOut);
776   EhcUnlinkQhFromAsync (Ehc, Urb->Qh);
777 
778   //
779   // Get the status from URB. The result is updated in EhcCheckUrbResult
780   // which is called by EhcExecTransfer
781   //
782   *TransferResult = Urb->Result;
783   *DataLength     = Urb->Completed;
784 
785   if (*TransferResult == EFI_USB_NOERROR) {
786     Status = EFI_SUCCESS;
787   }
788 
789   EhcAckAllInterrupt (Ehc);
790   EhcFreeUrb (Ehc, Urb);
791 
792 ON_EXIT:
793   Ehc->PciIo->Flush (Ehc->PciIo);
794   gBS->RestoreTPL (OldTpl);
795 
796   if (EFI_ERROR (Status)) {
797     DEBUG ((EFI_D_ERROR, "EhcControlTransfer: error - %r, transfer - %x\n", Status, *TransferResult));
798   }
799 
800   return Status;
801 }
802 
803 
804 /**
805   Submits bulk transfer to a bulk endpoint of a USB device.
806 
807   @param  This                  This EFI_USB2_HC_PROTOCOL instance.
808   @param  DeviceAddress         Target device address.
809   @param  EndPointAddress       Endpoint number and its direction in bit 7.
810   @param  DeviceSpeed           Device speed, Low speed device doesn't support bulk
811                                 transfer.
812   @param  MaximumPacketLength   Maximum packet size the endpoint is capable of
813                                 sending or receiving.
814   @param  DataBuffersNumber     Number of data buffers prepared for the transfer.
815   @param  Data                  Array of pointers to the buffers of data to transmit
816                                 from or receive into.
817   @param  DataLength            The lenght of the data buffer.
818   @param  DataToggle            On input, the initial data toggle for the transfer;
819                                 On output, it is updated to to next data toggle to
820                                 use of the subsequent bulk transfer.
821   @param  TimeOut               Indicates the maximum time, in millisecond, which
822                                 the transfer is allowed to complete.
823   @param  Translator            A pointr to the transaction translator data.
824   @param  TransferResult        A pointer to the detailed result information of the
825                                 bulk transfer.
826 
827   @retval EFI_SUCCESS           The transfer was completed successfully.
828   @retval EFI_OUT_OF_RESOURCES  The transfer failed due to lack of resource.
829   @retval EFI_INVALID_PARAMETER Some parameters are invalid.
830   @retval EFI_TIMEOUT           The transfer failed due to timeout.
831   @retval EFI_DEVICE_ERROR      The transfer failed due to host controller error.
832 
833 **/
834 EFI_STATUS
835 EFIAPI
EhcBulkTransfer(IN EFI_USB2_HC_PROTOCOL * This,IN UINT8 DeviceAddress,IN UINT8 EndPointAddress,IN UINT8 DeviceSpeed,IN UINTN MaximumPacketLength,IN UINT8 DataBuffersNumber,IN OUT VOID * Data[EFI_USB_MAX_BULK_BUFFER_NUM],IN OUT UINTN * DataLength,IN OUT UINT8 * DataToggle,IN UINTN TimeOut,IN EFI_USB2_HC_TRANSACTION_TRANSLATOR * Translator,OUT UINT32 * TransferResult)836 EhcBulkTransfer (
837   IN  EFI_USB2_HC_PROTOCOL                *This,
838   IN  UINT8                               DeviceAddress,
839   IN  UINT8                               EndPointAddress,
840   IN  UINT8                               DeviceSpeed,
841   IN  UINTN                               MaximumPacketLength,
842   IN  UINT8                               DataBuffersNumber,
843   IN  OUT VOID                            *Data[EFI_USB_MAX_BULK_BUFFER_NUM],
844   IN  OUT UINTN                           *DataLength,
845   IN  OUT UINT8                           *DataToggle,
846   IN  UINTN                               TimeOut,
847   IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
848   OUT UINT32                              *TransferResult
849   )
850 {
851   USB2_HC_DEV             *Ehc;
852   URB                     *Urb;
853   EFI_TPL                 OldTpl;
854   EFI_STATUS              Status;
855 
856   //
857   // Validate the parameters
858   //
859   if ((DataLength == NULL) || (*DataLength == 0) ||
860       (Data == NULL) || (Data[0] == NULL) || (TransferResult == NULL)) {
861     return EFI_INVALID_PARAMETER;
862   }
863 
864   if ((*DataToggle != 0) && (*DataToggle != 1)) {
865     return EFI_INVALID_PARAMETER;
866   }
867 
868   if ((DeviceSpeed == EFI_USB_SPEED_LOW) ||
869       ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||
870       ((EFI_USB_SPEED_HIGH == DeviceSpeed) && (MaximumPacketLength > 512))) {
871     return EFI_INVALID_PARAMETER;
872   }
873 
874   OldTpl          = gBS->RaiseTPL (EHC_TPL);
875   Ehc             = EHC_FROM_THIS (This);
876 
877   *TransferResult = EFI_USB_ERR_SYSTEM;
878   Status          = EFI_DEVICE_ERROR;
879 
880   if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {
881     DEBUG ((EFI_D_ERROR, "EhcBulkTransfer: HC is halted\n"));
882 
883     EhcAckAllInterrupt (Ehc);
884     goto ON_EXIT;
885   }
886 
887   EhcAckAllInterrupt (Ehc);
888 
889   //
890   // Create a new URB, insert it into the asynchronous
891   // schedule list, then poll the execution status.
892   //
893   Urb = EhcCreateUrb (
894           Ehc,
895           DeviceAddress,
896           EndPointAddress,
897           DeviceSpeed,
898           *DataToggle,
899           MaximumPacketLength,
900           Translator,
901           EHC_BULK_TRANSFER,
902           NULL,
903           Data[0],
904           *DataLength,
905           NULL,
906           NULL,
907           1
908           );
909 
910   if (Urb == NULL) {
911     DEBUG ((EFI_D_ERROR, "EhcBulkTransfer: failed to create URB\n"));
912 
913     Status = EFI_OUT_OF_RESOURCES;
914     goto ON_EXIT;
915   }
916 
917   EhcLinkQhToAsync (Ehc, Urb->Qh);
918   Status = EhcExecTransfer (Ehc, Urb, TimeOut);
919   EhcUnlinkQhFromAsync (Ehc, Urb->Qh);
920 
921   *TransferResult = Urb->Result;
922   *DataLength     = Urb->Completed;
923   *DataToggle     = Urb->DataToggle;
924 
925   if (*TransferResult == EFI_USB_NOERROR) {
926     Status = EFI_SUCCESS;
927   }
928 
929   EhcAckAllInterrupt (Ehc);
930   EhcFreeUrb (Ehc, Urb);
931 
932 ON_EXIT:
933   Ehc->PciIo->Flush (Ehc->PciIo);
934   gBS->RestoreTPL (OldTpl);
935 
936   if (EFI_ERROR (Status)) {
937     DEBUG ((EFI_D_ERROR, "EhcBulkTransfer: error - %r, transfer - %x\n", Status, *TransferResult));
938   }
939 
940   return Status;
941 }
942 
943 
944 /**
945   Submits an asynchronous interrupt transfer to an
946   interrupt endpoint of a USB device.
947 
948   @param  This                  This EFI_USB2_HC_PROTOCOL instance.
949   @param  DeviceAddress         Target device address.
950   @param  EndPointAddress       Endpoint number and its direction encoded in bit 7
951   @param  DeviceSpeed           Indicates device speed.
952   @param  MaximumPacketLength   Maximum packet size the target endpoint is capable
953   @param  IsNewTransfer         If TRUE, to submit an new asynchronous interrupt
954                                 transfer If FALSE, to remove the specified
955                                 asynchronous interrupt.
956   @param  DataToggle            On input, the initial data toggle to use; on output,
957                                 it is updated to indicate the next data toggle.
958   @param  PollingInterval       The he interval, in milliseconds, that the transfer
959                                 is polled.
960   @param  DataLength            The length of data to receive at the rate specified
961                                 by  PollingInterval.
962   @param  Translator            Transaction translator to use.
963   @param  CallBackFunction      Function to call at the rate specified by
964                                 PollingInterval.
965   @param  Context               Context to CallBackFunction.
966 
967   @retval EFI_SUCCESS           The request has been successfully submitted or canceled.
968   @retval EFI_INVALID_PARAMETER Some parameters are invalid.
969   @retval EFI_OUT_OF_RESOURCES  The request failed due to a lack of resources.
970   @retval EFI_DEVICE_ERROR      The transfer failed due to host controller error.
971 
972 **/
973 EFI_STATUS
974 EFIAPI
EhcAsyncInterruptTransfer(IN EFI_USB2_HC_PROTOCOL * This,IN UINT8 DeviceAddress,IN UINT8 EndPointAddress,IN UINT8 DeviceSpeed,IN UINTN MaximumPacketLength,IN BOOLEAN IsNewTransfer,IN OUT UINT8 * DataToggle,IN UINTN PollingInterval,IN UINTN DataLength,IN EFI_USB2_HC_TRANSACTION_TRANSLATOR * Translator,IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction,IN VOID * Context OPTIONAL)975 EhcAsyncInterruptTransfer (
976   IN  EFI_USB2_HC_PROTOCOL                  * This,
977   IN  UINT8                                 DeviceAddress,
978   IN  UINT8                                 EndPointAddress,
979   IN  UINT8                                 DeviceSpeed,
980   IN  UINTN                                 MaximumPacketLength,
981   IN  BOOLEAN                               IsNewTransfer,
982   IN  OUT UINT8                             *DataToggle,
983   IN  UINTN                                 PollingInterval,
984   IN  UINTN                                 DataLength,
985   IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR    * Translator,
986   IN  EFI_ASYNC_USB_TRANSFER_CALLBACK       CallBackFunction,
987   IN  VOID                                  *Context OPTIONAL
988   )
989 {
990   USB2_HC_DEV             *Ehc;
991   URB                     *Urb;
992   EFI_TPL                 OldTpl;
993   EFI_STATUS              Status;
994 
995   //
996   // Validate parameters
997   //
998   if (!EHCI_IS_DATAIN (EndPointAddress)) {
999     return EFI_INVALID_PARAMETER;
1000   }
1001 
1002   if (IsNewTransfer) {
1003     if (DataLength == 0) {
1004       return EFI_INVALID_PARAMETER;
1005     }
1006 
1007     if ((*DataToggle != 1) && (*DataToggle != 0)) {
1008       return EFI_INVALID_PARAMETER;
1009     }
1010 
1011     if ((PollingInterval > 255) || (PollingInterval < 1)) {
1012       return EFI_INVALID_PARAMETER;
1013     }
1014   }
1015 
1016   OldTpl  = gBS->RaiseTPL (EHC_TPL);
1017   Ehc     = EHC_FROM_THIS (This);
1018 
1019   //
1020   // Delete Async interrupt transfer request. DataToggle will return
1021   // the next data toggle to use.
1022   //
1023   if (!IsNewTransfer) {
1024     Status = EhciDelAsyncIntTransfer (Ehc, DeviceAddress, EndPointAddress, DataToggle);
1025 
1026     DEBUG ((EFI_D_INFO, "EhcAsyncInterruptTransfer: remove old transfer - %r\n", Status));
1027     goto ON_EXIT;
1028   }
1029 
1030   Status = EFI_SUCCESS;
1031 
1032   if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {
1033     DEBUG ((EFI_D_ERROR, "EhcAsyncInterruptTransfer: HC is halt\n"));
1034     EhcAckAllInterrupt (Ehc);
1035 
1036     Status = EFI_DEVICE_ERROR;
1037     goto ON_EXIT;
1038   }
1039 
1040   EhcAckAllInterrupt (Ehc);
1041 
1042   Urb = EhciInsertAsyncIntTransfer (
1043           Ehc,
1044           DeviceAddress,
1045           EndPointAddress,
1046           DeviceSpeed,
1047           *DataToggle,
1048           MaximumPacketLength,
1049           Translator,
1050           DataLength,
1051           CallBackFunction,
1052           Context,
1053           PollingInterval
1054           );
1055 
1056   if (Urb == NULL) {
1057     Status = EFI_OUT_OF_RESOURCES;
1058     goto ON_EXIT;
1059   }
1060 
1061 ON_EXIT:
1062   Ehc->PciIo->Flush (Ehc->PciIo);
1063   gBS->RestoreTPL (OldTpl);
1064 
1065   return Status;
1066 }
1067 
1068 
1069 /**
1070   Submits synchronous interrupt transfer to an interrupt endpoint
1071   of a USB device.
1072 
1073   @param  This                  This EFI_USB2_HC_PROTOCOL instance.
1074   @param  DeviceAddress         Target device address.
1075   @param  EndPointAddress       Endpoint number and its direction encoded in bit 7
1076   @param  DeviceSpeed           Indicates device speed.
1077   @param  MaximumPacketLength   Maximum packet size the target endpoint is capable
1078                                 of sending or receiving.
1079   @param  Data                  Buffer of data that will be transmitted to  USB
1080                                 device or received from USB device.
1081   @param  DataLength            On input, the size, in bytes, of the data buffer; On
1082                                 output, the number of bytes transferred.
1083   @param  DataToggle            On input, the initial data toggle to use; on output,
1084                                 it is updated to indicate the next data toggle.
1085   @param  TimeOut               Maximum time, in second, to complete.
1086   @param  Translator            Transaction translator to use.
1087   @param  TransferResult        Variable to receive the transfer result.
1088 
1089   @return EFI_SUCCESS           The transfer was completed successfully.
1090   @return EFI_OUT_OF_RESOURCES  The transfer failed due to lack of resource.
1091   @return EFI_INVALID_PARAMETER Some parameters are invalid.
1092   @return EFI_TIMEOUT           The transfer failed due to timeout.
1093   @return EFI_DEVICE_ERROR      The failed due to host controller or device error
1094 
1095 **/
1096 EFI_STATUS
1097 EFIAPI
EhcSyncInterruptTransfer(IN EFI_USB2_HC_PROTOCOL * This,IN UINT8 DeviceAddress,IN UINT8 EndPointAddress,IN UINT8 DeviceSpeed,IN UINTN MaximumPacketLength,IN OUT VOID * Data,IN OUT UINTN * DataLength,IN OUT UINT8 * DataToggle,IN UINTN TimeOut,IN EFI_USB2_HC_TRANSACTION_TRANSLATOR * Translator,OUT UINT32 * TransferResult)1098 EhcSyncInterruptTransfer (
1099   IN  EFI_USB2_HC_PROTOCOL                *This,
1100   IN  UINT8                               DeviceAddress,
1101   IN  UINT8                               EndPointAddress,
1102   IN  UINT8                               DeviceSpeed,
1103   IN  UINTN                               MaximumPacketLength,
1104   IN  OUT VOID                            *Data,
1105   IN  OUT UINTN                           *DataLength,
1106   IN  OUT UINT8                           *DataToggle,
1107   IN  UINTN                               TimeOut,
1108   IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
1109   OUT UINT32                              *TransferResult
1110   )
1111 {
1112   USB2_HC_DEV             *Ehc;
1113   EFI_TPL                 OldTpl;
1114   URB                     *Urb;
1115   EFI_STATUS              Status;
1116 
1117   //
1118   // Validates parameters
1119   //
1120   if ((DataLength == NULL) || (*DataLength == 0) ||
1121       (Data == NULL) || (TransferResult == NULL)) {
1122     return EFI_INVALID_PARAMETER;
1123   }
1124 
1125   if ((*DataToggle != 1) && (*DataToggle != 0)) {
1126     return EFI_INVALID_PARAMETER;
1127   }
1128 
1129   if (((DeviceSpeed == EFI_USB_SPEED_LOW) && (MaximumPacketLength != 8))  ||
1130       ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||
1131       ((DeviceSpeed == EFI_USB_SPEED_HIGH) && (MaximumPacketLength > 3072))) {
1132     return EFI_INVALID_PARAMETER;
1133   }
1134 
1135   OldTpl          = gBS->RaiseTPL (EHC_TPL);
1136   Ehc             = EHC_FROM_THIS (This);
1137 
1138   *TransferResult = EFI_USB_ERR_SYSTEM;
1139   Status          = EFI_DEVICE_ERROR;
1140 
1141   if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {
1142     DEBUG ((EFI_D_ERROR, "EhcSyncInterruptTransfer: HC is halt\n"));
1143 
1144     EhcAckAllInterrupt (Ehc);
1145     goto ON_EXIT;
1146   }
1147 
1148   EhcAckAllInterrupt (Ehc);
1149 
1150   Urb = EhcCreateUrb (
1151           Ehc,
1152           DeviceAddress,
1153           EndPointAddress,
1154           DeviceSpeed,
1155           *DataToggle,
1156           MaximumPacketLength,
1157           Translator,
1158           EHC_INT_TRANSFER_SYNC,
1159           NULL,
1160           Data,
1161           *DataLength,
1162           NULL,
1163           NULL,
1164           1
1165           );
1166 
1167   if (Urb == NULL) {
1168     DEBUG ((EFI_D_ERROR, "EhcSyncInterruptTransfer: failed to create URB\n"));
1169 
1170     Status = EFI_OUT_OF_RESOURCES;
1171     goto ON_EXIT;
1172   }
1173 
1174   EhcLinkQhToPeriod (Ehc, Urb->Qh);
1175   Status = EhcExecTransfer (Ehc, Urb, TimeOut);
1176   EhcUnlinkQhFromPeriod (Ehc, Urb->Qh);
1177 
1178   *TransferResult = Urb->Result;
1179   *DataLength     = Urb->Completed;
1180   *DataToggle     = Urb->DataToggle;
1181 
1182   if (*TransferResult == EFI_USB_NOERROR) {
1183     Status = EFI_SUCCESS;
1184   }
1185 
1186   EhcFreeUrb (Ehc, Urb);
1187 ON_EXIT:
1188   Ehc->PciIo->Flush (Ehc->PciIo);
1189   gBS->RestoreTPL (OldTpl);
1190 
1191   if (EFI_ERROR (Status)) {
1192     DEBUG ((EFI_D_ERROR, "EhcSyncInterruptTransfer: error - %r, transfer - %x\n", Status, *TransferResult));
1193   }
1194 
1195   return Status;
1196 }
1197 
1198 
1199 /**
1200   Submits isochronous transfer to a target USB device.
1201 
1202   @param  This                 This EFI_USB2_HC_PROTOCOL instance.
1203   @param  DeviceAddress        Target device address.
1204   @param  EndPointAddress      End point address with its direction.
1205   @param  DeviceSpeed          Device speed, Low speed device doesn't support this
1206                                type.
1207   @param  MaximumPacketLength  Maximum packet size that the endpoint is capable of
1208                                sending or receiving.
1209   @param  DataBuffersNumber    Number of data buffers prepared for the transfer.
1210   @param  Data                 Array of pointers to the buffers of data that will
1211                                be transmitted to USB device or received from USB
1212                                device.
1213   @param  DataLength           The size, in bytes, of the data buffer.
1214   @param  Translator           Transaction translator to use.
1215   @param  TransferResult       Variable to receive the transfer result.
1216 
1217   @return EFI_UNSUPPORTED      Isochronous transfer is unsupported.
1218 
1219 **/
1220 EFI_STATUS
1221 EFIAPI
EhcIsochronousTransfer(IN EFI_USB2_HC_PROTOCOL * This,IN UINT8 DeviceAddress,IN UINT8 EndPointAddress,IN UINT8 DeviceSpeed,IN UINTN MaximumPacketLength,IN UINT8 DataBuffersNumber,IN OUT VOID * Data[EFI_USB_MAX_ISO_BUFFER_NUM],IN UINTN DataLength,IN EFI_USB2_HC_TRANSACTION_TRANSLATOR * Translator,OUT UINT32 * TransferResult)1222 EhcIsochronousTransfer (
1223   IN  EFI_USB2_HC_PROTOCOL                *This,
1224   IN  UINT8                               DeviceAddress,
1225   IN  UINT8                               EndPointAddress,
1226   IN  UINT8                               DeviceSpeed,
1227   IN  UINTN                               MaximumPacketLength,
1228   IN  UINT8                               DataBuffersNumber,
1229   IN  OUT VOID                            *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
1230   IN  UINTN                               DataLength,
1231   IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
1232   OUT UINT32                              *TransferResult
1233   )
1234 {
1235   return EFI_UNSUPPORTED;
1236 }
1237 
1238 
1239 /**
1240   Submits Async isochronous transfer to a target USB device.
1241 
1242   @param  This                 This EFI_USB2_HC_PROTOCOL instance.
1243   @param  DeviceAddress        Target device address.
1244   @param  EndPointAddress      End point address with its direction.
1245   @param  DeviceSpeed          Device speed, Low speed device doesn't support this
1246                                type.
1247   @param  MaximumPacketLength  Maximum packet size that the endpoint is capable of
1248                                sending or receiving.
1249   @param  DataBuffersNumber    Number of data buffers prepared for the transfer.
1250   @param  Data                 Array of pointers to the buffers of data that will
1251                                be transmitted to USB device or received from USB
1252                                device.
1253   @param  DataLength           The size, in bytes, of the data buffer.
1254   @param  Translator           Transaction translator to use.
1255   @param  IsochronousCallBack  Function to be called when the transfer complete.
1256   @param  Context              Context passed to the call back function as
1257                                parameter.
1258 
1259   @return EFI_UNSUPPORTED      Isochronous transfer isn't supported.
1260 
1261 **/
1262 EFI_STATUS
1263 EFIAPI
EhcAsyncIsochronousTransfer(IN EFI_USB2_HC_PROTOCOL * This,IN UINT8 DeviceAddress,IN UINT8 EndPointAddress,IN UINT8 DeviceSpeed,IN UINTN MaximumPacketLength,IN UINT8 DataBuffersNumber,IN OUT VOID * Data[EFI_USB_MAX_ISO_BUFFER_NUM],IN UINTN DataLength,IN EFI_USB2_HC_TRANSACTION_TRANSLATOR * Translator,IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,IN VOID * Context)1264 EhcAsyncIsochronousTransfer (
1265   IN  EFI_USB2_HC_PROTOCOL                *This,
1266   IN  UINT8                               DeviceAddress,
1267   IN  UINT8                               EndPointAddress,
1268   IN  UINT8                               DeviceSpeed,
1269   IN  UINTN                               MaximumPacketLength,
1270   IN  UINT8                               DataBuffersNumber,
1271   IN  OUT VOID                            *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
1272   IN  UINTN                               DataLength,
1273   IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
1274   IN  EFI_ASYNC_USB_TRANSFER_CALLBACK     IsochronousCallBack,
1275   IN  VOID                                *Context
1276   )
1277 {
1278   return EFI_UNSUPPORTED;
1279 }
1280 
1281 /**
1282   Entry point for EFI drivers.
1283 
1284   @param  ImageHandle       EFI_HANDLE.
1285   @param  SystemTable       EFI_SYSTEM_TABLE.
1286 
1287   @return EFI_SUCCESS       Success.
1288           EFI_DEVICE_ERROR  Fail.
1289 
1290 **/
1291 EFI_STATUS
1292 EFIAPI
EhcDriverEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)1293 EhcDriverEntryPoint (
1294   IN EFI_HANDLE           ImageHandle,
1295   IN EFI_SYSTEM_TABLE     *SystemTable
1296   )
1297 {
1298   return EfiLibInstallDriverBindingComponentName2 (
1299            ImageHandle,
1300            SystemTable,
1301            &gEhciDriverBinding,
1302            ImageHandle,
1303            &gEhciComponentName,
1304            &gEhciComponentName2
1305            );
1306 }
1307 
1308 
1309 /**
1310   Test to see if this driver supports ControllerHandle. Any
1311   ControllerHandle that has Usb2HcProtocol installed will
1312   be supported.
1313 
1314   @param  This                 Protocol instance pointer.
1315   @param  Controller           Handle of device to test.
1316   @param  RemainingDevicePath  Not used.
1317 
1318   @return EFI_SUCCESS          This driver supports this device.
1319   @return EFI_UNSUPPORTED      This driver does not support this device.
1320 
1321 **/
1322 EFI_STATUS
1323 EFIAPI
EhcDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)1324 EhcDriverBindingSupported (
1325   IN EFI_DRIVER_BINDING_PROTOCOL *This,
1326   IN EFI_HANDLE                  Controller,
1327   IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath
1328   )
1329 {
1330   EFI_STATUS              Status;
1331   EFI_PCI_IO_PROTOCOL     *PciIo;
1332   USB_CLASSC              UsbClassCReg;
1333 
1334   //
1335   // Test whether there is PCI IO Protocol attached on the controller handle.
1336   //
1337   Status = gBS->OpenProtocol (
1338                   Controller,
1339                   &gEfiPciIoProtocolGuid,
1340                   (VOID **) &PciIo,
1341                   This->DriverBindingHandle,
1342                   Controller,
1343                   EFI_OPEN_PROTOCOL_BY_DRIVER
1344                   );
1345 
1346   if (EFI_ERROR (Status)) {
1347     return EFI_UNSUPPORTED;
1348   }
1349 
1350   Status = PciIo->Pci.Read (
1351                         PciIo,
1352                         EfiPciIoWidthUint8,
1353                         PCI_CLASSCODE_OFFSET,
1354                         sizeof (USB_CLASSC) / sizeof (UINT8),
1355                         &UsbClassCReg
1356                         );
1357 
1358   if (EFI_ERROR (Status)) {
1359     Status = EFI_UNSUPPORTED;
1360     goto ON_EXIT;
1361   }
1362 
1363   //
1364   // Test whether the controller belongs to Ehci type
1365   //
1366   if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) || (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB)
1367       || ((UsbClassCReg.ProgInterface != PCI_IF_EHCI) && (UsbClassCReg.ProgInterface != PCI_IF_UHCI) && (UsbClassCReg.ProgInterface != PCI_IF_OHCI))) {
1368 
1369     Status = EFI_UNSUPPORTED;
1370   }
1371 
1372 ON_EXIT:
1373   gBS->CloseProtocol (
1374          Controller,
1375          &gEfiPciIoProtocolGuid,
1376          This->DriverBindingHandle,
1377          Controller
1378          );
1379 
1380   return Status;
1381 }
1382 
1383 /**
1384   Get the usb debug port related information.
1385 
1386   @param  Ehc                The EHCI device.
1387 
1388   @retval RETURN_SUCCESS     Get debug port number, bar and offset successfully.
1389   @retval Others             The usb host controller does not supported usb debug port capability.
1390 
1391 **/
1392 EFI_STATUS
EhcGetUsbDebugPortInfo(IN USB2_HC_DEV * Ehc)1393 EhcGetUsbDebugPortInfo (
1394   IN  USB2_HC_DEV     *Ehc
1395  )
1396 {
1397   EFI_PCI_IO_PROTOCOL *PciIo;
1398   UINT16              PciStatus;
1399   UINT8               CapabilityPtr;
1400   UINT8               CapabilityId;
1401   UINT16              DebugPort;
1402   EFI_STATUS          Status;
1403 
1404   ASSERT (Ehc->PciIo != NULL);
1405   PciIo = Ehc->PciIo;
1406 
1407   //
1408   // Detect if the EHCI host controller support Capaility Pointer.
1409   //
1410   Status = PciIo->Pci.Read (
1411                         PciIo,
1412                         EfiPciIoWidthUint8,
1413                         PCI_PRIMARY_STATUS_OFFSET,
1414                         sizeof (UINT16),
1415                         &PciStatus
1416                         );
1417 
1418   if (EFI_ERROR (Status)) {
1419     return Status;
1420   }
1421 
1422   if ((PciStatus & EFI_PCI_STATUS_CAPABILITY) == 0) {
1423     //
1424     // The Pci Device Doesn't Support Capability Pointer.
1425     //
1426     return EFI_UNSUPPORTED;
1427   }
1428 
1429   //
1430   // Get Pointer To Capability List
1431   //
1432   Status = PciIo->Pci.Read (
1433                         PciIo,
1434                         EfiPciIoWidthUint8,
1435                         PCI_CAPBILITY_POINTER_OFFSET,
1436                         1,
1437                         &CapabilityPtr
1438                         );
1439 
1440   if (EFI_ERROR (Status)) {
1441     return Status;
1442   }
1443 
1444   //
1445   // Find Capability ID 0xA, Which Is For Debug Port
1446   //
1447   while (CapabilityPtr != 0) {
1448     Status = PciIo->Pci.Read (
1449                           PciIo,
1450                           EfiPciIoWidthUint8,
1451                           CapabilityPtr,
1452                           1,
1453                           &CapabilityId
1454                           );
1455 
1456     if (EFI_ERROR (Status)) {
1457       return Status;
1458     }
1459 
1460     if (CapabilityId == EHC_DEBUG_PORT_CAP_ID) {
1461       break;
1462     }
1463 
1464     Status = PciIo->Pci.Read (
1465                           PciIo,
1466                           EfiPciIoWidthUint8,
1467                           CapabilityPtr + 1,
1468                           1,
1469                           &CapabilityPtr
1470                           );
1471 
1472     if (EFI_ERROR (Status)) {
1473       return Status;
1474     }
1475   }
1476 
1477   //
1478   // No Debug Port Capability Found
1479   //
1480   if (CapabilityPtr == 0) {
1481     return EFI_UNSUPPORTED;
1482   }
1483 
1484   //
1485   // Get The Base Address Of Debug Port Register In Debug Port Capability Register
1486   //
1487   Status = PciIo->Pci.Read (
1488                         Ehc->PciIo,
1489                         EfiPciIoWidthUint8,
1490                         CapabilityPtr + 2,
1491                         sizeof (UINT16),
1492                         &DebugPort
1493                         );
1494 
1495   if (EFI_ERROR (Status)) {
1496     return Status;
1497   }
1498 
1499   Ehc->DebugPortOffset = DebugPort & 0x1FFF;
1500   Ehc->DebugPortBarNum = (UINT8)((DebugPort >> 13) - 1);
1501   Ehc->DebugPortNum    = (UINT8)((Ehc->HcStructParams & 0x00F00000) >> 20);
1502 
1503   return EFI_SUCCESS;
1504 }
1505 
1506 
1507 /**
1508   Create and initialize a USB2_HC_DEV.
1509 
1510   @param  PciIo                  The PciIo on this device.
1511   @param  DevicePath             The device path of host controller.
1512   @param  OriginalPciAttributes  Original PCI attributes.
1513 
1514   @return  The allocated and initialized USB2_HC_DEV structure if created,
1515            otherwise NULL.
1516 
1517 **/
1518 USB2_HC_DEV *
EhcCreateUsb2Hc(IN EFI_PCI_IO_PROTOCOL * PciIo,IN EFI_DEVICE_PATH_PROTOCOL * DevicePath,IN UINT64 OriginalPciAttributes)1519 EhcCreateUsb2Hc (
1520   IN EFI_PCI_IO_PROTOCOL       *PciIo,
1521   IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
1522   IN UINT64                    OriginalPciAttributes
1523   )
1524 {
1525   USB2_HC_DEV             *Ehc;
1526   EFI_STATUS              Status;
1527 
1528   Ehc = AllocateZeroPool (sizeof (USB2_HC_DEV));
1529 
1530   if (Ehc == NULL) {
1531     return NULL;
1532   }
1533 
1534   //
1535   // Init EFI_USB2_HC_PROTOCOL interface and private data structure
1536   //
1537   Ehc->Signature                        = USB2_HC_DEV_SIGNATURE;
1538 
1539   Ehc->Usb2Hc.GetCapability             = EhcGetCapability;
1540   Ehc->Usb2Hc.Reset                     = EhcReset;
1541   Ehc->Usb2Hc.GetState                  = EhcGetState;
1542   Ehc->Usb2Hc.SetState                  = EhcSetState;
1543   Ehc->Usb2Hc.ControlTransfer           = EhcControlTransfer;
1544   Ehc->Usb2Hc.BulkTransfer              = EhcBulkTransfer;
1545   Ehc->Usb2Hc.AsyncInterruptTransfer    = EhcAsyncInterruptTransfer;
1546   Ehc->Usb2Hc.SyncInterruptTransfer     = EhcSyncInterruptTransfer;
1547   Ehc->Usb2Hc.IsochronousTransfer       = EhcIsochronousTransfer;
1548   Ehc->Usb2Hc.AsyncIsochronousTransfer  = EhcAsyncIsochronousTransfer;
1549   Ehc->Usb2Hc.GetRootHubPortStatus      = EhcGetRootHubPortStatus;
1550   Ehc->Usb2Hc.SetRootHubPortFeature     = EhcSetRootHubPortFeature;
1551   Ehc->Usb2Hc.ClearRootHubPortFeature   = EhcClearRootHubPortFeature;
1552   Ehc->Usb2Hc.MajorRevision             = 0x2;
1553   Ehc->Usb2Hc.MinorRevision             = 0x0;
1554 
1555   Ehc->PciIo                 = PciIo;
1556   Ehc->DevicePath            = DevicePath;
1557   Ehc->OriginalPciAttributes = OriginalPciAttributes;
1558 
1559   InitializeListHead (&Ehc->AsyncIntTransfers);
1560 
1561   Ehc->HcStructParams = EhcReadCapRegister (Ehc, EHC_HCSPARAMS_OFFSET);
1562   Ehc->HcCapParams    = EhcReadCapRegister (Ehc, EHC_HCCPARAMS_OFFSET);
1563   Ehc->CapLen         = EhcReadCapRegister (Ehc, EHC_CAPLENGTH_OFFSET) & 0x0FF;
1564 
1565   DEBUG ((EFI_D_INFO, "EhcCreateUsb2Hc: capability length %d\n", Ehc->CapLen));
1566 
1567   //
1568   // EHCI Controllers with a CapLen of 0 are ignored.
1569   //
1570   if (Ehc->CapLen == 0) {
1571     gBS->FreePool (Ehc);
1572     return NULL;
1573   }
1574 
1575   EhcGetUsbDebugPortInfo (Ehc);
1576 
1577   //
1578   // Create AsyncRequest Polling Timer
1579   //
1580   Status = gBS->CreateEvent (
1581                   EVT_TIMER | EVT_NOTIFY_SIGNAL,
1582                   TPL_NOTIFY,
1583                   EhcMonitorAsyncRequests,
1584                   Ehc,
1585                   &Ehc->PollTimer
1586                   );
1587 
1588   if (EFI_ERROR (Status)) {
1589     gBS->FreePool (Ehc);
1590     return NULL;
1591   }
1592 
1593   return Ehc;
1594 }
1595 
1596 /**
1597   One notified function to stop the Host Controller when gBS->ExitBootServices() called.
1598 
1599   @param  Event                   Pointer to this event
1600   @param  Context                 Event handler private data
1601 
1602 **/
1603 VOID
1604 EFIAPI
EhcExitBootService(EFI_EVENT Event,VOID * Context)1605 EhcExitBootService (
1606   EFI_EVENT                      Event,
1607   VOID                           *Context
1608   )
1609 
1610 {
1611   USB2_HC_DEV   *Ehc;
1612 
1613   Ehc = (USB2_HC_DEV *) Context;
1614 
1615   //
1616   // Reset the Host Controller
1617   //
1618   EhcResetHC (Ehc, EHC_RESET_TIMEOUT);
1619 }
1620 
1621 
1622 /**
1623   Starting the Usb EHCI Driver.
1624 
1625   @param  This                 Protocol instance pointer.
1626   @param  Controller           Handle of device to test.
1627   @param  RemainingDevicePath  Not used.
1628 
1629   @return EFI_SUCCESS          supports this device.
1630   @return EFI_UNSUPPORTED      do not support this device.
1631   @return EFI_DEVICE_ERROR     cannot be started due to device Error.
1632   @return EFI_OUT_OF_RESOURCES cannot allocate resources.
1633 
1634 **/
1635 EFI_STATUS
1636 EFIAPI
EhcDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)1637 EhcDriverBindingStart (
1638   IN EFI_DRIVER_BINDING_PROTOCOL *This,
1639   IN EFI_HANDLE                  Controller,
1640   IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath
1641   )
1642 {
1643   EFI_STATUS              Status;
1644   USB2_HC_DEV             *Ehc;
1645   EFI_PCI_IO_PROTOCOL     *PciIo;
1646   EFI_PCI_IO_PROTOCOL     *Instance;
1647   UINT64                  Supports;
1648   UINT64                  OriginalPciAttributes;
1649   BOOLEAN                 PciAttributesSaved;
1650   USB_CLASSC              UsbClassCReg;
1651   EFI_HANDLE              *HandleBuffer;
1652   UINTN                   NumberOfHandles;
1653   UINTN                   Index;
1654   UINTN                   CompanionSegmentNumber;
1655   UINTN                   CompanionBusNumber;
1656   UINTN                   CompanionDeviceNumber;
1657   UINTN                   CompanionFunctionNumber;
1658   UINTN                   EhciSegmentNumber;
1659   UINTN                   EhciBusNumber;
1660   UINTN                   EhciDeviceNumber;
1661   UINTN                   EhciFunctionNumber;
1662   EFI_DEVICE_PATH_PROTOCOL  *HcDevicePath;
1663 
1664   //
1665   // Open the PciIo Protocol, then enable the USB host controller
1666   //
1667   Status = gBS->OpenProtocol (
1668                   Controller,
1669                   &gEfiPciIoProtocolGuid,
1670                   (VOID **) &PciIo,
1671                   This->DriverBindingHandle,
1672                   Controller,
1673                   EFI_OPEN_PROTOCOL_BY_DRIVER
1674                   );
1675 
1676   if (EFI_ERROR (Status)) {
1677     return Status;
1678   }
1679 
1680   //
1681   // Open Device Path Protocol for on USB host controller
1682   //
1683   HcDevicePath = NULL;
1684   Status = gBS->OpenProtocol (
1685                   Controller,
1686                   &gEfiDevicePathProtocolGuid,
1687                   (VOID **) &HcDevicePath,
1688                   This->DriverBindingHandle,
1689                   Controller,
1690                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
1691                   );
1692 
1693   PciAttributesSaved = FALSE;
1694   //
1695   // Save original PCI attributes
1696   //
1697   Status = PciIo->Attributes (
1698                     PciIo,
1699                     EfiPciIoAttributeOperationGet,
1700                     0,
1701                     &OriginalPciAttributes
1702                     );
1703 
1704   if (EFI_ERROR (Status)) {
1705     goto CLOSE_PCIIO;
1706   }
1707   PciAttributesSaved = TRUE;
1708 
1709   Status = PciIo->Attributes (
1710                     PciIo,
1711                     EfiPciIoAttributeOperationSupported,
1712                     0,
1713                     &Supports
1714                     );
1715   if (!EFI_ERROR (Status)) {
1716     Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
1717     Status = PciIo->Attributes (
1718                       PciIo,
1719                       EfiPciIoAttributeOperationEnable,
1720                       Supports,
1721                       NULL
1722                       );
1723   }
1724 
1725   if (EFI_ERROR (Status)) {
1726     DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to enable controller\n"));
1727     goto CLOSE_PCIIO;
1728   }
1729 
1730   //
1731   // Get the Pci device class code.
1732   //
1733   Status = PciIo->Pci.Read (
1734                         PciIo,
1735                         EfiPciIoWidthUint8,
1736                         PCI_CLASSCODE_OFFSET,
1737                         sizeof (USB_CLASSC) / sizeof (UINT8),
1738                         &UsbClassCReg
1739                         );
1740 
1741   if (EFI_ERROR (Status)) {
1742     Status = EFI_UNSUPPORTED;
1743     goto CLOSE_PCIIO;
1744   }
1745   //
1746   // Determine if the device is UHCI or OHCI host controller or not. If yes, then find out the
1747   // companion usb ehci host controller and force EHCI driver get attached to it before
1748   // UHCI or OHCI driver attaches to UHCI or OHCI host controller.
1749   //
1750   if ((UsbClassCReg.ProgInterface == PCI_IF_UHCI || UsbClassCReg.ProgInterface == PCI_IF_OHCI) &&
1751        (UsbClassCReg.BaseCode == PCI_CLASS_SERIAL) &&
1752        (UsbClassCReg.SubClassCode == PCI_CLASS_SERIAL_USB)) {
1753     Status = PciIo->GetLocation (
1754                     PciIo,
1755                     &CompanionSegmentNumber,
1756                     &CompanionBusNumber,
1757                     &CompanionDeviceNumber,
1758                     &CompanionFunctionNumber
1759                     );
1760     if (EFI_ERROR (Status)) {
1761       goto CLOSE_PCIIO;
1762     }
1763 
1764     Status = gBS->LocateHandleBuffer (
1765                     ByProtocol,
1766                     &gEfiPciIoProtocolGuid,
1767                     NULL,
1768                     &NumberOfHandles,
1769                     &HandleBuffer
1770                     );
1771     if (EFI_ERROR (Status)) {
1772       goto CLOSE_PCIIO;
1773     }
1774 
1775     for (Index = 0; Index < NumberOfHandles; Index++) {
1776       //
1777       // Get the device path on this handle
1778       //
1779       Status = gBS->HandleProtocol (
1780                     HandleBuffer[Index],
1781                     &gEfiPciIoProtocolGuid,
1782                     (VOID **)&Instance
1783                     );
1784       ASSERT_EFI_ERROR (Status);
1785 
1786       Status = Instance->Pci.Read (
1787                     Instance,
1788                     EfiPciIoWidthUint8,
1789                     PCI_CLASSCODE_OFFSET,
1790                     sizeof (USB_CLASSC) / sizeof (UINT8),
1791                     &UsbClassCReg
1792                     );
1793 
1794       if (EFI_ERROR (Status)) {
1795         Status = EFI_UNSUPPORTED;
1796         goto CLOSE_PCIIO;
1797       }
1798 
1799       if ((UsbClassCReg.ProgInterface == PCI_IF_EHCI) &&
1800            (UsbClassCReg.BaseCode == PCI_CLASS_SERIAL) &&
1801            (UsbClassCReg.SubClassCode == PCI_CLASS_SERIAL_USB)) {
1802         Status = Instance->GetLocation (
1803                     Instance,
1804                     &EhciSegmentNumber,
1805                     &EhciBusNumber,
1806                     &EhciDeviceNumber,
1807                     &EhciFunctionNumber
1808                     );
1809         if (EFI_ERROR (Status)) {
1810           goto CLOSE_PCIIO;
1811         }
1812         //
1813         // Currently, the judgment on the companion usb host controller is through the
1814         // same bus number, which may vary on different platform.
1815         //
1816         if (EhciBusNumber == CompanionBusNumber) {
1817           gBS->CloseProtocol (
1818                     Controller,
1819                     &gEfiPciIoProtocolGuid,
1820                     This->DriverBindingHandle,
1821                     Controller
1822                     );
1823           EhcDriverBindingStart(This, HandleBuffer[Index], NULL);
1824         }
1825       }
1826     }
1827     Status = EFI_NOT_FOUND;
1828     goto CLOSE_PCIIO;
1829   }
1830 
1831   //
1832   // Create then install USB2_HC_PROTOCOL
1833   //
1834   Ehc = EhcCreateUsb2Hc (PciIo, HcDevicePath, OriginalPciAttributes);
1835 
1836   if (Ehc == NULL) {
1837     DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to create USB2_HC\n"));
1838 
1839     Status = EFI_OUT_OF_RESOURCES;
1840     goto CLOSE_PCIIO;
1841   }
1842 
1843   //
1844   // Enable 64-bit DMA support in the PCI layer if this controller
1845   // supports it.
1846   //
1847   if (EHC_BIT_IS_SET (Ehc->HcCapParams, HCCP_64BIT)) {
1848     Status = PciIo->Attributes (
1849                       PciIo,
1850                       EfiPciIoAttributeOperationEnable,
1851                       EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE,
1852                       NULL
1853                       );
1854     if (!EFI_ERROR (Status)) {
1855       Ehc->Support64BitDma = TRUE;
1856     } else {
1857       DEBUG ((EFI_D_WARN,
1858         "%a: failed to enable 64-bit DMA on 64-bit capable controller @ %p (%r)\n",
1859         __FUNCTION__, Controller, Status));
1860     }
1861   }
1862 
1863   Status = gBS->InstallProtocolInterface (
1864                   &Controller,
1865                   &gEfiUsb2HcProtocolGuid,
1866                   EFI_NATIVE_INTERFACE,
1867                   &Ehc->Usb2Hc
1868                   );
1869 
1870   if (EFI_ERROR (Status)) {
1871     DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to install USB2_HC Protocol\n"));
1872     goto FREE_POOL;
1873   }
1874 
1875   //
1876   // Robustnesss improvement such as for Duet platform
1877   // Default is not required.
1878   //
1879   if (FeaturePcdGet (PcdTurnOffUsbLegacySupport)) {
1880     EhcClearLegacySupport (Ehc);
1881   }
1882 
1883   if (!EhcIsDebugPortInUse (Ehc, NULL)) {
1884     EhcResetHC (Ehc, EHC_RESET_TIMEOUT);
1885   }
1886 
1887   Status = EhcInitHC (Ehc);
1888 
1889   if (EFI_ERROR (Status)) {
1890     DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to init host controller\n"));
1891     goto UNINSTALL_USBHC;
1892   }
1893 
1894   //
1895   // Start the asynchronous interrupt monitor
1896   //
1897   Status = gBS->SetTimer (Ehc->PollTimer, TimerPeriodic, EHC_ASYNC_POLL_INTERVAL);
1898 
1899   if (EFI_ERROR (Status)) {
1900     DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to start async interrupt monitor\n"));
1901 
1902     EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);
1903     goto UNINSTALL_USBHC;
1904   }
1905 
1906   //
1907   // Create event to stop the HC when exit boot service.
1908   //
1909   Status = gBS->CreateEventEx (
1910                   EVT_NOTIFY_SIGNAL,
1911                   TPL_NOTIFY,
1912                   EhcExitBootService,
1913                   Ehc,
1914                   &gEfiEventExitBootServicesGuid,
1915                   &Ehc->ExitBootServiceEvent
1916                   );
1917   if (EFI_ERROR (Status)) {
1918     goto UNINSTALL_USBHC;
1919   }
1920 
1921   //
1922   // Install the component name protocol, don't fail the start
1923   // because of something for display.
1924   //
1925   AddUnicodeString2 (
1926     "eng",
1927     gEhciComponentName.SupportedLanguages,
1928     &Ehc->ControllerNameTable,
1929     L"Enhanced Host Controller (USB 2.0)",
1930     TRUE
1931     );
1932   AddUnicodeString2 (
1933     "en",
1934     gEhciComponentName2.SupportedLanguages,
1935     &Ehc->ControllerNameTable,
1936     L"Enhanced Host Controller (USB 2.0)",
1937     FALSE
1938     );
1939 
1940 
1941   DEBUG ((EFI_D_INFO, "EhcDriverBindingStart: EHCI started for controller @ %p\n", Controller));
1942   return EFI_SUCCESS;
1943 
1944 UNINSTALL_USBHC:
1945   gBS->UninstallProtocolInterface (
1946          Controller,
1947          &gEfiUsb2HcProtocolGuid,
1948          &Ehc->Usb2Hc
1949          );
1950 
1951 FREE_POOL:
1952   EhcFreeSched (Ehc);
1953   gBS->CloseEvent (Ehc->PollTimer);
1954   gBS->FreePool (Ehc);
1955 
1956 CLOSE_PCIIO:
1957   if (PciAttributesSaved) {
1958     //
1959     // Restore original PCI attributes
1960     //
1961     PciIo->Attributes (
1962                     PciIo,
1963                     EfiPciIoAttributeOperationSet,
1964                     OriginalPciAttributes,
1965                     NULL
1966                     );
1967   }
1968 
1969   gBS->CloseProtocol (
1970          Controller,
1971          &gEfiPciIoProtocolGuid,
1972          This->DriverBindingHandle,
1973          Controller
1974          );
1975 
1976   return Status;
1977 }
1978 
1979 
1980 /**
1981   Stop this driver on ControllerHandle. Support stopping any child handles
1982   created by this driver.
1983 
1984   @param  This                 Protocol instance pointer.
1985   @param  Controller           Handle of device to stop driver on.
1986   @param  NumberOfChildren     Number of Children in the ChildHandleBuffer.
1987   @param  ChildHandleBuffer    List of handles for the children we need to stop.
1988 
1989   @return EFI_SUCCESS          Success.
1990   @return EFI_DEVICE_ERROR     Fail.
1991 
1992 **/
1993 EFI_STATUS
1994 EFIAPI
EhcDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)1995 EhcDriverBindingStop (
1996   IN EFI_DRIVER_BINDING_PROTOCOL *This,
1997   IN EFI_HANDLE                  Controller,
1998   IN UINTN                       NumberOfChildren,
1999   IN EFI_HANDLE                  *ChildHandleBuffer
2000   )
2001 {
2002   EFI_STATUS            Status;
2003   EFI_USB2_HC_PROTOCOL  *Usb2Hc;
2004   EFI_PCI_IO_PROTOCOL   *PciIo;
2005   USB2_HC_DEV           *Ehc;
2006 
2007   //
2008   // Test whether the Controller handler passed in is a valid
2009   // Usb controller handle that should be supported, if not,
2010   // return the error status directly
2011   //
2012   Status = gBS->OpenProtocol (
2013                   Controller,
2014                   &gEfiUsb2HcProtocolGuid,
2015                   (VOID **) &Usb2Hc,
2016                   This->DriverBindingHandle,
2017                   Controller,
2018                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
2019                   );
2020 
2021   if (EFI_ERROR (Status)) {
2022     return Status;
2023   }
2024 
2025   Ehc   = EHC_FROM_THIS (Usb2Hc);
2026   PciIo = Ehc->PciIo;
2027 
2028   Status = gBS->UninstallProtocolInterface (
2029                   Controller,
2030                   &gEfiUsb2HcProtocolGuid,
2031                   Usb2Hc
2032                   );
2033 
2034   if (EFI_ERROR (Status)) {
2035     return Status;
2036   }
2037 
2038   //
2039   // Stop AsyncRequest Polling timer then stop the EHCI driver
2040   // and uninstall the EHCI protocl.
2041   //
2042   gBS->SetTimer (Ehc->PollTimer, TimerCancel, EHC_ASYNC_POLL_INTERVAL);
2043   EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);
2044 
2045   if (Ehc->PollTimer != NULL) {
2046     gBS->CloseEvent (Ehc->PollTimer);
2047   }
2048 
2049   if (Ehc->ExitBootServiceEvent != NULL) {
2050     gBS->CloseEvent (Ehc->ExitBootServiceEvent);
2051   }
2052 
2053   EhcFreeSched (Ehc);
2054 
2055   if (Ehc->ControllerNameTable != NULL) {
2056     FreeUnicodeStringTable (Ehc->ControllerNameTable);
2057   }
2058 
2059   //
2060   // Disable routing of all ports to EHCI controller, so all ports are
2061   // routed back to the UHCI or OHCI controller.
2062   //
2063   EhcClearOpRegBit (Ehc, EHC_CONFIG_FLAG_OFFSET, CONFIGFLAG_ROUTE_EHC);
2064 
2065   //
2066   // Restore original PCI attributes
2067   //
2068   PciIo->Attributes (
2069                   PciIo,
2070                   EfiPciIoAttributeOperationSet,
2071                   Ehc->OriginalPciAttributes,
2072                   NULL
2073                   );
2074 
2075   gBS->CloseProtocol (
2076          Controller,
2077          &gEfiPciIoProtocolGuid,
2078          This->DriverBindingHandle,
2079          Controller
2080          );
2081 
2082   FreePool (Ehc);
2083 
2084   return EFI_SUCCESS;
2085 }
2086 
2087