Index: uspace/drv/bus/usb/uhci/hc.c
===================================================================
--- uspace/drv/bus/usb/uhci/hc.c	(revision 5fe0a6978c5352e80c555f1545239199e05167eb)
+++ uspace/drv/bus/usb/uhci/hc.c	(revision 3afb7580ffb5859d718216a15a79100e3ab8aa0a)
@@ -48,9 +48,4 @@
     (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)
 
-static int schedule(hcd_t *hcd, usb_transfer_batch_t *batch)
-{
-	assert(hcd);
-	return hc_schedule(hcd->private_data, batch);
-}
 
 static const irq_cmd_t uhci_irq_commands[] =
@@ -64,7 +59,8 @@
 };
 
+static void hc_init_hw(const hc_t *instance);
+static int hc_init_mem_structures(hc_t *instance);
 static int hc_init_transfer_lists(hc_t *instance);
-static int hc_init_mem_structures(hc_t *instance);
-static void hc_init_hw(hc_t *instance);
+static int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch);
 
 static int hc_interrupt_emulator(void *arg);
@@ -102,4 +98,61 @@
 	cmds[3].addr = (void*)&registers->usbsts;
 	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Take action based on the interrupt cause.
+ *
+ * @param[in] instance UHCI structure to use.
+ * @param[in] status Value of the status register at the time of interrupt.
+ *
+ * Interrupt might indicate:
+ * - transaction completed, either by triggering IOC, SPD, or an error
+ * - some kind of device error
+ * - resume from suspend state (not implemented)
+ */
+void hc_interrupt(hc_t *instance, uint16_t status)
+{
+	assert(instance);
+	/* Lower 2 bits are transaction error and transaction complete */
+	if (status & (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)) {
+		LIST_INITIALIZE(done);
+		transfer_list_remove_finished(
+		    &instance->transfers_interrupt, &done);
+		transfer_list_remove_finished(
+		    &instance->transfers_control_slow, &done);
+		transfer_list_remove_finished(
+		    &instance->transfers_control_full, &done);
+		transfer_list_remove_finished(
+		    &instance->transfers_bulk_full, &done);
+
+		while (!list_empty(&done)) {
+			link_t *item = list_first(&done);
+			list_remove(item);
+			usb_transfer_batch_t *batch =
+			    list_get_instance(item, usb_transfer_batch_t, link);
+			usb_transfer_batch_finish(batch);
+		}
+	}
+	/* Resume interrupts are not supported */
+	if (status & UHCI_STATUS_RESUME) {
+		usb_log_error("Resume interrupt!\n");
+	}
+
+	/* Bits 4 and 5 indicate hc error */
+	if (status & (UHCI_STATUS_PROCESS_ERROR | UHCI_STATUS_SYSTEM_ERROR)) {
+		usb_log_error("UHCI hardware failure!.\n");
+		++instance->hw_failures;
+		transfer_list_abort_all(&instance->transfers_interrupt);
+		transfer_list_abort_all(&instance->transfers_control_slow);
+		transfer_list_abort_all(&instance->transfers_control_full);
+		transfer_list_abort_all(&instance->transfers_bulk_full);
+
+		if (instance->hw_failures < UHCI_ALLOWED_HW_FAIL) {
+			/* reinitialize hw, this triggers virtual disconnect*/
+			hc_init_hw(instance);
+		} else {
+			usb_log_fatal("Too many UHCI hardware failures!.\n");
+			hc_fini(instance);
+		}
+	}
 }
 /*----------------------------------------------------------------------------*/
@@ -138,14 +191,23 @@
 	usb_log_debug(
 	    "Device registers at %p (%zuB) accessible.\n", io, reg_size);
-	hcd_init(&instance->generic, BANDWIDTH_AVAILABLE_USB11);
+
+	ret = hcd_init(&instance->generic, BANDWIDTH_AVAILABLE_USB11);
+	CHECK_RET_RETURN(ret, "Failed to initialize HCD generic driver: %s.\n",
+	    str_error(ret));
+
 	instance->generic.private_data = instance;
-	instance->generic.schedule = schedule;
+	instance->generic.schedule = hc_schedule;
 	instance->generic.batch_private_ctor = uhci_transfer_batch_create;
 	instance->generic.batch_private_dtor = uhci_transfer_batch_dispose;
+#undef CHECK_RET_DEST_FUN_RETURN
 
 	ret = hc_init_mem_structures(instance);
-	CHECK_RET_RETURN(ret,
-	    "Failed to initialize UHCI memory structures: %s.\n",
-	    str_error(ret));
+	if (ret != EOK) {
+		usb_log_error(
+		    "Failed to initialize UHCI memory structures: %s.\n",
+		    str_error(ret));
+		hcd_destroy(&instance->generic);
+		return ret;
+	}
 
 	hc_init_hw(instance);
@@ -158,5 +220,4 @@
 
 	return EOK;
-#undef CHECK_RET_DEST_FUN_RETURN
 }
 /*----------------------------------------------------------------------------*/
@@ -166,5 +227,5 @@
  * For magic values see UHCI Design Guide
  */
-void hc_init_hw(hc_t *instance)
+void hc_init_hw(const hc_t *instance)
 {
 	assert(instance);
@@ -210,5 +271,4 @@
  *
  * Structures:
- *  - interrupt code (I/O addressses are customized per instance)
  *  - transfer lists (queue heads need to be accessible by the hw)
  *  - frame list page (needs to be one UHCI hw accessible 4K page)
@@ -217,32 +277,21 @@
 {
 	assert(instance);
-#define CHECK_RET_RETURN(ret, message...) \
-	if (ret != EOK) { \
-		usb_log_error(message); \
-		return ret; \
-	} else (void) 0
+
+	/* Init USB frame list page */
+	instance->frame_list = get_page();
+	if (!instance->frame_list) {
+		return ENOMEM;
+	}
+	usb_log_debug("Initialized frame list at %p.\n", instance->frame_list);
 
 	/* Init transfer lists */
 	int ret = hc_init_transfer_lists(instance);
-	CHECK_RET_RETURN(ret, "Failed to initialize transfer lists.\n");
+	if (ret != EOK) {
+		usb_log_error("Failed to initialize transfer lists.\n");
+		return_page(instance->frame_list);
+		return ENOMEM;
+	}
 	usb_log_debug("Initialized transfer lists.\n");
 
-	/* Init device keeper */
-	usb_device_keeper_init(&instance->manager);
-	usb_log_debug("Initialized device keeper.\n");
-
-	ret = usb_endpoint_manager_init(&instance->ep_manager,
-	    BANDWIDTH_AVAILABLE_USB11);
-	CHECK_RET_RETURN(ret, "Failed to initialize endpoint manager: %s.\n",
-	    str_error(ret));
-
-	/* Init USB frame list page*/
-	instance->frame_list = get_page();
-	if (!instance->frame_list) {
-		usb_log_error("Failed to get frame list page.\n");
-		usb_endpoint_manager_destroy(&instance->ep_manager);
-		return ENOMEM;
-	}
-	usb_log_debug("Initialized frame list at %p.\n", instance->frame_list);
 
 	/* Set all frames to point to the first queue head */
@@ -255,5 +304,4 @@
 
 	return EOK;
-#undef CHECK_RET_RETURN
 }
 /*----------------------------------------------------------------------------*/
@@ -328,6 +376,8 @@
  * Checks for bandwidth availability and appends the batch to the proper queue.
  */
-int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch)
-{
+int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch)
+{
+	assert(hcd);
+	hc_t *instance = hcd->private_data;
 	assert(instance);
 	assert(batch);
@@ -339,61 +389,4 @@
 
 	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-/** Take action based on the interrupt cause.
- *
- * @param[in] instance UHCI structure to use.
- * @param[in] status Value of the status register at the time of interrupt.
- *
- * Interrupt might indicate:
- * - transaction completed, either by triggering IOC, SPD, or an error
- * - some kind of device error
- * - resume from suspend state (not implemented)
- */
-void hc_interrupt(hc_t *instance, uint16_t status)
-{
-	assert(instance);
-	/* Lower 2 bits are transaction error and transaction complete */
-	if (status & (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)) {
-		LIST_INITIALIZE(done);
-		transfer_list_remove_finished(
-		    &instance->transfers_interrupt, &done);
-		transfer_list_remove_finished(
-		    &instance->transfers_control_slow, &done);
-		transfer_list_remove_finished(
-		    &instance->transfers_control_full, &done);
-		transfer_list_remove_finished(
-		    &instance->transfers_bulk_full, &done);
-
-		while (!list_empty(&done)) {
-			link_t *item = list_first(&done);
-			list_remove(item);
-			usb_transfer_batch_t *batch =
-			    list_get_instance(item, usb_transfer_batch_t, link);
-			usb_transfer_batch_finish(batch);
-		}
-	}
-	/* Resume interrupts are not supported */
-	if (status & UHCI_STATUS_RESUME) {
-		usb_log_error("Resume interrupt!\n");
-	}
-
-	/* Bits 4 and 5 indicate hc error */
-	if (status & (UHCI_STATUS_PROCESS_ERROR | UHCI_STATUS_SYSTEM_ERROR)) {
-		usb_log_error("UHCI hardware failure!.\n");
-		++instance->hw_failures;
-		transfer_list_abort_all(&instance->transfers_interrupt);
-		transfer_list_abort_all(&instance->transfers_control_slow);
-		transfer_list_abort_all(&instance->transfers_control_full);
-		transfer_list_abort_all(&instance->transfers_bulk_full);
-
-		if (instance->hw_failures < UHCI_ALLOWED_HW_FAIL) {
-			/* reinitialize hw, this triggers virtual disconnect*/
-			hc_init_hw(instance);
-		} else {
-			usb_log_fatal("Too many UHCI hardware failures!.\n");
-			hc_fini(instance);
-		}
-	}
 }
 /*----------------------------------------------------------------------------*/
@@ -415,8 +408,4 @@
 		if (status != 0)
 			usb_log_debug2("UHCI status: %x.\n", status);
-// Qemu fails to report stalled communication
-// see https://bugs.launchpad.net/qemu/+bug/757654
-// This is a simple workaround to force queue processing every time
-	//	status |= 1;
 		hc_interrupt(instance, status);
 		async_usleep(UHCI_INT_EMULATOR_TIMEOUT);
@@ -424,5 +413,5 @@
 	return EOK;
 }
-/*---------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------*/
 /** Debug function, checks consistency of memory structures.
  *
