Index: uspace/drv/bus/usb/ehci/ehci_bus.c
===================================================================
--- uspace/drv/bus/usb/ehci/ehci_bus.c	(revision 10cd715240ae1db3090d2fb49f7185790adc313a)
+++ uspace/drv/bus/usb/ehci/ehci_bus.c	(revision 6832245517c6257fe330523cebfec7b916fdb0bf)
@@ -79,7 +79,7 @@
 /** Creates new hcd endpoint representation.
  */
-static endpoint_t *ehci_endpoint_create(bus_t *bus)
+static endpoint_t *ehci_endpoint_create(device_t *dev, const usb_endpoint_desc_t *desc)
 {
-	assert(bus);
+	assert(dev);
 
 	ehci_endpoint_t *ehci_ep = malloc(sizeof(ehci_endpoint_t));
@@ -87,5 +87,7 @@
 		return NULL;
 
-	endpoint_init(&ehci_ep->base, bus);
+	endpoint_init(&ehci_ep->base, dev, desc);
+
+	// TODO: extract USB2 information from desc
 
 	ehci_ep->qh = malloc32(sizeof(qh_t));
@@ -114,12 +116,12 @@
 
 
-static int ehci_register_ep(bus_t *bus_base, device_t *dev, endpoint_t *ep, const usb_endpoint_desc_t *desc)
+static int ehci_register_ep(endpoint_t *ep)
 {
+	bus_t *bus_base = endpoint_get_bus(ep);
 	ehci_bus_t *bus = (ehci_bus_t *) bus_base;
 	ehci_endpoint_t *ehci_ep = ehci_endpoint_get(ep);
+	assert(fibril_mutex_is_locked(&bus_base->guard));
 
-	// TODO utilize desc->usb2
-
-	const int err = bus->parent_ops.register_endpoint(bus_base, dev, ep, desc);
+	const int err = usb2_bus_ops.endpoint_register(ep);
 	if (err)
 		return err;
@@ -131,11 +133,12 @@
 }
 
-static int ehci_unregister_ep(bus_t *bus_base, endpoint_t *ep)
+static int ehci_unregister_ep(endpoint_t *ep)
 {
+	bus_t *bus_base = endpoint_get_bus(ep);
 	ehci_bus_t *bus = (ehci_bus_t *) bus_base;
 	assert(bus);
 	assert(ep);
 
-	const int err = bus->parent_ops.unregister_endpoint(bus_base, ep);
+	const int err = usb2_bus_ops.endpoint_unregister(ep);
 	if (err)
 		return err;
@@ -145,5 +148,5 @@
 }
 
-static usb_transfer_batch_t *ehci_bus_create_batch(bus_t *bus, endpoint_t *ep)
+static usb_transfer_batch_t *ehci_create_batch(endpoint_t *ep)
 {
 	ehci_transfer_batch_t *batch = ehci_transfer_batch_create(ep);
@@ -151,29 +154,33 @@
 }
 
-static void ehci_bus_destroy_batch(usb_transfer_batch_t *batch)
+static void ehci_destroy_batch(usb_transfer_batch_t *batch)
 {
 	ehci_transfer_batch_destroy(ehci_transfer_batch_get(batch));
 }
 
-int ehci_bus_init(ehci_bus_t *bus, hc_t *hc)
+static const bus_ops_t ehci_bus_ops = {
+	.parent = &usb2_bus_ops,
+
+	.endpoint_destroy = ehci_endpoint_destroy,
+	.endpoint_create = ehci_endpoint_create,
+	.endpoint_register = ehci_register_ep,
+	.endpoint_unregister = ehci_unregister_ep,
+	.endpoint_set_toggle = ehci_ep_toggle_set,
+	.endpoint_get_toggle = ehci_ep_toggle_get,
+	.endpoint_count_bw = bandwidth_count_usb11,
+	.batch_create = ehci_create_batch,
+	.batch_destroy = ehci_destroy_batch,
+};
+
+int ehci_bus_init(ehci_bus_t *bus, hcd_t *hcd, hc_t *hc)
 {
 	assert(hc);
 	assert(bus);
 
-	// FIXME: Implement the USB2 bw counting.
-	usb2_bus_init(&bus->base, BANDWIDTH_AVAILABLE_USB11, bandwidth_count_usb11);
+	usb2_bus_t *usb2_bus = (usb2_bus_t *) bus;
+	bus_t *bus_base = (bus_t *) bus;
 
-	bus_ops_t *ops = &bus->base.base.ops;
-	bus->parent_ops = *ops;
-	ops->create_endpoint = ehci_endpoint_create;
-	ops->destroy_endpoint = ehci_endpoint_destroy;
-	ops->endpoint_set_toggle = ehci_ep_toggle_set;
-	ops->endpoint_get_toggle = ehci_ep_toggle_get;
-
-	ops->register_endpoint = ehci_register_ep;
-	ops->unregister_endpoint = ehci_unregister_ep;
-
-	ops->create_batch = ehci_bus_create_batch;
-	ops->destroy_batch = ehci_bus_destroy_batch;
+	usb2_bus_init(usb2_bus, hcd, BANDWIDTH_AVAILABLE_USB11);
+	bus_base->ops = &ehci_bus_ops;
 
 	bus->hc = hc;
Index: uspace/drv/bus/usb/ehci/ehci_bus.h
===================================================================
--- uspace/drv/bus/usb/ehci/ehci_bus.h	(revision 10cd715240ae1db3090d2fb49f7185790adc313a)
+++ uspace/drv/bus/usb/ehci/ehci_bus.h	(revision 6832245517c6257fe330523cebfec7b916fdb0bf)
@@ -59,10 +59,9 @@
 	usb2_bus_t base;
 	hc_t *hc;
-
-	/* Stored original ops from base, they are called in our handlers */
-	bus_ops_t parent_ops;
 } ehci_bus_t;
 
-int ehci_bus_init(ehci_bus_t *, hc_t *);
+void ehci_bus_prepare_ops(void);
+
+int ehci_bus_init(ehci_bus_t *, hcd_t *, hc_t *);
 
 /** Get and convert assigned ehci_endpoint_t structure
Index: uspace/drv/bus/usb/ehci/hc.c
===================================================================
--- uspace/drv/bus/usb/ehci/hc.c	(revision 10cd715240ae1db3090d2fb49f7185790adc313a)
+++ uspace/drv/bus/usb/ehci/hc.c	(revision 6832245517c6257fe330523cebfec7b916fdb0bf)
@@ -149,5 +149,5 @@
  * @return Error code
  */
-int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res)
+int hc_init(hc_t *instance, hcd_t *hcd, const hw_res_list_parsed_t *hw_res)
 {
 	assert(instance);
@@ -190,5 +190,5 @@
 	    &instance->rh, instance->caps, instance->registers, "ehci rh");
 
-	ehci_bus_init(&instance->bus, instance);
+	ehci_bus_init(&instance->bus, hcd, instance);
 	return EOK;
 }
Index: uspace/drv/bus/usb/ehci/hc.h
===================================================================
--- uspace/drv/bus/usb/ehci/hc.h	(revision 10cd715240ae1db3090d2fb49f7185790adc313a)
+++ uspace/drv/bus/usb/ehci/hc.h	(revision 6832245517c6257fe330523cebfec7b916fdb0bf)
@@ -85,5 +85,5 @@
 } hc_t;
 
-int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res);
+int hc_init(hc_t *instance, hcd_t *hcd, const hw_res_list_parsed_t *hw_res);
 int hc_start(hc_t *instance, bool interrupts);
 void hc_fini(hc_t *instance);
Index: uspace/drv/bus/usb/ehci/main.c
===================================================================
--- uspace/drv/bus/usb/ehci/main.c	(revision 10cd715240ae1db3090d2fb49f7185790adc313a)
+++ uspace/drv/bus/usb/ehci/main.c	(revision 6832245517c6257fe330523cebfec7b916fdb0bf)
@@ -81,5 +81,5 @@
 		return ENOMEM;
 
-	const int ret = hc_init(instance, res);
+	const int ret = hc_init(instance, hcd, res);
 	if (ret == EOK) {
 		hcd_set_implementation(hcd, instance, &ehci_hc_driver.ops, &instance->bus.base.base);
Index: uspace/drv/bus/usb/ohci/main.c
===================================================================
--- uspace/drv/bus/usb/ohci/main.c	(revision 10cd715240ae1db3090d2fb49f7185790adc313a)
+++ uspace/drv/bus/usb/ohci/main.c	(revision 6832245517c6257fe330523cebfec7b916fdb0bf)
@@ -83,5 +83,5 @@
 		goto err;
 
-	if ((err = ohci_bus_init(&instance->bus, instance)))
+	if ((err = ohci_bus_init(&instance->bus, hcd, instance)))
 		goto err;
 
Index: uspace/drv/bus/usb/ohci/ohci_bus.c
===================================================================
--- uspace/drv/bus/usb/ohci/ohci_bus.c	(revision 10cd715240ae1db3090d2fb49f7185790adc313a)
+++ uspace/drv/bus/usb/ohci/ohci_bus.c	(revision 6832245517c6257fe330523cebfec7b916fdb0bf)
@@ -72,7 +72,7 @@
 /** Creates new hcd endpoint representation.
  */
-static endpoint_t *ohci_endpoint_create(bus_t *bus)
+static endpoint_t *ohci_endpoint_create(device_t *dev, const usb_endpoint_desc_t *desc)
 {
-	assert(bus);
+	assert(dev);
 
 	ohci_endpoint_t *ohci_ep = malloc(sizeof(ohci_endpoint_t));
@@ -80,5 +80,5 @@
 		return NULL;
 
-	endpoint_init(&ohci_ep->base, bus);
+	endpoint_init(&ohci_ep->base, dev, desc);
 
 	ohci_ep->ed = malloc32(sizeof(ed_t));
@@ -115,10 +115,11 @@
 
 
-static int ohci_register_ep(bus_t *bus_base, device_t *dev, endpoint_t *ep, const usb_endpoint_desc_t *desc)
+static int ohci_register_ep(endpoint_t *ep)
 {
+	bus_t *bus_base = endpoint_get_bus(ep);
 	ohci_bus_t *bus = (ohci_bus_t *) bus_base;
 	ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ep);
 
-	const int err = bus->parent_ops.register_endpoint(bus_base, dev, ep, desc);
+	const int err = usb2_bus_ops.endpoint_register(ep);
 	if (err)
 		return err;
@@ -130,11 +131,10 @@
 }
 
-static int ohci_unregister_ep(bus_t *bus_base, endpoint_t *ep)
+static int ohci_unregister_ep(endpoint_t *ep)
 {
-	ohci_bus_t *bus = (ohci_bus_t *) bus_base;
-	assert(bus);
+	ohci_bus_t *bus = (ohci_bus_t *) endpoint_get_bus(ep);
 	assert(ep);
 
-	const int err = bus->parent_ops.unregister_endpoint(bus_base, ep);
+	const int err = usb2_bus_ops.endpoint_unregister(ep);
 	if (err)
 		return err;
@@ -144,5 +144,5 @@
 }
 
-static usb_transfer_batch_t *ohci_bus_create_batch(bus_t *bus, endpoint_t *ep)
+static usb_transfer_batch_t *ohci_create_batch(endpoint_t *ep)
 {
 	ohci_transfer_batch_t *batch = ohci_transfer_batch_create(ep);
@@ -150,28 +150,35 @@
 }
 
-static void ohci_bus_destroy_batch(usb_transfer_batch_t *batch)
+static void ohci_destroy_batch(usb_transfer_batch_t *batch)
 {
 	ohci_transfer_batch_destroy(ohci_transfer_batch_get(batch));
 }
 
-int ohci_bus_init(ohci_bus_t *bus, hc_t *hc)
+static const bus_ops_t ohci_bus_ops = {
+	.parent = &usb2_bus_ops,
+
+	.endpoint_destroy = ohci_endpoint_destroy,
+	.endpoint_create = ohci_endpoint_create,
+	.endpoint_register = ohci_register_ep,
+	.endpoint_unregister = ohci_unregister_ep,
+	.endpoint_count_bw = bandwidth_count_usb11,
+	.endpoint_set_toggle = ohci_ep_toggle_set,
+	.endpoint_get_toggle = ohci_ep_toggle_get,
+	.batch_create = ohci_create_batch,
+	.batch_destroy = ohci_destroy_batch,
+};
+
+
+int ohci_bus_init(ohci_bus_t *bus, hcd_t *hcd, hc_t *hc)
 {
 	assert(hc);
 	assert(bus);
 
-	usb2_bus_init(&bus->base, BANDWIDTH_AVAILABLE_USB11, bandwidth_count_usb11);
 
-	bus_ops_t *ops = &bus->base.base.ops;
-	bus->parent_ops = *ops;
-	ops->create_endpoint = ohci_endpoint_create;
-	ops->destroy_endpoint = ohci_endpoint_destroy;
-	ops->endpoint_set_toggle = ohci_ep_toggle_set;
-	ops->endpoint_get_toggle = ohci_ep_toggle_get;
+	usb2_bus_t *usb2_bus = (usb2_bus_t *) bus;
+	bus_t *bus_base = (bus_t *) bus;
 
-	ops->register_endpoint = ohci_register_ep;
-	ops->unregister_endpoint = ohci_unregister_ep;
-
-	ops->create_batch = ohci_bus_create_batch;
-	ops->destroy_batch = ohci_bus_destroy_batch;
+	usb2_bus_init(usb2_bus, hcd, BANDWIDTH_AVAILABLE_USB11);
+	bus_base->ops = &ohci_bus_ops;
 
 	bus->hc = hc;
Index: uspace/drv/bus/usb/ohci/ohci_bus.h
===================================================================
--- uspace/drv/bus/usb/ohci/ohci_bus.h	(revision 10cd715240ae1db3090d2fb49f7185790adc313a)
+++ uspace/drv/bus/usb/ohci/ohci_bus.h	(revision 6832245517c6257fe330523cebfec7b916fdb0bf)
@@ -60,10 +60,7 @@
 	usb2_bus_t base;
 	hc_t *hc;
-
-	/* Stored original ops from base, they are called in our handlers */
-	bus_ops_t parent_ops;
 } ohci_bus_t;
 
-int ohci_bus_init(ohci_bus_t *, hc_t *);
+int ohci_bus_init(ohci_bus_t *, hcd_t *, hc_t *);
 
 /** Get and convert assigned ohci_endpoint_t structure
Index: uspace/drv/bus/usb/uhci/hc.c
===================================================================
--- uspace/drv/bus/usb/uhci/hc.c	(revision 10cd715240ae1db3090d2fb49f7185790adc313a)
+++ uspace/drv/bus/usb/uhci/hc.c	(revision 6832245517c6257fe330523cebfec7b916fdb0bf)
@@ -95,5 +95,5 @@
 
 static void hc_init_hw(const hc_t *instance);
-static int hc_init_mem_structures(hc_t *instance);
+static int hc_init_mem_structures(hc_t *instance, hcd_t *);
 static int hc_init_transfer_lists(hc_t *instance);
 
@@ -215,5 +215,5 @@
  * interrupt fibrils.
  */
-int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res)
+int hc_init(hc_t *instance, hcd_t *hcd, const hw_res_list_parsed_t *hw_res)
 {
 	assert(instance);
@@ -238,5 +238,5 @@
 	    hw_res->io_ranges.ranges[0].size);
 
-	ret = hc_init_mem_structures(instance);
+	ret = hc_init_mem_structures(instance, hcd);
 	if (ret != EOK) {
 		usb_log_error("Failed to init UHCI memory structures: %s.\n",
@@ -309,5 +309,5 @@
 }
 
-static usb_transfer_batch_t *create_transfer_batch(bus_t *bus, endpoint_t *ep)
+static usb_transfer_batch_t *create_transfer_batch(endpoint_t *ep)
 {
 	uhci_transfer_batch_t *batch = uhci_transfer_batch_create(ep);
@@ -319,4 +319,12 @@
 	uhci_transfer_batch_destroy(uhci_transfer_batch_get(batch));
 }
+
+static const bus_ops_t uhci_bus_ops = {
+	.parent = &usb2_bus_ops,
+
+	.endpoint_count_bw = bandwidth_count_usb11,
+	.batch_create = create_transfer_batch,
+	.batch_destroy = destroy_transfer_batch,
+};
 
 /** Initialize UHCI hc memory structures.
@@ -330,14 +338,14 @@
  *  - frame list page (needs to be one UHCI hw accessible 4K page)
  */
-int hc_init_mem_structures(hc_t *instance)
+int hc_init_mem_structures(hc_t *instance, hcd_t *hcd)
 {
 	int err;
 	assert(instance);
 
-	if ((err = usb2_bus_init(&instance->bus, BANDWIDTH_AVAILABLE_USB11, bandwidth_count_usb11)))
+	if ((err = usb2_bus_init(&instance->bus, hcd, BANDWIDTH_AVAILABLE_USB11)))
 		return err;
 
-	instance->bus.base.ops.create_batch = create_transfer_batch;
-	instance->bus.base.ops.destroy_batch = destroy_transfer_batch;
+	bus_t *bus = (bus_t *) &instance->bus;
+	bus->ops = &uhci_bus_ops;
 
 	/* Init USB frame list page */
Index: uspace/drv/bus/usb/uhci/hc.h
===================================================================
--- uspace/drv/bus/usb/uhci/hc.h	(revision 10cd715240ae1db3090d2fb49f7185790adc313a)
+++ uspace/drv/bus/usb/uhci/hc.h	(revision 6832245517c6257fe330523cebfec7b916fdb0bf)
@@ -126,5 +126,5 @@
 } hc_t;
 
-extern int hc_init(hc_t *, const hw_res_list_parsed_t *);
+extern int hc_init(hc_t *, hcd_t *, const hw_res_list_parsed_t *);
 extern void hc_start(hc_t *);
 extern void hc_fini(hc_t *);
Index: uspace/drv/bus/usb/uhci/main.c
===================================================================
--- uspace/drv/bus/usb/uhci/main.c	(revision 10cd715240ae1db3090d2fb49f7185790adc313a)
+++ uspace/drv/bus/usb/uhci/main.c	(revision 6832245517c6257fe330523cebfec7b916fdb0bf)
@@ -80,5 +80,5 @@
 		return ENOMEM;
 
-	if ((err = hc_init(instance, res)) != EOK)
+	if ((err = hc_init(instance, hcd, res)) != EOK)
 		goto err;
 
Index: uspace/drv/bus/usb/vhc/main.c
===================================================================
--- uspace/drv/bus/usb/vhc/main.c	(revision 10cd715240ae1db3090d2fb49f7185790adc313a)
+++ uspace/drv/bus/usb/vhc/main.c	(revision 6832245517c6257fe330523cebfec7b916fdb0bf)
@@ -69,5 +69,5 @@
 		return ret;
 	}
-	vhc_init(vhc);
+	vhc_init(vhc, dev_to_hcd(dev));
 	return EOK;
 }
Index: uspace/drv/bus/usb/vhc/transfer.c
===================================================================
--- uspace/drv/bus/usb/vhc/transfer.c	(revision 10cd715240ae1db3090d2fb49f7185790adc313a)
+++ uspace/drv/bus/usb/vhc/transfer.c	(revision 6832245517c6257fe330523cebfec7b916fdb0bf)
@@ -157,10 +157,16 @@
 }
 
-int vhc_init(vhc_data_t *instance)
+static const bus_ops_t vhc_bus_ops = {
+	.parent = &usb2_bus_ops,
+	.endpoint_count_bw = bandwidth_count_usb11,
+};
+
+int vhc_init(vhc_data_t *instance, hcd_t *hcd)
 {
 	assert(instance);
 	list_initialize(&instance->devices);
 	fibril_mutex_initialize(&instance->guard);
-	usb2_bus_init(&instance->bus, BANDWIDTH_AVAILABLE_USB11, bandwidth_count_usb11);
+	usb2_bus_init(&instance->bus, hcd, BANDWIDTH_AVAILABLE_USB11);
+	instance->bus.base.ops = &vhc_bus_ops;
 	instance->magic = 0xDEADBEEF;
 	return virthub_init(&instance->hub, "root hub");
Index: uspace/drv/bus/usb/vhc/vhcd.h
===================================================================
--- uspace/drv/bus/usb/vhc/vhcd.h	(revision 10cd715240ae1db3090d2fb49f7185790adc313a)
+++ uspace/drv/bus/usb/vhc/vhcd.h	(revision 6832245517c6257fe330523cebfec7b916fdb0bf)
@@ -77,5 +77,5 @@
 void vhc_virtdev_unplug(vhc_data_t *, uintptr_t);
 
-int vhc_init(vhc_data_t *instance);
+int vhc_init(vhc_data_t *instance, hcd_t *);
 int vhc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch);
 int vhc_transfer_queue_processor(void *arg);
Index: uspace/drv/bus/usb/xhci/bus.c
===================================================================
--- uspace/drv/bus/usb/xhci/bus.c	(revision 10cd715240ae1db3090d2fb49f7185790adc313a)
+++ uspace/drv/bus/usb/xhci/bus.c	(revision 6832245517c6257fe330523cebfec7b916fdb0bf)
@@ -58,50 +58,17 @@
 };
 
-static int prepare_endpoint(xhci_endpoint_t *ep, const usb_endpoint_desc_t *desc)
-{
-	/* Extract information from endpoint_desc */
-	ep->base.endpoint = desc->endpoint_no;
-	ep->base.direction = desc->direction;
-	ep->base.transfer_type = desc->transfer_type;
-	ep->base.max_packet_size = desc->max_packet_size;
-	ep->base.packets = desc->packets;
-	ep->max_streams = desc->usb3.max_streams;
-	ep->max_burst = desc->usb3.max_burst;
-	ep->mult = desc->usb3.mult;
-
-	if (ep->base.transfer_type == USB_TRANSFER_ISOCHRONOUS) {
-		if (ep->base.device->speed <= USB_SPEED_HIGH) {
-			ep->isoch_max_size = desc->max_packet_size * (desc->packets + 1);
-		}
-		else if (ep->base.device->speed == USB_SPEED_SUPER) {
-			ep->isoch_max_size = desc->usb3.bytes_per_interval;
-		}
-		/* Technically there could be superspeed plus too. */
-
-		/* Allocate and setup isochronous-specific structures. */
-		ep->isoch_enqueue = 0;
-		ep->isoch_dequeue = XHCI_ISOCH_BUFFER_COUNT - 1;
-		ep->isoch_started = false;
-
-		fibril_mutex_initialize(&ep->isoch_guard);
-		fibril_condvar_initialize(&ep->isoch_avail);
-	}
-
-	return xhci_endpoint_alloc_transfer_ds(ep);
-}
-
-static endpoint_t *create_endpoint(bus_t *base);
-
-static int address_device(xhci_hc_t *hc, xhci_device_t *dev)
+static endpoint_t *endpoint_create(device_t *, const usb_endpoint_desc_t *);
+
+static int address_device(xhci_bus_t *bus, xhci_device_t *dev)
 {
 	int err;
 
 	/* Enable new slot. */
-	if ((err = hc_enable_slot(hc, &dev->slot_id)) != EOK)
+	if ((err = hc_enable_slot(bus->hc, &dev->slot_id)) != EOK)
 		return err;
 	usb_log_debug2("Obtained slot ID: %u.\n", dev->slot_id);
 
 	/* Create and configure control endpoint. */
-	endpoint_t *ep0_base = create_endpoint(&hc->bus.base);
+	endpoint_t *ep0_base = endpoint_create(&dev->base, &ep0_initial_desc);
 	if (!ep0_base)
 		goto err_slot;
@@ -112,5 +79,5 @@
 	xhci_endpoint_t *ep0 = xhci_endpoint_get(ep0_base);
 
-	if ((err = prepare_endpoint(ep0, &ep0_initial_desc)))
+	if ((err = xhci_endpoint_alloc_transfer_ds(ep0)))
 		goto err_ep;
 
@@ -120,5 +87,5 @@
 
 	/* Address device */
-	if ((err = hc_address_device(hc, dev, ep0)))
+	if ((err = hc_address_device(bus->hc, dev, ep0)))
 		goto err_added;
 
@@ -135,5 +102,5 @@
 	endpoint_del_ref(ep0_base);
 err_slot:
-	hc_disable_slot(hc, dev);
+	hc_disable_slot(bus->hc, dev);
 	return err;
 }
@@ -164,5 +131,5 @@
 }
 
-int xhci_bus_enumerate_device(xhci_bus_t *bus, xhci_hc_t *hc, device_t *dev)
+int xhci_bus_enumerate_device(xhci_bus_t *bus, device_t *dev)
 {
 	int err;
@@ -184,5 +151,5 @@
 
 	/* Assign an address to the device */
-	if ((err = address_device(hc, xhci_dev))) {
+	if ((err = address_device(bus, xhci_dev))) {
 		usb_log_error("Failed to setup address of the new device: %s", str_error(err));
 		return err;
@@ -195,5 +162,5 @@
 	fibril_mutex_unlock(&bus->base.guard);
 
-	if ((err = setup_ep0_packet_size(hc, xhci_dev))) {
+	if ((err = setup_ep0_packet_size(bus->hc, xhci_dev))) {
 		usb_log_error("Failed to setup control endpoint of the new device: %s", str_error(err));
 		goto err_address;
@@ -201,5 +168,5 @@
 
 	/* Read the device descriptor, derive the match ids */
-	if ((err = hcd_ddf_device_explore(hc->hcd, dev))) {
+	if ((err = hcd_ddf_device_explore(dev))) {
 		usb_log_error("Device(%d): Failed to explore device: %s", dev->address, str_error(err));
 		goto err_address;
@@ -213,7 +180,7 @@
 }
 
-static int unregister_endpoint(bus_t *, endpoint_t *);
-
-int xhci_bus_remove_device(xhci_bus_t *bus, xhci_hc_t *hc, device_t *dev)
+static int endpoint_unregister(endpoint_t *);
+
+int xhci_bus_remove_device(xhci_bus_t *bus, device_t *dev)
 {
 	int err;
@@ -246,5 +213,5 @@
 	/* Disable the slot, dropping all endpoints. */
 	const uint32_t slot_id = xhci_dev->slot_id;
-	if ((err = hc_disable_slot(hc, xhci_dev))) {
+	if ((err = hc_disable_slot(bus->hc, xhci_dev))) {
 		usb_log_warning("Failed to disable slot of device " XHCI_DEV_FMT ": %s",
 		    XHCI_DEV_ARGS(*xhci_dev), str_error(err));
@@ -258,5 +225,5 @@
 			continue;
 
-		if ((err = unregister_endpoint(&bus->base, &xhci_dev->endpoints[i]->base))) {
+		if ((err = endpoint_unregister(&xhci_dev->endpoints[i]->base))) {
 			usb_log_warning("Failed to unregister endpoint " XHCI_EP_FMT ": %s",
 			    XHCI_EP_ARGS(*xhci_dev->endpoints[i]), str_error(err));
@@ -278,34 +245,21 @@
 }
 
-static int enumerate_device(bus_t *bus_base, hcd_t *hcd, device_t *dev)
-{
-	xhci_hc_t *hc = hcd_get_driver_data(hcd);
-	assert(hc);
-
-	xhci_bus_t *bus = bus_to_xhci_bus(bus_base);
-	assert(bus);
-
-	return xhci_bus_enumerate_device(bus, hc, dev);
-}
-
-static int remove_device(bus_t *bus_base, hcd_t *hcd, device_t *dev)
-{
-	xhci_hc_t *hc = hcd_get_driver_data(hcd);
-	assert(hc);
-
-	xhci_bus_t *bus = bus_to_xhci_bus(bus_base);
-	assert(bus);
-
-	return xhci_bus_remove_device(bus, hc, dev);
-}
-
-static int online_device(bus_t *bus_base, hcd_t *hcd, device_t *dev_base)
-{
-	int err;
-
-	xhci_hc_t *hc = hcd_get_driver_data(hcd);
-	assert(hc);
-
-	xhci_bus_t *bus = bus_to_xhci_bus(bus_base);
+static int device_enumerate(device_t *dev)
+{
+	xhci_bus_t *bus = bus_to_xhci_bus(dev->bus);
+	return xhci_bus_enumerate_device(bus, dev);
+}
+
+static int device_remove(device_t *dev)
+{
+	xhci_bus_t *bus = bus_to_xhci_bus(dev->bus);
+	return xhci_bus_remove_device(bus, dev);
+}
+
+static int device_online(device_t *dev_base)
+{
+	int err;
+
+	xhci_bus_t *bus = bus_to_xhci_bus(dev_base->bus);
 	assert(bus);
 
@@ -314,5 +268,5 @@
 
 	/* Transition the device from the Addressed to the Configured state. */
-	if ((err = hc_configure_device(hc, dev->slot_id))) {
+	if ((err = hc_configure_device(bus->hc, dev->slot_id))) {
 		usb_log_warning("Failed to configure device " XHCI_DEV_FMT ".", XHCI_DEV_ARGS(*dev));
 	}
@@ -331,12 +285,9 @@
 }
 
-static int offline_device(bus_t *bus_base, hcd_t *hcd, device_t *dev_base)
-{
-	int err;
-
-	xhci_hc_t *hc = hcd_get_driver_data(hcd);
-	assert(hc);
-
-	xhci_bus_t *bus = bus_to_xhci_bus(bus_base);
+static int device_offline(device_t *dev_base)
+{
+	int err;
+
+	xhci_bus_t *bus = bus_to_xhci_bus(dev_base->bus);
 	assert(bus);
 
@@ -370,5 +321,5 @@
 
 	/* Issue one HC command to simultaneously drop all endpoints except zero. */
-	if ((err = hc_deconfigure_device(hc, dev->slot_id))) {
+	if ((err = hc_deconfigure_device(bus->hc, dev->slot_id))) {
 		usb_log_warning("Failed to deconfigure device " XHCI_DEV_FMT ".",
 		    XHCI_DEV_ARGS(*dev));
@@ -388,13 +339,11 @@
 }
 
-static endpoint_t *create_endpoint(bus_t *base)
-{
-	xhci_bus_t *bus = bus_to_xhci_bus(base);
-
+static endpoint_t *endpoint_create(device_t *dev, const usb_endpoint_desc_t *desc)
+{
 	xhci_endpoint_t *ep = calloc(1, sizeof(xhci_endpoint_t));
 	if (!ep)
 		return NULL;
 
-	if (xhci_endpoint_init(ep, bus)) {
+	if (xhci_endpoint_init(ep, dev, desc)) {
 		free(ep);
 		return NULL;
@@ -404,5 +353,5 @@
 }
 
-static void destroy_endpoint(endpoint_t *ep)
+static void endpoint_destroy(endpoint_t *ep)
 {
 	xhci_endpoint_t *xhci_ep = xhci_endpoint_get(ep);
@@ -412,13 +361,13 @@
 }
 
-static int register_endpoint(bus_t *bus_base, device_t *device, endpoint_t *ep_base, const usb_endpoint_desc_t *desc)
-{
-	int err;
-	xhci_bus_t *bus = bus_to_xhci_bus(bus_base);
+static int endpoint_register(endpoint_t *ep_base)
+{
+	int err;
+	xhci_bus_t *bus = bus_to_xhci_bus(endpoint_get_bus(ep_base));
 	xhci_endpoint_t *ep = xhci_endpoint_get(ep_base);
 
-	xhci_device_t *dev = xhci_device_get(device);
-
-	if ((err = prepare_endpoint(ep, desc)))
+	xhci_device_t *dev = xhci_device_get(ep_base->device);
+
+	if ((err = xhci_endpoint_alloc_transfer_ds(ep)))
 		return err;
 
@@ -443,8 +392,8 @@
 }
 
-static int unregister_endpoint(bus_t *bus_base, endpoint_t *ep_base)
-{
-	int err;
-	xhci_bus_t *bus = bus_to_xhci_bus(bus_base);
+static int endpoint_unregister(endpoint_t *ep_base)
+{
+	int err;
+	xhci_bus_t *bus = bus_to_xhci_bus(endpoint_get_bus(ep_base));
 	xhci_endpoint_t *ep = xhci_endpoint_get(ep_base);
 	xhci_device_t *dev = xhci_device_get(ep_base->device);
@@ -470,5 +419,5 @@
 }
 
-static endpoint_t* find_endpoint(bus_t *bus_base, device_t *dev_base, usb_target_t target, usb_direction_t direction)
+static endpoint_t* device_find_endpoint(device_t *dev_base, usb_target_t target, usb_direction_t direction)
 {
 	xhci_device_t *dev = xhci_device_get(dev_base);
@@ -487,10 +436,4 @@
 }
 
-static size_t count_bw(endpoint_t *ep, size_t size)
-{
-	// TODO: Implement me!
-	return 0;
-}
-
 /* Endpoint ops, optional (have generic fallback) */
 static bool endpoint_get_toggle(endpoint_t *ep)
@@ -525,5 +468,5 @@
 }
 
-static usb_transfer_batch_t *create_batch(bus_t *bus, endpoint_t *ep)
+static usb_transfer_batch_t *batch_create(endpoint_t *ep)
 {
 	xhci_transfer_t *transfer = xhci_transfer_create(ep);
@@ -531,5 +474,5 @@
 }
 
-static void destroy_batch(usb_transfer_batch_t *batch)
+static void batch_destroy(usb_transfer_batch_t *batch)
 {
 	xhci_transfer_destroy(xhci_transfer_from_batch(batch));
@@ -538,28 +481,23 @@
 static const bus_ops_t xhci_bus_ops = {
 #define BIND_OP(op) .op = op,
-	BIND_OP(enumerate_device)
-	BIND_OP(remove_device)
-
-	BIND_OP(online_device)
-	BIND_OP(offline_device)
-
-	BIND_OP(create_endpoint)
-	BIND_OP(destroy_endpoint)
-
-	BIND_OP(register_endpoint)
-	BIND_OP(unregister_endpoint)
-	BIND_OP(find_endpoint)
-
 	BIND_OP(reserve_default_address)
 	BIND_OP(release_default_address)
-
 	BIND_OP(reset_toggle)
-	BIND_OP(count_bw)
-
+
+	BIND_OP(device_enumerate)
+	BIND_OP(device_remove)
+	BIND_OP(device_online)
+	BIND_OP(device_offline)
+	BIND_OP(device_find_endpoint)
+
+	BIND_OP(endpoint_create)
+	BIND_OP(endpoint_destroy)
+	BIND_OP(endpoint_register)
+	BIND_OP(endpoint_unregister)
 	BIND_OP(endpoint_get_toggle)
 	BIND_OP(endpoint_set_toggle)
 
-	BIND_OP(create_batch)
-	BIND_OP(destroy_batch)
+	BIND_OP(batch_create)
+	BIND_OP(batch_destroy)
 #undef BIND_OP
 };
@@ -569,5 +507,5 @@
 	assert(bus);
 
-	bus_init(&bus->base, sizeof(xhci_device_t));
+	bus_init(&bus->base, hc->hcd, sizeof(xhci_device_t));
 
 	bus->devices_by_slot = calloc(hc->max_slots, sizeof(xhci_device_t *));
@@ -576,5 +514,5 @@
 
 	bus->hc = hc;
-	bus->base.ops = xhci_bus_ops;
+	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 10cd715240ae1db3090d2fb49f7185790adc313a)
+++ uspace/drv/bus/usb/xhci/bus.h	(revision 6832245517c6257fe330523cebfec7b916fdb0bf)
@@ -58,6 +58,6 @@
 void xhci_bus_fini(xhci_bus_t *);
 
-int xhci_bus_enumerate_device(xhci_bus_t *, xhci_hc_t *, device_t *);
-int xhci_bus_remove_device(xhci_bus_t *, xhci_hc_t *, device_t *);
+int xhci_bus_enumerate_device(xhci_bus_t *, device_t *);
+int xhci_bus_remove_device(xhci_bus_t *, device_t *);
 
 #endif
Index: uspace/drv/bus/usb/xhci/endpoint.c
===================================================================
--- uspace/drv/bus/usb/xhci/endpoint.c	(revision 10cd715240ae1db3090d2fb49f7185790adc313a)
+++ uspace/drv/bus/usb/xhci/endpoint.c	(revision 6832245517c6257fe330523cebfec7b916fdb0bf)
@@ -45,13 +45,30 @@
 #include "endpoint.h"
 
-int xhci_endpoint_init(xhci_endpoint_t *xhci_ep, xhci_bus_t *xhci_bus)
+int xhci_endpoint_init(xhci_endpoint_t *xhci_ep, device_t *dev, const usb_endpoint_desc_t *desc)
 {
 	assert(xhci_ep);
-	assert(xhci_bus);
-
-	bus_t *bus = &xhci_bus->base;
+
 	endpoint_t *ep = &xhci_ep->base;
 
-	endpoint_init(ep, bus);
+	endpoint_init(ep, dev, desc);
+
+	xhci_ep->max_streams = desc->usb3.max_streams;
+	xhci_ep->max_burst = desc->usb3.max_burst;
+	xhci_ep->mult = desc->usb3.mult;
+
+	if (xhci_ep->base.transfer_type == USB_TRANSFER_ISOCHRONOUS) {
+		xhci_ep->isoch_max_size = desc->usb3.bytes_per_interval
+			? desc->usb3.bytes_per_interval
+			: desc->max_packet_size * (desc->packets + 1);
+		/* Technically there could be superspeed plus too. */
+
+		/* Allocate and setup isochronous-specific structures. */
+		xhci_ep->isoch_enqueue = 0;
+		xhci_ep->isoch_dequeue = XHCI_ISOCH_BUFFER_COUNT - 1;
+		xhci_ep->isoch_started = false;
+
+		fibril_mutex_initialize(&xhci_ep->isoch_guard);
+		fibril_condvar_initialize(&xhci_ep->isoch_avail);
+	}
 
 	return EOK;
Index: uspace/drv/bus/usb/xhci/endpoint.h
===================================================================
--- uspace/drv/bus/usb/xhci/endpoint.h	(revision 10cd715240ae1db3090d2fb49f7185790adc313a)
+++ uspace/drv/bus/usb/xhci/endpoint.h	(revision 6832245517c6257fe330523cebfec7b916fdb0bf)
@@ -149,5 +149,5 @@
 #define XHCI_DEV_ARGS(dev)		 ddf_fun_get_name((dev).base.fun), (dev).slot_id
 
-int xhci_endpoint_init(xhci_endpoint_t *, xhci_bus_t *);
+int xhci_endpoint_init(xhci_endpoint_t *, device_t *, const usb_endpoint_desc_t *);
 void xhci_endpoint_fini(xhci_endpoint_t *);
 int xhci_endpoint_alloc_transfer_ds(xhci_endpoint_t *);
Index: uspace/drv/bus/usb/xhci/hc.c
===================================================================
--- uspace/drv/bus/usb/xhci/hc.c	(revision 10cd715240ae1db3090d2fb49f7185790adc313a)
+++ uspace/drv/bus/usb/xhci/hc.c	(revision 6832245517c6257fe330523cebfec7b916fdb0bf)
@@ -212,15 +212,14 @@
 		goto err_scratch;
 
+	if ((err = xhci_bus_init(&hc->bus, hc)))
+		goto err_cmd;
+
 	if ((err = xhci_rh_init(&hc->rh, hc, device)))
-		goto err_cmd;
-
-	if ((err = xhci_bus_init(&hc->bus, hc)))
-		goto err_rh;
-
-
-	return EOK;
-
-err_rh:
-	xhci_rh_fini(&hc->rh);
+		goto err_bus;
+
+	return EOK;
+
+err_bus:
+	xhci_bus_fini(&hc->bus);
 err_cmd:
 	xhci_fini_commands(hc);
Index: uspace/drv/bus/usb/xhci/main.c
===================================================================
--- uspace/drv/bus/usb/xhci/main.c	(revision 10cd715240ae1db3090d2fb49f7185790adc313a)
+++ uspace/drv/bus/usb/xhci/main.c	(revision 6832245517c6257fe330523cebfec7b916fdb0bf)
@@ -82,9 +82,10 @@
 		goto err;
 
+	hc->hcd = hcd;
+
 	if ((err = hc_init_memory(hc, device)))
 		goto err;
 
 	hcd_set_implementation(hcd, hc, &xhci_ddf_hc_driver.ops, &hc->bus.base);
-	hc->hcd = hcd;
 
 	return EOK;
Index: uspace/drv/bus/usb/xhci/rh.c
===================================================================
--- uspace/drv/bus/usb/xhci/rh.c	(revision 10cd715240ae1db3090d2fb49f7185790adc313a)
+++ uspace/drv/bus/usb/xhci/rh.c	(revision 6832245517c6257fe330523cebfec7b916fdb0bf)
@@ -71,5 +71,5 @@
 	rh->hc_device = device;
 
-	const int err = device_init(&rh->device.base);
+	const int err = bus_device_init(&rh->device.base, &rh->hc->bus.base);
 	if (err)
 		return err;
@@ -94,5 +94,5 @@
 	xhci_bus_t *bus = &rh->hc->bus;
 
-	device_t *dev = hcd_ddf_device_create(rh->hc_device, bus->base.device_size);
+	device_t *dev = hcd_ddf_device_create(rh->hc_device, &bus->base);
 	if (!dev) {
 		usb_log_error("Failed to create USB device function.");
@@ -109,5 +109,5 @@
 	dev->speed = port_speed->usb_speed;
 
-	if ((err = xhci_bus_enumerate_device(bus, rh->hc, dev))) {
+	if ((err = xhci_bus_enumerate_device(bus, dev))) {
 		usb_log_error("Failed to enumerate USB device: %s", str_error(err));
 		return err;
@@ -115,5 +115,5 @@
 
 	if (!ddf_fun_get_name(dev->fun)) {
-		device_set_default_name(dev);
+		bus_device_set_default_name(dev);
 	}
 
@@ -196,5 +196,5 @@
 
 	/* Remove device from XHCI bus. */
-	if ((err = xhci_bus_remove_device(&rh->hc->bus, rh->hc, &dev->base))) {
+	if ((err = xhci_bus_remove_device(&rh->hc->bus, &dev->base))) {
 		usb_log_warning("Failed to remove device " XHCI_DEV_FMT " from XHCI bus: %s",
 		    XHCI_DEV_ARGS(*dev), str_error(err));
