]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c
MdeModulePkg/XhciDxe: Event Ring traverse algorithm enhancement to avoid that those...
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbBusDxe / UsbHub.c
index fdcde5d90f76231b8203de9c084d506f26016e73..78af917ca0400826b53352e4841a2165a76b1397 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 - 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
@@ -252,7 +313,7 @@ UsbHubCtrlGetHubStatus (
   @param  State                 Variable to return the hub port state.\r
 \r
   @retval EFI_SUCCESS           The port state is returned in State.\r
-  @retval Others                Failed to retrive the port state.\r
+  @retval Others                Failed to retrieve the port state.\r
 \r
 **/\r
 EFI_STATUS\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
@@ -516,6 +585,7 @@ UsbIsHubInterface (
 \r
 **/\r
 EFI_STATUS\r
+EFIAPI\r
 UsbOnHubInterrupt (\r
   IN  VOID                *Data,\r
   IN  UINTN               DataLength,\r
@@ -627,6 +697,8 @@ UsbHubInit (
   USB_DEVICE              *HubDev;\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
@@ -635,8 +707,9 @@ UsbHubInit (
   Setting       = HubIf->IfSetting;\r
   HubDev        = HubIf->Device;\r
   EpDesc        = NULL;\r
+  NumEndpoints  = Setting->Desc.NumEndpoints;\r
 \r
-  for (Index = 0; Index < Setting->Desc.NumEndpoints; Index++) {\r
+  for (Index = 0; Index < NumEndpoints; Index++) {\r
     ASSERT ((Setting->Endpoints != NULL) && (Setting->Endpoints[Index] != NULL));\r
 \r
     EpDesc = Setting->Endpoints[Index];\r
@@ -647,7 +720,7 @@ UsbHubInit (
     }\r
   }\r
 \r
-  if (Index == Setting->Desc.NumEndpoints) {\r
+  if (Index == NumEndpoints) {\r
     DEBUG (( EFI_D_ERROR, "UsbHubInit: no interrupt endpoint found for hub %d\n", HubDev->Address));\r
     return EFI_DEVICE_ERROR;\r
   }\r
@@ -663,6 +736,37 @@ 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
+    gBS->Stall (HubDesc.PwrOn2PwrGood * USB_SET_PORT_POWER_STALL);\r
+    UsbHubAckHubStatus (HubIf->Device);\r
+  }\r
+\r
   //\r
   // Create an event to enumerate the hub's port. On\r
   //\r
@@ -709,27 +813,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
@@ -772,8 +855,6 @@ UsbHubGetPortStatus (
   @param  HubIf                 The hub interface.\r
   @param  Port                  The hub port.\r
 \r
-  @return None.\r
-\r
 **/\r
 VOID\r
 UsbHubClearPortChange (\r
@@ -798,7 +879,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
@@ -862,7 +943,7 @@ UsbHubClearPortFeature (
 \r
 \r
 /**\r
-  Interface funtion to reset the port.\r
+  Interface function to reset the port.\r
 \r
   @param  HubIf                 The hub interface.\r
   @param  Port                  The port to reset.\r
@@ -964,7 +1045,7 @@ UsbHubRelease (
 \r
   @param  HubIf                 The root hub interface.\r
 \r
-  @retval EFI_SUCCESS           The interface is initialied for root hub.\r
+  @retval EFI_SUCCESS           The interface is initialized for root hub.\r
   @retval Others                Failed to initialize the hub.\r
 \r
 **/\r
@@ -1066,8 +1147,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
@@ -1092,7 +1171,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
@@ -1155,7 +1234,7 @@ UsbRootHubClearPortFeature (
 \r
 \r
 /**\r
-  Interface funtion to reset the root hub port.\r
+  Interface function to reset the root hub port.\r
 \r
   @param  RootIf                The root hub interface.\r
   @param  Port                  The port to reset.\r