3 Unified interface for RootHub and Hub.
5 Copyright (c) 2007, Intel Corporation
6 All rights reserved. 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 #define USB_HUB_MAP_SIZE 5
27 USB_CHANGE_FEATURE_MAP mHubFeatureMap
[USB_HUB_MAP_SIZE
] = {
28 {USB_PORT_STAT_C_CONNECTION
, EfiUsbPortConnectChange
},
29 {USB_PORT_STAT_C_ENABLE
, EfiUsbPortEnableChange
},
30 {USB_PORT_STAT_C_SUSPEND
, EfiUsbPortSuspendChange
},
31 {USB_PORT_STAT_C_OVERCURRENT
, EfiUsbPortOverCurrentChange
},
32 {USB_PORT_STAT_C_RESET
, EfiUsbPortResetChange
},
35 #define USB_ROOT_HUB_MAP_SIZE 5
37 USB_CHANGE_FEATURE_MAP mRootHubFeatureMap
[USB_ROOT_HUB_MAP_SIZE
] = {
38 {USB_PORT_STAT_C_CONNECTION
, EfiUsbPortConnectChange
},
39 {USB_PORT_STAT_C_ENABLE
, EfiUsbPortEnableChange
},
40 {USB_PORT_STAT_C_SUSPEND
, EfiUsbPortSuspendChange
},
41 {USB_PORT_STAT_C_OVERCURRENT
, EfiUsbPortOverCurrentChange
},
42 {USB_PORT_STAT_C_RESET
, EfiUsbPortResetChange
},
46 // USB hub class specific requests. Although USB hub
47 // is related to an interface, these requests are sent
48 // to the control endpoint of the device.
53 USB hub control transfer to clear the hub feature.
55 @param HubDev The device of the hub.
56 @param Feature The feature to clear.
58 @retval EFI_SUCCESS Feature of the hub is cleared.
59 @retval Others Failed to clear the feature.
63 UsbHubCtrlClearHubFeature (
64 IN USB_DEVICE
*HubDev
,
70 Status
= UsbCtrlRequest (
75 USB_HUB_REQ_CLEAR_FEATURE
,
87 Clear the feature of the device's port.
89 @param HubDev The hub device.
90 @param Port The port to clear feature.
91 @param Feature The feature to clear.
93 @retval EFI_SUCCESS The feature of the port is cleared.
94 @retval Others Failed to clear the feature.
98 UsbHubCtrlClearPortFeature (
99 IN USB_DEVICE
*HubDev
,
107 // In USB bus, all the port index starts from 0. But HUB
108 // indexes its port from 1. So, port number is added one.
110 Status
= UsbCtrlRequest (
115 USB_HUB_REQ_CLEAR_FEATURE
,
127 Clear the transaction translate buffer if full/low
128 speed control/bulk transfer failed and the transfer
129 uses this hub as translator.Remember to clear the TT
130 buffer of transaction translator, not that of the
133 @param HubDev The hub device.
134 @param Port The port of the hub.
135 @param DevAddr Address of the failed transaction.
136 @param EpNum The endpoint number of the failed transaction.
137 @param EpType The type of failed transaction.
139 @retval EFI_SUCCESS The TT buffer is cleared.
140 @retval Others Failed to clear the TT buffer.
144 UsbHubCtrlClearTTBuffer (
145 IN USB_DEVICE
*HubDev
,
156 // Check USB2.0 spec page 424 for wValue's encoding
158 Value
= (UINT16
) ((EpNum
& 0x0F) | (DevAddr
<< 4) |
159 ((EpType
& 0x03) << 11) | ((EpNum
& 0x80) << 15));
161 Status
= UsbCtrlRequest (
166 USB_HUB_REQ_CLEAR_TT
,
178 Usb hub control transfer to get the hub descriptor.
180 @param HubDev The hub device.
181 @param Buf The buffer to hold the descriptor.
182 @param Len The length to retrieve.
184 @retval EFI_SUCCESS The hub descriptor is retrieved.
185 @retval Others Failed to retrieve the hub descriptor.
189 UsbHubCtrlGetHubDesc (
190 IN USB_DEVICE
*HubDev
,
197 Status
= UsbCtrlRequest (
202 USB_HUB_REQ_GET_DESC
,
203 (UINT16
) (USB_DESC_TYPE_HUB
<< 8),
214 Usb hub control transfer to get the hub status.
216 @param HubDev The hub device.
217 @param State The variable to return the status.
219 @retval EFI_SUCCESS The hub status is returned in State.
220 @retval Others Failed to get the hub status.
224 UsbHubCtrlGetHubStatus (
225 IN USB_DEVICE
*HubDev
,
231 Status
= UsbCtrlRequest (
236 USB_HUB_REQ_GET_STATUS
,
248 Usb hub control transfer to get the port status.
250 @param HubDev The hub device.
251 @param Port The port of the hub.
252 @param State Variable to return the hub port state.
254 @retval EFI_SUCCESS The port state is returned in State.
255 @retval Others Failed to retrive the port state.
259 UsbHubCtrlGetPortStatus (
260 IN USB_DEVICE
*HubDev
,
268 // In USB bus, all the port index starts from 0. But HUB
269 // indexes its port from 1. So, port number is added one.
270 // No need to convert the hub bit to UEFI definition, they
273 Status
= UsbCtrlRequest (
278 USB_HUB_REQ_GET_STATUS
,
290 Usb hub control transfer to reset the TT (Transaction Transaltor).
292 @param HubDev The hub device.
293 @param Port The port of the hub.
295 @retval EFI_SUCCESS The TT of the hub is reset.
296 @retval Others Failed to reset the port.
301 IN USB_DEVICE
*HubDev
,
307 Status
= UsbCtrlRequest (
312 USB_HUB_REQ_RESET_TT
,
324 Usb hub control transfer to set the hub feature.
326 @param HubDev The hub device.
327 @param Feature The feature to set.
329 @retval EFI_SUCESS The feature is set for the hub.
330 @retval Others Failed to set the feature.
334 UsbHubCtrlSetHubFeature (
335 IN USB_DEVICE
*HubDev
,
341 Status
= UsbCtrlRequest (
346 USB_HUB_REQ_SET_FEATURE
,
358 Usb hub control transfer to set the port feature.
360 @param HubDev The Usb hub device.
361 @param Port The Usb port to set feature for.
362 @param Feature The feature to set.
364 @retval EFI_SUCCESS The feature is set for the port.
365 @retval Others Failed to set the feature.
369 UsbHubCtrlSetPortFeature (
370 IN USB_DEVICE
*HubDev
,
378 // In USB bus, all the port index starts from 0. But HUB
379 // indexes its port from 1. So, port number is added one.
381 Status
= UsbCtrlRequest (
386 USB_HUB_REQ_SET_FEATURE
,
398 Read the whole usb hub descriptor. It is necessary
399 to do it in two steps because hub descriptor is of
402 @param HubDev The hub device.
403 @param HubDesc The variable to return the descriptor.
405 @retval EFI_SUCCESS The hub descriptor is read.
406 @retval Others Failed to read the hub descriptor.
411 IN USB_DEVICE
*HubDev
,
412 OUT EFI_USB_HUB_DESCRIPTOR
*HubDesc
418 // First get the hub descriptor length
420 Status
= UsbHubCtrlGetHubDesc (HubDev
, HubDesc
, 2);
422 if (EFI_ERROR (Status
)) {
427 // Get the whole hub descriptor
429 Status
= UsbHubCtrlGetHubDesc (HubDev
, HubDesc
, HubDesc
->Length
);
437 Ack the hub change bits. If these bits are not ACKed, Hub will
438 always return changed bit map from its interrupt endpoint.
440 @param HubDev The hub device.
442 @retval EFI_SUCCESS The hub change status is ACKed.
443 @retval Others Failed to ACK the hub status.
448 IN USB_DEVICE
*HubDev
451 EFI_USB_PORT_STATUS HubState
;
454 Status
= UsbHubCtrlGetHubStatus (HubDev
, (UINT32
*) &HubState
);
456 if (EFI_ERROR (Status
)) {
460 if (USB_BIT_IS_SET (HubState
.PortChangeStatus
, USB_HUB_STAT_C_LOCAL_POWER
)) {
461 UsbHubCtrlClearHubFeature (HubDev
, USB_HUB_C_HUB_LOCAL_POWER
);
464 if (USB_BIT_IS_SET (HubState
.PortChangeStatus
, USB_HUB_STAT_C_OVER_CURRENT
)) {
465 UsbHubCtrlClearHubFeature (HubDev
, USB_HUB_C_HUB_OVER_CURRENT
);
473 Test whether the interface is a hub interface.
475 @param UsbIf The interface to test.
477 @retval TRUE The interface is a hub interface.
478 @retval FALSE The interface isn't a hub interface.
483 IN USB_INTERFACE
*UsbIf
486 EFI_USB_INTERFACE_DESCRIPTOR
*Setting
;
489 // If the hub is a high-speed hub with multiple TT,
490 // the hub will has a default setting of single TT.
492 Setting
= &UsbIf
->IfSetting
->Desc
;
494 if ((Setting
->InterfaceClass
== USB_HUB_CLASS_CODE
) &&
495 (Setting
->InterfaceSubClass
== USB_HUB_SUBCLASS_CODE
)) {
505 The callback function to the USB hub status change
506 interrupt endpoint. It is called periodically by
507 the underlying host controller.
509 @param Data The data read.
510 @param DataLength The length of the data read.
511 @param Context The context.
512 @param Result The result of the last interrupt transfer.
514 @retval EFI_SUCCESS The process is OK.
515 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource.
526 USB_INTERFACE
*HubIf
;
527 EFI_USB_IO_PROTOCOL
*UsbIo
;
528 EFI_USB_ENDPOINT_DESCRIPTOR
*EpDesc
;
531 HubIf
= (USB_INTERFACE
*) Context
;
532 UsbIo
= &(HubIf
->UsbIo
);
533 EpDesc
= &(HubIf
->HubEp
->Desc
);
535 if (Result
!= EFI_USB_NOERROR
) {
537 // If endpoint is stalled, clear the stall. Use UsbIo to access
538 // the control transfer so internal status are maintained.
540 if (USB_BIT_IS_SET (Result
, EFI_USB_ERR_STALL
)) {
544 USB_FEATURE_ENDPOINT_HALT
,
545 EpDesc
->EndpointAddress
550 // Delete and submit a new async interrupt
552 Status
= UsbIo
->UsbAsyncInterruptTransfer (
554 EpDesc
->EndpointAddress
,
562 if (EFI_ERROR (Status
)) {
563 DEBUG (( EFI_D_ERROR
, "UsbOnHubInterrupt: failed to remove async transfer - %r\n", Status
));
567 Status
= UsbIo
->UsbAsyncInterruptTransfer (
569 EpDesc
->EndpointAddress
,
571 USB_HUB_POLL_INTERVAL
,
572 HubIf
->NumOfPort
/ 8 + 1,
577 if (EFI_ERROR (Status
)) {
578 DEBUG (( EFI_D_ERROR
, "UsbOnHubInterrupt: failed to submit new async transfer - %r\n", Status
));
584 if ((DataLength
== 0) || (Data
== NULL
)) {
589 // OK, actually something is changed, save the change map
590 // then signal the HUB to do enumeration. This is a good
591 // practise since UsbOnHubInterrupt is called in the context
592 // of host contrller's AsyncInterrupt monitor.
594 HubIf
->ChangeMap
= AllocateZeroPool (DataLength
);
596 if (HubIf
->ChangeMap
== NULL
) {
597 return EFI_OUT_OF_RESOURCES
;
600 CopyMem (HubIf
->ChangeMap
, Data
, DataLength
);
601 gBS
->SignalEvent (HubIf
->HubNotify
);
610 Initialize the device for a non-root hub.
612 @param HubIf The USB hub interface.
614 @retval EFI_SUCCESS The hub is initialized.
615 @retval EFI_DEVICE_ERROR Failed to initialize the hub.
620 IN USB_INTERFACE
*HubIf
623 EFI_USB_HUB_DESCRIPTOR HubDesc
;
624 USB_ENDPOINT_DESC
*EpDesc
;
625 USB_INTERFACE_SETTING
*Setting
;
626 EFI_USB_IO_PROTOCOL
*UsbIo
;
632 // Locate the interrupt endpoint for port change map
634 HubIf
->IsHub
= FALSE
;
635 Setting
= HubIf
->IfSetting
;
636 HubDev
= HubIf
->Device
;
639 for (Index
= 0; Index
< Setting
->Desc
.NumEndpoints
; Index
++) {
640 ASSERT ((Setting
->Endpoints
!= NULL
) && (Setting
->Endpoints
[Index
] != NULL
));
642 EpDesc
= Setting
->Endpoints
[Index
];
644 if (USB_BIT_IS_SET (EpDesc
->Desc
.EndpointAddress
, USB_ENDPOINT_DIR_IN
) &&
645 (USB_ENDPOINT_TYPE (&EpDesc
->Desc
) == USB_ENDPOINT_INTERRUPT
)) {
650 if (Index
== Setting
->Desc
.NumEndpoints
) {
651 DEBUG (( EFI_D_ERROR
, "UsbHubInit: no interrupt endpoint found for hub %d\n", HubDev
->Address
));
652 return EFI_DEVICE_ERROR
;
655 Status
= UsbHubReadDesc (HubDev
, &HubDesc
);
657 if (EFI_ERROR (Status
)) {
658 DEBUG (( EFI_D_ERROR
, "UsbHubInit: failed to read HUB descriptor %r\n", Status
));
662 HubIf
->NumOfPort
= HubDesc
.NumPorts
;
664 DEBUG (( EFI_D_INFO
, "UsbHubInit: hub %d has %d ports\n", HubDev
->Address
,HubIf
->NumOfPort
));
667 // Create an event to enumerate the hub's port. On
669 Status
= gBS
->CreateEvent (
677 if (EFI_ERROR (Status
)) {
678 DEBUG (( EFI_D_ERROR
, "UsbHubInit: failed to create signal for hub %d - %r\n",
679 HubDev
->Address
, Status
));
685 // Create AsyncInterrupt to query hub port change endpoint
686 // periodically. If the hub ports are changed, hub will return
687 // changed port map from the interrupt endpoint. The port map
688 // must be able to hold (HubIf->NumOfPort + 1) bits (one bit for
689 // host change status).
691 UsbIo
= &HubIf
->UsbIo
;
692 Status
= UsbIo
->UsbAsyncInterruptTransfer (
694 EpDesc
->Desc
.EndpointAddress
,
696 USB_HUB_POLL_INTERVAL
,
697 HubIf
->NumOfPort
/ 8 + 1,
702 if (EFI_ERROR (Status
)) {
703 DEBUG (( EFI_D_ERROR
, "UsbHubInit: failed to queue interrupt transfer for hub %d - %r\n",
704 HubDev
->Address
, Status
));
706 gBS
->CloseEvent (HubIf
->HubNotify
);
707 HubIf
->HubNotify
= NULL
;
713 // OK, set IsHub to TRUE. Now usb bus can handle this device
714 // as a working HUB. If failed eariler, bus driver will not
715 // recognize it as a hub. Other parts of the bus should be able
719 HubIf
->HubApi
= &mUsbHubApi
;
720 HubIf
->HubEp
= EpDesc
;
723 // Feed power to all the hub ports. It should be ok
724 // for both gang/individual powered hubs.
726 for (Index
= 0; Index
< HubDesc
.NumPorts
; Index
++) {
727 UsbHubCtrlSetPortFeature (HubIf
->Device
, Index
, (EFI_USB_PORT_FEATURE
) USB_HUB_PORT_POWER
);
730 gBS
->Stall (HubDesc
.PwrOn2PwrGood
* USB_SET_PORT_POWER_STALL
);
731 UsbHubAckHubStatus (HubIf
->Device
);
733 DEBUG (( EFI_D_INFO
, "UsbHubInit: hub %d initialized\n", HubDev
->Address
));
740 Get the port status. This function is required to
741 ACK the port change bits although it will return
742 the port changes in PortState. Bus enumeration code
743 doesn't need to ACK the port change bits.
745 @param HubIf The hub interface.
746 @param Port The port of the hub to get state.
747 @param PortState Variable to return the port state.
749 @retval EFI_SUCCESS The port status is successfully returned.
750 @retval Others Failed to return the status.
754 UsbHubGetPortStatus (
755 IN USB_INTERFACE
*HubIf
,
757 OUT EFI_USB_PORT_STATUS
*PortState
762 Status
= UsbHubCtrlGetPortStatus (HubIf
->Device
, Port
, PortState
);
770 Clear the port change status.
772 @param HubIf The hub interface.
773 @param Port The hub port.
779 UsbHubClearPortChange (
780 IN USB_INTERFACE
*HubIf
,
784 EFI_USB_PORT_STATUS PortState
;
785 USB_CHANGE_FEATURE_MAP
*Map
;
789 Status
= UsbHubGetPortStatus (HubIf
, Port
, &PortState
);
791 if (EFI_ERROR (Status
)) {
796 // OK, get the usb port status, now ACK the change bits.
797 // Don't return error when failed to clear the change bits.
798 // It may lead to extra port state report. USB bus should
799 // be able to handle this.
801 for (Index
= 0; Index
< USB_HUB_MAP_SIZE
; Index
++) {
802 Map
= &mHubFeatureMap
[Index
];
804 if (USB_BIT_IS_SET (PortState
.PortChangeStatus
, Map
->ChangedBit
)) {
805 UsbHubCtrlClearPortFeature (HubIf
->Device
, Port
, (UINT16
) Map
->Feature
);
813 Function to set the port feature for non-root hub.
815 @param HubIf The hub interface.
816 @param Port The port of the hub.
817 @param Feature The feature of the port to set.
819 @retval EFI_SUCCESS The hub port feature is set.
820 @retval Others Failed to set the port feature.
824 UsbHubSetPortFeature (
825 IN USB_INTERFACE
*HubIf
,
827 IN EFI_USB_PORT_FEATURE Feature
832 Status
= UsbHubCtrlSetPortFeature (HubIf
->Device
, Port
, (UINT8
) Feature
);
839 Interface function to clear the port feature for non-root hub.
841 @param HubIf The hub interface.
842 @param Port The port of the hub to clear feature for.
843 @param Feature The feature to clear.
845 @retval EFI_SUCCESS The port feature is cleared.
846 @retval Others Failed to clear the port feature.
850 UsbHubClearPortFeature (
851 IN USB_INTERFACE
*HubIf
,
853 IN EFI_USB_PORT_FEATURE Feature
858 Status
= UsbHubCtrlClearPortFeature (HubIf
->Device
, Port
, (UINT8
) Feature
);
865 Interface funtion to reset the port.
867 @param HubIf The hub interface.
868 @param Port The port to reset.
870 @retval EFI_SUCCESS The hub port is reset.
871 @retval EFI_TIMEOUT Failed to reset the port in time.
872 @retval Others Failed to reset the port.
877 IN USB_INTERFACE
*HubIf
,
881 EFI_USB_PORT_STATUS PortState
;
885 Status
= UsbHubSetPortFeature (HubIf
, Port
, (EFI_USB_PORT_FEATURE
) USB_HUB_PORT_RESET
);
887 if (EFI_ERROR (Status
)) {
892 // Drive the reset signal for at least 10ms. Check USB 2.0 Spec
893 // section 7.1.7.5 for timing requirements.
895 gBS
->Stall (USB_SET_PORT_RESET_STALL
);
898 // USB hub will clear RESET bit if reset is actually finished.
900 ZeroMem (&PortState
, sizeof (EFI_USB_PORT_STATUS
));
902 for (Index
= 0; Index
< USB_WAIT_PORT_STS_CHANGE_LOOP
; Index
++) {
903 Status
= UsbHubGetPortStatus (HubIf
, Port
, &PortState
);
905 if (!EFI_ERROR (Status
) &&
906 !USB_BIT_IS_SET (PortState
.PortStatus
, USB_PORT_STAT_RESET
)) {
911 gBS
->Stall (USB_WAIT_PORT_STS_CHANGE_STALL
);
919 Release the hub's control of the interface.
921 @param HubIf The hub interface.
923 @retval EFI_SUCCESS The interface is release of hub control.
928 IN USB_INTERFACE
*HubIf
931 EFI_USB_IO_PROTOCOL
*UsbIo
;
934 UsbIo
= &HubIf
->UsbIo
;
935 Status
= UsbIo
->UsbAsyncInterruptTransfer (
937 HubIf
->HubEp
->Desc
.EndpointAddress
,
939 USB_HUB_POLL_INTERVAL
,
945 if (EFI_ERROR (Status
)) {
949 gBS
->CloseEvent (HubIf
->HubNotify
);
951 HubIf
->IsHub
= FALSE
;
952 HubIf
->HubApi
= NULL
;
954 HubIf
->HubNotify
= NULL
;
956 DEBUG (( EFI_D_INFO
, "UsbHubRelease: hub device %d released\n", HubIf
->Device
->Address
));
963 Initialize the interface for root hub.
965 @param HubIf The root hub interface.
967 @retval EFI_SUCCESS The interface is initialied for root hub.
968 @retval Others Failed to initialize the hub.
973 IN USB_INTERFACE
*HubIf
981 Status
= UsbHcGetCapability (HubIf
->Device
->Bus
, &MaxSpeed
, &NumOfPort
, &Support64
);
983 if (EFI_ERROR (Status
)) {
987 DEBUG (( EFI_D_INFO
, "UsbRootHubInit: root hub %p - max speed %d, %d ports\n",
988 HubIf
, MaxSpeed
, NumOfPort
));
991 HubIf
->HubApi
= &mUsbRootHubApi
;
993 HubIf
->MaxSpeed
= MaxSpeed
;
994 HubIf
->NumOfPort
= NumOfPort
;
995 HubIf
->HubNotify
= NULL
;
998 // Create a timer to poll root hub ports periodically
1000 Status
= gBS
->CreateEvent (
1001 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
1003 UsbRootHubEnumeration
,
1008 if (EFI_ERROR (Status
)) {
1013 // It should signal the event immediately here, or device detection
1014 // by bus enumeration might be delayed by the timer interval.
1016 gBS
->SignalEvent (HubIf
->HubNotify
);
1018 Status
= gBS
->SetTimer (
1021 USB_ROOTHUB_POLL_INTERVAL
1024 if (EFI_ERROR (Status
)) {
1025 gBS
->CloseEvent (HubIf
->HubNotify
);
1033 Get the port status. This function is required to
1034 ACK the port change bits although it will return
1035 the port changes in PortState. Bus enumeration code
1036 doesn't need to ACK the port change bits.
1038 @param HubIf The root hub interface.
1039 @param Port The root hub port to get the state.
1040 @param PortState Variable to return the port state.
1042 @retval EFI_SUCCESS The port state is returned.
1043 @retval Others Failed to retrieve the port state.
1047 UsbRootHubGetPortStatus (
1048 IN USB_INTERFACE
*HubIf
,
1050 OUT EFI_USB_PORT_STATUS
*PortState
1056 Bus
= HubIf
->Device
->Bus
;
1057 Status
= UsbHcGetRootHubPortStatus (Bus
, Port
, PortState
);
1064 Clear the port change status.
1066 @param HubIf The root hub interface.
1067 @param Port The root hub port.
1073 UsbRootHubClearPortChange (
1074 IN USB_INTERFACE
*HubIf
,
1078 EFI_USB_PORT_STATUS PortState
;
1079 USB_CHANGE_FEATURE_MAP
*Map
;
1083 Status
= UsbRootHubGetPortStatus (HubIf
, Port
, &PortState
);
1085 if (EFI_ERROR (Status
)) {
1090 // OK, get the usb port status, now ACK the change bits.
1091 // Don't return error when failed to clear the change bits.
1092 // It may lead to extra port state report. USB bus should
1093 // be able to handle this.
1095 for (Index
= 0; Index
< USB_ROOT_HUB_MAP_SIZE
; Index
++) {
1096 Map
= &mRootHubFeatureMap
[Index
];
1098 if (USB_BIT_IS_SET (PortState
.PortChangeStatus
, Map
->ChangedBit
)) {
1099 UsbHcClearRootHubPortFeature (HubIf
->Device
->Bus
, Port
, (EFI_USB_PORT_FEATURE
) Map
->Feature
);
1106 Set the root hub port feature.
1108 @param HubIf The Usb hub interface.
1109 @param Port The hub port.
1110 @param Feature The feature to set.
1112 @retval EFI_SUCCESS The root hub port is set with the feature.
1113 @retval Others Failed to set the feature.
1117 UsbRootHubSetPortFeature (
1118 IN USB_INTERFACE
*HubIf
,
1120 IN EFI_USB_PORT_FEATURE Feature
1125 Status
= UsbHcSetRootHubPortFeature (HubIf
->Device
->Bus
, Port
, Feature
);
1132 Clear the root hub port feature.
1134 @param HubIf The root hub interface.
1135 @param Port The root hub port.
1136 @param Feature The feature to clear.
1138 @retval EFI_SUCCESS The root hub port is cleared of the feature.
1139 @retval Others Failed to clear the feature.
1143 UsbRootHubClearPortFeature (
1144 IN USB_INTERFACE
*HubIf
,
1146 IN EFI_USB_PORT_FEATURE Feature
1151 Status
= UsbHcClearRootHubPortFeature (HubIf
->Device
->Bus
, Port
, Feature
);
1158 Interface funtion to reset the root hub port.
1160 @param RootIf The root hub interface.
1161 @param Port The port to reset.
1163 @retval EFI_SUCCESS The hub port is reset.
1164 @retval EFI_TIMEOUT Failed to reset the port in time.
1165 @retval EFI_NOT_FOUND The low/full speed device connected to high speed.
1166 root hub is released to the companion UHCI.
1167 @retval Others Failed to reset the port.
1171 UsbRootHubResetPort (
1172 IN USB_INTERFACE
*RootIf
,
1178 EFI_USB_PORT_STATUS PortState
;
1182 // Notice: although EHCI requires that ENABLED bit be cleared
1183 // when reset the port, we don't need to care that here. It
1184 // should be handled in the EHCI driver.
1186 Bus
= RootIf
->Device
->Bus
;
1187 Status
= UsbHcSetRootHubPortFeature (Bus
, Port
, EfiUsbPortReset
);
1189 if (EFI_ERROR (Status
)) {
1190 DEBUG (( EFI_D_ERROR
, "UsbRootHubResetPort: failed to start reset on port %d\n", Port
));
1195 // Drive the reset signal for at least 50ms. Check USB 2.0 Spec
1196 // section 7.1.7.5 for timing requirements.
1198 gBS
->Stall (USB_SET_ROOT_PORT_RESET_STALL
);
1200 Status
= UsbHcClearRootHubPortFeature (Bus
, Port
, EfiUsbPortReset
);
1202 if (EFI_ERROR (Status
)) {
1203 DEBUG (( EFI_D_ERROR
, "UsbRootHubResetPort: failed to clear reset on port %d\n", Port
));
1207 gBS
->Stall (USB_CLR_ROOT_PORT_RESET_STALL
);
1210 // USB host controller won't clear the RESET bit until
1211 // reset is actually finished.
1213 ZeroMem (&PortState
, sizeof (EFI_USB_PORT_STATUS
));
1215 for (Index
= 0; Index
< USB_WAIT_PORT_STS_CHANGE_LOOP
; Index
++) {
1216 Status
= UsbHcGetRootHubPortStatus (Bus
, Port
, &PortState
);
1218 if (EFI_ERROR (Status
)) {
1222 if (!USB_BIT_IS_SET (PortState
.PortStatus
, USB_PORT_STAT_RESET
)) {
1226 gBS
->Stall (USB_WAIT_PORT_STS_CHANGE_STALL
);
1229 if (Index
== USB_WAIT_PORT_STS_CHANGE_LOOP
) {
1230 DEBUG ((EFI_D_ERROR
, "UsbRootHubResetPort: reset not finished in time on port %d\n", Port
));
1234 if (!USB_BIT_IS_SET (PortState
.PortStatus
, USB_PORT_STAT_ENABLE
)) {
1236 // OK, the port is reset. If root hub is of high speed and
1237 // the device is of low/full speed, release the ownership to
1238 // companion UHCI. If root hub is of full speed, it won't
1239 // automatically enable the port, we need to enable it manually.
1241 if (RootIf
->MaxSpeed
== EFI_USB_SPEED_HIGH
) {
1242 DEBUG (( EFI_D_ERROR
, "UsbRootHubResetPort: release low/full speed device (%d) to UHCI\n", Port
));
1244 UsbRootHubSetPortFeature (RootIf
, Port
, EfiUsbPortOwner
);
1245 return EFI_NOT_FOUND
;
1249 Status
= UsbRootHubSetPortFeature (RootIf
, Port
, EfiUsbPortEnable
);
1251 if (EFI_ERROR (Status
)) {
1252 DEBUG (( EFI_D_ERROR
, "UsbRootHubResetPort: failed to enable port %d for UHCI\n", Port
));
1256 gBS
->Stall (USB_SET_ROOT_PORT_ENABLE_STALL
);
1265 Release the root hub's control of the interface.
1267 @param HubIf The root hub interface.
1269 @retval EFI_SUCCESS The root hub's control of the interface is
1275 IN USB_INTERFACE
*HubIf
1278 DEBUG (( EFI_D_INFO
, "UsbRootHubRelease: root hub released for hub %p\n", HubIf
));
1280 gBS
->SetTimer (HubIf
->HubNotify
, TimerCancel
, USB_ROOTHUB_POLL_INTERVAL
);
1281 gBS
->CloseEvent (HubIf
->HubNotify
);
1286 USB_HUB_API mUsbHubApi
= {
1288 UsbHubGetPortStatus
,
1289 UsbHubClearPortChange
,
1290 UsbHubSetPortFeature
,
1291 UsbHubClearPortFeature
,
1296 USB_HUB_API mUsbRootHubApi
= {
1298 UsbRootHubGetPortStatus
,
1299 UsbRootHubClearPortChange
,
1300 UsbRootHubSetPortFeature
,
1301 UsbRootHubClearPortFeature
,
1302 UsbRootHubResetPort
,