3 Unified interface for RootHub and Hub.
5 Copyright (c) 2007 - 2009, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 // Array that maps the change bit to feature value which is
20 // used to clear these change bit. USB HUB API will clear
21 // these change bit automatically. For non-root hub, these
22 // bits determine whether hub will report the port in changed
25 USB_CHANGE_FEATURE_MAP mHubFeatureMap
[] = {
26 {USB_PORT_STAT_C_CONNECTION
, EfiUsbPortConnectChange
},
27 {USB_PORT_STAT_C_ENABLE
, EfiUsbPortEnableChange
},
28 {USB_PORT_STAT_C_SUSPEND
, EfiUsbPortSuspendChange
},
29 {USB_PORT_STAT_C_OVERCURRENT
, EfiUsbPortOverCurrentChange
},
30 {USB_PORT_STAT_C_RESET
, EfiUsbPortResetChange
}
33 USB_CHANGE_FEATURE_MAP mRootHubFeatureMap
[] = {
34 {USB_PORT_STAT_C_CONNECTION
, EfiUsbPortConnectChange
},
35 {USB_PORT_STAT_C_ENABLE
, EfiUsbPortEnableChange
},
36 {USB_PORT_STAT_C_SUSPEND
, EfiUsbPortSuspendChange
},
37 {USB_PORT_STAT_C_OVERCURRENT
, EfiUsbPortOverCurrentChange
},
38 {USB_PORT_STAT_C_RESET
, EfiUsbPortResetChange
},
42 // USB hub class specific requests. Although USB hub
43 // is related to an interface, these requests are sent
44 // to the control endpoint of the device.
47 USB hub control transfer to set the hub depth.
49 @param HubDev The device of the hub.
50 @param Depth The depth to set.
52 @retval EFI_SUCCESS Depth of the hub is set.
53 @retval Others Failed to set the depth.
57 UsbHubCtrlSetHubDepth (
58 IN USB_DEVICE
*HubDev
,
64 Status
= UsbCtrlRequest (
69 USB_HUB_REQ_SET_DEPTH
,
80 USB hub control transfer to clear the hub feature.
82 @param HubDev The device of the hub.
83 @param Feature The feature to clear.
85 @retval EFI_SUCCESS Feature of the hub is cleared.
86 @retval Others Failed to clear the feature.
90 UsbHubCtrlClearHubFeature (
91 IN USB_DEVICE
*HubDev
,
97 Status
= UsbCtrlRequest (
102 USB_HUB_REQ_CLEAR_FEATURE
,
114 Clear the feature of the device's port.
116 @param HubDev The hub device.
117 @param Port The port to clear feature.
118 @param Feature The feature to clear.
120 @retval EFI_SUCCESS The feature of the port is cleared.
121 @retval Others Failed to clear the feature.
125 UsbHubCtrlClearPortFeature (
126 IN USB_DEVICE
*HubDev
,
134 // In USB bus, all the port index starts from 0. But HUB
135 // indexes its port from 1. So, port number is added one.
137 Status
= UsbCtrlRequest (
142 USB_HUB_REQ_CLEAR_FEATURE
,
154 Clear the transaction translate buffer if full/low
155 speed control/bulk transfer failed and the transfer
156 uses this hub as translator.Remember to clear the TT
157 buffer of transaction translator, not that of the
160 @param HubDev The hub device.
161 @param Port The port of the hub.
162 @param DevAddr Address of the failed transaction.
163 @param EpNum The endpoint number of the failed transaction.
164 @param EpType The type of failed transaction.
166 @retval EFI_SUCCESS The TT buffer is cleared.
167 @retval Others Failed to clear the TT buffer.
171 UsbHubCtrlClearTTBuffer (
172 IN USB_DEVICE
*HubDev
,
183 // Check USB2.0 spec page 424 for wValue's encoding
185 Value
= (UINT16
) ((EpNum
& 0x0F) | (DevAddr
<< 4) |
186 ((EpType
& 0x03) << 11) | ((EpNum
& 0x80) << 15));
188 Status
= UsbCtrlRequest (
193 USB_HUB_REQ_CLEAR_TT
,
204 Usb hub control transfer to get the super speed hub descriptor.
206 @param HubDev The hub device.
207 @param Buf The buffer to hold the descriptor.
208 @param Len The length to retrieve.
210 @retval EFI_SUCCESS The hub descriptor is retrieved.
211 @retval Others Failed to retrieve the hub descriptor.
215 UsbHubCtrlGetSuperSpeedHubDesc (
216 IN USB_DEVICE
*HubDev
,
222 Status
= EFI_INVALID_PARAMETER
;
224 Status
= UsbCtrlRequest (
229 USB_HUB_REQ_GET_DESC
,
230 (UINT16
) (USB_DESC_TYPE_HUB_SUPER_SPEED
<< 8),
240 Usb hub control transfer to get the hub descriptor.
242 @param HubDev The hub device.
243 @param Buf The buffer to hold the descriptor.
244 @param Len The length to retrieve.
246 @retval EFI_SUCCESS The hub descriptor is retrieved.
247 @retval Others Failed to retrieve the hub descriptor.
251 UsbHubCtrlGetHubDesc (
252 IN USB_DEVICE
*HubDev
,
259 Status
= UsbCtrlRequest (
264 USB_HUB_REQ_GET_DESC
,
265 (UINT16
) (USB_DESC_TYPE_HUB
<< 8),
276 Usb hub control transfer to get the hub status.
278 @param HubDev The hub device.
279 @param State The variable to return the status.
281 @retval EFI_SUCCESS The hub status is returned in State.
282 @retval Others Failed to get the hub status.
286 UsbHubCtrlGetHubStatus (
287 IN USB_DEVICE
*HubDev
,
293 Status
= UsbCtrlRequest (
298 USB_HUB_REQ_GET_STATUS
,
310 Usb hub control transfer to get the port status.
312 @param HubDev The hub device.
313 @param Port The port of the hub.
314 @param State Variable to return the hub port state.
316 @retval EFI_SUCCESS The port state is returned in State.
317 @retval Others Failed to retrieve the port state.
321 UsbHubCtrlGetPortStatus (
322 IN USB_DEVICE
*HubDev
,
330 // In USB bus, all the port index starts from 0. But HUB
331 // indexes its port from 1. So, port number is added one.
332 // No need to convert the hub bit to UEFI definition, they
335 Status
= UsbCtrlRequest (
340 USB_HUB_REQ_GET_STATUS
,
352 Usb hub control transfer to reset the TT (Transaction Transaltor).
354 @param HubDev The hub device.
355 @param Port The port of the hub.
357 @retval EFI_SUCCESS The TT of the hub is reset.
358 @retval Others Failed to reset the port.
363 IN USB_DEVICE
*HubDev
,
369 Status
= UsbCtrlRequest (
374 USB_HUB_REQ_RESET_TT
,
386 Usb hub control transfer to set the hub feature.
388 @param HubDev The hub device.
389 @param Feature The feature to set.
391 @retval EFI_SUCESS The feature is set for the hub.
392 @retval Others Failed to set the feature.
396 UsbHubCtrlSetHubFeature (
397 IN USB_DEVICE
*HubDev
,
403 Status
= UsbCtrlRequest (
408 USB_HUB_REQ_SET_FEATURE
,
420 Usb hub control transfer to set the port feature.
422 @param HubDev The Usb hub device.
423 @param Port The Usb port to set feature for.
424 @param Feature The feature to set.
426 @retval EFI_SUCCESS The feature is set for the port.
427 @retval Others Failed to set the feature.
431 UsbHubCtrlSetPortFeature (
432 IN USB_DEVICE
*HubDev
,
440 // In USB bus, all the port index starts from 0. But HUB
441 // indexes its port from 1. So, port number is added one.
443 Status
= UsbCtrlRequest (
448 USB_HUB_REQ_SET_FEATURE
,
460 Read the whole usb hub descriptor. It is necessary
461 to do it in two steps because hub descriptor is of
464 @param HubDev The hub device.
465 @param HubDesc The variable to return the descriptor.
467 @retval EFI_SUCCESS The hub descriptor is read.
468 @retval Others Failed to read the hub descriptor.
473 IN USB_DEVICE
*HubDev
,
474 OUT EFI_USB_HUB_DESCRIPTOR
*HubDesc
479 if (HubDev
->Speed
== EFI_USB_SPEED_SUPER
) {
481 // Get the super speed hub descriptor
483 Status
= UsbHubCtrlGetSuperSpeedHubDesc (HubDev
, HubDesc
);
487 // First get the hub descriptor length
489 Status
= UsbHubCtrlGetHubDesc (HubDev
, HubDesc
, 2);
491 if (EFI_ERROR (Status
)) {
496 // Get the whole hub descriptor
498 Status
= UsbHubCtrlGetHubDesc (HubDev
, HubDesc
, HubDesc
->Length
);
507 Ack the hub change bits. If these bits are not ACKed, Hub will
508 always return changed bit map from its interrupt endpoint.
510 @param HubDev The hub device.
512 @retval EFI_SUCCESS The hub change status is ACKed.
513 @retval Others Failed to ACK the hub status.
518 IN USB_DEVICE
*HubDev
521 EFI_USB_PORT_STATUS HubState
;
524 Status
= UsbHubCtrlGetHubStatus (HubDev
, (UINT32
*) &HubState
);
526 if (EFI_ERROR (Status
)) {
530 if (USB_BIT_IS_SET (HubState
.PortChangeStatus
, USB_HUB_STAT_C_LOCAL_POWER
)) {
531 UsbHubCtrlClearHubFeature (HubDev
, USB_HUB_C_HUB_LOCAL_POWER
);
534 if (USB_BIT_IS_SET (HubState
.PortChangeStatus
, USB_HUB_STAT_C_OVER_CURRENT
)) {
535 UsbHubCtrlClearHubFeature (HubDev
, USB_HUB_C_HUB_OVER_CURRENT
);
543 Test whether the interface is a hub interface.
545 @param UsbIf The interface to test.
547 @retval TRUE The interface is a hub interface.
548 @retval FALSE The interface isn't a hub interface.
553 IN USB_INTERFACE
*UsbIf
556 EFI_USB_INTERFACE_DESCRIPTOR
*Setting
;
559 // If the hub is a high-speed hub with multiple TT,
560 // the hub will has a default setting of single TT.
562 Setting
= &UsbIf
->IfSetting
->Desc
;
564 if ((Setting
->InterfaceClass
== USB_HUB_CLASS_CODE
) &&
565 (Setting
->InterfaceSubClass
== USB_HUB_SUBCLASS_CODE
)) {
575 The callback function to the USB hub status change
576 interrupt endpoint. It is called periodically by
577 the underlying host controller.
579 @param Data The data read.
580 @param DataLength The length of the data read.
581 @param Context The context.
582 @param Result The result of the last interrupt transfer.
584 @retval EFI_SUCCESS The process is OK.
585 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource.
597 USB_INTERFACE
*HubIf
;
598 EFI_USB_IO_PROTOCOL
*UsbIo
;
599 EFI_USB_ENDPOINT_DESCRIPTOR
*EpDesc
;
602 HubIf
= (USB_INTERFACE
*) Context
;
603 UsbIo
= &(HubIf
->UsbIo
);
604 EpDesc
= &(HubIf
->HubEp
->Desc
);
606 if (Result
!= EFI_USB_NOERROR
) {
608 // If endpoint is stalled, clear the stall. Use UsbIo to access
609 // the control transfer so internal status are maintained.
611 if (USB_BIT_IS_SET (Result
, EFI_USB_ERR_STALL
)) {
615 USB_FEATURE_ENDPOINT_HALT
,
616 EpDesc
->EndpointAddress
621 // Delete and submit a new async interrupt
623 Status
= UsbIo
->UsbAsyncInterruptTransfer (
625 EpDesc
->EndpointAddress
,
633 if (EFI_ERROR (Status
)) {
634 DEBUG (( EFI_D_ERROR
, "UsbOnHubInterrupt: failed to remove async transfer - %r\n", Status
));
638 Status
= UsbIo
->UsbAsyncInterruptTransfer (
640 EpDesc
->EndpointAddress
,
642 USB_HUB_POLL_INTERVAL
,
643 HubIf
->NumOfPort
/ 8 + 1,
648 if (EFI_ERROR (Status
)) {
649 DEBUG (( EFI_D_ERROR
, "UsbOnHubInterrupt: failed to submit new async transfer - %r\n", Status
));
655 if ((DataLength
== 0) || (Data
== NULL
)) {
660 // OK, actually something is changed, save the change map
661 // then signal the HUB to do enumeration. This is a good
662 // practise since UsbOnHubInterrupt is called in the context
663 // of host contrller's AsyncInterrupt monitor.
665 HubIf
->ChangeMap
= AllocateZeroPool (DataLength
);
667 if (HubIf
->ChangeMap
== NULL
) {
668 return EFI_OUT_OF_RESOURCES
;
671 CopyMem (HubIf
->ChangeMap
, Data
, DataLength
);
672 gBS
->SignalEvent (HubIf
->HubNotify
);
681 Initialize the device for a non-root hub.
683 @param HubIf The USB hub interface.
685 @retval EFI_SUCCESS The hub is initialized.
686 @retval EFI_DEVICE_ERROR Failed to initialize the hub.
691 IN USB_INTERFACE
*HubIf
694 EFI_USB_HUB_DESCRIPTOR HubDesc
;
695 USB_ENDPOINT_DESC
*EpDesc
;
696 USB_INTERFACE_SETTING
*Setting
;
697 EFI_USB_IO_PROTOCOL
*UsbIo
;
705 // Locate the interrupt endpoint for port change map
707 HubIf
->IsHub
= FALSE
;
708 Setting
= HubIf
->IfSetting
;
709 HubDev
= HubIf
->Device
;
711 NumEndpoints
= Setting
->Desc
.NumEndpoints
;
713 for (Index
= 0; Index
< NumEndpoints
; Index
++) {
714 ASSERT ((Setting
->Endpoints
!= NULL
) && (Setting
->Endpoints
[Index
] != NULL
));
716 EpDesc
= Setting
->Endpoints
[Index
];
718 if (USB_BIT_IS_SET (EpDesc
->Desc
.EndpointAddress
, USB_ENDPOINT_DIR_IN
) &&
719 (USB_ENDPOINT_TYPE (&EpDesc
->Desc
) == USB_ENDPOINT_INTERRUPT
)) {
724 if (Index
== NumEndpoints
) {
725 DEBUG (( EFI_D_ERROR
, "UsbHubInit: no interrupt endpoint found for hub %d\n", HubDev
->Address
));
726 return EFI_DEVICE_ERROR
;
729 Status
= UsbHubReadDesc (HubDev
, &HubDesc
);
731 if (EFI_ERROR (Status
)) {
732 DEBUG (( EFI_D_ERROR
, "UsbHubInit: failed to read HUB descriptor %r\n", Status
));
736 HubIf
->NumOfPort
= HubDesc
.NumPorts
;
738 DEBUG (( EFI_D_INFO
, "UsbHubInit: hub %d has %d ports\n", HubDev
->Address
,HubIf
->NumOfPort
));
741 // OK, set IsHub to TRUE. Now usb bus can handle this device
742 // as a working HUB. If failed eariler, bus driver will not
743 // recognize it as a hub. Other parts of the bus should be able
747 HubIf
->HubApi
= &mUsbHubApi
;
748 HubIf
->HubEp
= EpDesc
;
750 if (HubIf
->Device
->Speed
== EFI_USB_SPEED_SUPER
) {
751 Depth
= (UINT16
)(HubIf
->Device
->Tier
- 1);
752 DEBUG ((EFI_D_INFO
, "UsbHubInit: Set Hub Depth as 0x%x\n", Depth
));
753 UsbHubCtrlSetHubDepth (HubIf
->Device
, Depth
);
755 for (Index
= 0; Index
< HubDesc
.NumPorts
; Index
++) {
756 UsbHubCtrlSetPortFeature (HubIf
->Device
, Index
, USB_HUB_PORT_REMOTE_WAKE_MASK
);
760 // Feed power to all the hub ports. It should be ok
761 // for both gang/individual powered hubs.
763 for (Index
= 0; Index
< HubDesc
.NumPorts
; Index
++) {
764 UsbHubCtrlSetPortFeature (HubIf
->Device
, Index
, (EFI_USB_PORT_FEATURE
) USB_HUB_PORT_POWER
);
767 gBS
->Stall (HubDesc
.PwrOn2PwrGood
* USB_SET_PORT_POWER_STALL
);
768 UsbHubAckHubStatus (HubIf
->Device
);
772 // Create an event to enumerate the hub's port. On
774 Status
= gBS
->CreateEvent (
782 if (EFI_ERROR (Status
)) {
783 DEBUG (( EFI_D_ERROR
, "UsbHubInit: failed to create signal for hub %d - %r\n",
784 HubDev
->Address
, Status
));
790 // Create AsyncInterrupt to query hub port change endpoint
791 // periodically. If the hub ports are changed, hub will return
792 // changed port map from the interrupt endpoint. The port map
793 // must be able to hold (HubIf->NumOfPort + 1) bits (one bit for
794 // host change status).
796 UsbIo
= &HubIf
->UsbIo
;
797 Status
= UsbIo
->UsbAsyncInterruptTransfer (
799 EpDesc
->Desc
.EndpointAddress
,
801 USB_HUB_POLL_INTERVAL
,
802 HubIf
->NumOfPort
/ 8 + 1,
807 if (EFI_ERROR (Status
)) {
808 DEBUG (( EFI_D_ERROR
, "UsbHubInit: failed to queue interrupt transfer for hub %d - %r\n",
809 HubDev
->Address
, Status
));
811 gBS
->CloseEvent (HubIf
->HubNotify
);
812 HubIf
->HubNotify
= NULL
;
817 DEBUG (( EFI_D_INFO
, "UsbHubInit: hub %d initialized\n", HubDev
->Address
));
824 Get the port status. This function is required to
825 ACK the port change bits although it will return
826 the port changes in PortState. Bus enumeration code
827 doesn't need to ACK the port change bits.
829 @param HubIf The hub interface.
830 @param Port The port of the hub to get state.
831 @param PortState Variable to return the port state.
833 @retval EFI_SUCCESS The port status is successfully returned.
834 @retval Others Failed to return the status.
838 UsbHubGetPortStatus (
839 IN USB_INTERFACE
*HubIf
,
841 OUT EFI_USB_PORT_STATUS
*PortState
846 Status
= UsbHubCtrlGetPortStatus (HubIf
->Device
, Port
, PortState
);
849 // Mark the USB_PORT_STAT_SUPER_SPEED bit if SuperSpeed
851 if (HubIf
->Device
->Speed
== EFI_USB_SPEED_SUPER
) {
852 PortState
->PortStatus
|= USB_PORT_STAT_SUPER_SPEED
;
860 Clear the port change status.
862 @param HubIf The hub interface.
863 @param Port The hub port.
867 UsbHubClearPortChange (
868 IN USB_INTERFACE
*HubIf
,
872 EFI_USB_PORT_STATUS PortState
;
873 USB_CHANGE_FEATURE_MAP
*Map
;
877 Status
= UsbHubGetPortStatus (HubIf
, Port
, &PortState
);
879 if (EFI_ERROR (Status
)) {
884 // OK, get the usb port status, now ACK the change bits.
885 // Don't return error when failed to clear the change bits.
886 // It may lead to extra port state report. USB bus should
887 // be able to handle this.
889 for (Index
= 0; Index
< sizeof (mHubFeatureMap
) / sizeof (mHubFeatureMap
[0]); Index
++) {
890 Map
= &mHubFeatureMap
[Index
];
892 if (USB_BIT_IS_SET (PortState
.PortChangeStatus
, Map
->ChangedBit
)) {
893 UsbHubCtrlClearPortFeature (HubIf
->Device
, Port
, (UINT16
) Map
->Feature
);
901 Function to set the port feature for non-root hub.
903 @param HubIf The hub interface.
904 @param Port The port of the hub.
905 @param Feature The feature of the port to set.
907 @retval EFI_SUCCESS The hub port feature is set.
908 @retval Others Failed to set the port feature.
912 UsbHubSetPortFeature (
913 IN USB_INTERFACE
*HubIf
,
915 IN EFI_USB_PORT_FEATURE Feature
920 Status
= UsbHubCtrlSetPortFeature (HubIf
->Device
, Port
, (UINT8
) Feature
);
927 Interface function to clear the port feature for non-root hub.
929 @param HubIf The hub interface.
930 @param Port The port of the hub to clear feature for.
931 @param Feature The feature to clear.
933 @retval EFI_SUCCESS The port feature is cleared.
934 @retval Others Failed to clear the port feature.
938 UsbHubClearPortFeature (
939 IN USB_INTERFACE
*HubIf
,
941 IN EFI_USB_PORT_FEATURE Feature
946 Status
= UsbHubCtrlClearPortFeature (HubIf
->Device
, Port
, (UINT8
) Feature
);
953 Interface function to reset the port.
955 @param HubIf The hub interface.
956 @param Port The port to reset.
958 @retval EFI_SUCCESS The hub port is reset.
959 @retval EFI_TIMEOUT Failed to reset the port in time.
960 @retval Others Failed to reset the port.
965 IN USB_INTERFACE
*HubIf
,
969 EFI_USB_PORT_STATUS PortState
;
973 Status
= UsbHubSetPortFeature (HubIf
, Port
, (EFI_USB_PORT_FEATURE
) USB_HUB_PORT_RESET
);
975 if (EFI_ERROR (Status
)) {
980 // Drive the reset signal for at least 10ms. Check USB 2.0 Spec
981 // section 7.1.7.5 for timing requirements.
983 gBS
->Stall (USB_SET_PORT_RESET_STALL
);
986 // USB hub will clear RESET bit if reset is actually finished.
988 ZeroMem (&PortState
, sizeof (EFI_USB_PORT_STATUS
));
990 for (Index
= 0; Index
< USB_WAIT_PORT_STS_CHANGE_LOOP
; Index
++) {
991 Status
= UsbHubGetPortStatus (HubIf
, Port
, &PortState
);
993 if (!EFI_ERROR (Status
) &&
994 !USB_BIT_IS_SET (PortState
.PortStatus
, USB_PORT_STAT_RESET
)) {
999 gBS
->Stall (USB_WAIT_PORT_STS_CHANGE_STALL
);
1007 Release the hub's control of the interface.
1009 @param HubIf The hub interface.
1011 @retval EFI_SUCCESS The interface is release of hub control.
1016 IN USB_INTERFACE
*HubIf
1019 EFI_USB_IO_PROTOCOL
*UsbIo
;
1022 UsbIo
= &HubIf
->UsbIo
;
1023 Status
= UsbIo
->UsbAsyncInterruptTransfer (
1025 HubIf
->HubEp
->Desc
.EndpointAddress
,
1027 USB_HUB_POLL_INTERVAL
,
1033 if (EFI_ERROR (Status
)) {
1037 gBS
->CloseEvent (HubIf
->HubNotify
);
1039 HubIf
->IsHub
= FALSE
;
1040 HubIf
->HubApi
= NULL
;
1041 HubIf
->HubEp
= NULL
;
1042 HubIf
->HubNotify
= NULL
;
1044 DEBUG (( EFI_D_INFO
, "UsbHubRelease: hub device %d released\n", HubIf
->Device
->Address
));
1051 Initialize the interface for root hub.
1053 @param HubIf The root hub interface.
1055 @retval EFI_SUCCESS The interface is initialized for root hub.
1056 @retval Others Failed to initialize the hub.
1061 IN USB_INTERFACE
*HubIf
1069 Status
= UsbHcGetCapability (HubIf
->Device
->Bus
, &MaxSpeed
, &NumOfPort
, &Support64
);
1071 if (EFI_ERROR (Status
)) {
1075 DEBUG (( EFI_D_INFO
, "UsbRootHubInit: root hub %p - max speed %d, %d ports\n",
1076 HubIf
, MaxSpeed
, NumOfPort
));
1078 HubIf
->IsHub
= TRUE
;
1079 HubIf
->HubApi
= &mUsbRootHubApi
;
1080 HubIf
->HubEp
= NULL
;
1081 HubIf
->MaxSpeed
= MaxSpeed
;
1082 HubIf
->NumOfPort
= NumOfPort
;
1083 HubIf
->HubNotify
= NULL
;
1086 // Create a timer to poll root hub ports periodically
1088 Status
= gBS
->CreateEvent (
1089 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
1091 UsbRootHubEnumeration
,
1096 if (EFI_ERROR (Status
)) {
1101 // It should signal the event immediately here, or device detection
1102 // by bus enumeration might be delayed by the timer interval.
1104 gBS
->SignalEvent (HubIf
->HubNotify
);
1106 Status
= gBS
->SetTimer (
1109 USB_ROOTHUB_POLL_INTERVAL
1112 if (EFI_ERROR (Status
)) {
1113 gBS
->CloseEvent (HubIf
->HubNotify
);
1121 Get the port status. This function is required to
1122 ACK the port change bits although it will return
1123 the port changes in PortState. Bus enumeration code
1124 doesn't need to ACK the port change bits.
1126 @param HubIf The root hub interface.
1127 @param Port The root hub port to get the state.
1128 @param PortState Variable to return the port state.
1130 @retval EFI_SUCCESS The port state is returned.
1131 @retval Others Failed to retrieve the port state.
1135 UsbRootHubGetPortStatus (
1136 IN USB_INTERFACE
*HubIf
,
1138 OUT EFI_USB_PORT_STATUS
*PortState
1144 Bus
= HubIf
->Device
->Bus
;
1145 Status
= UsbHcGetRootHubPortStatus (Bus
, Port
, PortState
);
1152 Clear the port change status.
1154 @param HubIf The root hub interface.
1155 @param Port The root hub port.
1159 UsbRootHubClearPortChange (
1160 IN USB_INTERFACE
*HubIf
,
1164 EFI_USB_PORT_STATUS PortState
;
1165 USB_CHANGE_FEATURE_MAP
*Map
;
1169 Status
= UsbRootHubGetPortStatus (HubIf
, Port
, &PortState
);
1171 if (EFI_ERROR (Status
)) {
1176 // OK, get the usb port status, now ACK the change bits.
1177 // Don't return error when failed to clear the change bits.
1178 // It may lead to extra port state report. USB bus should
1179 // be able to handle this.
1181 for (Index
= 0; Index
< sizeof (mRootHubFeatureMap
) / sizeof (mRootHubFeatureMap
[0]); Index
++) {
1182 Map
= &mRootHubFeatureMap
[Index
];
1184 if (USB_BIT_IS_SET (PortState
.PortChangeStatus
, Map
->ChangedBit
)) {
1185 UsbHcClearRootHubPortFeature (HubIf
->Device
->Bus
, Port
, (EFI_USB_PORT_FEATURE
) Map
->Feature
);
1192 Set the root hub port feature.
1194 @param HubIf The Usb hub interface.
1195 @param Port The hub port.
1196 @param Feature The feature to set.
1198 @retval EFI_SUCCESS The root hub port is set with the feature.
1199 @retval Others Failed to set the feature.
1203 UsbRootHubSetPortFeature (
1204 IN USB_INTERFACE
*HubIf
,
1206 IN EFI_USB_PORT_FEATURE Feature
1211 Status
= UsbHcSetRootHubPortFeature (HubIf
->Device
->Bus
, Port
, Feature
);
1218 Clear the root hub port feature.
1220 @param HubIf The root hub interface.
1221 @param Port The root hub port.
1222 @param Feature The feature to clear.
1224 @retval EFI_SUCCESS The root hub port is cleared of the feature.
1225 @retval Others Failed to clear the feature.
1229 UsbRootHubClearPortFeature (
1230 IN USB_INTERFACE
*HubIf
,
1232 IN EFI_USB_PORT_FEATURE Feature
1237 Status
= UsbHcClearRootHubPortFeature (HubIf
->Device
->Bus
, Port
, Feature
);
1244 Interface function to reset the root hub port.
1246 @param RootIf The root hub interface.
1247 @param Port The port to reset.
1249 @retval EFI_SUCCESS The hub port is reset.
1250 @retval EFI_TIMEOUT Failed to reset the port in time.
1251 @retval EFI_NOT_FOUND The low/full speed device connected to high speed.
1252 root hub is released to the companion UHCI.
1253 @retval Others Failed to reset the port.
1257 UsbRootHubResetPort (
1258 IN USB_INTERFACE
*RootIf
,
1264 EFI_USB_PORT_STATUS PortState
;
1268 // Notice: although EHCI requires that ENABLED bit be cleared
1269 // when reset the port, we don't need to care that here. It
1270 // should be handled in the EHCI driver.
1272 Bus
= RootIf
->Device
->Bus
;
1273 Status
= UsbHcSetRootHubPortFeature (Bus
, Port
, EfiUsbPortReset
);
1275 if (EFI_ERROR (Status
)) {
1276 DEBUG (( EFI_D_ERROR
, "UsbRootHubResetPort: failed to start reset on port %d\n", Port
));
1281 // Drive the reset signal for at least 50ms. Check USB 2.0 Spec
1282 // section 7.1.7.5 for timing requirements.
1284 gBS
->Stall (USB_SET_ROOT_PORT_RESET_STALL
);
1286 Status
= UsbHcClearRootHubPortFeature (Bus
, Port
, EfiUsbPortReset
);
1288 if (EFI_ERROR (Status
)) {
1289 DEBUG (( EFI_D_ERROR
, "UsbRootHubResetPort: failed to clear reset on port %d\n", Port
));
1293 gBS
->Stall (USB_CLR_ROOT_PORT_RESET_STALL
);
1296 // USB host controller won't clear the RESET bit until
1297 // reset is actually finished.
1299 ZeroMem (&PortState
, sizeof (EFI_USB_PORT_STATUS
));
1301 for (Index
= 0; Index
< USB_WAIT_PORT_STS_CHANGE_LOOP
; Index
++) {
1302 Status
= UsbHcGetRootHubPortStatus (Bus
, Port
, &PortState
);
1304 if (EFI_ERROR (Status
)) {
1308 if (!USB_BIT_IS_SET (PortState
.PortStatus
, USB_PORT_STAT_RESET
)) {
1312 gBS
->Stall (USB_WAIT_PORT_STS_CHANGE_STALL
);
1315 if (Index
== USB_WAIT_PORT_STS_CHANGE_LOOP
) {
1316 DEBUG ((EFI_D_ERROR
, "UsbRootHubResetPort: reset not finished in time on port %d\n", Port
));
1320 if (!USB_BIT_IS_SET (PortState
.PortStatus
, USB_PORT_STAT_ENABLE
)) {
1322 // OK, the port is reset. If root hub is of high speed and
1323 // the device is of low/full speed, release the ownership to
1324 // companion UHCI. If root hub is of full speed, it won't
1325 // automatically enable the port, we need to enable it manually.
1327 if (RootIf
->MaxSpeed
== EFI_USB_SPEED_HIGH
) {
1328 DEBUG (( EFI_D_ERROR
, "UsbRootHubResetPort: release low/full speed device (%d) to UHCI\n", Port
));
1330 UsbRootHubSetPortFeature (RootIf
, Port
, EfiUsbPortOwner
);
1331 return EFI_NOT_FOUND
;
1335 Status
= UsbRootHubSetPortFeature (RootIf
, Port
, EfiUsbPortEnable
);
1337 if (EFI_ERROR (Status
)) {
1338 DEBUG (( EFI_D_ERROR
, "UsbRootHubResetPort: failed to enable port %d for UHCI\n", Port
));
1342 gBS
->Stall (USB_SET_ROOT_PORT_ENABLE_STALL
);
1351 Release the root hub's control of the interface.
1353 @param HubIf The root hub interface.
1355 @retval EFI_SUCCESS The root hub's control of the interface is
1361 IN USB_INTERFACE
*HubIf
1364 DEBUG (( EFI_D_INFO
, "UsbRootHubRelease: root hub released for hub %p\n", HubIf
));
1366 gBS
->SetTimer (HubIf
->HubNotify
, TimerCancel
, USB_ROOTHUB_POLL_INTERVAL
);
1367 gBS
->CloseEvent (HubIf
->HubNotify
);
1372 USB_HUB_API mUsbHubApi
= {
1374 UsbHubGetPortStatus
,
1375 UsbHubClearPortChange
,
1376 UsbHubSetPortFeature
,
1377 UsbHubClearPortFeature
,
1382 USB_HUB_API mUsbRootHubApi
= {
1384 UsbRootHubGetPortStatus
,
1385 UsbRootHubClearPortChange
,
1386 UsbRootHubSetPortFeature
,
1387 UsbRootHubClearPortFeature
,
1388 UsbRootHubResetPort
,