summaryrefslogtreecommitdiff
path: root/config/grub/xhci/patches/0020-grub-core-bus-usb-usbhub-Add-xHCI-non-root-hub-suppo.patch
diff options
context:
space:
mode:
Diffstat (limited to 'config/grub/xhci/patches/0020-grub-core-bus-usb-usbhub-Add-xHCI-non-root-hub-suppo.patch')
-rw-r--r--config/grub/xhci/patches/0020-grub-core-bus-usb-usbhub-Add-xHCI-non-root-hub-suppo.patch127
1 files changed, 127 insertions, 0 deletions
diff --git a/config/grub/xhci/patches/0020-grub-core-bus-usb-usbhub-Add-xHCI-non-root-hub-suppo.patch b/config/grub/xhci/patches/0020-grub-core-bus-usb-usbhub-Add-xHCI-non-root-hub-suppo.patch
new file mode 100644
index 00000000..735ef22d
--- /dev/null
+++ b/config/grub/xhci/patches/0020-grub-core-bus-usb-usbhub-Add-xHCI-non-root-hub-suppo.patch
@@ -0,0 +1,127 @@
+From 127961742cf7992f6989c6e89a18ab6d8f0b297f Mon Sep 17 00:00:00 2001
+From: Patrick Rudolph <patrick.rudolph@9elements.com>
+Date: Thu, 3 Dec 2020 13:44:55 +0100
+Subject: [PATCH 20/22] grub-core/bus/usb/usbhub: Add xHCI non root hub support
+
+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 | 38 +++++++++++++++++++++++++++++++++-----
+ include/grub/usbdesc.h | 1 +
+ include/grub/usbtrans.h | 4 ++++
+ 3 files changed, 38 insertions(+), 5 deletions(-)
+
+diff --git a/grub-core/bus/usb/usbhub.c b/grub-core/bus/usb/usbhub.c
+index b4b3a1a61..e96505aa9 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 039ebed65..d6c3f71dc 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.39.2
+