Super speed hubs (usb3 spec) have specific initialization requirements. Add the code necessary to detect and initialize these hubs.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/hw/usb-hub.c | 36 ++++++++++++++++++++++++++++++++++-- src/hw/usb-hub.h | 6 +++++- 2 files changed, 39 insertions(+), 3 deletions(-)
diff --git a/src/hw/usb-hub.c b/src/hw/usb-hub.c index c21cbfb..54e341b 100644 --- a/src/hw/usb-hub.c +++ b/src/hw/usb-hub.c @@ -17,13 +17,28 @@ get_hub_desc(struct usb_pipe *pipe, struct usb_hub_descriptor *desc) struct usb_ctrlrequest req; req.bRequestType = USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_DEVICE; req.bRequest = USB_REQ_GET_DESCRIPTOR; - req.wValue = USB_DT_HUB<<8; + if (pipe->speed == USB_SUPERSPEED) + req.wValue = USB_DT_HUB3<<8; + else + req.wValue = USB_DT_HUB<<8; req.wIndex = 0; req.wLength = sizeof(*desc); return usb_send_default_control(pipe, &req, desc); }
static int +set_hub_depth(struct usb_pipe *pipe, u16 depth) +{ + struct usb_ctrlrequest req; + req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_DEVICE; + req.bRequest = HUB_REQ_SET_HUB_DEPTH; + req.wValue = depth; + req.wIndex = 0; + req.wLength = 0; + return usb_send_default_control(pipe, &req, NULL); +} + +static int set_port_feature(struct usbhub_s *hub, int port, int feature) { struct usb_ctrlrequest req; @@ -105,7 +120,9 @@ usb_hub_reset(struct usbhub_s *hub, u32 port) ret = get_port_status(hub, port, &sts); if (ret) goto fail; - if (!(sts.wPortStatus & USB_PORT_STAT_RESET)) + if (!(sts.wPortStatus & USB_PORT_STAT_RESET) + && (hub->usbdev->speed != USB_SUPERSPEED + || !(sts.wPortStatus & USB_PORT_STAT_LINK_MASK))) break; if (timer_check(end)) { warn_timeout(); @@ -119,6 +136,8 @@ usb_hub_reset(struct usbhub_s *hub, u32 port) // Device no longer present return -1;
+ if (hub->usbdev->speed == USB_SUPERSPEED) + return USB_SUPERSPEED; return ((sts.wPortStatus & USB_PORT_STAT_SPEED_MASK) >> USB_PORT_STAT_SPEED_SHIFT);
@@ -154,6 +173,19 @@ usb_hub_setup(struct usbdevice_s *usbdev) hub.portcount = desc.bNbrPorts; hub.op = &HubOp;
+ if (usbdev->speed == USB_SUPERSPEED) { + int depth = 0; + struct usbdevice_s *parent = usbdev->hub->usbdev; + while (parent) { + depth++; + parent = parent->hub->usbdev; + } + + ret = set_hub_depth(usbdev->defpipe, depth); + if (ret) + return ret; + } + // Turn on power to ports. int port; for (port=0; port<desc.bNbrPorts; port++) { diff --git a/src/hw/usb-hub.h b/src/hw/usb-hub.h index 5b09947..880378c 100644 --- a/src/hw/usb-hub.h +++ b/src/hw/usb-hub.h @@ -11,6 +11,9 @@ int usb_hub_setup(struct usbdevice_s *usbdev); ****************************************************************/
#define USB_DT_HUB (USB_TYPE_CLASS | 0x09) +#define USB_DT_HUB3 (USB_TYPE_CLASS | 0x0a) + +#define HUB_REQ_SET_HUB_DEPTH 0x0C
struct usb_hub_descriptor { u8 bDescLength; @@ -48,7 +51,8 @@ struct usb_port_status { #define USB_PORT_STAT_SUSPEND 0x0004 #define USB_PORT_STAT_OVERCURRENT 0x0008 #define USB_PORT_STAT_RESET 0x0010 -#define USB_PORT_STAT_L1 0x0020 +#define USB_PORT_STAT_LINK_SHIFT 5 +#define USB_PORT_STAT_LINK_MASK (0x7 << USB_PORT_STAT_LINK_SHIFT) #define USB_PORT_STAT_POWER 0x0100 #define USB_PORT_STAT_SPEED_SHIFT 9 #define USB_PORT_STAT_SPEED_MASK (0x3 << USB_PORT_STAT_SPEED_SHIFT)
Dear Kevin,
thank you for the patch! I am adding Werner to CC.
Am Montag, den 15.12.2014, 21:47 -0500 schrieb Kevin O'Connor:
Super speed hubs (usb3 spec) have specific initialization requirements. Add the code necessary to detect and initialize these hubs.
Could you please add how you tested this? For example the board, the hub and what you booted from it for example.
Thanks,
Paul
Signed-off-by: Kevin O'Connor kevin@koconnor.net
src/hw/usb-hub.c | 36 ++++++++++++++++++++++++++++++++++-- src/hw/usb-hub.h | 6 +++++- 2 files changed, 39 insertions(+), 3 deletions(-)
diff --git a/src/hw/usb-hub.c b/src/hw/usb-hub.c index c21cbfb..54e341b 100644 --- a/src/hw/usb-hub.c +++ b/src/hw/usb-hub.c @@ -17,13 +17,28 @@ get_hub_desc(struct usb_pipe *pipe, struct usb_hub_descriptor *desc) struct usb_ctrlrequest req; req.bRequestType = USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_DEVICE; req.bRequest = USB_REQ_GET_DESCRIPTOR;
- req.wValue = USB_DT_HUB<<8;
- if (pipe->speed == USB_SUPERSPEED)
req.wValue = USB_DT_HUB3<<8;
- else
req.wIndex = 0; req.wLength = sizeof(*desc); return usb_send_default_control(pipe, &req, desc);req.wValue = USB_DT_HUB<<8;
}
static int +set_hub_depth(struct usb_pipe *pipe, u16 depth) +{
- struct usb_ctrlrequest req;
- req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_DEVICE;
- req.bRequest = HUB_REQ_SET_HUB_DEPTH;
- req.wValue = depth;
- req.wIndex = 0;
- req.wLength = 0;
- return usb_send_default_control(pipe, &req, NULL);
+}
+static int set_port_feature(struct usbhub_s *hub, int port, int feature) { struct usb_ctrlrequest req; @@ -105,7 +120,9 @@ usb_hub_reset(struct usbhub_s *hub, u32 port) ret = get_port_status(hub, port, &sts); if (ret) goto fail;
if (!(sts.wPortStatus & USB_PORT_STAT_RESET))
if (!(sts.wPortStatus & USB_PORT_STAT_RESET)
&& (hub->usbdev->speed != USB_SUPERSPEED
|| !(sts.wPortStatus & USB_PORT_STAT_LINK_MASK))) break; if (timer_check(end)) { warn_timeout();
@@ -119,6 +136,8 @@ usb_hub_reset(struct usbhub_s *hub, u32 port) // Device no longer present return -1;
- if (hub->usbdev->speed == USB_SUPERSPEED)
return ((sts.wPortStatus & USB_PORT_STAT_SPEED_MASK) >> USB_PORT_STAT_SPEED_SHIFT);return USB_SUPERSPEED;
@@ -154,6 +173,19 @@ usb_hub_setup(struct usbdevice_s *usbdev) hub.portcount = desc.bNbrPorts; hub.op = &HubOp;
- if (usbdev->speed == USB_SUPERSPEED) {
int depth = 0;
struct usbdevice_s *parent = usbdev->hub->usbdev;
while (parent) {
depth++;
parent = parent->hub->usbdev;
}
ret = set_hub_depth(usbdev->defpipe, depth);
if (ret)
return ret;
- }
- // Turn on power to ports. int port; for (port=0; port<desc.bNbrPorts; port++) {
diff --git a/src/hw/usb-hub.h b/src/hw/usb-hub.h index 5b09947..880378c 100644 --- a/src/hw/usb-hub.h +++ b/src/hw/usb-hub.h @@ -11,6 +11,9 @@ int usb_hub_setup(struct usbdevice_s *usbdev); ****************************************************************/
#define USB_DT_HUB (USB_TYPE_CLASS | 0x09) +#define USB_DT_HUB3 (USB_TYPE_CLASS | 0x0a)
+#define HUB_REQ_SET_HUB_DEPTH 0x0C
struct usb_hub_descriptor { u8 bDescLength; @@ -48,7 +51,8 @@ struct usb_port_status { #define USB_PORT_STAT_SUSPEND 0x0004 #define USB_PORT_STAT_OVERCURRENT 0x0008 #define USB_PORT_STAT_RESET 0x0010 -#define USB_PORT_STAT_L1 0x0020 +#define USB_PORT_STAT_LINK_SHIFT 5 +#define USB_PORT_STAT_LINK_MASK (0x7 << USB_PORT_STAT_LINK_SHIFT) #define USB_PORT_STAT_POWER 0x0100 #define USB_PORT_STAT_SPEED_SHIFT 9 #define USB_PORT_STAT_SPEED_MASK (0x3 << USB_PORT_STAT_SPEED_SHIFT)
On Tue, Dec 16, 2014 at 11:06:29PM +0100, Paul Menzel wrote:
Dear Kevin,
thank you for the patch! I am adding Werner to CC.
The patch from this email was identical to the patch I sent the other day.
Am Montag, den 15.12.2014, 21:47 -0500 schrieb Kevin O'Connor:
Super speed hubs (usb3 spec) have specific initialization requirements. Add the code necessary to detect and initialize these hubs.
Could you please add how you tested this? For example the board, the hub and what you booted from it for example.
I used an Anker 4 port usb3.0 hub, which I tested with an ADATA 16GB usb3.0 flash drive on both my Acer c720 and Asrock e350m1-usb3.
If you're requesting that info be in the commit message - I don't think that level of detail is required there.
-Kevin
Hi Kevin.
The patch from this email was identical to the patch I sent the other day.
I can not confirm with that. For your reference I have added the patch you sent on 11.12.2014 19:46:
It looks like the hub is found, but responds with a "stall" error on the get_hub_desc() request. Looks like usb3 hubs use a different descriptor id. You could try the patch below - it's a lot of guess work though.
-Kevin
diff --git a/src/hw/usb-hub.c b/src/hw/usb-hub.c index c21cbfb..7688ef2 100644 --- a/src/hw/usb-hub.c +++ b/src/hw/usb-hub.c @@ -17,7 +17,10 @@ get_hub_desc(struct usb_pipe *pipe, struct usb_hub_descriptor *desc) struct usb_ctrlrequest req; req.bRequestType = USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_DEVICE; req.bRequest = USB_REQ_GET_DESCRIPTOR; - req.wValue = USB_DT_HUB<<8; + if (pipe->speed == USB_SUPERSPEED) + req.wValue = USB_DT_HUB3<<8; + else + req.wValue = USB_DT_HUB<<8; req.wIndex = 0; req.wLength = sizeof(*desc); return usb_send_default_control(pipe, &req, desc); @@ -105,7 +108,9 @@ usb_hub_reset(struct usbhub_s *hub, u32 port) ret = get_port_status(hub, port, &sts); if (ret) goto fail; - if (!(sts.wPortStatus & USB_PORT_STAT_RESET)) + if (!(sts.wPortStatus & USB_PORT_STAT_RESET) + && (hub->usbdev->speed != USB_SUPERSPEED + || !(sts.wPortStatus & USB_PORT_STAT_LINK_MASK))) break; if (timer_check(end)) { warn_timeout(); @@ -119,6 +124,8 @@ usb_hub_reset(struct usbhub_s *hub, u32 port) // Device no longer present return -1;
+ if (hub->usbdev->speed == USB_SUPERSPEED) + return USB_SUPERSPEED; return ((sts.wPortStatus & USB_PORT_STAT_SPEED_MASK) >> USB_PORT_STAT_SPEED_SHIFT);
diff --git a/src/hw/usb-hub.h b/src/hw/usb-hub.h index 5b09947..f7436a5 100644 --- a/src/hw/usb-hub.h +++ b/src/hw/usb-hub.h @@ -11,6 +11,7 @@ int usb_hub_setup(struct usbdevice_s *usbdev); ****************************************************************/
#define USB_DT_HUB (USB_TYPE_CLASS | 0x09) +#define USB_DT_HUB3 (USB_TYPE_CLASS | 0x0a)
struct usb_hub_descriptor { u8 bDescLength; @@ -48,7 +49,8 @@ struct usb_port_status { #define USB_PORT_STAT_SUSPEND 0x0004 #define USB_PORT_STAT_OVERCURRENT 0x0008 #define USB_PORT_STAT_RESET 0x0010 -#define USB_PORT_STAT_L1 0x0020 +#define USB_PORT_STAT_LINK_SHIFT 5 +#define USB_PORT_STAT_LINK_MASK (0x7 << USB_PORT_STAT_LINK_SHIFT) #define USB_PORT_STAT_POWER 0x0100 #define USB_PORT_STAT_SPEED_SHIFT 9 #define USB_PORT_STAT_SPEED_MASK (0x3 << USB_PORT_STAT_SPEED_SHIFT)
This is way different from your latest patch Paul mentioned. Did I missed something or wath your first patch not the right one?
Werner
Am 17.12.2014 um 14:14 schrieb Kevin O'Connor:
On Tue, Dec 16, 2014 at 11:06:29PM +0100, Paul Menzel wrote:
Dear Kevin,
thank you for the patch! I am adding Werner to CC.
The patch from this email was identical to the patch I sent the other day.
Am Montag, den 15.12.2014, 21:47 -0500 schrieb Kevin O'Connor:
Super speed hubs (usb3 spec) have specific initialization requirements. Add the code necessary to detect and initialize these hubs.
Could you please add how you tested this? For example the board, the hub and what you booted from it for example.
I used an Anker 4 port usb3.0 hub, which I tested with an ADATA 16GB usb3.0 flash drive on both my Acer c720 and Asrock e350m1-usb3.
If you're requesting that info be in the commit message - I don't think that level of detail is required there.
-Kevin
On Wed, Dec 17, 2014 at 08:25:11PM +0100, Werner Zeh wrote:
Hi Kevin.
The patch from this email was identical to the patch I sent the other day.
I can not confirm with that. For your reference I have added the patch you sent on 11.12.2014 19:46:
I sent a follow up on 20141215: https://www.marc.info/?l=linuxbios&m=141866325530787&w=2
Can you retry with the updated patch?
-Kevin
Hi Kevin.
I tried your patch and it works just fine for me. I made a test with a baytrail based board and the earlier mentioned USB-Hub. Thanks a lot for the really fast replay, great support!
Werner
Gesendet: Mittwoch, 17. Dezember 2014 um 14:14 Uhr Von: "Kevin O'Connor" kevin@koconnor.net An: "Paul Menzel" paulepanter@users.sourceforge.net Cc: seabios@seabios.org, "Werner Zeh" werner.zeh@gmx.net Betreff: Re: [SeaBIOS] [PATCH] usb: Update USB hub code to support super speed hubs
On Tue, Dec 16, 2014 at 11:06:29PM +0100, Paul Menzel wrote:
Dear Kevin,
thank you for the patch! I am adding Werner to CC.
The patch from this email was identical to the patch I sent the other day.
Am Montag, den 15.12.2014, 21:47 -0500 schrieb Kevin O'Connor:
Super speed hubs (usb3 spec) have specific initialization requirements. Add the code necessary to detect and initialize these hubs.
Could you please add how you tested this? For example the board, the hub and what you booted from it for example.
I used an Anker 4 port usb3.0 hub, which I tested with an ADATA 16GB usb3.0 flash drive on both my Acer c720 and Asrock e350m1-usb3.
If you're requesting that info be in the commit message - I don't think that level of detail is required there.
-Kevin