3 Copyright (c) 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Unified interface for RootHub and Hub
28 // USB hub class specific requests. Although USB hub
29 // is related to an interface, these requests are sent
30 // to the control endpoint of the device.
35 USB hub control transfer to clear the hub feature
37 @param HubDev The device of the hub
38 @param Feature The feature to clear
40 @retval EFI_SUCCESS Feature of the hub is cleared
41 @retval Others Failed to clear the feature
46 UsbHubCtrlClearHubFeature (
47 IN USB_DEVICE
*HubDev
,
53 Status
= UsbCtrlRequest (
58 USB_HUB_REQ_CLEAR_FEATURE
,
70 Clear the feature of the device's port
72 @param HubDev The hub device
73 @param Port The port to clear feature
74 @param Feature The feature to clear
76 @retval EFI_SUCCESS The feature of the port is cleared.
77 @retval Others Failed to clear the feature.
82 UsbHubCtrlClearPortFeature (
83 IN USB_DEVICE
*HubDev
,
91 // In USB bus, all the port index starts from 0. But HUB
92 // indexes its port from 1. So, port number is added one.
94 Status
= UsbCtrlRequest (
99 USB_HUB_REQ_CLEAR_FEATURE
,
112 Clear the transaction translate buffer if full/low
113 speed control/bulk transfer failed and the transfer
114 uses this hub as translator.Remember to clear the TT
115 buffer of transaction translator, not that of the
118 @param HubDev The hub device
119 @param Port The port of the hub
120 @param DevAddr Address of the failed transaction
121 @param EpNum The endpoint number of the failed transaction
122 @param EpType The type of failed transaction
124 @retval EFI_SUCCESS The TT buffer is cleared
125 @retval Others Failed to clear the TT buffer
129 UsbHubCtrlClearTTBuffer (
130 IN USB_DEVICE
*HubDev
,
141 // Check USB2.0 spec page 424 for wValue's encoding
143 Value
= (UINT16
) ((EpNum
& 0x0F) | (DevAddr
<< 4) |
144 ((EpType
& 0x03) << 11) | ((EpNum
& 0x80) << 15));
146 Status
= UsbCtrlRequest (
151 USB_HUB_REQ_CLEAR_TT
,
163 Usb hub control transfer to get the hub descriptor
165 @param HubDev The hub device
166 @param Buf The buffer to hold the descriptor
167 @param Len The length to retrieve
169 @retval EFI_SUCCESS The hub descriptor is retrieved
170 @retval Others Failed to retrieve the hub descriptor
175 UsbHubCtrlGetHubDesc (
176 IN USB_DEVICE
*HubDev
,
183 Status
= UsbCtrlRequest (
188 USB_HUB_REQ_GET_DESC
,
189 (UINT16
) (USB_DESC_TYPE_HUB
<< 8),
200 Usb hub control transfer to get the hub status
202 @param HubDev The hub device
203 @param State The variable to return the status
205 @retval EFI_SUCCESS The hub status is returned in State
206 @retval Others Failed to get the hub status
211 UsbHubCtrlGetHubStatus (
212 IN USB_DEVICE
*HubDev
,
218 Status
= UsbCtrlRequest (
223 USB_HUB_REQ_GET_STATUS
,
235 Usb hub control transfer to get the port status
237 @param HubDev The hub device
238 @param Port The port of the hub
239 @param State Variable to return the hub port state
241 @retval EFI_SUCCESS The port state is returned in State
242 @retval Others Failed to retrive the port state
247 UsbHubCtrlGetPortStatus (
248 IN USB_DEVICE
*HubDev
,
256 // In USB bus, all the port index starts from 0. But HUB
257 // indexes its port from 1. So, port number is added one.
258 // No need to convert the hub bit to UEFI definition, they
261 Status
= UsbCtrlRequest (
266 USB_HUB_REQ_GET_STATUS
,
278 Usb hub control transfer to reset the TT (Transaction Transaltor)
280 @param HubDev The hub device
281 @param Port The port of the hub
283 @retval EFI_SUCCESS The TT of the hub is reset
284 @retval Others Failed to reset the port
289 IN USB_DEVICE
*HubDev
,
295 Status
= UsbCtrlRequest (
300 USB_HUB_REQ_RESET_TT
,
312 Usb hub control transfer to set the hub feature
314 @param HubDev The hub device
315 @param Feature The feature to set
317 @retval EFI_SUCESS The feature is set for the hub
318 @retval Others Failed to set the feature
322 UsbHubCtrlSetHubFeature (
323 IN USB_DEVICE
*HubDev
,
329 Status
= UsbCtrlRequest (
334 USB_HUB_REQ_SET_FEATURE
,
346 Usb hub control transfer to set the port feature
348 @param HubDev The Usb hub device
349 @param Port The Usb port to set feature for
350 @param Feature The feature to set
352 @retval EFI_SUCCESS The feature is set for the port
353 @retval Others Failed to set the feature
358 UsbHubCtrlSetPortFeature (
359 IN USB_DEVICE
*HubDev
,
367 // In USB bus, all the port index starts from 0. But HUB
368 // indexes its port from 1. So, port number is added one.
370 Status
= UsbCtrlRequest (
375 USB_HUB_REQ_SET_FEATURE
,
387 Read the whole usb hub descriptor. It is necessary
388 to do it in two steps because hub descriptor is of
391 @param HubDev The hub device
392 @param HubDesc The variable to return the descriptor
394 @retval EFI_SUCCESS The hub descriptor is read
395 @retval Others Failed to read the hub descriptor
401 IN USB_DEVICE
*HubDev
,
402 OUT EFI_USB_HUB_DESCRIPTOR
*HubDesc
408 // First get the hub descriptor length
410 Status
= UsbHubCtrlGetHubDesc (HubDev
, HubDesc
, 2);
412 if (EFI_ERROR (Status
)) {
417 // Get the whole hub descriptor
419 Status
= UsbHubCtrlGetHubDesc (HubDev
, HubDesc
, HubDesc
->Length
);
427 Ack the hub change bits. If these bits are not ACKed, Hub will
428 always return changed bit map from its interrupt endpoint.
430 @param HubDev The hub device
432 @retval EFI_SUCCESS The hub change status is ACKed
433 @retval Others Failed to ACK the hub status
438 IN USB_DEVICE
*HubDev
441 EFI_USB_PORT_STATUS HubState
;
444 Status
= UsbHubCtrlGetHubStatus (HubDev
, (UINT32
*) &HubState
);
446 if (EFI_ERROR (Status
)) {
450 if (USB_BIT_IS_SET (HubState
.PortChangeStatus
, USB_HUB_STAT_C_LOCAL_POWER
)) {
451 UsbHubCtrlClearHubFeature (HubDev
, USB_HUB_C_HUB_LOCAL_POWER
);
454 if (USB_BIT_IS_SET (HubState
.PortChangeStatus
, USB_HUB_STAT_C_OVER_CURRENT
)) {
455 UsbHubCtrlClearHubFeature (HubDev
, USB_HUB_C_HUB_OVER_CURRENT
);
463 Test whether the interface is a hub interface.
465 @param UsbIf The interface to test
467 @retval TRUE The interface is a hub interface
468 @retval FALSE The interface isn't a hub interface
473 IN USB_INTERFACE
*UsbIf
476 EFI_USB_INTERFACE_DESCRIPTOR
*Setting
;
479 // If the hub is a high-speed hub with multiple TT,
480 // the hub will has a default setting of single TT.
482 Setting
= &UsbIf
->IfSetting
->Desc
;
484 if ((Setting
->InterfaceClass
== USB_HUB_CLASS_CODE
) &&
485 (Setting
->InterfaceSubClass
== USB_HUB_SUBCLASS_CODE
)) {
495 The callback function to the USB hub status change
496 interrupt endpoint. It is called periodically by
497 the underlying host controller.
499 @param Data The data read
500 @param DataLength The length of the data read
501 @param Context The context
502 @param Result The result of the last interrupt transfer
504 @retval EFI_SUCCESS The process is OK
505 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource
517 USB_INTERFACE
*HubIf
;
518 EFI_USB_IO_PROTOCOL
*UsbIo
;
519 EFI_USB_ENDPOINT_DESCRIPTOR
*EpDesc
;
522 HubIf
= (USB_INTERFACE
*) Context
;
523 UsbIo
= &(HubIf
->UsbIo
);
524 EpDesc
= &(HubIf
->HubEp
->Desc
);
526 if (Result
!= EFI_USB_NOERROR
) {
528 // If endpoint is stalled, clear the stall. Use UsbIo to access
529 // the control transfer so internal status are maintained.
531 if (USB_BIT_IS_SET (Result
, EFI_USB_ERR_STALL
)) {
535 USB_FEATURE_ENDPOINT_HALT
,
536 EpDesc
->EndpointAddress
541 // Delete and submit a new async interrupt
543 Status
= UsbIo
->UsbAsyncInterruptTransfer (
545 EpDesc
->EndpointAddress
,
553 if (EFI_ERROR (Status
)) {
554 DEBUG (( EFI_D_ERROR
, "UsbOnHubInterrupt: failed to remove async transfer - %r\n", Status
));
558 Status
= UsbIo
->UsbAsyncInterruptTransfer (
560 EpDesc
->EndpointAddress
,
562 USB_HUB_POLL_INTERVAL
,
563 HubIf
->NumOfPort
/ 8 + 1,
568 if (EFI_ERROR (Status
)) {
569 DEBUG (( EFI_D_ERROR
, "UsbOnHubInterrupt: failed to submit new async transfer - %r\n", Status
));
575 if ((DataLength
== 0) || (Data
== NULL
)) {
580 // OK, actually something is changed, save the change map
581 // then signal the HUB to do enumeration. This is a good
582 // practise since UsbOnHubInterrupt is called in the context
583 // of host contrller's AsyncInterrupt monitor.
585 HubIf
->ChangeMap
= AllocateZeroPool (DataLength
);
587 if (HubIf
->ChangeMap
== NULL
) {
588 return EFI_OUT_OF_RESOURCES
;
591 CopyMem (HubIf
->ChangeMap
, Data
, DataLength
);
592 gBS
->SignalEvent (HubIf
->HubNotify
);
598 // Array that maps the change bit to feature value which is
599 // used to clear these change bit. USB HUB API will clear
600 // these change bit automatically. For non-root hub, these
601 // bits determine whether hub will report the port in changed
604 #define USB_HUB_MAP_SIZE 5
606 USB_CHANGE_FEATURE_MAP mHubFeatureMap
[USB_HUB_MAP_SIZE
] = {
607 {USB_PORT_STAT_C_CONNECTION
, EfiUsbPortConnectChange
},
608 {USB_PORT_STAT_C_ENABLE
, EfiUsbPortEnableChange
},
609 {USB_PORT_STAT_C_SUSPEND
, EfiUsbPortSuspendChange
},
610 {USB_PORT_STAT_C_OVERCURRENT
, EfiUsbPortOverCurrentChange
},
611 {USB_PORT_STAT_C_RESET
, EfiUsbPortResetChange
},
614 #define USB_ROOT_HUB_MAP_SIZE 5
616 USB_CHANGE_FEATURE_MAP mRootHubFeatureMap
[USB_ROOT_HUB_MAP_SIZE
] = {
617 {USB_PORT_STAT_C_CONNECTION
, EfiUsbPortConnectChange
},
618 {USB_PORT_STAT_C_ENABLE
, EfiUsbPortEnableChange
},
619 {USB_PORT_STAT_C_SUSPEND
, EfiUsbPortSuspendChange
},
620 {USB_PORT_STAT_C_OVERCURRENT
, EfiUsbPortOverCurrentChange
},
621 {USB_PORT_STAT_C_RESET
, EfiUsbPortResetChange
},
627 Initialize the device for a non-root hub
629 @param HubIf The USB hub interface
631 @retval EFI_SUCCESS The hub is initialized
632 @retval EFI_DEVICE_ERROR Failed to initialize the hub
638 IN USB_INTERFACE
*HubIf
641 EFI_USB_HUB_DESCRIPTOR HubDesc
;
642 USB_ENDPOINT_DESC
*EpDesc
;
643 USB_INTERFACE_SETTING
*Setting
;
644 EFI_USB_IO_PROTOCOL
*UsbIo
;
650 // Locate the interrupt endpoint for port change map
652 HubIf
->IsHub
= FALSE
;
653 Setting
= HubIf
->IfSetting
;
654 HubDev
= HubIf
->Device
;
657 for (Index
= 0; Index
< Setting
->Desc
.NumEndpoints
; Index
++) {
658 ASSERT ((Setting
->Endpoints
!= NULL
) && (Setting
->Endpoints
[Index
] != NULL
));
660 EpDesc
= Setting
->Endpoints
[Index
];
662 if (USB_BIT_IS_SET (EpDesc
->Desc
.EndpointAddress
, USB_ENDPOINT_DIR_IN
) &&
663 (USB_ENDPOINT_TYPE (&EpDesc
->Desc
) == USB_ENDPOINT_INTERRUPT
)) {
668 if (Index
== Setting
->Desc
.NumEndpoints
) {
669 DEBUG (( EFI_D_ERROR
, "UsbHubInit: no interrupt endpoint found for hub %d\n", HubDev
->Address
));
670 return EFI_DEVICE_ERROR
;
673 Status
= UsbHubReadDesc (HubDev
, &HubDesc
);
675 if (EFI_ERROR (Status
)) {
676 DEBUG (( EFI_D_ERROR
, "UsbHubInit: failed to read HUB descriptor %r\n", Status
));
680 HubIf
->NumOfPort
= HubDesc
.NumPorts
;
682 DEBUG (( EFI_D_INFO
, "UsbHubInit: hub %d has %d ports\n", HubDev
->Address
,HubIf
->NumOfPort
));
685 // Create an event to enumerate the hub's port. On
687 Status
= gBS
->CreateEvent (
695 if (EFI_ERROR (Status
)) {
696 DEBUG (( EFI_D_ERROR
, "UsbHubInit: failed to create signal for hub %d - %r\n",
697 HubDev
->Address
, Status
));
703 // Create AsyncInterrupt to query hub port change endpoint
704 // periodically. If the hub ports are changed, hub will return
705 // changed port map from the interrupt endpoint. The port map
706 // must be able to hold (HubIf->NumOfPort + 1) bits (one bit for
707 // host change status).
709 UsbIo
= &HubIf
->UsbIo
;
710 Status
= UsbIo
->UsbAsyncInterruptTransfer (
712 EpDesc
->Desc
.EndpointAddress
,
714 USB_HUB_POLL_INTERVAL
,
715 HubIf
->NumOfPort
/ 8 + 1,
720 if (EFI_ERROR (Status
)) {
721 DEBUG (( EFI_D_ERROR
, "UsbHubInit: failed to queue interrupt transfer for hub %d - %r\n",
722 HubDev
->Address
, Status
));
724 gBS
->CloseEvent (HubIf
->HubNotify
);
725 HubIf
->HubNotify
= NULL
;
731 // OK, set IsHub to TRUE. Now usb bus can handle this device
732 // as a working HUB. If failed eariler, bus driver will not
733 // recognize it as a hub. Other parts of the bus should be able
737 HubIf
->HubApi
= &mUsbHubApi
;
738 HubIf
->HubEp
= EpDesc
;
741 // Feed power to all the hub ports. It should be ok
742 // for both gang/individual powered hubs.
744 for (Index
= 0; Index
< HubDesc
.NumPorts
; Index
++) {
745 UsbHubCtrlSetPortFeature (HubIf
->Device
, Index
, (EFI_USB_PORT_FEATURE
) USB_HUB_PORT_POWER
);
748 gBS
->Stall (HubDesc
.PwrOn2PwrGood
* USB_SET_PORT_POWER_STALL
);
749 UsbHubAckHubStatus (HubIf
->Device
);
751 DEBUG (( EFI_D_INFO
, "UsbHubInit: hub %d initialized\n", HubDev
->Address
));
758 Get the port status. This function is required to
759 ACK the port change bits although it will return
760 the port changes in PortState. Bus enumeration code
761 doesn't need to ACK the port change bits.
763 @param HubIf The hub interface
764 @param Port The port of the hub to get state
765 @param PortState Variable to return the port state
767 @retval EFI_SUCCESS The port status is successfully returned
768 @retval Others Failed to return the status
773 UsbHubGetPortStatus (
774 IN USB_INTERFACE
*HubIf
,
776 OUT EFI_USB_PORT_STATUS
*PortState
781 Status
= UsbHubCtrlGetPortStatus (HubIf
->Device
, Port
, PortState
);
789 Clear the port change status.
791 @param HubIf The hub interface
792 @param Port The hub port
799 UsbHubClearPortChange (
800 IN USB_INTERFACE
*HubIf
,
804 EFI_USB_PORT_STATUS PortState
;
805 USB_CHANGE_FEATURE_MAP
*Map
;
809 Status
= UsbHubGetPortStatus (HubIf
, Port
, &PortState
);
811 if (EFI_ERROR (Status
)) {
816 // OK, get the usb port status, now ACK the change bits.
817 // Don't return error when failed to clear the change bits.
818 // It may lead to extra port state report. USB bus should
819 // be able to handle this.
821 for (Index
= 0; Index
< USB_HUB_MAP_SIZE
; Index
++) {
822 Map
= &mHubFeatureMap
[Index
];
824 if (USB_BIT_IS_SET (PortState
.PortChangeStatus
, Map
->ChangedBit
)) {
825 UsbHubCtrlClearPortFeature (HubIf
->Device
, Port
, (UINT16
) Map
->Feature
);
833 Function to set the port feature for non-root hub
835 @param HubIf The hub interface
836 @param Port The port of the hub
837 @param Feature The feature of the port to set
839 @retval EFI_SUCCESS The hub port feature is set
840 @retval Others Failed to set the port feature
845 UsbHubSetPortFeature (
846 IN USB_INTERFACE
*HubIf
,
848 IN EFI_USB_PORT_FEATURE Feature
853 Status
= UsbHubCtrlSetPortFeature (HubIf
->Device
, Port
, (UINT8
) Feature
);
860 Interface function to clear the port feature for non-root hub
862 @param HubIf The hub interface
863 @param Port The port of the hub to clear feature for
864 @param Feature The feature to clear
866 @retval EFI_SUCCESS The port feature is cleared
867 @retval Others Failed to clear the port feature
872 UsbHubClearPortFeature (
873 IN USB_INTERFACE
*HubIf
,
875 IN EFI_USB_PORT_FEATURE Feature
880 Status
= UsbHubCtrlClearPortFeature (HubIf
->Device
, Port
, (UINT8
) Feature
);
887 Interface funtion to reset the port
889 @param HubIf The hub interface
890 @param Port The port to reset
892 @retval EFI_SUCCESS The hub port is reset
893 @retval EFI_TIMEOUT Failed to reset the port in time
894 @retval Others Failed to reset the port
900 IN USB_INTERFACE
*HubIf
,
904 EFI_USB_PORT_STATUS PortState
;
908 Status
= UsbHubSetPortFeature (HubIf
, Port
, (EFI_USB_PORT_FEATURE
) USB_HUB_PORT_RESET
);
910 if (EFI_ERROR (Status
)) {
915 // Drive the reset signal for at least 10ms. Check USB 2.0 Spec
916 // section 7.1.7.5 for timing requirements.
918 gBS
->Stall (USB_SET_PORT_RESET_STALL
);
921 // USB hub will clear RESET bit if reset is actually finished.
923 ZeroMem (&PortState
, sizeof (EFI_USB_PORT_STATUS
));
925 for (Index
= 0; Index
< USB_WAIT_PORT_STS_CHANGE_LOOP
; Index
++) {
926 Status
= UsbHubGetPortStatus (HubIf
, Port
, &PortState
);
928 if (!EFI_ERROR (Status
) &&
929 !USB_BIT_IS_SET (PortState
.PortStatus
, USB_PORT_STAT_RESET
)) {
934 gBS
->Stall (USB_WAIT_PORT_STS_CHANGE_STALL
);
942 Release the hub's control of the interface
944 @param HubIf The hub interface
946 @retval EFI_SUCCESS The interface is release of hub control
952 IN USB_INTERFACE
*HubIf
955 EFI_USB_IO_PROTOCOL
*UsbIo
;
958 UsbIo
= &HubIf
->UsbIo
;
959 Status
= UsbIo
->UsbAsyncInterruptTransfer (
961 HubIf
->HubEp
->Desc
.EndpointAddress
,
963 USB_HUB_POLL_INTERVAL
,
969 if (EFI_ERROR (Status
)) {
973 gBS
->CloseEvent (HubIf
->HubNotify
);
975 HubIf
->IsHub
= FALSE
;
976 HubIf
->HubApi
= NULL
;
978 HubIf
->HubNotify
= NULL
;
980 DEBUG (( EFI_D_INFO
, "UsbHubRelease: hub device %d released\n", HubIf
->Device
->Address
));
987 Initialize the interface for root hub
989 @param HubIf The root hub interface
991 @retval EFI_SUCCESS The interface is initialied for root hub
992 @retval Others Failed to initialize the hub
998 IN USB_INTERFACE
*HubIf
1006 Status
= UsbHcGetCapability (HubIf
->Device
->Bus
, &MaxSpeed
, &NumOfPort
, &Support64
);
1008 if (EFI_ERROR (Status
)) {
1012 DEBUG (( EFI_D_INFO
, "UsbRootHubInit: root hub %x - max speed %d, %d ports\n",
1013 HubIf
, MaxSpeed
, NumOfPort
));
1015 HubIf
->IsHub
= TRUE
;
1016 HubIf
->HubApi
= &mUsbRootHubApi
;
1017 HubIf
->HubEp
= NULL
;
1018 HubIf
->MaxSpeed
= MaxSpeed
;
1019 HubIf
->NumOfPort
= NumOfPort
;
1020 HubIf
->HubNotify
= NULL
;
1023 // Create a timer to poll root hub ports periodically
1025 Status
= gBS
->CreateEvent (
1026 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
1028 UsbRootHubEnumeration
,
1033 if (EFI_ERROR (Status
)) {
1038 // It should signal the event immediately here, or device detection
1039 // by bus enumeration might be delayed by the timer interval.
1041 gBS
->SignalEvent (HubIf
->HubNotify
);
1043 Status
= gBS
->SetTimer (
1046 USB_ROOTHUB_POLL_INTERVAL
1049 if (EFI_ERROR (Status
)) {
1050 gBS
->CloseEvent (HubIf
->HubNotify
);
1059 Get the port status. This function is required to
1060 ACK the port change bits although it will return
1061 the port changes in PortState. Bus enumeration code
1062 doesn't need to ACK the port change bits.
1064 @param HubIf The root hub interface
1065 @param Port The root hub port to get the state
1066 @param PortState Variable to return the port state
1068 @retval EFI_SUCCESS The port state is returned
1069 @retval Others Failed to retrieve the port state
1074 UsbRootHubGetPortStatus (
1075 IN USB_INTERFACE
*HubIf
,
1077 OUT EFI_USB_PORT_STATUS
*PortState
1083 Bus
= HubIf
->Device
->Bus
;
1084 Status
= UsbHcGetRootHubPortStatus (Bus
, Port
, PortState
);
1091 Clear the port change status.
1093 @param HubIf The root hub interface
1094 @param Port The root hub port
1096 @retval EFI_SUCCESS The port state is returned
1097 @retval Others Failed to retrieve the port state
1102 UsbRootHubClearPortChange (
1103 IN USB_INTERFACE
*HubIf
,
1107 EFI_USB_PORT_STATUS PortState
;
1108 USB_CHANGE_FEATURE_MAP
*Map
;
1112 Status
= UsbRootHubGetPortStatus (HubIf
, Port
, &PortState
);
1114 if (EFI_ERROR (Status
)) {
1119 // OK, get the usb port status, now ACK the change bits.
1120 // Don't return error when failed to clear the change bits.
1121 // It may lead to extra port state report. USB bus should
1122 // be able to handle this.
1124 for (Index
= 0; Index
< USB_ROOT_HUB_MAP_SIZE
; Index
++) {
1125 Map
= &mRootHubFeatureMap
[Index
];
1127 if (USB_BIT_IS_SET (PortState
.PortChangeStatus
, Map
->ChangedBit
)) {
1128 UsbHcClearRootHubPortFeature (HubIf
->Device
->Bus
, Port
, (EFI_USB_PORT_FEATURE
) Map
->Feature
);
1136 Set the root hub port feature
1138 @param HubIf The Usb hub interface
1139 @param Port The hub port
1140 @param Feature The feature to set
1142 @retval EFI_SUCCESS The root hub port is set with the feature
1143 @retval Others Failed to set the feature
1148 UsbRootHubSetPortFeature (
1149 IN USB_INTERFACE
*HubIf
,
1151 IN EFI_USB_PORT_FEATURE Feature
1156 Status
= UsbHcSetRootHubPortFeature (HubIf
->Device
->Bus
, Port
, Feature
);
1163 Clear the root hub port feature
1165 @param HubIf The root hub interface
1166 @param Port The root hub port
1167 @param Feature The feature to clear
1169 @retval EFI_SUCCESS The root hub port is cleared of the feature
1170 @retval Others Failed to clear the feature
1175 UsbRootHubClearPortFeature (
1176 IN USB_INTERFACE
*HubIf
,
1178 IN EFI_USB_PORT_FEATURE Feature
1183 Status
= UsbHcClearRootHubPortFeature (HubIf
->Device
->Bus
, Port
, Feature
);
1190 Interface funtion to reset the root hub port
1192 @param RootIf The root hub interface
1193 @param Port The port to reset
1195 @retval EFI_SUCCESS The hub port is reset
1196 @retval EFI_TIMEOUT Failed to reset the port in time
1197 @retval EFI_NOT_FOUND The low/full speed device connected to high speed
1198 root hub is released to the companion UHCI
1199 @retval Others Failed to reset the port
1204 UsbRootHubResetPort (
1205 IN USB_INTERFACE
*RootIf
,
1211 EFI_USB_PORT_STATUS PortState
;
1215 // Notice: although EHCI requires that ENABLED bit be cleared
1216 // when reset the port, we don't need to care that here. It
1217 // should be handled in the EHCI driver.
1219 Bus
= RootIf
->Device
->Bus
;
1220 Status
= UsbHcSetRootHubPortFeature (Bus
, Port
, EfiUsbPortReset
);
1222 if (EFI_ERROR (Status
)) {
1223 DEBUG (( EFI_D_ERROR
, "UsbRootHubResetPort: failed to start reset on port %d\n", Port
));
1228 // Drive the reset signal for at least 50ms. Check USB 2.0 Spec
1229 // section 7.1.7.5 for timing requirements.
1231 gBS
->Stall (USB_SET_ROOT_PORT_RESET_STALL
);
1233 Status
= UsbHcClearRootHubPortFeature (Bus
, Port
, EfiUsbPortReset
);
1235 if (EFI_ERROR (Status
)) {
1236 DEBUG (( EFI_D_ERROR
, "UsbRootHubResetPort: failed to clear reset on port %d\n", Port
));
1240 gBS
->Stall (USB_CLR_ROOT_PORT_RESET_STALL
);
1243 // USB host controller won't clear the RESET bit until
1244 // reset is actually finished.
1246 ZeroMem (&PortState
, sizeof (EFI_USB_PORT_STATUS
));
1248 for (Index
= 0; Index
< USB_WAIT_PORT_STS_CHANGE_LOOP
; Index
++) {
1249 Status
= UsbHcGetRootHubPortStatus (Bus
, Port
, &PortState
);
1251 if (EFI_ERROR (Status
)) {
1255 if (!USB_BIT_IS_SET (PortState
.PortStatus
, USB_PORT_STAT_RESET
)) {
1259 gBS
->Stall (USB_WAIT_PORT_STS_CHANGE_STALL
);
1262 if (Index
== USB_WAIT_PORT_STS_CHANGE_LOOP
) {
1263 DEBUG ((EFI_D_ERROR
, "UsbRootHubResetPort: reset not finished in time on port %d\n", Port
));
1267 if (!USB_BIT_IS_SET (PortState
.PortStatus
, USB_PORT_STAT_ENABLE
)) {
1269 // OK, the port is reset. If root hub is of high speed and
1270 // the device is of low/full speed, release the ownership to
1271 // companion UHCI. If root hub is of full speed, it won't
1272 // automatically enable the port, we need to enable it manually.
1274 if (RootIf
->MaxSpeed
== EFI_USB_SPEED_HIGH
) {
1275 DEBUG (( EFI_D_ERROR
, "UsbRootHubResetPort: release low/full speed device (%d) to UHCI\n", Port
));
1277 UsbRootHubSetPortFeature (RootIf
, Port
, EfiUsbPortOwner
);
1278 return EFI_NOT_FOUND
;
1282 Status
= UsbRootHubSetPortFeature (RootIf
, Port
, EfiUsbPortEnable
);
1284 if (EFI_ERROR (Status
)) {
1285 DEBUG (( EFI_D_ERROR
, "UsbRootHubResetPort: failed to enable port %d for UHCI\n", Port
));
1289 gBS
->Stall (USB_SET_ROOT_PORT_ENABLE_STALL
);
1298 Release the root hub's control of the interface
1300 @param HubIf The root hub interface
1302 @retval EFI_SUCCESS The root hub's control of the interface is
1309 IN USB_INTERFACE
*HubIf
1312 DEBUG (( EFI_D_INFO
, "UsbRootHubRelease: root hub released for hub %x\n", HubIf
));
1314 gBS
->SetTimer (HubIf
->HubNotify
, TimerCancel
, USB_ROOTHUB_POLL_INTERVAL
);
1315 gBS
->CloseEvent (HubIf
->HubNotify
);
1320 USB_HUB_API mUsbHubApi
= {
1322 UsbHubGetPortStatus
,
1323 UsbHubClearPortChange
,
1324 UsbHubSetPortFeature
,
1325 UsbHubClearPortFeature
,
1330 USB_HUB_API mUsbRootHubApi
= {
1332 UsbRootHubGetPortStatus
,
1333 UsbRootHubClearPortChange
,
1334 UsbRootHubSetPortFeature
,
1335 UsbRootHubClearPortFeature
,
1336 UsbRootHubResetPort
,