grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v2 7/7] grub-core/bus/usb/usbhub: Add xHCI non root hub support


From: Patrick Rudolph
Subject: [PATCH v2 7/7] grub-core/bus/usb/usbhub: Add xHCI non root hub support
Date: Mon, 7 Dec 2020 08:41:27 +0100

Tested on Intel PCH C246, the USB3 hub can be configured by grub.

Issues:
* USB3 devices connected behind that hub are sometimes not detected.

Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
---
 grub-core/bus/usb/usbhub.c | 40 ++++++++++++++++++++++++++++++++------
 include/grub/usbdesc.h     |  1 +
 include/grub/usbtrans.h    |  4 ++++
 3 files changed, 39 insertions(+), 6 deletions(-)

diff --git a/grub-core/bus/usb/usbhub.c b/grub-core/bus/usb/usbhub.c
index 63bee1d1a..841796f2f 100644
--- a/grub-core/bus/usb/usbhub.c
+++ b/grub-core/bus/usb/usbhub.c
@@ -148,19 +148,32 @@ grub_usb_hub_add_dev (grub_usb_controller_t controller,
   return dev;
 }
 
-
+static grub_usb_err_t
+grub_usb_set_hub_depth(grub_usb_device_t dev, grub_uint8_t depth)
+{
+  return grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
+                                   | GRUB_USB_REQTYPE_CLASS
+                                   | GRUB_USB_REQTYPE_TARGET_DEV),
+                             GRUB_USB_HUB_REQ_SET_HUB_DEPTH, depth,
+                             0, 0, NULL);
+}
+
 static grub_usb_err_t
 grub_usb_add_hub (grub_usb_device_t dev)
 {
   struct grub_usb_usb_hubdesc hubdesc;
   grub_usb_err_t err;
+  grub_uint16_t req;
   int i;
-  
+
+  req = (dev->speed == GRUB_USB_SPEED_SUPER) ? GRUB_USB_DESCRIPTOR_SS_HUB :
+    GRUB_USB_DESCRIPTOR_HUB;
+
   err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN
                                    | GRUB_USB_REQTYPE_CLASS
                                    | GRUB_USB_REQTYPE_TARGET_DEV),
-                              GRUB_USB_REQ_GET_DESCRIPTOR,
-                             (GRUB_USB_DESCRIPTOR_HUB << 8) | 0,
+                             GRUB_USB_REQ_GET_DESCRIPTOR,
+                             (req << 8) | 0,
                              0, sizeof (hubdesc), (char *) &hubdesc);
   if (err)
     return err;
@@ -183,6 +196,19 @@ grub_usb_add_hub (grub_usb_device_t dev)
       return GRUB_USB_ERR_INTERNAL;
     }
 
+  if (dev->speed == GRUB_USB_SPEED_SUPER)
+    {
+      grub_uint8_t depth;
+      grub_uint32_t route;
+      /* Depth maximum value is 5, but root hubs doesn't count */
+      for (depth = 0, route = dev->route; (route & 0xf) > 0; route >>= 4)
+       depth++;
+
+      err = grub_usb_set_hub_depth(dev, depth);
+      if (err)
+        return err;
+    }
+
   /* Power on all Hub ports.  */
   for (i = 1; i <= hubdesc.portcnt; i++)
     {
@@ -637,7 +663,9 @@ poll_nonroot_hub (grub_usb_device_t dev)
              int split_hubaddr = 0;
 
              /* Determine the device speed.  */
-             if (status & GRUB_USB_HUB_STATUS_PORT_LOWSPEED)
+             if (dev->speed == GRUB_USB_SPEED_SUPER)
+               speed = GRUB_USB_SPEED_SUPER;
+             else if (status & GRUB_USB_HUB_STATUS_PORT_LOWSPEED)
                speed = GRUB_USB_SPEED_LOW;
              else
                {
@@ -651,7 +679,7 @@ poll_nonroot_hub (grub_usb_device_t dev)
              grub_millisleep (10);
 
               /* Find correct values for SPLIT hubport and hubaddr */
-             if (speed == GRUB_USB_SPEED_HIGH)
+             if (speed == GRUB_USB_SPEED_HIGH || speed == GRUB_USB_SPEED_SUPER)
                {
                  /* HIGH speed device needs not transaction translation */
                  split_hubport = 0;
diff --git a/include/grub/usbdesc.h b/include/grub/usbdesc.h
index bb2ab2e27..1697aa465 100644
--- a/include/grub/usbdesc.h
+++ b/include/grub/usbdesc.h
@@ -30,6 +30,7 @@ typedef enum {
   GRUB_USB_DESCRIPTOR_ENDPOINT,
   GRUB_USB_DESCRIPTOR_DEBUG = 10,
   GRUB_USB_DESCRIPTOR_HUB = 0x29,
+  GRUB_USB_DESCRIPTOR_SS_HUB = 0x2a,
   GRUB_USB_DESCRIPTOR_SS_ENDPOINT_COMPANION = 0x30
 } grub_usb_descriptor_t;
 
diff --git a/include/grub/usbtrans.h b/include/grub/usbtrans.h
index aef482cb9..a5891e663 100644
--- a/include/grub/usbtrans.h
+++ b/include/grub/usbtrans.h
@@ -110,6 +110,10 @@ enum
     GRUB_USB_REQ_SET_INTERFACE = 0x0B,
     GRUB_USB_REQ_SYNC_FRAME = 0x0C
   };
+enum
+  {
+    GRUB_USB_HUB_REQ_SET_HUB_DEPTH = 0x0C,
+  };
 
 #define GRUB_USB_FEATURE_ENDP_HALT     0x00
 #define GRUB_USB_FEATURE_DEV_REMOTE_WU 0x01
-- 
2.26.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]