Index: uspace/drv/bus/usb/xhci/debug.c
===================================================================
--- uspace/drv/bus/usb/xhci/debug.c	(revision 5c5c9407d96c6783501670de58c0973d0f0717cc)
+++ uspace/drv/bus/usb/xhci/debug.c	(revision 816335cd9d1194df5ee9bf8ddbd84d42d45bffaf)
@@ -288,5 +288,5 @@
 			ports_from = XHCI_REG_RD(ec, XHCI_EC_SP_CP_OFF);
 			ports_to = ports_from + XHCI_REG_RD(ec, XHCI_EC_SP_CP_COUNT) - 1;
-			usb_log_debug("\tProtocol %4s%u.%u, ports %u-%u", name.str,
+			usb_log_debug("\tProtocol %.4s%u.%u, ports %u-%u", name.str,
 			    XHCI_REG_RD(ec, XHCI_EC_SP_MAJOR),
 			    XHCI_REG_RD(ec, XHCI_EC_SP_MINOR),
Index: uspace/drv/bus/usb/xhci/hc.c
===================================================================
--- uspace/drv/bus/usb/xhci/hc.c	(revision 5c5c9407d96c6783501670de58c0973d0f0717cc)
+++ uspace/drv/bus/usb/xhci/hc.c	(revision 816335cd9d1194df5ee9bf8ddbd84d42d45bffaf)
@@ -48,12 +48,15 @@
  */
 #define PSI_TO_BPS(psie, psim) (((uint64_t) psim) << (10 * psie))
-#define PORT_SPEED(psie, psim) { \
+#define PORT_SPEED(mjr, psie, psim) { \
+	.name = "USB ", \
+	.major = mjr, \
+	.minor = 0, \
 	.rx_bps = PSI_TO_BPS(psie, psim), \
 	.tx_bps = PSI_TO_BPS(psie, psim) \
 }
-static const xhci_port_speed_t ps_default_full  = PORT_SPEED(2, 12);
-static const xhci_port_speed_t ps_default_low   = PORT_SPEED(1, 1500);
-static const xhci_port_speed_t ps_default_high  = PORT_SPEED(2, 480);
-static const xhci_port_speed_t ps_default_super = PORT_SPEED(3, 5);
+static const xhci_port_speed_t ps_default_full  = PORT_SPEED(2, 2, 12);
+static const xhci_port_speed_t ps_default_low   = PORT_SPEED(2, 1, 1500);
+static const xhci_port_speed_t ps_default_high  = PORT_SPEED(2, 2, 480);
+static const xhci_port_speed_t ps_default_super = PORT_SPEED(3, 3, 5);
 
 /**
@@ -62,5 +65,8 @@
 static int hc_parse_ec(xhci_hc_t *hc)
 {
-	unsigned psic, major;
+	unsigned psic, major, minor;
+	xhci_sp_name_t name;
+
+	xhci_port_speed_t *speeds = hc->rh.speeds;
 
 	for (xhci_extcap_t *ec = hc->xecp; ec; ec = xhci_extcap_next(ec)) {
@@ -74,33 +80,32 @@
 			psic = XHCI_REG_RD(ec, XHCI_EC_SP_PSIC);
 			major = XHCI_REG_RD(ec, XHCI_EC_SP_MAJOR);
+			minor = XHCI_REG_RD(ec, XHCI_EC_SP_MINOR);
+			name.packed = host2uint32_t_le(XHCI_REG_RD(ec, XHCI_EC_SP_NAME));
+
+			if (name.packed != xhci_name_usb.packed) {
+				/**
+				 * The detection of such protocol would work,
+				 * but the rest of the implementation is made
+				 * for the USB protocol only.
+				 */
+				usb_log_error("Unknown protocol %.4s.", name.str);
+				return ENOTSUP;
+			}
 
 			// "Implied" speed
 			if (psic == 0) {
-				/*
-				 * According to section 7.2.2.1.2, only USB 2.0
-				 * and USB 3.0 can have psic == 0. So we
-				 * blindly assume the name == "USB " and minor
-				 * == 0.
-				 */
-
-				unsigned ports_from = XHCI_REG_RD(ec, XHCI_EC_SP_CP_OFF);
-				unsigned ports_to = ports_from
-					+ XHCI_REG_RD(ec, XHCI_EC_SP_CP_COUNT) - 1;
+				assert(minor == 0);
 
 				if (major == 2) {
-					hc->speeds[1] = ps_default_full;
-					hc->speeds[2] = ps_default_low;
-					hc->speeds[3] = ps_default_high;
-					hc->rh.usb2_port_start = ports_from;
-					hc->rh.usb2_port_end = ports_to;
+					speeds[1] = ps_default_full;
+					speeds[2] = ps_default_low;
+					speeds[3] = ps_default_high;
 				} else if (major == 3) {
-					hc->speeds[4] = ps_default_super;
-					hc->rh.usb3_port_start = ports_from;
-					hc->rh.usb3_port_end = ports_to;
+					speeds[4] = ps_default_super;
 				} else {
 					return EINVAL;
 				}
 
-				usb_log_debug2("Implied speed of USB %u set up.", major);
+				usb_log_debug2("Implied speed of USB %u.0 set up.", major);
 			} else {
 				for (unsigned i = 0; i < psic; i++) {
@@ -111,11 +116,15 @@
 					unsigned psim = XHCI_REG_RD(psi, XHCI_PSI_PSIM);
 
+					speeds[psiv].major = major;
+					speeds[psiv].minor = minor;
+					str_ncpy(speeds[psiv].name, 4, name.str, 4);
+
 					uint64_t bps = PSI_TO_BPS(psie, psim);
 
 					if (sim == XHCI_PSI_PLT_SYMM || sim == XHCI_PSI_PLT_RX)
-						hc->speeds[psiv].rx_bps = bps;
+						speeds[psiv].rx_bps = bps;
 					if (sim == XHCI_PSI_PLT_SYMM || sim == XHCI_PSI_PLT_TX) {
-						hc->speeds[psiv].tx_bps = bps;
-						usb_log_debug2("Speed %u set up for bps %" PRIu64 " / %" PRIu64 ".", psiv, hc->speeds[psiv].rx_bps, hc->speeds[psiv].tx_bps);
+						speeds[psiv].tx_bps = bps;
+						usb_log_debug2("Speed %u set up for bps %" PRIu64 " / %" PRIu64 ".", psiv, speeds[psiv].rx_bps, speeds[psiv].tx_bps);
 					}
 				}
@@ -202,5 +211,5 @@
 		goto err_scratch;
 
-	if ((err = xhci_rh_init(&hc->rh, hc->op_regs)))
+	if ((err = xhci_rh_init(&hc->rh, hc)))
 		goto err_cmd;
 
Index: uspace/drv/bus/usb/xhci/hc.h
===================================================================
--- uspace/drv/bus/usb/xhci/hc.h	(revision 5c5c9407d96c6783501670de58c0973d0f0717cc)
+++ uspace/drv/bus/usb/xhci/hc.h	(revision 816335cd9d1194df5ee9bf8ddbd84d42d45bffaf)
@@ -49,11 +49,4 @@
 } xhci_virt_device_ctx_t;
 
-/**
- * xHCI lets the controller define speeds of ports it controls.
- */
-typedef struct xhci_port_speed {
-	uint64_t rx_bps, tx_bps;
-} xhci_port_speed_t;
-
 typedef struct xhci_hc {
 	/* MMIO range */
@@ -80,5 +73,4 @@
 
 	/* Cached capabilities */
-	xhci_port_speed_t speeds [16];
 	unsigned max_slots;
 	bool ac64;
Index: uspace/drv/bus/usb/xhci/hw_struct/regs.h
===================================================================
--- uspace/drv/bus/usb/xhci/hw_struct/regs.h	(revision 5c5c9407d96c6783501670de58c0973d0f0717cc)
+++ uspace/drv/bus/usb/xhci/hw_struct/regs.h	(revision 816335cd9d1194df5ee9bf8ddbd84d42d45bffaf)
@@ -241,5 +241,5 @@
 	 * 15:14 - PIC
 	 *          27  26  25  24  23  22  21  20  19  18  17  16
-     * 27:16 - WOE WDE WCE CAS CEC PLC PRC OCC WRC PEC CSC LWS
+	 * 27:16 - WOE WDE WCE CAS CEC PLC PRC OCC WRC PEC CSC LWS
 	 *    30 - DR
 	 *    31 - WPR
@@ -546,4 +546,8 @@
 } xhci_sp_name_t;
 
+static const xhci_sp_name_t xhci_name_usb = {
+    .str = "USB "
+};
+
 static inline xhci_extcap_t *xhci_extcap_next(const xhci_extcap_t *cur)
 {
Index: uspace/drv/bus/usb/xhci/rh.c
===================================================================
--- uspace/drv/bus/usb/xhci/rh.c	(revision 5c5c9407d96c6783501670de58c0973d0f0717cc)
+++ uspace/drv/bus/usb/xhci/rh.c	(revision 816335cd9d1194df5ee9bf8ddbd84d42d45bffaf)
@@ -51,8 +51,10 @@
 static usbvirt_device_ops_t ops;
 
-int xhci_rh_init(xhci_rh_t *rh, xhci_op_regs_t *op_regs)
+int xhci_rh_init(xhci_rh_t *rh, xhci_hc_t *hc)
 {
 	assert(rh);
-	rh->op_regs = op_regs;
+	assert(hc);
+
+	rh->hc = hc;
 
 	usb_hub_descriptor_header_t *header = &rh->hub_descriptor.header;
@@ -172,11 +174,11 @@
 {
 	uint8_t link_state = XHCI_REG_RD(regs, XHCI_PORT_PLS);
-	// FIXME: do we have a better way to detect if this is usb2 or usb3 device?
-	if (xhci_is_usb3_port(&hc->rh, port_id)) {
+	const xhci_port_speed_t *speed = xhci_get_port_speed(&hc->rh, port_id);
+
+	usb_log_info("Detected new %.4s%u.%u device on port %u.", speed->name, speed->major, speed->minor, port_id);
+
+	if (speed->major == 3) {
 		if(link_state == 0) {
 			/* USB3 is automatically advanced to enabled. */
-			uint8_t port_speed = XHCI_REG_RD(regs, XHCI_PORT_PS);
-			usb_log_debug("Detected new device on port %u, port speed id %u.", port_id, port_speed);
-
 			return alloc_dev(hc, port_id, 0);
 		}
@@ -237,4 +239,12 @@
 
 	return EOK;
+}
+
+const xhci_port_speed_t *xhci_get_port_speed(xhci_rh_t *rh, uint8_t port)
+{
+	xhci_port_regs_t *port_regs = &rh->hc->op_regs->portrs[port - 1];
+
+	unsigned psiv = XHCI_REG_RD(port_regs, XHCI_PORT_PS);
+	return &rh->speeds[psiv];
 }
 
@@ -343,5 +353,5 @@
 
 	/* The index is 1-based. */
-	xhci_port_regs_t* regs = &hub->op_regs->portrs[setup_packet->index - 1];
+	xhci_port_regs_t* regs = &hub->hc->op_regs->portrs[setup_packet->index - 1];
 
 	const uint32_t status = uint32_host2usb(
Index: uspace/drv/bus/usb/xhci/rh.h
===================================================================
--- uspace/drv/bus/usb/xhci/rh.h	(revision 5c5c9407d96c6783501670de58c0973d0f0717cc)
+++ uspace/drv/bus/usb/xhci/rh.h	(revision 816335cd9d1194df5ee9bf8ddbd84d42d45bffaf)
@@ -39,4 +39,7 @@
 #include <usb/host/usb_transfer_batch.h>
 #include <usbvirt/virthub_base.h>
+#include "hw_struct/regs.h"
+
+typedef struct xhci_hc xhci_hc_t;
 
 enum {
@@ -44,10 +47,24 @@
 };
 
+/**
+ * xHCI lets the controller define speeds of ports it controls.
+ */
+typedef struct xhci_port_speed {
+	char name [4];
+	uint8_t major, minor;
+	uint64_t rx_bps, tx_bps;
+} xhci_port_speed_t;
+
 /* XHCI root hub instance */
 typedef struct {
 	/** Virtual hub instance */
 	virthub_base_t base;
-	/** XHCI operational registers */
-	xhci_op_regs_t *op_regs;
+
+	/** Host controller */
+	xhci_hc_t *hc;
+
+	/** Port speeds reported from HC */
+	xhci_port_speed_t speeds [16];
+
 	/** USB hub descriptor describing the XHCI root hub */
 	struct {
@@ -57,13 +74,9 @@
 	/** Interrupt transfer waiting for an actual interrupt to occur */
 	usb_transfer_batch_t *unfinished_interrupt_transfer;
-
-	uint8_t usb2_port_start;
-	uint8_t usb2_port_end;
-	uint8_t usb3_port_start;
-	uint8_t usb3_port_end;
 } xhci_rh_t;
 
-int xhci_rh_init(xhci_rh_t *, xhci_op_regs_t *);
+int xhci_rh_init(xhci_rh_t *, xhci_hc_t *);
 int xhci_rh_fini(xhci_rh_t *);
+const xhci_port_speed_t *xhci_get_port_speed(xhci_rh_t *, uint8_t);
 int xhci_handle_port_status_change_event(xhci_hc_t *, xhci_trb_t *);
 int xhci_get_hub_port(xhci_trb_t *);
@@ -84,8 +97,8 @@
 }
 
-static inline bool xhci_is_usb3_port(xhci_rh_t* rh, uint8_t port) {
-	return port >= rh->usb3_port_start && port <= rh->usb3_port_end;
+static inline bool xhci_is_usb3_port(xhci_rh_t* rh, uint8_t port)
+{
+	return xhci_get_port_speed(rh, port)->major == 3;
 }
-
 #endif
 
