\r
Unified interface for RootHub and Hub.\r
\r
-Copyright (c) 2007, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
// bits determine whether hub will report the port in changed\r
// bit maps.\r
//\r
-#define USB_HUB_MAP_SIZE 5\r
-\r
-USB_CHANGE_FEATURE_MAP mHubFeatureMap[USB_HUB_MAP_SIZE] = {\r
+USB_CHANGE_FEATURE_MAP mHubFeatureMap[] = {\r
{USB_PORT_STAT_C_CONNECTION, EfiUsbPortConnectChange},\r
{USB_PORT_STAT_C_ENABLE, EfiUsbPortEnableChange},\r
{USB_PORT_STAT_C_SUSPEND, EfiUsbPortSuspendChange},\r
{USB_PORT_STAT_C_OVERCURRENT, EfiUsbPortOverCurrentChange},\r
- {USB_PORT_STAT_C_RESET, EfiUsbPortResetChange},\r
+ {USB_PORT_STAT_C_RESET, EfiUsbPortResetChange}\r
};\r
\r
-#define USB_ROOT_HUB_MAP_SIZE 5\r
-\r
-USB_CHANGE_FEATURE_MAP mRootHubFeatureMap[USB_ROOT_HUB_MAP_SIZE] = {\r
+USB_CHANGE_FEATURE_MAP mRootHubFeatureMap[] = {\r
{USB_PORT_STAT_C_CONNECTION, EfiUsbPortConnectChange},\r
{USB_PORT_STAT_C_ENABLE, EfiUsbPortEnableChange},\r
{USB_PORT_STAT_C_SUSPEND, EfiUsbPortSuspendChange},\r
// is related to an interface, these requests are sent\r
// to the control endpoint of the device.\r
//\r
+/**\r
+ USB hub control transfer to set the hub depth.\r
+\r
+ @param HubDev The device of the hub.\r
+ @param Depth The depth to set.\r
+\r
+ @retval EFI_SUCCESS Depth of the hub is set.\r
+ @retval Others Failed to set the depth.\r
+\r
+**/\r
+EFI_STATUS\r
+UsbHubCtrlSetHubDepth (\r
+ IN USB_DEVICE *HubDev,\r
+ IN UINT16 Depth\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = UsbCtrlRequest (\r
+ HubDev,\r
+ EfiUsbNoData,\r
+ USB_REQ_TYPE_CLASS,\r
+ USB_HUB_TARGET_HUB,\r
+ USB_HUB_REQ_SET_DEPTH,\r
+ Depth,\r
+ 0,\r
+ NULL,\r
+ 0\r
+ );\r
\r
+ return Status;\r
+}\r
\r
/**\r
USB hub control transfer to clear the hub feature.\r
return Status;\r
}\r
\r
-\r
/**\r
- Usb hub control transfer to get the hub descriptor.\r
+ Usb hub control transfer to get the (super speed) hub descriptor.\r
\r
@param HubDev The hub device.\r
@param Buf The buffer to hold the descriptor.\r
)\r
{\r
EFI_STATUS Status;\r
+ UINT8 DescType;\r
+\r
+ DescType = (HubDev->Speed == EFI_USB_SPEED_SUPER) ?\r
+ USB_DESC_TYPE_HUB_SUPER_SPEED :\r
+ USB_DESC_TYPE_HUB;\r
\r
Status = UsbCtrlRequest (\r
HubDev,\r
USB_REQ_TYPE_CLASS,\r
USB_HUB_TARGET_HUB,\r
USB_HUB_REQ_GET_DESC,\r
- (UINT16) (USB_DESC_TYPE_HUB << 8),\r
+ (UINT16) (DescType << 8),\r
0,\r
Buf,\r
Len\r
}\r
\r
\r
-/**\r
- Usb hub control transfer to reset the TT (Transaction Transaltor).\r
-\r
- @param HubDev The hub device.\r
- @param Port The port of the hub.\r
-\r
- @retval EFI_SUCCESS The TT of the hub is reset.\r
- @retval Others Failed to reset the port.\r
-\r
-**/\r
-EFI_STATUS\r
-UsbHubCtrlResetTT (\r
- IN USB_DEVICE *HubDev,\r
- IN UINT8 Port\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- Status = UsbCtrlRequest (\r
- HubDev,\r
- EfiUsbNoData,\r
- USB_REQ_TYPE_CLASS,\r
- USB_HUB_TARGET_HUB,\r
- USB_HUB_REQ_RESET_TT,\r
- 0,\r
- (UINT16) (Port + 1),\r
- NULL,\r
- 0\r
- );\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Usb hub control transfer to set the hub feature.\r
-\r
- @param HubDev The hub device.\r
- @param Feature The feature to set.\r
-\r
- @retval EFI_SUCESS The feature is set for the hub.\r
- @retval Others Failed to set the feature.\r
-\r
-**/\r
-EFI_STATUS\r
-UsbHubCtrlSetHubFeature (\r
- IN USB_DEVICE *HubDev,\r
- IN UINT8 Feature\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- Status = UsbCtrlRequest (\r
- HubDev,\r
- EfiUsbNoData,\r
- USB_REQ_TYPE_CLASS,\r
- USB_HUB_TARGET_HUB,\r
- USB_HUB_REQ_SET_FEATURE,\r
- Feature,\r
- 0,\r
- NULL,\r
- 0\r
- );\r
-\r
- return Status;\r
-}\r
-\r
-\r
/**\r
Usb hub control transfer to set the port feature.\r
\r
//\r
// Get the whole hub descriptor\r
//\r
- Status = UsbHubCtrlGetHubDesc (HubDev, HubDesc, HubDesc->Length);\r
-\r
- return Status;\r
+ return UsbHubCtrlGetHubDesc (HubDev, HubDesc, HubDesc->Length);\r
}\r
\r
\r
\r
**/\r
EFI_STATUS\r
+EFIAPI\r
UsbOnHubInterrupt (\r
IN VOID *Data,\r
IN UINTN DataLength,\r
IN USB_INTERFACE *HubIf\r
)\r
{\r
- EFI_USB_HUB_DESCRIPTOR HubDesc;\r
+ UINT8 HubDescBuffer[256];\r
+ EFI_USB_HUB_DESCRIPTOR *HubDesc;\r
USB_ENDPOINT_DESC *EpDesc;\r
USB_INTERFACE_SETTING *Setting;\r
EFI_USB_IO_PROTOCOL *UsbIo;\r
EFI_STATUS Status;\r
UINT8 Index;\r
UINT8 NumEndpoints;\r
+ UINT16 Depth;\r
\r
//\r
// Locate the interrupt endpoint for port change map\r
return EFI_DEVICE_ERROR;\r
}\r
\r
- Status = UsbHubReadDesc (HubDev, &HubDesc);\r
+ //\r
+ // The length field of descriptor is UINT8 type, so the buffer\r
+ // with 256 bytes is enough to hold the descriptor data.\r
+ //\r
+ HubDesc = (EFI_USB_HUB_DESCRIPTOR *) HubDescBuffer;\r
+ Status = UsbHubReadDesc (HubDev, HubDesc);\r
\r
if (EFI_ERROR (Status)) {\r
DEBUG (( EFI_D_ERROR, "UsbHubInit: failed to read HUB descriptor %r\n", Status));\r
return Status;\r
}\r
\r
- HubIf->NumOfPort = HubDesc.NumPorts;\r
+ HubIf->NumOfPort = HubDesc->NumPorts;\r
\r
DEBUG (( EFI_D_INFO, "UsbHubInit: hub %d has %d ports\n", HubDev->Address,HubIf->NumOfPort));\r
\r
+ //\r
+ // OK, set IsHub to TRUE. Now usb bus can handle this device\r
+ // as a working HUB. If failed eariler, bus driver will not\r
+ // recognize it as a hub. Other parts of the bus should be able\r
+ // to work.\r
+ //\r
+ HubIf->IsHub = TRUE;\r
+ HubIf->HubApi = &mUsbHubApi;\r
+ HubIf->HubEp = EpDesc;\r
+\r
+ if (HubIf->Device->Speed == EFI_USB_SPEED_SUPER) {\r
+ Depth = (UINT16)(HubIf->Device->Tier - 1);\r
+ DEBUG ((EFI_D_INFO, "UsbHubInit: Set Hub Depth as 0x%x\n", Depth));\r
+ UsbHubCtrlSetHubDepth (HubIf->Device, Depth);\r
+\r
+ for (Index = 0; Index < HubDesc->NumPorts; Index++) {\r
+ UsbHubCtrlSetPortFeature (HubIf->Device, Index, USB_HUB_PORT_REMOTE_WAKE_MASK);\r
+ }\r
+ } else {\r
+ //\r
+ // Feed power to all the hub ports. It should be ok\r
+ // for both gang/individual powered hubs.\r
+ //\r
+ for (Index = 0; Index < HubDesc->NumPorts; Index++) {\r
+ UsbHubCtrlSetPortFeature (HubIf->Device, Index, (EFI_USB_PORT_FEATURE) USB_HUB_PORT_POWER);\r
+ }\r
+\r
+ //\r
+ // Update for the usb hub has no power on delay requirement\r
+ //\r
+ if (HubDesc->PwrOn2PwrGood > 0) {\r
+ gBS->Stall (HubDesc->PwrOn2PwrGood * USB_SET_PORT_POWER_STALL);\r
+ }\r
+ UsbHubAckHubStatus (HubIf->Device);\r
+ }\r
+\r
//\r
// Create an event to enumerate the hub's port. On\r
//\r
return Status;\r
}\r
\r
- //\r
- // OK, set IsHub to TRUE. Now usb bus can handle this device\r
- // as a working HUB. If failed eariler, bus driver will not\r
- // recognize it as a hub. Other parts of the bus should be able\r
- // to work.\r
- //\r
- HubIf->IsHub = TRUE;\r
- HubIf->HubApi = &mUsbHubApi;\r
- HubIf->HubEp = EpDesc;\r
-\r
- //\r
- // Feed power to all the hub ports. It should be ok\r
- // for both gang/individual powered hubs.\r
- //\r
- for (Index = 0; Index < HubDesc.NumPorts; Index++) {\r
- UsbHubCtrlSetPortFeature (HubIf->Device, Index, (EFI_USB_PORT_FEATURE) USB_HUB_PORT_POWER);\r
- }\r
-\r
- gBS->Stall (HubDesc.PwrOn2PwrGood * USB_SET_PORT_POWER_STALL);\r
- UsbHubAckHubStatus (HubIf->Device);\r
-\r
DEBUG (( EFI_D_INFO, "UsbHubInit: hub %d initialized\n", HubDev->Address));\r
return Status;\r
}\r
// It may lead to extra port state report. USB bus should\r
// be able to handle this.\r
//\r
- for (Index = 0; Index < USB_HUB_MAP_SIZE; Index++) {\r
+ for (Index = 0; Index < ARRAY_SIZE (mHubFeatureMap); Index++) {\r
Map = &mHubFeatureMap[Index];\r
\r
if (USB_BIT_IS_SET (PortState.PortChangeStatus, Map->ChangedBit)) {\r
}\r
\r
//\r
- // Drive the reset signal for at least 10ms. Check USB 2.0 Spec\r
+ // Drive the reset signal for worst 20ms. Check USB 2.0 Spec\r
// section 7.1.7.5 for timing requirements.\r
//\r
gBS->Stall (USB_SET_PORT_RESET_STALL);\r
\r
//\r
- // USB hub will clear RESET bit if reset is actually finished.\r
+ // Check USB_PORT_STAT_C_RESET bit to see if the resetting state is done.\r
//\r
ZeroMem (&PortState, sizeof (EFI_USB_PORT_STATUS));\r
\r
for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) {\r
Status = UsbHubGetPortStatus (HubIf, Port, &PortState);\r
\r
- if (!EFI_ERROR (Status) &&\r
- !USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_RESET)) {\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
\r
+ if (!EFI_ERROR (Status) &&\r
+ USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_RESET)) {\r
+ gBS->Stall (USB_SET_PORT_RECOVERY_STALL);\r
return EFI_SUCCESS;\r
}\r
\r
// It may lead to extra port state report. USB bus should\r
// be able to handle this.\r
//\r
- for (Index = 0; Index < USB_ROOT_HUB_MAP_SIZE; Index++) {\r
+ for (Index = 0; Index < ARRAY_SIZE (mRootHubFeatureMap); Index++) {\r
Map = &mRootHubFeatureMap[Index];\r
\r
if (USB_BIT_IS_SET (PortState.PortChangeStatus, Map->ChangedBit)) {\r
// should be handled in the EHCI driver.\r
//\r
Bus = RootIf->Device->Bus;\r
+\r
Status = UsbHcSetRootHubPortFeature (Bus, Port, EfiUsbPortReset);\r
\r
if (EFI_ERROR (Status)) {\r