Index: uspace/drv/bus/usb/xhci/bus.c
===================================================================
--- uspace/drv/bus/usb/xhci/bus.c	(revision f668d602a75538d4476f1df11550b29c815f0af8)
+++ uspace/drv/bus/usb/xhci/bus.c	(revision 2cf28b9d069a6ca711200eb94197fa3b893ee323)
@@ -45,4 +45,5 @@
 #include <stdbool.h>
 
+#include "hc.h"
 #include "bus.h"
 #include "endpoint.h"
@@ -136,4 +137,16 @@
 	}
 
+	/* Calculate route string */
+	xhci_device_t *xhci_hub = xhci_device_get(dev->hub);
+	xhci_dev->tier = xhci_hub->tier + 1;
+	xhci_dev->route_str = xhci_hub->route_str;
+
+	/* Roothub port is not part of the route string */
+	if (xhci_dev->tier >= 2) {
+		const unsigned offset = 4 * (xhci_dev->tier - 2);
+		xhci_dev->route_str |= (dev->port & 0xf) << offset;
+	}
+
+	fibril_mutex_lock(&bus->base.guard);
 	/* Assign an address to the device */
 	if ((err = address_device(hc, xhci_dev))) {
@@ -147,4 +160,5 @@
 	assert(bus->devices_by_slot[xhci_dev->slot_id] == NULL);
 	bus->devices_by_slot[xhci_dev->slot_id] = xhci_dev;
+	fibril_mutex_unlock(&bus->base.guard);
 
 	/* Read the device descriptor, derive the match ids */
@@ -305,4 +319,35 @@
 }
 
+static int request_address(bus_t *bus_base, usb_address_t *addr, bool strict, usb_speed_t speed)
+{
+	assert(addr);
+
+	if (*addr != USB_ADDRESS_DEFAULT)
+		/* xHCI does not allow software to assign addresses. */
+		return ENOTSUP;
+
+	assert(strict);
+
+	xhci_bus_t *xhci_bus = bus_to_xhci_bus(bus_base);
+
+	if (xhci_bus->default_address_speed != USB_SPEED_MAX)
+		/* Already allocated */
+		return ENOENT;
+
+	xhci_bus->default_address_speed = speed;
+	return EOK;
+}
+
+static int release_address(bus_t *bus_base, usb_address_t addr)
+{
+	if (addr != USB_ADDRESS_DEFAULT)
+		return ENOTSUP;
+
+	xhci_bus_t *xhci_bus = bus_to_xhci_bus(bus_base);
+
+	xhci_bus->default_address_speed = USB_SPEED_MAX;
+	return EOK;
+}
+
 static usb_transfer_batch_t *create_batch(bus_t *bus, endpoint_t *ep)
 {
@@ -327,6 +372,6 @@
 	.find_endpoint = find_endpoint,
 
-	.request_address = NULL,
-	.release_address = NULL,
+	.request_address = request_address,
+	.release_address = release_address,
 	.reset_toggle = reset_toggle,
 
@@ -351,4 +396,5 @@
 
 	bus->base.ops = xhci_bus_ops;
+	bus->default_address_speed = USB_SPEED_MAX;
 	return EOK;
 }
Index: uspace/drv/bus/usb/xhci/bus.h
===================================================================
--- uspace/drv/bus/usb/xhci/bus.h	(revision f668d602a75538d4476f1df11550b29c815f0af8)
+++ uspace/drv/bus/usb/xhci/bus.h	(revision 2cf28b9d069a6ca711200eb94197fa3b893ee323)
@@ -49,4 +49,6 @@
 
 	xhci_device_t **devices_by_slot;	/**< Devices by Slot ID */
+
+	usb_speed_t default_address_speed;	/**< Used to get speed from usb hubs */
 } xhci_bus_t;
 
Index: uspace/drv/bus/usb/xhci/endpoint.c
===================================================================
--- uspace/drv/bus/usb/xhci/endpoint.c	(revision f668d602a75538d4476f1df11550b29c815f0af8)
+++ uspace/drv/bus/usb/xhci/endpoint.c	(revision 2cf28b9d069a6ca711200eb94197fa3b893ee323)
@@ -39,5 +39,7 @@
 
 #include <errno.h>
-
+#include <macros.h>
+
+#include "hc.h"
 #include "bus.h"
 #include "commands.h"
Index: uspace/drv/bus/usb/xhci/endpoint.h
===================================================================
--- uspace/drv/bus/usb/xhci/endpoint.h	(revision f668d602a75538d4476f1df11550b29c815f0af8)
+++ uspace/drv/bus/usb/xhci/endpoint.h	(revision 2cf28b9d069a6ca711200eb94197fa3b893ee323)
@@ -43,5 +43,6 @@
 #include <usb/host/hcd.h>
 
-#include "hc.h"
+#include "trb_ring.h"
+
 #include "transfers.h"
 
@@ -97,4 +98,13 @@
 	/** Slot ID assigned to the device by xHC. */
 	uint32_t slot_id;
+
+	/** Corresponding port on RH */
+	uint8_t rh_port;
+
+	/** USB Tier of the device */
+	uint8_t tier;
+
+	/** Route string */
+	uint32_t route_str;
 
 	/** Place to store virtual address for allocated context */
Index: uspace/drv/bus/usb/xhci/hc.c
===================================================================
--- uspace/drv/bus/usb/xhci/hc.c	(revision f668d602a75538d4476f1df11550b29c815f0af8)
+++ uspace/drv/bus/usb/xhci/hc.c	(revision 2cf28b9d069a6ca711200eb94197fa3b893ee323)
@@ -657,4 +657,11 @@
 	int err = ENOMEM;
 
+	/* Although we have the precise PSIV value on devices of tier 1,
+	 * we have to rely on reverse mapping on others. */
+	if (!hc->speed_to_psiv[dev->base.speed]) {
+		usb_log_error("Device reported an usb speed that cannot be mapped to HC port speed.");
+		return EINVAL;
+	}
+
 	/* Setup and register device context */
 	dev->dev_ctx = malloc32(sizeof(xhci_device_ctx_t));
@@ -672,9 +679,14 @@
 
 	/* Initialize slot_ctx according to section 4.3.3 point 3. */
-	XHCI_SLOT_ROOT_HUB_PORT_SET(ictx->slot_ctx, dev->base.port); // FIXME: This should be port at RH
+	XHCI_SLOT_ROOT_HUB_PORT_SET(ictx->slot_ctx, dev->rh_port);
 	XHCI_SLOT_CTX_ENTRIES_SET(ictx->slot_ctx, 1);
-
-	/* Attaching to root hub port, root string equals to 0. */
-	XHCI_SLOT_ROUTE_STRING_SET(ictx->slot_ctx, 0); // FIXME: This is apparently valid in limited cases
+	XHCI_SLOT_ROUTE_STRING_SET(ictx->slot_ctx, dev->route_str);
+	XHCI_SLOT_SPEED_SET(ictx->slot_ctx, hc->speed_to_psiv[dev->base.speed]);
+
+	/* In a very specific case, we have to set also these. But before that,
+	 * we need to refactor how TT is handled in libusbhost. */
+	XHCI_SLOT_TT_HUB_SLOT_ID_SET(ictx->slot_ctx, 0);
+	XHCI_SLOT_TT_HUB_PORT_SET(ictx->slot_ctx, 0);
+	XHCI_SLOT_MTT_SET(ictx->slot_ctx, 0);
 
 	/* Copy endpoint 0 context and set A1 flag. */
Index: uspace/drv/bus/usb/xhci/hc.h
===================================================================
--- uspace/drv/bus/usb/xhci/hc.h	(revision f668d602a75538d4476f1df11550b29c815f0af8)
+++ uspace/drv/bus/usb/xhci/hc.h	(revision 2cf28b9d069a6ca711200eb94197fa3b893ee323)
@@ -43,4 +43,5 @@
 #include "scratchpad.h"
 #include "trb_ring.h"
+
 #include "rh.h"
 #include "bus.h"
Index: uspace/drv/bus/usb/xhci/hw_struct/context.h
===================================================================
--- uspace/drv/bus/usb/xhci/hw_struct/context.h	(revision f668d602a75538d4476f1df11550b29c815f0af8)
+++ uspace/drv/bus/usb/xhci/hw_struct/context.h	(revision 2cf28b9d069a6ca711200eb94197fa3b893ee323)
@@ -111,10 +111,20 @@
 	xhci_dword_t reserved [4];
 
+#define XHCI_SLOT_ROUTE_STRING_SET(ctx, val) \
+	xhci_dword_set_bits(&(ctx).data[0], (val & 0xFFFFF), 19, 0)
+#define XHCI_SLOT_SPEED_SET(ctx, val) \
+	xhci_dword_set_bits(&(ctx).data[0], (val & 0xF), 23, 20)
+#define XHCI_SLOT_MTT_SET(ctx, val) \
+	xhci_dword_set_bits(&(ctx).data[0], !!val, 25, 25)
+#define XHCI_SLOT_CTX_ENTRIES_SET(ctx, val) \
+	xhci_dword_set_bits(&(ctx).data[0], val, 31, 27)
+
 #define XHCI_SLOT_ROOT_HUB_PORT_SET(ctx, val) \
 	xhci_dword_set_bits(&(ctx).data[1], val, 23, 16)
-#define XHCI_SLOT_CTX_ENTRIES_SET(ctx, val) \
-	xhci_dword_set_bits(&(ctx).data[0], val, 31, 27)
-#define XHCI_SLOT_ROUTE_STRING_SET(ctx, val) \
-	xhci_dword_set_bits(&(ctx).data[0], (val & 0xFFFFF), 19, 0)
+
+#define XHCI_SLOT_TT_HUB_SLOT_ID_SET(ctx, val) \
+	xhci_dword_set_bits(&(ctx).data[2], (val & 0xFF), 7, 0)
+#define XHCI_SLOT_TT_HUB_PORT_SET(ctx, val) \
+	xhci_dword_set_bits(&(ctx).data[2], (val & 0xFF), 15, 8)
 
 #define XHCI_SLOT_ROUTE_STRING(ctx)     XHCI_DWORD_EXTRACT((ctx).data[0], 19,  0)
Index: uspace/drv/bus/usb/xhci/rh.c
===================================================================
--- uspace/drv/bus/usb/xhci/rh.c	(revision f668d602a75538d4476f1df11550b29c815f0af8)
+++ uspace/drv/bus/usb/xhci/rh.c	(revision 2cf28b9d069a6ca711200eb94197fa3b893ee323)
@@ -69,7 +69,15 @@
 	rh->max_ports = XHCI_REG_RD(hc->cap_regs, XHCI_CAP_MAX_PORTS);
 	rh->devices = (xhci_device_t **) calloc(rh->max_ports, sizeof(xhci_device_t *));
-	hc->rh.hc_device = device;
-
-	return device_init(&hc->rh.device);
+	rh->hc_device = device;
+
+	const int err = device_init(&rh->device.base);
+	if (err)
+		return err;
+
+	/* Initialize route string */
+	rh->device.route_str = 0;
+	rh->device.tier = 0;
+
+	return EOK;
 }
 
@@ -81,4 +89,6 @@
 	assert(rh);
 	assert(rh->hc_device);
+
+	assert(rh->devices[port_id - 1] == NULL);
 
 	xhci_bus_t *bus = &rh->hc->bus;
@@ -94,6 +104,7 @@
 	xhci_dev->hc = rh->hc;
 	xhci_dev->usb3 = port_speed->major == 3;
-
-	dev->hub = &rh->device;
+	xhci_dev->rh_port = port_id;
+
+	dev->hub = &rh->device.base;
 	dev->port = port_id;
 	dev->speed = port_speed->usb_speed;
@@ -113,11 +124,8 @@
 	}
 
-	fibril_mutex_lock(&rh->device.guard);
-	list_append(&dev->link, &rh->device.devices);
-	if (!rh->devices[port_id - 1]) {
-		/* Only save the device if it's the first one connected to this port. */
-		rh->devices[port_id - 1] = xhci_dev;
-	}
-	fibril_mutex_unlock(&rh->device.guard);
+	fibril_mutex_lock(&rh->device.base.guard);
+	list_append(&dev->link, &rh->device.base.devices);
+	rh->devices[port_id - 1] = xhci_dev;
+	fibril_mutex_unlock(&rh->device.base.guard);
 
 	return EOK;
@@ -185,9 +193,9 @@
 	fibril_mutex_unlock(&dev->base.guard);
 
-	fibril_mutex_lock(&rh->device.guard);
+	fibril_mutex_lock(&rh->device.base.guard);
 	list_remove(&dev->base.link);
-	fibril_mutex_unlock(&rh->device.guard);
-
 	rh->devices[port_id - 1] = NULL;
+	fibril_mutex_unlock(&rh->device.base.guard);
+
 	usb_log_debug2("Aborting all active transfers to '%s'.", ddf_fun_get_name(dev->base.fun));
 
Index: uspace/drv/bus/usb/xhci/rh.h
===================================================================
--- uspace/drv/bus/usb/xhci/rh.h	(revision f668d602a75538d4476f1df11550b29c815f0af8)
+++ uspace/drv/bus/usb/xhci/rh.h	(revision 2cf28b9d069a6ca711200eb94197fa3b893ee323)
@@ -39,5 +39,7 @@
 #include <usb/host/usb_transfer_batch.h>
 #include <usb/host/bus.h>
+
 #include "hw_struct/regs.h"
+#include "endpoint.h"
 
 typedef struct xhci_hc xhci_hc_t;
@@ -56,5 +58,4 @@
 typedef struct hcd_roothub hcd_roothub_t;
 typedef struct xhci_bus xhci_bus_t;
-typedef struct xhci_device xhci_device_t;
 
 /* XHCI root hub instance */
@@ -64,5 +65,5 @@
 
 	/* Root for the device tree */
-	device_t device;
+	xhci_device_t device;
 
 	/* We need this to attach children to */
Index: uspace/drv/bus/usb/xhci/transfers.h
===================================================================
--- uspace/drv/bus/usb/xhci/transfers.h	(revision f668d602a75538d4476f1df11550b29c815f0af8)
+++ uspace/drv/bus/usb/xhci/transfers.h	(revision 2cf28b9d069a6ca711200eb94197fa3b893ee323)
@@ -39,6 +39,8 @@
 #include <usb/host/usb_transfer_batch.h>
 
-#include "hc.h"
+#include "hw_struct/context.h"
 #include "trb_ring.h"
+
+typedef struct xhci_hc xhci_hc_t;
 
 typedef struct {
Index: uspace/lib/usbhost/include/usb/host/bus.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/bus.h	(revision f668d602a75538d4476f1df11550b29c815f0af8)
+++ uspace/lib/usbhost/include/usb/host/bus.h	(revision 2cf28b9d069a6ca711200eb94197fa3b893ee323)
@@ -82,4 +82,5 @@
 	int (*remove_device)(bus_t *, hcd_t *, device_t *);
 
+	/* The following operations are protected by a bus guard. */
 	endpoint_t *(*create_endpoint)(bus_t *);
 	int (*register_endpoint)(bus_t *, endpoint_t *, const usb_endpoint_desc_t *);
Index: uspace/lib/usbhost/src/bus.c
===================================================================
--- uspace/lib/usbhost/src/bus.c	(revision f668d602a75538d4476f1df11550b29c815f0af8)
+++ uspace/lib/usbhost/src/bus.c	(revision 2cf28b9d069a6ca711200eb94197fa3b893ee323)
@@ -87,8 +87,5 @@
 		return ENOTSUP;
 
-	fibril_mutex_lock(&bus->guard);
-	const int r = bus->ops.enumerate_device(bus, hcd, dev);
-	fibril_mutex_unlock(&bus->guard);
-	return r;
+	return bus->ops.enumerate_device(bus, hcd, dev);
 }
 
@@ -101,8 +98,5 @@
 		return ENOTSUP;
 
-	fibril_mutex_lock(&bus->guard);
-	const int r = bus->ops.remove_device(bus, hcd, dev);
-	fibril_mutex_unlock(&bus->guard);
-	return r;
+	return bus->ops.remove_device(bus, hcd, dev);
 }
 
