]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c
Refine the code to avoid error report.
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbBusDxe / UsbHub.c
index f20d933f0399f8662518a476c7321c62c7fea803..2d24bb4b8a23484a2f6fea429a28d727af4c5df6 100644 (file)
@@ -2,8 +2,8 @@
 \r
     Unified interface for RootHub and Hub.\r
 \r
-Copyright (c) 2007, 2009, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
+Copyright (c) 2007 - 2012, 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,6 +200,40 @@ UsbHubCtrlClearTTBuffer (
   return Status;\r
 }\r
 \r
+/**\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
+  @retval EFI_SUCCESS           The hub descriptor is retrieved.\r
+  @retval Others                Failed to retrieve the hub descriptor.\r
+\r
+**/\r
+EFI_STATUS\r
+UsbHubCtrlGetSuperSpeedHubDesc (\r
+  IN  USB_DEVICE          *HubDev,\r
+  OUT VOID                *Buf\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  \r
+  Status = EFI_INVALID_PARAMETER;\r
+  \r
+  Status = UsbCtrlRequest (\r
+             HubDev,\r
+             EfiUsbDataIn,\r
+             USB_REQ_TYPE_CLASS,\r
+             USB_HUB_TARGET_HUB,\r
+             USB_HUB_REQ_GET_DESC,\r
+             (UINT16) (USB_DESC_TYPE_HUB_SUPER_SPEED << 8),\r
+             0,\r
+             Buf,\r
+             32\r
+             );\r
+\r
+  return Status;\r
+}\r
 \r
 /**\r
   Usb hub control transfer to get the hub descriptor.\r
@@ -414,19 +475,27 @@ UsbHubReadDesc (
 {\r
   EFI_STATUS              Status;\r
 \r
-  //\r
-  // First get the hub descriptor length\r
-  //\r
-  Status = UsbHubCtrlGetHubDesc (HubDev, HubDesc, 2);\r
+  if (HubDev->Speed == EFI_USB_SPEED_SUPER) {\r
+    //\r
+    // Get the super speed hub descriptor\r
+    //\r
+    Status = UsbHubCtrlGetSuperSpeedHubDesc (HubDev, HubDesc);\r
+  } else {\r
 \r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
+    //\r
+    // First get the hub descriptor length\r
+    //\r
+    Status = UsbHubCtrlGetHubDesc (HubDev, HubDesc, 2);\r
 \r
-  //\r
-  // Get the whole hub descriptor\r
-  //\r
-  Status = UsbHubCtrlGetHubDesc (HubDev, HubDesc, HubDesc->Length);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // Get the whole hub descriptor\r
+    //\r
+    Status = UsbHubCtrlGetHubDesc (HubDev, HubDesc, HubDesc->Length);\r
+  }\r
 \r
   return Status;\r
 }\r
@@ -629,6 +698,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
@@ -666,6 +736,42 @@ UsbHubInit (
 \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
@@ -712,27 +818,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
@@ -799,7 +884,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 < sizeof (mHubFeatureMap) / sizeof (mHubFeatureMap[0]); Index++) {\r
     Map = &mHubFeatureMap[Index];\r
 \r
     if (USB_BIT_IS_SET (PortState.PortChangeStatus, Map->ChangedBit)) {\r
@@ -1091,7 +1176,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 < sizeof (mRootHubFeatureMap) / sizeof (mRootHubFeatureMap[0]); Index++) {\r
     Map = &mRootHubFeatureMap[Index];\r
 \r
     if (USB_BIT_IS_SET (PortState.PortChangeStatus, Map->ChangedBit)) {\r