summaryrefslogtreecommitdiff
path: root/config/grub/xhci/patches/0020-grub-core-bus-usb-usbhub-Add-xHCI-non-root-hub-suppo.patch
blob: 735ef22dee9cc9c993ea17ae0168a0b1228f63a8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
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