2 The Ehci controller driver.
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.
8 Note that EhciDxe driver is enhanced to guarantee that the EHCI controller get attached
9 to the EHCI controller before the UHCI driver attaches to the companion UHCI controller.
10 This way avoids the control transfer on a shared port between EHCI and companion host
11 controller when UHCI gets attached earlier than EHCI and a USB 2.0 device inserts.
13 Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
14 This program and the accompanying materials
15 are licensed and made available under the terms and conditions of the BSD License
16 which accompanies this distribution. The full text of the license may be found at
17 http://opensource.org/licenses/bsd-license.php
19 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
20 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
28 // Two arrays used to translate the EHCI port state (change)
29 // to the UEFI protocol's port state (change).
31 USB_PORT_STATE_MAP mUsbPortStateMap
[] = {
32 {PORTSC_CONN
, USB_PORT_STAT_CONNECTION
},
33 {PORTSC_ENABLED
, USB_PORT_STAT_ENABLE
},
34 {PORTSC_SUSPEND
, USB_PORT_STAT_SUSPEND
},
35 {PORTSC_OVERCUR
, USB_PORT_STAT_OVERCURRENT
},
36 {PORTSC_RESET
, USB_PORT_STAT_RESET
},
37 {PORTSC_POWER
, USB_PORT_STAT_POWER
},
38 {PORTSC_OWNER
, USB_PORT_STAT_OWNER
}
41 USB_PORT_STATE_MAP mUsbPortChangeMap
[] = {
42 {PORTSC_CONN_CHANGE
, USB_PORT_STAT_C_CONNECTION
},
43 {PORTSC_ENABLE_CHANGE
, USB_PORT_STAT_C_ENABLE
},
44 {PORTSC_OVERCUR_CHANGE
, USB_PORT_STAT_C_OVERCURRENT
}
47 EFI_DRIVER_BINDING_PROTOCOL
48 gEhciDriverBinding
= {
49 EhcDriverBindingSupported
,
50 EhcDriverBindingStart
,
58 Retrieves the capability of root hub ports.
60 @param This This EFI_USB_HC_PROTOCOL instance.
61 @param MaxSpeed Max speed supported by the controller.
62 @param PortNumber Number of the root hub ports.
63 @param Is64BitCapable Whether the controller supports 64-bit memory
66 @retval EFI_SUCCESS Host controller capability were retrieved successfully.
67 @retval EFI_INVALID_PARAMETER Either of the three capability pointer is NULL.
73 IN EFI_USB2_HC_PROTOCOL
*This
,
75 OUT UINT8
*PortNumber
,
76 OUT UINT8
*Is64BitCapable
82 if ((MaxSpeed
== NULL
) || (PortNumber
== NULL
) || (Is64BitCapable
== NULL
)) {
83 return EFI_INVALID_PARAMETER
;
86 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
87 Ehc
= EHC_FROM_THIS (This
);
89 *MaxSpeed
= EFI_USB_SPEED_HIGH
;
90 *PortNumber
= (UINT8
) (Ehc
->HcStructParams
& HCSP_NPORTS
);
91 *Is64BitCapable
= (UINT8
) (Ehc
->HcCapParams
& HCCP_64BIT
);
93 DEBUG ((EFI_D_INFO
, "EhcGetCapability: %d ports, 64 bit %d\n", *PortNumber
, *Is64BitCapable
));
95 gBS
->RestoreTPL (OldTpl
);
101 Provides software reset for the USB host controller.
103 @param This This EFI_USB2_HC_PROTOCOL instance.
104 @param Attributes A bit mask of the reset operation to perform.
106 @retval EFI_SUCCESS The reset operation succeeded.
107 @retval EFI_INVALID_PARAMETER Attributes is not valid.
108 @retval EFI_UNSUPPOURTED The type of reset specified by Attributes is
109 not currently supported by the host controller.
110 @retval EFI_DEVICE_ERROR Host controller isn't halted to reset.
116 IN EFI_USB2_HC_PROTOCOL
*This
,
123 UINT32 DbgCtrlStatus
;
125 Ehc
= EHC_FROM_THIS (This
);
127 if (Ehc
->DevicePath
!= NULL
) {
129 // Report Status Code to indicate reset happens
131 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
133 (EFI_IO_BUS_USB
| EFI_IOB_PC_RESET
),
138 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
140 switch (Attributes
) {
141 case EFI_USB_HC_RESET_GLOBAL
:
143 // Flow through, same behavior as Host Controller Reset
145 case EFI_USB_HC_RESET_HOST_CONTROLLER
:
147 // Host Controller must be Halt when Reset it
149 if (Ehc
->DebugPortNum
!= 0) {
150 DbgCtrlStatus
= EhcReadDbgRegister(Ehc
, 0);
151 if ((DbgCtrlStatus
& (USB_DEBUG_PORT_IN_USE
| USB_DEBUG_PORT_OWNER
)) == (USB_DEBUG_PORT_IN_USE
| USB_DEBUG_PORT_OWNER
)) {
152 Status
= EFI_SUCCESS
;
157 if (!EhcIsHalt (Ehc
)) {
158 Status
= EhcHaltHC (Ehc
, EHC_GENERIC_TIMEOUT
);
160 if (EFI_ERROR (Status
)) {
161 Status
= EFI_DEVICE_ERROR
;
167 // Clean up the asynchronous transfers, currently only
168 // interrupt supports asynchronous operation.
170 EhciDelAllAsyncIntTransfers (Ehc
);
171 EhcAckAllInterrupt (Ehc
);
174 Status
= EhcResetHC (Ehc
, EHC_RESET_TIMEOUT
);
176 if (EFI_ERROR (Status
)) {
180 Status
= EhcInitHC (Ehc
);
183 case EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG
:
184 case EFI_USB_HC_RESET_HOST_WITH_DEBUG
:
185 Status
= EFI_UNSUPPORTED
;
189 Status
= EFI_INVALID_PARAMETER
;
193 DEBUG ((EFI_D_INFO
, "EhcReset: exit status %r\n", Status
));
194 gBS
->RestoreTPL (OldTpl
);
200 Retrieve the current state of the USB host controller.
202 @param This This EFI_USB2_HC_PROTOCOL instance.
203 @param State Variable to return the current host controller
206 @retval EFI_SUCCESS Host controller state was returned in State.
207 @retval EFI_INVALID_PARAMETER State is NULL.
208 @retval EFI_DEVICE_ERROR An error was encountered while attempting to
209 retrieve the host controller's current state.
215 IN EFI_USB2_HC_PROTOCOL
*This
,
216 OUT EFI_USB_HC_STATE
*State
223 return EFI_INVALID_PARAMETER
;
226 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
227 Ehc
= EHC_FROM_THIS (This
);
229 if (EHC_REG_BIT_IS_SET (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_HALT
)) {
230 *State
= EfiUsbHcStateHalt
;
232 *State
= EfiUsbHcStateOperational
;
235 gBS
->RestoreTPL (OldTpl
);
237 DEBUG ((EFI_D_INFO
, "EhcGetState: current state %d\n", *State
));
243 Sets the USB host controller to a specific state.
245 @param This This EFI_USB2_HC_PROTOCOL instance.
246 @param State The state of the host controller that will be set.
248 @retval EFI_SUCCESS The USB host controller was successfully placed
249 in the state specified by State.
250 @retval EFI_INVALID_PARAMETER State is invalid.
251 @retval EFI_DEVICE_ERROR Failed to set the state due to device error.
257 IN EFI_USB2_HC_PROTOCOL
*This
,
258 IN EFI_USB_HC_STATE State
264 EFI_USB_HC_STATE CurState
;
266 Status
= EhcGetState (This
, &CurState
);
268 if (EFI_ERROR (Status
)) {
269 return EFI_DEVICE_ERROR
;
272 if (CurState
== State
) {
276 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
277 Ehc
= EHC_FROM_THIS (This
);
280 case EfiUsbHcStateHalt
:
281 Status
= EhcHaltHC (Ehc
, EHC_GENERIC_TIMEOUT
);
284 case EfiUsbHcStateOperational
:
285 if (EHC_REG_BIT_IS_SET (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_SYS_ERROR
)) {
286 Status
= EFI_DEVICE_ERROR
;
291 // Software must not write a one to this field unless the host controller
292 // is in the Halted state. Doing so will yield undefined results.
293 // refers to Spec[EHCI1.0-2.3.1]
295 if (!EHC_REG_BIT_IS_SET (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_HALT
)) {
296 Status
= EFI_DEVICE_ERROR
;
300 Status
= EhcRunHC (Ehc
, EHC_GENERIC_TIMEOUT
);
303 case EfiUsbHcStateSuspend
:
304 Status
= EFI_UNSUPPORTED
;
308 Status
= EFI_INVALID_PARAMETER
;
311 DEBUG ((EFI_D_INFO
, "EhcSetState: exit status %r\n", Status
));
312 gBS
->RestoreTPL (OldTpl
);
318 Retrieves the current status of a USB root hub port.
320 @param This This EFI_USB2_HC_PROTOCOL instance.
321 @param PortNumber The root hub port to retrieve the state from.
322 This value is zero-based.
323 @param PortStatus Variable to receive the port state.
325 @retval EFI_SUCCESS The status of the USB root hub port specified.
326 by PortNumber was returned in PortStatus.
327 @retval EFI_INVALID_PARAMETER PortNumber is invalid.
328 @retval EFI_DEVICE_ERROR Can't read register.
333 EhcGetRootHubPortStatus (
334 IN EFI_USB2_HC_PROTOCOL
*This
,
336 OUT EFI_USB_PORT_STATUS
*PortStatus
347 UINT32 DbgCtrlStatus
;
349 if (PortStatus
== NULL
) {
350 return EFI_INVALID_PARAMETER
;
353 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
355 Ehc
= EHC_FROM_THIS (This
);
356 Status
= EFI_SUCCESS
;
358 TotalPort
= (Ehc
->HcStructParams
& HCSP_NPORTS
);
360 if (PortNumber
>= TotalPort
) {
361 Status
= EFI_INVALID_PARAMETER
;
365 Offset
= (UINT32
) (EHC_PORT_STAT_OFFSET
+ (4 * PortNumber
));
366 PortStatus
->PortStatus
= 0;
367 PortStatus
->PortChangeStatus
= 0;
369 if ((Ehc
->DebugPortNum
!= 0) && (PortNumber
== (Ehc
->DebugPortNum
- 1))) {
370 DbgCtrlStatus
= EhcReadDbgRegister(Ehc
, 0);
371 if ((DbgCtrlStatus
& (USB_DEBUG_PORT_IN_USE
| USB_DEBUG_PORT_OWNER
)) == (USB_DEBUG_PORT_IN_USE
| USB_DEBUG_PORT_OWNER
)) {
376 State
= EhcReadOpReg (Ehc
, Offset
);
379 // Identify device speed. If in K state, it is low speed.
380 // If the port is enabled after reset, the device is of
381 // high speed. The USB bus driver should retrieve the actual
382 // port speed after reset.
384 if (EHC_BIT_IS_SET (State
, PORTSC_LINESTATE_K
)) {
385 PortStatus
->PortStatus
|= USB_PORT_STAT_LOW_SPEED
;
387 } else if (EHC_BIT_IS_SET (State
, PORTSC_ENABLED
)) {
388 PortStatus
->PortStatus
|= USB_PORT_STAT_HIGH_SPEED
;
392 // Convert the EHCI port/port change state to UEFI status
394 MapSize
= sizeof (mUsbPortStateMap
) / sizeof (USB_PORT_STATE_MAP
);
396 for (Index
= 0; Index
< MapSize
; Index
++) {
397 if (EHC_BIT_IS_SET (State
, mUsbPortStateMap
[Index
].HwState
)) {
398 PortStatus
->PortStatus
= (UINT16
) (PortStatus
->PortStatus
| mUsbPortStateMap
[Index
].UefiState
);
402 MapSize
= sizeof (mUsbPortChangeMap
) / sizeof (USB_PORT_STATE_MAP
);
404 for (Index
= 0; Index
< MapSize
; Index
++) {
405 if (EHC_BIT_IS_SET (State
, mUsbPortChangeMap
[Index
].HwState
)) {
406 PortStatus
->PortChangeStatus
= (UINT16
) (PortStatus
->PortChangeStatus
| mUsbPortChangeMap
[Index
].UefiState
);
411 gBS
->RestoreTPL (OldTpl
);
417 Sets a feature for the specified root hub port.
419 @param This This EFI_USB2_HC_PROTOCOL instance.
420 @param PortNumber Root hub port to set.
421 @param PortFeature Feature to set.
423 @retval EFI_SUCCESS The feature specified by PortFeature was set.
424 @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
425 @retval EFI_DEVICE_ERROR Can't read register.
430 EhcSetRootHubPortFeature (
431 IN EFI_USB2_HC_PROTOCOL
*This
,
433 IN EFI_USB_PORT_FEATURE PortFeature
443 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
444 Ehc
= EHC_FROM_THIS (This
);
445 Status
= EFI_SUCCESS
;
447 TotalPort
= (Ehc
->HcStructParams
& HCSP_NPORTS
);
449 if (PortNumber
>= TotalPort
) {
450 Status
= EFI_INVALID_PARAMETER
;
454 Offset
= (UINT32
) (EHC_PORT_STAT_OFFSET
+ (4 * PortNumber
));
455 State
= EhcReadOpReg (Ehc
, Offset
);
458 // Mask off the port status change bits, these bits are
461 State
&= ~PORTSC_CHANGE_MASK
;
463 switch (PortFeature
) {
464 case EfiUsbPortEnable
:
466 // Sofeware can't set this bit, Port can only be enable by
467 // EHCI as a part of the reset and enable
469 State
|= PORTSC_ENABLED
;
470 EhcWriteOpReg (Ehc
, Offset
, State
);
473 case EfiUsbPortSuspend
:
474 State
|= PORTSC_SUSPEND
;
475 EhcWriteOpReg (Ehc
, Offset
, State
);
478 case EfiUsbPortReset
:
480 // Make sure Host Controller not halt before reset it
482 if (EhcIsHalt (Ehc
)) {
483 Status
= EhcRunHC (Ehc
, EHC_GENERIC_TIMEOUT
);
485 if (EFI_ERROR (Status
)) {
486 DEBUG ((EFI_D_INFO
, "EhcSetRootHubPortFeature :failed to start HC - %r\n", Status
));
492 // Set one to PortReset bit must also set zero to PortEnable bit
494 State
|= PORTSC_RESET
;
495 State
&= ~PORTSC_ENABLED
;
496 EhcWriteOpReg (Ehc
, Offset
, State
);
499 case EfiUsbPortPower
:
501 // Set port power bit when PPC is 1
503 if ((Ehc
->HcCapParams
& HCSP_PPC
) == HCSP_PPC
) {
504 State
|= PORTSC_POWER
;
505 EhcWriteOpReg (Ehc
, Offset
, State
);
509 case EfiUsbPortOwner
:
510 State
|= PORTSC_OWNER
;
511 EhcWriteOpReg (Ehc
, Offset
, State
);
515 Status
= EFI_INVALID_PARAMETER
;
519 DEBUG ((EFI_D_INFO
, "EhcSetRootHubPortFeature: exit status %r\n", Status
));
521 gBS
->RestoreTPL (OldTpl
);
527 Clears a feature for the specified root hub port.
529 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
530 @param PortNumber Specifies the root hub port whose feature is
531 requested to be cleared.
532 @param PortFeature Indicates the feature selector associated with the
533 feature clear request.
535 @retval EFI_SUCCESS The feature specified by PortFeature was cleared
536 for the USB root hub port specified by PortNumber.
537 @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
538 @retval EFI_DEVICE_ERROR Can't read register.
543 EhcClearRootHubPortFeature (
544 IN EFI_USB2_HC_PROTOCOL
*This
,
546 IN EFI_USB_PORT_FEATURE PortFeature
556 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
557 Ehc
= EHC_FROM_THIS (This
);
558 Status
= EFI_SUCCESS
;
560 TotalPort
= (Ehc
->HcStructParams
& HCSP_NPORTS
);
562 if (PortNumber
>= TotalPort
) {
563 Status
= EFI_INVALID_PARAMETER
;
567 Offset
= EHC_PORT_STAT_OFFSET
+ (4 * PortNumber
);
568 State
= EhcReadOpReg (Ehc
, Offset
);
569 State
&= ~PORTSC_CHANGE_MASK
;
571 switch (PortFeature
) {
572 case EfiUsbPortEnable
:
574 // Clear PORT_ENABLE feature means disable port.
576 State
&= ~PORTSC_ENABLED
;
577 EhcWriteOpReg (Ehc
, Offset
, State
);
580 case EfiUsbPortSuspend
:
582 // A write of zero to this bit is ignored by the host
583 // controller. The host controller will unconditionally
584 // set this bit to a zero when:
585 // 1. software sets the Forct Port Resume bit to a zero from a one.
586 // 2. software sets the Port Reset bit to a one frome a zero.
588 State
&= ~PORSTSC_RESUME
;
589 EhcWriteOpReg (Ehc
, Offset
, State
);
592 case EfiUsbPortReset
:
594 // Clear PORT_RESET means clear the reset signal.
596 State
&= ~PORTSC_RESET
;
597 EhcWriteOpReg (Ehc
, Offset
, State
);
600 case EfiUsbPortOwner
:
602 // Clear port owner means this port owned by EHC
604 State
&= ~PORTSC_OWNER
;
605 EhcWriteOpReg (Ehc
, Offset
, State
);
608 case EfiUsbPortConnectChange
:
610 // Clear connect status change
612 State
|= PORTSC_CONN_CHANGE
;
613 EhcWriteOpReg (Ehc
, Offset
, State
);
616 case EfiUsbPortEnableChange
:
618 // Clear enable status change
620 State
|= PORTSC_ENABLE_CHANGE
;
621 EhcWriteOpReg (Ehc
, Offset
, State
);
624 case EfiUsbPortOverCurrentChange
:
626 // Clear PortOverCurrent change
628 State
|= PORTSC_OVERCUR_CHANGE
;
629 EhcWriteOpReg (Ehc
, Offset
, State
);
632 case EfiUsbPortPower
:
634 // Clear port power bit when PPC is 1
636 if ((Ehc
->HcCapParams
& HCSP_PPC
) == HCSP_PPC
) {
637 State
&= ~PORTSC_POWER
;
638 EhcWriteOpReg (Ehc
, Offset
, State
);
641 case EfiUsbPortSuspendChange
:
642 case EfiUsbPortResetChange
:
644 // Not supported or not related operation
649 Status
= EFI_INVALID_PARAMETER
;
654 DEBUG ((EFI_D_INFO
, "EhcClearRootHubPortFeature: exit status %r\n", Status
));
655 gBS
->RestoreTPL (OldTpl
);
661 Submits control transfer to a target USB device.
663 @param This This EFI_USB2_HC_PROTOCOL instance.
664 @param DeviceAddress The target device address.
665 @param DeviceSpeed Target device speed.
666 @param MaximumPacketLength Maximum packet size the default control transfer
667 endpoint is capable of sending or receiving.
668 @param Request USB device request to send.
669 @param TransferDirection Specifies the data direction for the data stage
670 @param Data Data buffer to be transmitted or received from USB
672 @param DataLength The size (in bytes) of the data buffer.
673 @param TimeOut Indicates the maximum timeout, in millisecond.
674 @param Translator Transaction translator to be used by this device.
675 @param TransferResult Return the result of this control transfer.
677 @retval EFI_SUCCESS Transfer was completed successfully.
678 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resources.
679 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
680 @retval EFI_TIMEOUT Transfer failed due to timeout.
681 @retval EFI_DEVICE_ERROR Transfer failed due to host controller or device error.
687 IN EFI_USB2_HC_PROTOCOL
*This
,
688 IN UINT8 DeviceAddress
,
689 IN UINT8 DeviceSpeed
,
690 IN UINTN MaximumPacketLength
,
691 IN EFI_USB_DEVICE_REQUEST
*Request
,
692 IN EFI_USB_DATA_DIRECTION TransferDirection
,
694 IN OUT UINTN
*DataLength
,
696 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
697 OUT UINT32
*TransferResult
707 // Validate parameters
709 if ((Request
== NULL
) || (TransferResult
== NULL
)) {
710 return EFI_INVALID_PARAMETER
;
713 if ((TransferDirection
!= EfiUsbDataIn
) &&
714 (TransferDirection
!= EfiUsbDataOut
) &&
715 (TransferDirection
!= EfiUsbNoData
)) {
716 return EFI_INVALID_PARAMETER
;
719 if ((TransferDirection
== EfiUsbNoData
) &&
720 ((Data
!= NULL
) || (*DataLength
!= 0))) {
721 return EFI_INVALID_PARAMETER
;
724 if ((TransferDirection
!= EfiUsbNoData
) &&
725 ((Data
== NULL
) || (*DataLength
== 0))) {
726 return EFI_INVALID_PARAMETER
;
729 if ((MaximumPacketLength
!= 8) && (MaximumPacketLength
!= 16) &&
730 (MaximumPacketLength
!= 32) && (MaximumPacketLength
!= 64)) {
731 return EFI_INVALID_PARAMETER
;
734 if ((DeviceSpeed
== EFI_USB_SPEED_LOW
) && (MaximumPacketLength
!= 8)) {
735 return EFI_INVALID_PARAMETER
;
738 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
739 Ehc
= EHC_FROM_THIS (This
);
741 Status
= EFI_DEVICE_ERROR
;
742 *TransferResult
= EFI_USB_ERR_SYSTEM
;
744 if (EhcIsHalt (Ehc
) || EhcIsSysError (Ehc
)) {
745 DEBUG ((EFI_D_ERROR
, "EhcControlTransfer: HC halted at entrance\n"));
747 EhcAckAllInterrupt (Ehc
);
751 EhcAckAllInterrupt (Ehc
);
754 // Create a new URB, insert it into the asynchronous
755 // schedule list, then poll the execution status.
758 // Encode the direction in address, although default control
759 // endpoint is bidirectional. EhcCreateUrb expects this
760 // combination of Ep addr and its direction.
762 Endpoint
= (UINT8
) (0 | ((TransferDirection
== EfiUsbDataIn
) ? 0x80 : 0));
781 DEBUG ((EFI_D_ERROR
, "EhcControlTransfer: failed to create URB"));
783 Status
= EFI_OUT_OF_RESOURCES
;
787 EhcLinkQhToAsync (Ehc
, Urb
->Qh
);
788 Status
= EhcExecTransfer (Ehc
, Urb
, TimeOut
);
789 EhcUnlinkQhFromAsync (Ehc
, Urb
->Qh
);
792 // Get the status from URB. The result is updated in EhcCheckUrbResult
793 // which is called by EhcExecTransfer
795 *TransferResult
= Urb
->Result
;
796 *DataLength
= Urb
->Completed
;
798 if (*TransferResult
== EFI_USB_NOERROR
) {
799 Status
= EFI_SUCCESS
;
802 EhcAckAllInterrupt (Ehc
);
803 EhcFreeUrb (Ehc
, Urb
);
806 Ehc
->PciIo
->Flush (Ehc
->PciIo
);
807 gBS
->RestoreTPL (OldTpl
);
809 if (EFI_ERROR (Status
)) {
810 DEBUG ((EFI_D_ERROR
, "EhcControlTransfer: error - %r, transfer - %x\n", Status
, *TransferResult
));
818 Submits bulk transfer to a bulk endpoint of a USB device.
820 @param This This EFI_USB2_HC_PROTOCOL instance.
821 @param DeviceAddress Target device address.
822 @param EndPointAddress Endpoint number and its direction in bit 7.
823 @param DeviceSpeed Device speed, Low speed device doesn't support bulk
825 @param MaximumPacketLength Maximum packet size the endpoint is capable of
826 sending or receiving.
827 @param DataBuffersNumber Number of data buffers prepared for the transfer.
828 @param Data Array of pointers to the buffers of data to transmit
829 from or receive into.
830 @param DataLength The lenght of the data buffer.
831 @param DataToggle On input, the initial data toggle for the transfer;
832 On output, it is updated to to next data toggle to
833 use of the subsequent bulk transfer.
834 @param TimeOut Indicates the maximum time, in millisecond, which
835 the transfer is allowed to complete.
836 @param Translator A pointr to the transaction translator data.
837 @param TransferResult A pointer to the detailed result information of the
840 @retval EFI_SUCCESS The transfer was completed successfully.
841 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
842 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
843 @retval EFI_TIMEOUT The transfer failed due to timeout.
844 @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
850 IN EFI_USB2_HC_PROTOCOL
*This
,
851 IN UINT8 DeviceAddress
,
852 IN UINT8 EndPointAddress
,
853 IN UINT8 DeviceSpeed
,
854 IN UINTN MaximumPacketLength
,
855 IN UINT8 DataBuffersNumber
,
856 IN OUT VOID
*Data
[EFI_USB_MAX_BULK_BUFFER_NUM
],
857 IN OUT UINTN
*DataLength
,
858 IN OUT UINT8
*DataToggle
,
860 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
861 OUT UINT32
*TransferResult
870 // Validate the parameters
872 if ((DataLength
== NULL
) || (*DataLength
== 0) ||
873 (Data
== NULL
) || (Data
[0] == NULL
) || (TransferResult
== NULL
)) {
874 return EFI_INVALID_PARAMETER
;
877 if ((*DataToggle
!= 0) && (*DataToggle
!= 1)) {
878 return EFI_INVALID_PARAMETER
;
881 if ((DeviceSpeed
== EFI_USB_SPEED_LOW
) ||
882 ((DeviceSpeed
== EFI_USB_SPEED_FULL
) && (MaximumPacketLength
> 64)) ||
883 ((EFI_USB_SPEED_HIGH
== DeviceSpeed
) && (MaximumPacketLength
> 512))) {
884 return EFI_INVALID_PARAMETER
;
887 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
888 Ehc
= EHC_FROM_THIS (This
);
890 *TransferResult
= EFI_USB_ERR_SYSTEM
;
891 Status
= EFI_DEVICE_ERROR
;
893 if (EhcIsHalt (Ehc
) || EhcIsSysError (Ehc
)) {
894 DEBUG ((EFI_D_ERROR
, "EhcBulkTransfer: HC is halted\n"));
896 EhcAckAllInterrupt (Ehc
);
900 EhcAckAllInterrupt (Ehc
);
903 // Create a new URB, insert it into the asynchronous
904 // schedule list, then poll the execution status.
924 DEBUG ((EFI_D_ERROR
, "EhcBulkTransfer: failed to create URB\n"));
926 Status
= EFI_OUT_OF_RESOURCES
;
930 EhcLinkQhToAsync (Ehc
, Urb
->Qh
);
931 Status
= EhcExecTransfer (Ehc
, Urb
, TimeOut
);
932 EhcUnlinkQhFromAsync (Ehc
, Urb
->Qh
);
934 *TransferResult
= Urb
->Result
;
935 *DataLength
= Urb
->Completed
;
936 *DataToggle
= Urb
->DataToggle
;
938 if (*TransferResult
== EFI_USB_NOERROR
) {
939 Status
= EFI_SUCCESS
;
942 EhcAckAllInterrupt (Ehc
);
943 EhcFreeUrb (Ehc
, Urb
);
946 Ehc
->PciIo
->Flush (Ehc
->PciIo
);
947 gBS
->RestoreTPL (OldTpl
);
949 if (EFI_ERROR (Status
)) {
950 DEBUG ((EFI_D_ERROR
, "EhcBulkTransfer: error - %r, transfer - %x\n", Status
, *TransferResult
));
958 Submits an asynchronous interrupt transfer to an
959 interrupt endpoint of a USB device.
961 @param This This EFI_USB2_HC_PROTOCOL instance.
962 @param DeviceAddress Target device address.
963 @param EndPointAddress Endpoint number and its direction encoded in bit 7
964 @param DeviceSpeed Indicates device speed.
965 @param MaximumPacketLength Maximum packet size the target endpoint is capable
966 @param IsNewTransfer If TRUE, to submit an new asynchronous interrupt
967 transfer If FALSE, to remove the specified
968 asynchronous interrupt.
969 @param DataToggle On input, the initial data toggle to use; on output,
970 it is updated to indicate the next data toggle.
971 @param PollingInterval The he interval, in milliseconds, that the transfer
973 @param DataLength The length of data to receive at the rate specified
975 @param Translator Transaction translator to use.
976 @param CallBackFunction Function to call at the rate specified by
978 @param Context Context to CallBackFunction.
980 @retval EFI_SUCCESS The request has been successfully submitted or canceled.
981 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
982 @retval EFI_OUT_OF_RESOURCES The request failed due to a lack of resources.
983 @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
988 EhcAsyncInterruptTransfer (
989 IN EFI_USB2_HC_PROTOCOL
* This
,
990 IN UINT8 DeviceAddress
,
991 IN UINT8 EndPointAddress
,
992 IN UINT8 DeviceSpeed
,
993 IN UINTN MaximumPacketLength
,
994 IN BOOLEAN IsNewTransfer
,
995 IN OUT UINT8
*DataToggle
,
996 IN UINTN PollingInterval
,
998 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
* Translator
,
999 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction
,
1000 IN VOID
*Context OPTIONAL
1010 // Validate parameters
1012 if (!EHCI_IS_DATAIN (EndPointAddress
)) {
1013 return EFI_INVALID_PARAMETER
;
1016 if (IsNewTransfer
) {
1017 if (DataLength
== 0) {
1018 return EFI_INVALID_PARAMETER
;
1021 if ((*DataToggle
!= 1) && (*DataToggle
!= 0)) {
1022 return EFI_INVALID_PARAMETER
;
1025 if ((PollingInterval
> 255) || (PollingInterval
< 1)) {
1026 return EFI_INVALID_PARAMETER
;
1030 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
1031 Ehc
= EHC_FROM_THIS (This
);
1034 // Delete Async interrupt transfer request. DataToggle will return
1035 // the next data toggle to use.
1037 if (!IsNewTransfer
) {
1038 Status
= EhciDelAsyncIntTransfer (Ehc
, DeviceAddress
, EndPointAddress
, DataToggle
);
1040 DEBUG ((EFI_D_INFO
, "EhcAsyncInterruptTransfer: remove old transfer - %r\n", Status
));
1044 Status
= EFI_SUCCESS
;
1046 if (EhcIsHalt (Ehc
) || EhcIsSysError (Ehc
)) {
1047 DEBUG ((EFI_D_ERROR
, "EhcAsyncInterruptTransfer: HC is halt\n"));
1048 EhcAckAllInterrupt (Ehc
);
1050 Status
= EFI_DEVICE_ERROR
;
1054 EhcAckAllInterrupt (Ehc
);
1056 Data
= AllocatePool (DataLength
);
1059 DEBUG ((EFI_D_ERROR
, "EhcAsyncInterruptTransfer: failed to allocate buffer\n"));
1061 Status
= EFI_OUT_OF_RESOURCES
;
1065 Urb
= EhcCreateUrb (
1071 MaximumPacketLength
,
1073 EHC_INT_TRANSFER_ASYNC
,
1083 DEBUG ((EFI_D_ERROR
, "EhcAsyncInterruptTransfer: failed to create URB\n"));
1085 gBS
->FreePool (Data
);
1086 Status
= EFI_OUT_OF_RESOURCES
;
1091 // New asynchronous transfer must inserted to the head.
1092 // Check the comments in EhcMoniteAsyncRequests
1094 EhcLinkQhToPeriod (Ehc
, Urb
->Qh
);
1095 InsertHeadList (&Ehc
->AsyncIntTransfers
, &Urb
->UrbList
);
1098 Ehc
->PciIo
->Flush (Ehc
->PciIo
);
1099 gBS
->RestoreTPL (OldTpl
);
1106 Submits synchronous interrupt transfer to an interrupt endpoint
1109 @param This This EFI_USB2_HC_PROTOCOL instance.
1110 @param DeviceAddress Target device address.
1111 @param EndPointAddress Endpoint number and its direction encoded in bit 7
1112 @param DeviceSpeed Indicates device speed.
1113 @param MaximumPacketLength Maximum packet size the target endpoint is capable
1114 of sending or receiving.
1115 @param Data Buffer of data that will be transmitted to USB
1116 device or received from USB device.
1117 @param DataLength On input, the size, in bytes, of the data buffer; On
1118 output, the number of bytes transferred.
1119 @param DataToggle On input, the initial data toggle to use; on output,
1120 it is updated to indicate the next data toggle.
1121 @param TimeOut Maximum time, in second, to complete.
1122 @param Translator Transaction translator to use.
1123 @param TransferResult Variable to receive the transfer result.
1125 @return EFI_SUCCESS The transfer was completed successfully.
1126 @return EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
1127 @return EFI_INVALID_PARAMETER Some parameters are invalid.
1128 @return EFI_TIMEOUT The transfer failed due to timeout.
1129 @return EFI_DEVICE_ERROR The failed due to host controller or device error
1134 EhcSyncInterruptTransfer (
1135 IN EFI_USB2_HC_PROTOCOL
*This
,
1136 IN UINT8 DeviceAddress
,
1137 IN UINT8 EndPointAddress
,
1138 IN UINT8 DeviceSpeed
,
1139 IN UINTN MaximumPacketLength
,
1141 IN OUT UINTN
*DataLength
,
1142 IN OUT UINT8
*DataToggle
,
1144 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
1145 OUT UINT32
*TransferResult
1154 // Validates parameters
1156 if ((DataLength
== NULL
) || (*DataLength
== 0) ||
1157 (Data
== NULL
) || (TransferResult
== NULL
)) {
1158 return EFI_INVALID_PARAMETER
;
1161 if (!EHCI_IS_DATAIN (EndPointAddress
)) {
1162 return EFI_INVALID_PARAMETER
;
1165 if ((*DataToggle
!= 1) && (*DataToggle
!= 0)) {
1166 return EFI_INVALID_PARAMETER
;
1169 if (((DeviceSpeed
== EFI_USB_SPEED_LOW
) && (MaximumPacketLength
!= 8)) ||
1170 ((DeviceSpeed
== EFI_USB_SPEED_FULL
) && (MaximumPacketLength
> 64)) ||
1171 ((DeviceSpeed
== EFI_USB_SPEED_HIGH
) && (MaximumPacketLength
> 3072))) {
1172 return EFI_INVALID_PARAMETER
;
1175 OldTpl
= gBS
->RaiseTPL (EHC_TPL
);
1176 Ehc
= EHC_FROM_THIS (This
);
1178 *TransferResult
= EFI_USB_ERR_SYSTEM
;
1179 Status
= EFI_DEVICE_ERROR
;
1181 if (EhcIsHalt (Ehc
) || EhcIsSysError (Ehc
)) {
1182 DEBUG ((EFI_D_ERROR
, "EhcSyncInterruptTransfer: HC is halt\n"));
1184 EhcAckAllInterrupt (Ehc
);
1188 EhcAckAllInterrupt (Ehc
);
1190 Urb
= EhcCreateUrb (
1196 MaximumPacketLength
,
1198 EHC_INT_TRANSFER_SYNC
,
1208 DEBUG ((EFI_D_ERROR
, "EhcSyncInterruptTransfer: failed to create URB\n"));
1210 Status
= EFI_OUT_OF_RESOURCES
;
1214 EhcLinkQhToPeriod (Ehc
, Urb
->Qh
);
1215 Status
= EhcExecTransfer (Ehc
, Urb
, TimeOut
);
1216 EhcUnlinkQhFromPeriod (Ehc
, Urb
->Qh
);
1218 *TransferResult
= Urb
->Result
;
1219 *DataLength
= Urb
->Completed
;
1220 *DataToggle
= Urb
->DataToggle
;
1222 if (*TransferResult
== EFI_USB_NOERROR
) {
1223 Status
= EFI_SUCCESS
;
1227 Ehc
->PciIo
->Flush (Ehc
->PciIo
);
1228 gBS
->RestoreTPL (OldTpl
);
1230 if (EFI_ERROR (Status
)) {
1231 DEBUG ((EFI_D_ERROR
, "EhcSyncInterruptTransfer: error - %r, transfer - %x\n", Status
, *TransferResult
));
1239 Submits isochronous transfer to a target USB device.
1241 @param This This EFI_USB2_HC_PROTOCOL instance.
1242 @param DeviceAddress Target device address.
1243 @param EndPointAddress End point address with its direction.
1244 @param DeviceSpeed Device speed, Low speed device doesn't support this
1246 @param MaximumPacketLength Maximum packet size that the endpoint is capable of
1247 sending or receiving.
1248 @param DataBuffersNumber Number of data buffers prepared for the transfer.
1249 @param Data Array of pointers to the buffers of data that will
1250 be transmitted to USB device or received from USB
1252 @param DataLength The size, in bytes, of the data buffer.
1253 @param Translator Transaction translator to use.
1254 @param TransferResult Variable to receive the transfer result.
1256 @return EFI_UNSUPPORTED Isochronous transfer is unsupported.
1261 EhcIsochronousTransfer (
1262 IN EFI_USB2_HC_PROTOCOL
*This
,
1263 IN UINT8 DeviceAddress
,
1264 IN UINT8 EndPointAddress
,
1265 IN UINT8 DeviceSpeed
,
1266 IN UINTN MaximumPacketLength
,
1267 IN UINT8 DataBuffersNumber
,
1268 IN OUT VOID
*Data
[EFI_USB_MAX_ISO_BUFFER_NUM
],
1269 IN UINTN DataLength
,
1270 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
1271 OUT UINT32
*TransferResult
1274 return EFI_UNSUPPORTED
;
1279 Submits Async isochronous transfer to a target USB device.
1281 @param This This EFI_USB2_HC_PROTOCOL instance.
1282 @param DeviceAddress Target device address.
1283 @param EndPointAddress End point address with its direction.
1284 @param DeviceSpeed Device speed, Low speed device doesn't support this
1286 @param MaximumPacketLength Maximum packet size that the endpoint is capable of
1287 sending or receiving.
1288 @param DataBuffersNumber Number of data buffers prepared for the transfer.
1289 @param Data Array of pointers to the buffers of data that will
1290 be transmitted to USB device or received from USB
1292 @param DataLength The size, in bytes, of the data buffer.
1293 @param Translator Transaction translator to use.
1294 @param IsochronousCallBack Function to be called when the transfer complete.
1295 @param Context Context passed to the call back function as
1298 @return EFI_UNSUPPORTED Isochronous transfer isn't supported.
1303 EhcAsyncIsochronousTransfer (
1304 IN EFI_USB2_HC_PROTOCOL
*This
,
1305 IN UINT8 DeviceAddress
,
1306 IN UINT8 EndPointAddress
,
1307 IN UINT8 DeviceSpeed
,
1308 IN UINTN MaximumPacketLength
,
1309 IN UINT8 DataBuffersNumber
,
1310 IN OUT VOID
*Data
[EFI_USB_MAX_ISO_BUFFER_NUM
],
1311 IN UINTN DataLength
,
1312 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
1313 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack
,
1317 return EFI_UNSUPPORTED
;
1321 Entry point for EFI drivers.
1323 @param ImageHandle EFI_HANDLE.
1324 @param SystemTable EFI_SYSTEM_TABLE.
1326 @return EFI_SUCCESS Success.
1327 EFI_DEVICE_ERROR Fail.
1332 EhcDriverEntryPoint (
1333 IN EFI_HANDLE ImageHandle
,
1334 IN EFI_SYSTEM_TABLE
*SystemTable
1337 return EfiLibInstallDriverBindingComponentName2 (
1340 &gEhciDriverBinding
,
1342 &gEhciComponentName
,
1343 &gEhciComponentName2
1349 Test to see if this driver supports ControllerHandle. Any
1350 ControllerHandle that has Usb2HcProtocol installed will
1353 @param This Protocol instance pointer.
1354 @param Controller Handle of device to test.
1355 @param RemainingDevicePath Not used.
1357 @return EFI_SUCCESS This driver supports this device.
1358 @return EFI_UNSUPPORTED This driver does not support this device.
1363 EhcDriverBindingSupported (
1364 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1365 IN EFI_HANDLE Controller
,
1366 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1370 EFI_PCI_IO_PROTOCOL
*PciIo
;
1371 USB_CLASSC UsbClassCReg
;
1374 // Test whether there is PCI IO Protocol attached on the controller handle.
1376 Status
= gBS
->OpenProtocol (
1378 &gEfiPciIoProtocolGuid
,
1380 This
->DriverBindingHandle
,
1382 EFI_OPEN_PROTOCOL_BY_DRIVER
1385 if (EFI_ERROR (Status
)) {
1386 return EFI_UNSUPPORTED
;
1389 Status
= PciIo
->Pci
.Read (
1392 PCI_CLASSCODE_OFFSET
,
1393 sizeof (USB_CLASSC
) / sizeof (UINT8
),
1397 if (EFI_ERROR (Status
)) {
1398 Status
= EFI_UNSUPPORTED
;
1403 // Test whether the controller belongs to Ehci type
1405 if ((UsbClassCReg
.BaseCode
!= PCI_CLASS_SERIAL
) || (UsbClassCReg
.SubClassCode
!= PCI_CLASS_SERIAL_USB
)
1406 || ((UsbClassCReg
.ProgInterface
!= PCI_IF_EHCI
) && (UsbClassCReg
.ProgInterface
!=PCI_IF_UHCI
))) {
1408 Status
= EFI_UNSUPPORTED
;
1412 gBS
->CloseProtocol (
1414 &gEfiPciIoProtocolGuid
,
1415 This
->DriverBindingHandle
,
1423 Get the usb debug port related information.
1425 @param Ehc The EHCI device.
1427 @retval RETURN_SUCCESS Get debug port number, bar and offset successfully.
1428 @retval Others The usb host controller does not supported usb debug port capability.
1432 EhcGetUsbDebugPortInfo (
1436 EFI_PCI_IO_PROTOCOL
*PciIo
;
1438 UINT8 CapabilityPtr
;
1443 ASSERT (Ehc
->PciIo
!= NULL
);
1447 // Detect if the EHCI host controller support Capaility Pointer.
1449 Status
= PciIo
->Pci
.Read (
1452 PCI_PRIMARY_STATUS_OFFSET
,
1457 if (EFI_ERROR (Status
)) {
1461 if ((PciStatus
& EFI_PCI_STATUS_CAPABILITY
) == 0) {
1463 // The Pci Device Doesn't Support Capability Pointer.
1465 return EFI_UNSUPPORTED
;
1469 // Get Pointer To Capability List
1471 Status
= PciIo
->Pci
.Read (
1474 PCI_CAPBILITY_POINTER_OFFSET
,
1479 if (EFI_ERROR (Status
)) {
1484 // Find Capability ID 0xA, Which Is For Debug Port
1486 while (CapabilityPtr
!= 0) {
1487 Status
= PciIo
->Pci
.Read (
1495 if (EFI_ERROR (Status
)) {
1499 if (CapabilityId
== EHC_DEBUG_PORT_CAP_ID
) {
1503 Status
= PciIo
->Pci
.Read (
1511 if (EFI_ERROR (Status
)) {
1517 // No Debug Port Capability Found
1519 if (CapabilityPtr
== 0) {
1520 return EFI_UNSUPPORTED
;
1524 // Get The Base Address Of Debug Port Register In Debug Port Capability Register
1526 Status
= PciIo
->Pci
.Read (
1534 if (EFI_ERROR (Status
)) {
1538 Ehc
->DebugPortOffset
= DebugPort
& 0x1FFF;
1539 Ehc
->DebugPortBarNum
= (UINT8
)((DebugPort
>> 13) - 1);
1540 Ehc
->DebugPortNum
= (UINT8
)((Ehc
->HcStructParams
& 0x00F00000) >> 20);
1547 Create and initialize a USB2_HC_DEV.
1549 @param PciIo The PciIo on this device.
1550 @param OriginalPciAttributes Original PCI attributes.
1552 @return The allocated and initialized USB2_HC_DEV structure if created,
1558 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1559 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
1560 IN UINT64 OriginalPciAttributes
1566 Ehc
= AllocateZeroPool (sizeof (USB2_HC_DEV
));
1573 // Init EFI_USB2_HC_PROTOCOL interface and private data structure
1575 Ehc
->Signature
= USB2_HC_DEV_SIGNATURE
;
1577 Ehc
->Usb2Hc
.GetCapability
= EhcGetCapability
;
1578 Ehc
->Usb2Hc
.Reset
= EhcReset
;
1579 Ehc
->Usb2Hc
.GetState
= EhcGetState
;
1580 Ehc
->Usb2Hc
.SetState
= EhcSetState
;
1581 Ehc
->Usb2Hc
.ControlTransfer
= EhcControlTransfer
;
1582 Ehc
->Usb2Hc
.BulkTransfer
= EhcBulkTransfer
;
1583 Ehc
->Usb2Hc
.AsyncInterruptTransfer
= EhcAsyncInterruptTransfer
;
1584 Ehc
->Usb2Hc
.SyncInterruptTransfer
= EhcSyncInterruptTransfer
;
1585 Ehc
->Usb2Hc
.IsochronousTransfer
= EhcIsochronousTransfer
;
1586 Ehc
->Usb2Hc
.AsyncIsochronousTransfer
= EhcAsyncIsochronousTransfer
;
1587 Ehc
->Usb2Hc
.GetRootHubPortStatus
= EhcGetRootHubPortStatus
;
1588 Ehc
->Usb2Hc
.SetRootHubPortFeature
= EhcSetRootHubPortFeature
;
1589 Ehc
->Usb2Hc
.ClearRootHubPortFeature
= EhcClearRootHubPortFeature
;
1590 Ehc
->Usb2Hc
.MajorRevision
= 0x2;
1591 Ehc
->Usb2Hc
.MinorRevision
= 0x0;
1594 Ehc
->DevicePath
= DevicePath
;
1595 Ehc
->OriginalPciAttributes
= OriginalPciAttributes
;
1597 InitializeListHead (&Ehc
->AsyncIntTransfers
);
1599 Ehc
->HcStructParams
= EhcReadCapRegister (Ehc
, EHC_HCSPARAMS_OFFSET
);
1600 Ehc
->HcCapParams
= EhcReadCapRegister (Ehc
, EHC_HCCPARAMS_OFFSET
);
1601 Ehc
->CapLen
= EhcReadCapRegister (Ehc
, EHC_CAPLENGTH_OFFSET
) & 0x0FF;
1603 DEBUG ((EFI_D_INFO
, "EhcCreateUsb2Hc: capability length %d\n", Ehc
->CapLen
));
1606 // EHCI Controllers with a CapLen of 0 are ignored.
1608 if (Ehc
->CapLen
== 0) {
1609 gBS
->FreePool (Ehc
);
1613 EhcGetUsbDebugPortInfo (Ehc
);
1616 // Create AsyncRequest Polling Timer
1618 Status
= gBS
->CreateEvent (
1619 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
1621 EhcMonitorAsyncRequests
,
1626 if (EFI_ERROR (Status
)) {
1627 gBS
->FreePool (Ehc
);
1635 One notified function to stop the Host Controller when gBS->ExitBootServices() called.
1637 @param Event Pointer to this event
1638 @param Context Event hanlder private data
1643 EhcExitBootService (
1651 Ehc
= (USB2_HC_DEV
*) Context
;
1654 // Reset the Host Controller
1656 EhcResetHC (Ehc
, EHC_RESET_TIMEOUT
);
1661 Starting the Usb EHCI Driver.
1663 @param This Protocol instance pointer.
1664 @param Controller Handle of device to test.
1665 @param RemainingDevicePath Not used.
1667 @return EFI_SUCCESS supports this device.
1668 @return EFI_UNSUPPORTED do not support this device.
1669 @return EFI_DEVICE_ERROR cannot be started due to device Error.
1670 @return EFI_OUT_OF_RESOURCES cannot allocate resources.
1675 EhcDriverBindingStart (
1676 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1677 IN EFI_HANDLE Controller
,
1678 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1683 EFI_PCI_IO_PROTOCOL
*PciIo
;
1684 EFI_PCI_IO_PROTOCOL
*Instance
;
1686 UINT64 OriginalPciAttributes
;
1687 BOOLEAN PciAttributesSaved
;
1688 USB_CLASSC UsbClassCReg
;
1689 EFI_HANDLE
*HandleBuffer
;
1690 UINTN NumberOfHandles
;
1692 UINTN UhciSegmentNumber
;
1693 UINTN UhciBusNumber
;
1694 UINTN UhciDeviceNumber
;
1695 UINTN UhciFunctionNumber
;
1696 UINTN EhciSegmentNumber
;
1697 UINTN EhciBusNumber
;
1698 UINTN EhciDeviceNumber
;
1699 UINTN EhciFunctionNumber
;
1701 EFI_DEVICE_PATH_PROTOCOL
*HcDevicePath
;
1704 // Open the PciIo Protocol, then enable the USB host controller
1706 Status
= gBS
->OpenProtocol (
1708 &gEfiPciIoProtocolGuid
,
1710 This
->DriverBindingHandle
,
1712 EFI_OPEN_PROTOCOL_BY_DRIVER
1715 if (EFI_ERROR (Status
)) {
1720 // Open Device Path Protocol for on USB host controller
1722 HcDevicePath
= NULL
;
1723 Status
= gBS
->OpenProtocol (
1725 &gEfiDevicePathProtocolGuid
,
1726 (VOID
**) &HcDevicePath
,
1727 This
->DriverBindingHandle
,
1729 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1732 PciAttributesSaved
= FALSE
;
1734 // Save original PCI attributes
1736 Status
= PciIo
->Attributes (
1738 EfiPciIoAttributeOperationGet
,
1740 &OriginalPciAttributes
1743 if (EFI_ERROR (Status
)) {
1746 PciAttributesSaved
= TRUE
;
1748 Status
= PciIo
->Attributes (
1750 EfiPciIoAttributeOperationSupported
,
1754 if (!EFI_ERROR (Status
)) {
1755 Supports
&= EFI_PCI_DEVICE_ENABLE
;
1756 Status
= PciIo
->Attributes (
1758 EfiPciIoAttributeOperationEnable
,
1764 if (EFI_ERROR (Status
)) {
1765 DEBUG ((EFI_D_ERROR
, "EhcDriverBindingStart: failed to enable controller\n"));
1770 // Get the Pci device class code.
1772 Status
= PciIo
->Pci
.Read (
1775 PCI_CLASSCODE_OFFSET
,
1776 sizeof (USB_CLASSC
) / sizeof (UINT8
),
1780 if (EFI_ERROR (Status
)) {
1781 Status
= EFI_UNSUPPORTED
;
1785 // determine if the device is UHCI host controller or not. If yes, then find out the
1786 // companion usb ehci host controller and force EHCI driver get attached to it before
1787 // UHCI driver attaches to UHCI host controller.
1789 if ((UsbClassCReg
.ProgInterface
== PCI_IF_UHCI
) &&
1790 (UsbClassCReg
.BaseCode
== PCI_CLASS_SERIAL
) &&
1791 (UsbClassCReg
.SubClassCode
== PCI_CLASS_SERIAL_USB
)) {
1792 Status
= PciIo
->GetLocation (
1799 if (EFI_ERROR (Status
)) {
1803 Status
= gBS
->LocateHandleBuffer (
1805 &gEfiPciIoProtocolGuid
,
1810 if (EFI_ERROR (Status
)) {
1814 for (Index
= 0; Index
< NumberOfHandles
; Index
++) {
1816 // Get the device path on this handle
1818 Status
= gBS
->HandleProtocol (
1819 HandleBuffer
[Index
],
1820 &gEfiPciIoProtocolGuid
,
1823 ASSERT_EFI_ERROR (Status
);
1825 Status
= Instance
->Pci
.Read (
1828 PCI_CLASSCODE_OFFSET
,
1829 sizeof (USB_CLASSC
) / sizeof (UINT8
),
1833 if (EFI_ERROR (Status
)) {
1834 Status
= EFI_UNSUPPORTED
;
1838 if ((UsbClassCReg
.ProgInterface
== PCI_IF_EHCI
) &&
1839 (UsbClassCReg
.BaseCode
== PCI_CLASS_SERIAL
) &&
1840 (UsbClassCReg
.SubClassCode
== PCI_CLASS_SERIAL_USB
)) {
1841 Status
= Instance
->GetLocation (
1848 if (EFI_ERROR (Status
)) {
1852 // Currently, the judgment on the companion usb host controller is through the
1853 // same bus number, which may vary on different platform.
1855 if (EhciBusNumber
== UhciBusNumber
) {
1856 gBS
->CloseProtocol (
1858 &gEfiPciIoProtocolGuid
,
1859 This
->DriverBindingHandle
,
1862 EhcDriverBindingStart(This
, HandleBuffer
[Index
], NULL
);
1866 Status
= EFI_NOT_FOUND
;
1871 // Create then install USB2_HC_PROTOCOL
1873 Ehc
= EhcCreateUsb2Hc (PciIo
, HcDevicePath
, OriginalPciAttributes
);
1876 DEBUG ((EFI_D_ERROR
, "EhcDriverBindingStart: failed to create USB2_HC\n"));
1878 Status
= EFI_OUT_OF_RESOURCES
;
1882 Status
= gBS
->InstallProtocolInterface (
1884 &gEfiUsb2HcProtocolGuid
,
1885 EFI_NATIVE_INTERFACE
,
1889 if (EFI_ERROR (Status
)) {
1890 DEBUG ((EFI_D_ERROR
, "EhcDriverBindingStart: failed to install USB2_HC Protocol\n"));
1895 // Robustnesss improvement such as for Duet platform
1896 // Default is not required.
1898 if (FeaturePcdGet (PcdTurnOffUsbLegacySupport
)) {
1899 EhcClearLegacySupport (Ehc
);
1902 if (Ehc
->DebugPortNum
!= 0) {
1903 State
= EhcReadDbgRegister(Ehc
, 0);
1904 if ((State
& (USB_DEBUG_PORT_IN_USE
| USB_DEBUG_PORT_OWNER
)) != (USB_DEBUG_PORT_IN_USE
| USB_DEBUG_PORT_OWNER
)) {
1905 EhcResetHC (Ehc
, EHC_RESET_TIMEOUT
);
1909 Status
= EhcInitHC (Ehc
);
1911 if (EFI_ERROR (Status
)) {
1912 DEBUG ((EFI_D_ERROR
, "EhcDriverBindingStart: failed to init host controller\n"));
1913 goto UNINSTALL_USBHC
;
1917 // Start the asynchronous interrupt monitor
1919 Status
= gBS
->SetTimer (Ehc
->PollTimer
, TimerPeriodic
, EHC_ASYNC_POLL_INTERVAL
);
1921 if (EFI_ERROR (Status
)) {
1922 DEBUG ((EFI_D_ERROR
, "EhcDriverBindingStart: failed to start async interrupt monitor\n"));
1924 EhcHaltHC (Ehc
, EHC_GENERIC_TIMEOUT
);
1925 goto UNINSTALL_USBHC
;
1929 // Create event to stop the HC when exit boot service.
1931 Status
= gBS
->CreateEventEx (
1936 &gEfiEventExitBootServicesGuid
,
1937 &Ehc
->ExitBootServiceEvent
1939 if (EFI_ERROR (Status
)) {
1940 goto UNINSTALL_USBHC
;
1944 // Install the component name protocol, don't fail the start
1945 // because of something for display.
1949 gEhciComponentName
.SupportedLanguages
,
1950 &Ehc
->ControllerNameTable
,
1951 L
"Enhanced Host Controller (USB 2.0)",
1956 gEhciComponentName2
.SupportedLanguages
,
1957 &Ehc
->ControllerNameTable
,
1958 L
"Enhanced Host Controller (USB 2.0)",
1963 DEBUG ((EFI_D_INFO
, "EhcDriverBindingStart: EHCI started for controller @ %p\n", Controller
));
1967 gBS
->UninstallProtocolInterface (
1969 &gEfiUsb2HcProtocolGuid
,
1975 gBS
->CloseEvent (Ehc
->PollTimer
);
1976 gBS
->FreePool (Ehc
);
1979 if (PciAttributesSaved
) {
1981 // Restore original PCI attributes
1985 EfiPciIoAttributeOperationSet
,
1986 OriginalPciAttributes
,
1991 gBS
->CloseProtocol (
1993 &gEfiPciIoProtocolGuid
,
1994 This
->DriverBindingHandle
,
2003 Stop this driver on ControllerHandle. Support stoping any child handles
2004 created by this driver.
2006 @param This Protocol instance pointer.
2007 @param Controller Handle of device to stop driver on.
2008 @param NumberOfChildren Number of Children in the ChildHandleBuffer.
2009 @param ChildHandleBuffer List of handles for the children we need to stop.
2011 @return EFI_SUCCESS Success.
2012 @return EFI_DEVICE_ERROR Fail.
2017 EhcDriverBindingStop (
2018 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
2019 IN EFI_HANDLE Controller
,
2020 IN UINTN NumberOfChildren
,
2021 IN EFI_HANDLE
*ChildHandleBuffer
2025 EFI_USB2_HC_PROTOCOL
*Usb2Hc
;
2026 EFI_PCI_IO_PROTOCOL
*PciIo
;
2030 // Test whether the Controller handler passed in is a valid
2031 // Usb controller handle that should be supported, if not,
2032 // return the error status directly
2034 Status
= gBS
->OpenProtocol (
2036 &gEfiUsb2HcProtocolGuid
,
2038 This
->DriverBindingHandle
,
2040 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2043 if (EFI_ERROR (Status
)) {
2047 Ehc
= EHC_FROM_THIS (Usb2Hc
);
2051 // Stop AsyncRequest Polling timer then stop the EHCI driver
2052 // and uninstall the EHCI protocl.
2054 gBS
->SetTimer (Ehc
->PollTimer
, TimerCancel
, EHC_ASYNC_POLL_INTERVAL
);
2055 EhcHaltHC (Ehc
, EHC_GENERIC_TIMEOUT
);
2057 Status
= gBS
->UninstallProtocolInterface (
2059 &gEfiUsb2HcProtocolGuid
,
2063 if (EFI_ERROR (Status
)) {
2067 if (Ehc
->PollTimer
!= NULL
) {
2068 gBS
->CloseEvent (Ehc
->PollTimer
);
2071 if (Ehc
->ExitBootServiceEvent
!= NULL
) {
2072 gBS
->CloseEvent (Ehc
->ExitBootServiceEvent
);
2077 if (Ehc
->ControllerNameTable
!= NULL
) {
2078 FreeUnicodeStringTable (Ehc
->ControllerNameTable
);
2082 // Disable routing of all ports to EHCI controller, so all ports are
2083 // routed back to the UHCI controller.
2085 EhcClearOpRegBit (Ehc
, EHC_CONFIG_FLAG_OFFSET
, CONFIGFLAG_ROUTE_EHC
);
2088 // Restore original PCI attributes
2092 EfiPciIoAttributeOperationSet
,
2093 Ehc
->OriginalPciAttributes
,
2097 gBS
->CloseProtocol (
2099 &gEfiPciIoProtocolGuid
,
2100 This
->DriverBindingHandle
,