]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c
MdeModulePkg: Clean up source files
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbBusDxe / UsbHub.c
index ac893e4e2a4d021425dd2b3b0263e3d67dac03f6..2ce5726e632d5f7694a737a9cc9b7f3a248ffa15 100644 (file)
@@ -2,8 +2,8 @@
 \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
+Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
+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
@@ -22,19 +22,15 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 // 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
@@ -47,7 +43,38 @@ USB_CHANGE_FEATURE_MAP  mRootHubFeatureMap[USB_ROOT_HUB_MAP_SIZE] = {
 // 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
@@ -173,9 +200,8 @@ UsbHubCtrlClearTTBuffer (
   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
@@ -193,6 +219,11 @@ UsbHubCtrlGetHubDesc (
   )\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
@@ -200,7 +231,7 @@ UsbHubCtrlGetHubDesc (
              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
@@ -426,9 +457,7 @@ UsbHubReadDesc (
   //\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
@@ -516,6 +545,7 @@ UsbIsHubInterface (
 \r
 **/\r
 EFI_STATUS\r
+EFIAPI\r
 UsbOnHubInterrupt (\r
   IN  VOID                *Data,\r
   IN  UINTN               DataLength,\r
@@ -620,7 +650,8 @@ UsbHubInit (
   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
@@ -628,6 +659,7 @@ UsbHubInit (
   EFI_STATUS              Status;\r
   UINT8                   Index;\r
   UINT8                   NumEndpoints;\r
+  UINT16                  Depth;\r
 \r
   //\r
   // Locate the interrupt endpoint for port change map\r
@@ -654,17 +686,58 @@ UsbHubInit (
     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
@@ -711,27 +784,6 @@ UsbHubInit (
     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
@@ -774,8 +826,6 @@ UsbHubGetPortStatus (
   @param  HubIf                 The hub interface.\r
   @param  Port                  The hub port.\r
 \r
-  @return None.\r
-\r
 **/\r
 VOID\r
 UsbHubClearPortChange (\r
@@ -800,7 +850,7 @@ UsbHubClearPortChange (
   // 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
@@ -891,22 +941,26 @@ UsbHubResetPort (
   }\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
@@ -1068,8 +1122,6 @@ UsbRootHubGetPortStatus (
   @param  HubIf                 The root hub interface.\r
   @param  Port                  The root hub port.\r
 \r
-  @return None.\r
-\r
 **/\r
 VOID\r
 UsbRootHubClearPortChange (\r
@@ -1094,7 +1146,7 @@ UsbRootHubClearPortChange (
   // 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
@@ -1186,6 +1238,7 @@ UsbRootHubResetPort (
   // 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