Index: uspace/drv/pciintel/pci.c
===================================================================
--- uspace/drv/pciintel/pci.c	(revision 6bb83c7617113ccde4bfaaec20df6a91f8b48ebd)
+++ uspace/drv/pciintel/pci.c	(revision 62066b4b9236cbb36a30b4ca96c26e641093692c)
@@ -49,4 +49,8 @@
 #include <ipc/devman.h>
 #include <ipc/dev_iface.h>
+#include <ipc/irc.h>
+#include <ipc/ns.h>
+#include <ipc/services.h>
+#include <sysinfo.h>
 #include <ops/hw_res.h>
 #include <device/hw_res.h>
@@ -72,7 +76,36 @@
 static bool pciintel_enable_child_interrupt(device_t *dev)
 {
-	/* TODO */
-	
-	return false;
+	/* This is an old ugly way, copied from ne2000 driver */
+	assert(dev);
+	pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data;
+
+  sysarg_t apic;
+  sysarg_t i8259;
+	int irc_phone = -1;
+	int irc_service = 0;
+
+  if ((sysinfo_get_value("apic", &apic) == EOK) && (apic)) {
+    irc_service = SERVICE_APIC;
+	} else if ((sysinfo_get_value("i8259", &i8259) == EOK) && (i8259)) {
+    irc_service = SERVICE_I8259;
+	}
+
+  if (irc_service) {
+    while (irc_phone < 0)
+      irc_phone = service_connect_blocking(irc_service, 0, 0);
+  } else {
+		return false;
+	}
+
+	size_t i;
+  for (i = 0; i < dev_data->hw_resources.count; i++) {
+		if (dev_data->hw_resources.resources[i].type == INTERRUPT) {
+			int irq = dev_data->hw_resources.resources[i].res.interrupt.irq;
+			async_msg_1(irc_phone, IRC_ENABLE_INTERRUPT, irq);
+		}
+	}
+
+	async_hangup(irc_phone);
+	return true;
 }
 
Index: uspace/drv/uhci-hcd/batch.c
===================================================================
--- uspace/drv/uhci-hcd/batch.c	(revision 6bb83c7617113ccde4bfaaec20df6a91f8b48ebd)
+++ uspace/drv/uhci-hcd/batch.c	(revision 62066b4b9236cbb36a30b4ca96c26e641093692c)
@@ -141,5 +141,4 @@
 	usb_log_debug("Checking(%p) %d packet for completion.\n",
 	    instance, instance->packets);
-	/* This is just an ugly trick to support the old API */
 	instance->transfered_size = 0;
 	size_t i = 0;
@@ -157,4 +156,5 @@
 		    transfer_descriptor_actual_size(&instance->tds[i]);
 	}
+	/* This is just an ugly trick to support the old API */
 	instance->transfered_size -= instance->setup_size;
 	return true;
@@ -191,4 +191,6 @@
 	    0, 1, false, instance->target, USB_PID_IN, NULL, NULL);
 
+	instance->tds[i].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
+
 	instance->next_step = batch_call_out_and_dispose;
 	batch_schedule(instance);
@@ -221,4 +223,6 @@
 	transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
 	    0, 1, false, instance->target, USB_PID_OUT, NULL, NULL);
+
+	instance->tds[i].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
 
 	instance->next_step = batch_call_in_and_dispose;
@@ -244,4 +248,6 @@
 	}
 
+	instance->tds[i - 1].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
+
 	instance->next_step = batch_call_in_and_dispose;
 	batch_schedule(instance);
@@ -268,4 +274,6 @@
 	}
 
+	instance->tds[i - 1].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
+
 	instance->next_step = batch_call_out_and_dispose;
 	batch_schedule(instance);
Index: uspace/drv/uhci-hcd/iface.c
===================================================================
--- uspace/drv/uhci-hcd/iface.c	(revision 6bb83c7617113ccde4bfaaec20df6a91f8b48ebd)
+++ uspace/drv/uhci-hcd/iface.c	(revision 62066b4b9236cbb36a30b4ca96c26e641093692c)
@@ -54,5 +54,5 @@
 }
 /*----------------------------------------------------------------------------*/
-static int reserve_default_address(device_t *dev, bool full_speed)
+static int reserve_default_address(device_t *dev, usb_speed_t speed)
 {
 	assert(dev);
@@ -72,5 +72,5 @@
 }
 /*----------------------------------------------------------------------------*/
-static int request_address(device_t *dev, bool full_speed,
+static int request_address(device_t *dev, usb_speed_t speed,
     usb_address_t *address)
 {
@@ -164,98 +164,6 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
-static int control_write_setup(device_t *dev, usb_target_t target,
-    size_t max_packet_size,
-    void *data, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	dev_speed_t speed = FULL_SPEED;
 
-	usb_log_warning("Using deprecated API %s.\n", __FUNCTION__);
-	batch_t *batch = batch_get(dev, target, USB_TRANSFER_CONTROL,
-	    max_packet_size, speed, NULL, 0, data, size, NULL, callback, arg);
-	if (!batch)
-		return ENOMEM;
-	batch_control_setup_old(batch);
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-static int control_write_data(device_t *dev, usb_target_t target,
-    size_t max_packet_size,
-    void *data, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	dev_speed_t speed = FULL_SPEED;
 
-	usb_log_warning("Using deprecated API %s.\n", __FUNCTION__);
-	batch_t *batch = batch_get(dev, target, USB_TRANSFER_CONTROL,
-	    max_packet_size, speed, data, size, NULL, 0, NULL, callback, arg);
-	if (!batch)
-		return ENOMEM;
-	batch_control_write_data_old(batch);
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-static int control_write_status(device_t *dev, usb_target_t target,
-    usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-	size_t max_packet_size = 8;
-	dev_speed_t speed = FULL_SPEED;
-
-	usb_log_warning("Using deprecated API %s.\n", __FUNCTION__);
-	batch_t *batch = batch_get(dev, target, USB_TRANSFER_CONTROL,
-	    max_packet_size, speed, NULL, 0, NULL, 0, callback, NULL, arg);
-	if (!batch)
-		return ENOMEM;
-	batch_control_write_status_old(batch);
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-static int control_read_setup(device_t *dev, usb_target_t target,
-    size_t max_packet_size,
-    void *data, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	dev_speed_t speed = FULL_SPEED;
-
-	usb_log_warning("Using deprecated API %s.\n", __FUNCTION__);
-	batch_t *batch = batch_get(dev, target, USB_TRANSFER_CONTROL,
-	    max_packet_size, speed, NULL, 0, data, size, NULL, callback, arg);
-	if (!batch)
-		return ENOMEM;
-	batch_control_setup_old(batch);
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-static int control_read_data(device_t *dev, usb_target_t target,
-    size_t max_packet_size,
-    void *data, size_t size,
-    usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-	dev_speed_t speed = FULL_SPEED;
-
-	usb_log_warning("Using deprecated API %s.\n", __FUNCTION__);
-	batch_t *batch = batch_get(dev, target, USB_TRANSFER_CONTROL,
-	    max_packet_size, speed, data, size, NULL, 0, callback, NULL, arg);
-	if (!batch)
-		return ENOMEM;
-	batch_control_read_data_old(batch);
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-static int control_read_status(device_t *dev, usb_target_t target,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	size_t max_packet_size = 8;
-	dev_speed_t speed = FULL_SPEED;
-
-	usb_log_warning("Using deprecated API %s.\n", __FUNCTION__);
-	batch_t *batch = batch_get(dev, target, USB_TRANSFER_CONTROL,
-	    max_packet_size, speed, NULL, 0, NULL, 0, NULL, callback, arg);
-	if (!batch)
-		return ENOMEM;
-	batch_control_read_status_old(batch);
-	return EOK;
-}
 /*----------------------------------------------------------------------------*/
 usbhc_iface_t uhci_iface = {
@@ -273,12 +181,4 @@
 	.control_read = control_read,
 	.control_write = control_write,
-
-	.control_write_setup = control_write_setup,
-	.control_write_data = control_write_data,
-	.control_write_status = control_write_status,
-
-	.control_read_setup = control_read_setup,
-	.control_read_data = control_read_data,
-	.control_read_status = control_read_status
 };
 /**
Index: uspace/drv/uhci-hcd/main.c
===================================================================
--- uspace/drv/uhci-hcd/main.c	(revision 6bb83c7617113ccde4bfaaec20df6a91f8b48ebd)
+++ uspace/drv/uhci-hcd/main.c	(revision 62066b4b9236cbb36a30b4ca96c26e641093692c)
@@ -34,4 +34,5 @@
 #include <driver.h>
 #include <usb_iface.h>
+#include <device/hw_res.h>
 
 #include <errno.h>
@@ -46,4 +47,7 @@
 #define NAME "uhci-hcd"
 
+static int uhci_add_device(device_t *device);
+static int usb_iface_get_hc_handle(device_t *dev, devman_handle_t *handle);
+/*----------------------------------------------------------------------------*/
 static int usb_iface_get_hc_handle(device_t *dev, devman_handle_t *handle)
 {
@@ -54,13 +58,37 @@
 	return EOK;
 }
-
+/*----------------------------------------------------------------------------*/
 static usb_iface_t hc_usb_iface = {
 	.get_hc_handle = usb_iface_get_hc_handle
 };
-
+/*----------------------------------------------------------------------------*/
 static device_ops_t uhci_ops = {
 	.interfaces[USB_DEV_IFACE] = &hc_usb_iface,
 	.interfaces[USBHC_DEV_IFACE] = &uhci_iface
 };
+/*----------------------------------------------------------------------------*/
+static driver_ops_t uhci_driver_ops = {
+	.add_device = uhci_add_device,
+};
+/*----------------------------------------------------------------------------*/
+static driver_t uhci_driver = {
+	.name = NAME,
+	.driver_ops = &uhci_driver_ops
+};
+/*----------------------------------------------------------------------------*/
+static void irq_handler(device_t *device, ipc_callid_t iid, ipc_call_t *call)
+{
+	assert(device);
+	uhci_t *hc = dev_to_uhci(device);
+	uint16_t status = IPC_GET_ARG1(*call);
+	assert(hc);
+	uhci_interrupt(hc, status);
+}
+/*----------------------------------------------------------------------------*/
+#define CHECK_RET_RETURN(ret, message...) \
+if (ret != EOK) { \
+	usb_log_error(message); \
+	return ret; \
+}
 
 static int uhci_add_device(device_t *device)
@@ -75,33 +103,41 @@
 	int irq;
 
-	int rc = pci_get_my_registers(device,
-	    &io_reg_base, &io_reg_size, &irq);
+	int ret =
+	    pci_get_my_registers(device, &io_reg_base, &io_reg_size, &irq);
 
-	if (rc != EOK) {
-		usb_log_error("Failed(%d) to get I/O registers addresses for device:.\n",
-		    rc, device->handle);
-		return rc;
-	}
-
+	CHECK_RET_RETURN(ret,
+	    "Failed(%d) to get I/O addresses:.\n", ret, device->handle);
 	usb_log_info("I/O regs at 0x%X (size %zu), IRQ %d.\n",
 	    io_reg_base, io_reg_size, irq);
 
+	ret = pci_enable_interrupts(device);
+	CHECK_RET_RETURN(ret, "Failed(%d) to get enable interrupts:\n", ret);
+
 	uhci_t *uhci_hc = malloc(sizeof(uhci_t));
-	if (!uhci_hc) {
-		usb_log_error("Failed to allocaete memory for uhci hcd driver.\n");
-		return ENOMEM;
+	ret = (uhci_hc != NULL) ? EOK : ENOMEM;
+	CHECK_RET_RETURN(ret, "Failed to allocate memory for uhci hcd driver.\n");
+
+	ret = uhci_init(uhci_hc, (void*)io_reg_base, io_reg_size);
+	if (ret != EOK) {
+		usb_log_error("Failed to init uhci-hcd.\n");
+		free(uhci_hc);
+		return ret;
 	}
 
-	int ret = uhci_init(uhci_hc, (void*)io_reg_base, io_reg_size);
+	ret = register_interrupt_handler(device, irq, irq_handler,
+	    &uhci_hc->interrupt_code);
 	if (ret != EOK) {
-		usb_log_error("Failed to init uhci-hcd.\n");
+		usb_log_error("Failed to register interrupt handler.\n");
+		uhci_fini(uhci_hc);
+		free(uhci_hc);
 		return ret;
 	}
+
 	device_t *rh;
 	ret = setup_root_hub(&rh, device);
-
 	if (ret != EOK) {
 		usb_log_error("Failed to setup uhci root hub.\n");
-		/* TODO: destroy uhci here */
+		uhci_fini(uhci_hc);
+		free(uhci_hc);
 		return ret;
 	}
@@ -110,29 +146,18 @@
 	if (ret != EOK) {
 		usb_log_error("Failed to register root hub.\n");
-		/* TODO: destroy uhci here */
+		uhci_fini(uhci_hc);
+		free(uhci_hc);
+		free(rh);
 		return ret;
 	}
 
 	device->driver_data = uhci_hc;
-
 	return EOK;
 }
-
-static driver_ops_t uhci_driver_ops = {
-	.add_device = uhci_add_device,
-};
-
-static driver_t uhci_driver = {
-	.name = NAME,
-	.driver_ops = &uhci_driver_ops
-};
-
+/*----------------------------------------------------------------------------*/
 int main(int argc, char *argv[])
 {
-	/*
-	 * Do some global initializations.
-	 */
-	sleep(5);
-	usb_log_enable(USB_LOG_LEVEL_INFO, NAME);
+	sleep(3);
+	usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
 
 	return driver_main(&uhci_driver);
Index: uspace/drv/uhci-hcd/pci.c
===================================================================
--- uspace/drv/uhci-hcd/pci.c	(revision 6bb83c7617113ccde4bfaaec20df6a91f8b48ebd)
+++ uspace/drv/uhci-hcd/pci.c	(revision 62066b4b9236cbb36a30b4ca96c26e641093692c)
@@ -121,5 +121,12 @@
 	return rc;
 }
-
+/*----------------------------------------------------------------------------*/
+int pci_enable_interrupts(device_t *device)
+{
+	int parent_phone = devman_parent_device_connect(device->handle,
+	    IPC_FLAG_BLOCKING);
+	bool enabled = hw_res_enable_interrupt(parent_phone);
+	return enabled ? EOK : EIO;
+}
 /**
  * @}
Index: uspace/drv/uhci-hcd/pci.h
===================================================================
--- uspace/drv/uhci-hcd/pci.h	(revision 6bb83c7617113ccde4bfaaec20df6a91f8b48ebd)
+++ uspace/drv/uhci-hcd/pci.h	(revision 62066b4b9236cbb36a30b4ca96c26e641093692c)
@@ -39,4 +39,5 @@
 
 int pci_get_my_registers(device_t *, uintptr_t *, size_t *, int *);
+int pci_enable_interrupts(device_t *device);
 
 #endif
Index: uspace/drv/uhci-hcd/transfer_list.c
===================================================================
--- uspace/drv/uhci-hcd/transfer_list.c	(revision 6bb83c7617113ccde4bfaaec20df6a91f8b48ebd)
+++ uspace/drv/uhci-hcd/transfer_list.c	(revision 62066b4b9236cbb36a30b4ca96c26e641093692c)
@@ -111,9 +111,9 @@
 	/* I'm the first one here */
 	if (batch->link.prev == &instance->batch_list) {
-		usb_log_debug("Removing tracer %p was first, next element %x.\n",
+		usb_log_debug("Removing batch %p was first, next element %x.\n",
 			batch, batch->qh->next_queue);
 		instance->queue_head->element = batch->qh->next_queue;
 	} else {
-		usb_log_debug("Removing tracer %p was NOT first, next element %x.\n",
+		usb_log_debug("Removing batch %p was NOT first, next element %x.\n",
 			batch, batch->qh->next_queue);
 		batch_t *prev = list_get_instance(batch->link.prev, batch_t, link);
Index: uspace/drv/uhci-hcd/uhci-hcd.ma
===================================================================
--- uspace/drv/uhci-hcd/uhci-hcd.ma	(revision 6bb83c7617113ccde4bfaaec20df6a91f8b48ebd)
+++ uspace/drv/uhci-hcd/uhci-hcd.ma	(revision 62066b4b9236cbb36a30b4ca96c26e641093692c)
@@ -1,2 +1,2 @@
 10 pci/ven=8086&dev=7020
-
+10 pci/ven=8086&dev=7112
Index: uspace/drv/uhci-hcd/uhci.c
===================================================================
--- uspace/drv/uhci-hcd/uhci.c	(revision 6bb83c7617113ccde4bfaaec20df6a91f8b48ebd)
+++ uspace/drv/uhci-hcd/uhci.c	(revision 62066b4b9236cbb36a30b4ca96c26e641093692c)
@@ -39,14 +39,31 @@
 
 #include "uhci.h"
+static irq_cmd_t uhci_cmds[] = {
+	{
+		.cmd = CMD_PIO_READ_16,
+		.addr = (void*)0xc022,
+		.dstarg = 1
+	},
+	{
+		.cmd = CMD_PIO_WRITE_16,
+		.addr = (void*)0xc022,
+		.value = 0x1f
+	},
+	{
+		.cmd = CMD_ACCEPT
+	}
+};
 
 static int uhci_init_transfer_lists(uhci_t *instance);
-static int uhci_clean_finished(void *arg);
+static int uhci_init_mem_structures(uhci_t *instance);
+static void uhci_init_hw(uhci_t *instance);
+
+static int uhci_interrupt_emulator(void *arg);
 static int uhci_debug_checker(void *arg);
+
 static bool allowed_usb_packet(
 	bool low_speed, usb_transfer_type_t, size_t size);
 
-int uhci_init(uhci_t *instance, void *regs, size_t reg_size)
-{
-#define CHECK_RET_RETURN(message...) \
+#define CHECK_RET_RETURN(ret, message...) \
 	if (ret != EOK) { \
 		usb_log_error(message); \
@@ -54,26 +71,72 @@
 	} else (void) 0
 
-	/* init address keeper(libusb) */
-	usb_address_keeping_init(&instance->address_manager, USB11_ADDRESS_MAX);
-	usb_log_debug("Initialized address manager.\n");
+int uhci_init(uhci_t *instance, void *regs, size_t reg_size)
+{
+	assert(reg_size >= sizeof(regs_t));
 
 	/* allow access to hc control registers */
 	regs_t *io;
-	assert(reg_size >= sizeof(regs_t));
 	int ret = pio_enable(regs, reg_size, (void**)&io);
-	CHECK_RET_RETURN("Failed to gain access to registers at %p.\n", io);
+	CHECK_RET_RETURN(ret, "Failed to gain access to registers at %p.\n", io);
 	instance->registers = io;
 	usb_log_debug("Device registers accessible.\n");
 
+	ret = uhci_init_mem_structures(instance);
+	CHECK_RET_RETURN(ret, "Failed to initialize memory structures.\n");
+
+	uhci_init_hw(instance);
+
+	instance->cleaner = fibril_create(uhci_interrupt_emulator, instance);
+//	fibril_add_ready(instance->cleaner);
+
+	instance->debug_checker = fibril_create(uhci_debug_checker, instance);
+	fibril_add_ready(instance->debug_checker);
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+void uhci_init_hw(uhci_t *instance)
+{
+
+	/* set framelist pointer */
+	const uint32_t pa = addr_to_phys(instance->frame_list);
+	pio_write_32(&instance->registers->flbaseadd, pa);
+
+	/* enable all interrupts, but resume interrupt */
+	pio_write_16(&instance->registers->usbintr,
+		  UHCI_INTR_CRC | UHCI_INTR_COMPLETE | UHCI_INTR_SHORT_PACKET);
+
+	/* Start the hc with large(64B) packet FSBR */
+	pio_write_16(&instance->registers->usbcmd,
+	    UHCI_CMD_RUN_STOP | UHCI_CMD_MAX_PACKET | UHCI_CMD_CONFIGURE);
+	usb_log_debug("Started UHCI HC.\n");
+}
+/*----------------------------------------------------------------------------*/
+int uhci_init_mem_structures(uhci_t *instance)
+{
+	assert(instance);
+
+	/* init interrupt code */
+	irq_cmd_t *interrupt_commands = malloc(sizeof(uhci_cmds));
+	if (interrupt_commands == NULL) {
+		return ENOMEM;
+	}
+	memcpy(interrupt_commands, uhci_cmds, sizeof(uhci_cmds));
+	interrupt_commands[0].addr = (void*)&instance->registers->usbsts;
+	interrupt_commands[1].addr = (void*)&instance->registers->usbsts;
+	instance->interrupt_code.cmds = interrupt_commands;
+	instance->interrupt_code.cmdcount =
+	    sizeof(uhci_cmds) / sizeof(irq_cmd_t);
+
 	/* init transfer lists */
-	ret = uhci_init_transfer_lists(instance);
-	CHECK_RET_RETURN("Failed to initialize transfer lists.\n");
-	usb_log_debug("Transfer lists initialized.\n");
-
-
-	usb_log_debug("Initializing frame list.\n");
+	int ret = uhci_init_transfer_lists(instance);
+	CHECK_RET_RETURN(ret, "Failed to initialize transfer lists.\n");
+	usb_log_debug("Initialized transfer lists.\n");
+
+	/* frame list initialization */
 	instance->frame_list = get_page();
 	ret = instance ? EOK : ENOMEM;
-	CHECK_RET_RETURN("Failed to get frame list page.\n");
+	CHECK_RET_RETURN(ret, "Failed to get frame list page.\n");
+	usb_log_debug("Initialized frame list.\n");
 
 	/* initialize all frames to point to the first queue head */
@@ -86,24 +149,7 @@
 	}
 
-	const uintptr_t pa = (uintptr_t)addr_to_phys(instance->frame_list);
-	pio_write_32(&instance->registers->flbaseadd, (uint32_t)pa);
-
-	list_initialize(&instance->batch_list);
-	fibril_mutex_initialize(&instance->batch_list_mutex);
-
-	instance->cleaner = fibril_create(uhci_clean_finished, instance);
-	fibril_add_ready(instance->cleaner);
-
-	instance->debug_checker = fibril_create(uhci_debug_checker, instance);
-	fibril_add_ready(instance->debug_checker);
-
-	/* Start the hc with large(64B) packet FSBR */
-	pio_write_16(&instance->registers->usbcmd,
-	    UHCI_CMD_RUN_STOP | UHCI_CMD_MAX_PACKET);
-	usb_log_debug("Started UHCI HC.\n");
-
-	uint16_t cmd = pio_read_16(&instance->registers->usbcmd);
-	cmd |= UHCI_CMD_DEBUG;
-	pio_write_16(&instance->registers->usbcmd, cmd);
+	/* init address keeper(libusb) */
+	usb_address_keeping_init(&instance->address_manager, USB11_ADDRESS_MAX);
+	usb_log_debug("Initialized address manager.\n");
 
 	return EOK;
@@ -114,5 +160,5 @@
 	assert(instance);
 
-	/* initialize */
+	/* initialize TODO: check errors */
 	int ret;
 	ret = transfer_list_init(&instance->transfers_bulk_full, "BULK_FULL");
@@ -146,6 +192,6 @@
 	instance->transfers[1][USB_TRANSFER_CONTROL] =
 	  &instance->transfers_control_slow;
-	instance->transfers[0][USB_TRANSFER_CONTROL] =
-	  &instance->transfers_control_full;
+	instance->transfers[0][USB_TRANSFER_BULK] =
+	  &instance->transfers_bulk_full;
 
 	return EOK;
@@ -174,15 +220,25 @@
 }
 /*----------------------------------------------------------------------------*/
-int uhci_clean_finished(void* arg)
-{
-	usb_log_debug("Started cleaning fibril.\n");
+void uhci_interrupt(uhci_t *instance, uint16_t status)
+{
+	assert(instance);
+	if ((status & (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)) == 0)
+		return;
+	usb_log_debug("UHCI interrupt: %X.\n", status);
+	transfer_list_check(&instance->transfers_interrupt);
+	transfer_list_check(&instance->transfers_control_slow);
+	transfer_list_check(&instance->transfers_control_full);
+	transfer_list_check(&instance->transfers_bulk_full);
+}
+/*----------------------------------------------------------------------------*/
+int uhci_interrupt_emulator(void* arg)
+{
+	usb_log_debug("Started interrupt emulator.\n");
 	uhci_t *instance = (uhci_t*)arg;
 	assert(instance);
 
 	while(1) {
-		transfer_list_check(&instance->transfers_interrupt);
-		transfer_list_check(&instance->transfers_control_slow);
-		transfer_list_check(&instance->transfers_control_full);
-		transfer_list_check(&instance->transfers_bulk_full);
+		uint16_t status = pio_read_16(&instance->registers->usbsts);
+		uhci_interrupt(instance, status);
 		async_usleep(UHCI_CLEANER_TIMEOUT);
 	}
@@ -195,10 +251,12 @@
 	assert(instance);
 	while (1) {
-		uint16_t cmd = pio_read_16(&instance->registers->usbcmd);
-		uint16_t sts = pio_read_16(&instance->registers->usbsts);
-		usb_log_debug("Command register: %X Status register: %X\n", cmd, sts);
+		const uint16_t cmd = pio_read_16(&instance->registers->usbcmd);
+		const uint16_t sts = pio_read_16(&instance->registers->usbsts);
+		const uint16_t intr = pio_read_16(&instance->registers->usbintr);
+		usb_log_debug("Command: %X Status: %X Interrupts: %x\n",
+		    cmd, sts, intr);
 
 		uintptr_t frame_list = pio_read_32(&instance->registers->flbaseadd);
-		if (frame_list != (uintptr_t)addr_to_phys(instance->frame_list)) {
+		if (frame_list != addr_to_phys(instance->frame_list)) {
 			usb_log_debug("Framelist address: %p vs. %p.\n",
 				frame_list, addr_to_phys(instance->frame_list));
Index: uspace/drv/uhci-hcd/uhci.h
===================================================================
--- uspace/drv/uhci-hcd/uhci.h	(revision 6bb83c7617113ccde4bfaaec20df6a91f8b48ebd)
+++ uspace/drv/uhci-hcd/uhci.h	(revision 62066b4b9236cbb36a30b4ca96c26e641093692c)
@@ -66,4 +66,9 @@
 
 	uint16_t usbintr;
+#define UHCI_INTR_SHORT_PACKET (1 << 3)
+#define UHCI_INTR_COMPLETE (1 << 2)
+#define UHCI_INTR_RESUME (1 << 1)
+#define UHCI_INTR_CRC (1 << 0)
+
 	uint16_t frnum;
 	uint32_t flbaseadd;
@@ -81,7 +86,4 @@
 	link_pointer_t *frame_list;
 
-	link_t batch_list;
-	fibril_mutex_t batch_list_mutex;
-
 	transfer_list_t transfers_bulk_full;
 	transfer_list_t transfers_control_full;
@@ -90,4 +92,6 @@
 
 	transfer_list_t *transfers[2][4];
+
+	irq_code_t interrupt_code;
 
 	fid_t cleaner;
@@ -98,23 +102,13 @@
 int uhci_init(uhci_t *instance, void *regs, size_t reg_size);
 
-int uhci_fini(uhci_t *device);
-
-int uhci_transfer(
-  uhci_t *instance,
-  device_t *dev,
-  usb_target_t target,
-  usb_transfer_type_t transfer_type,
-	bool toggle,
-  usb_packet_id pid,
-	bool low_speed,
-  void *buffer, size_t size,
-  usbhc_iface_transfer_out_callback_t callback_out,
-  usbhc_iface_transfer_in_callback_t callback_in,
-  void *arg );
+static inline void uhci_fini(uhci_t *instance) {};
 
 int uhci_schedule(uhci_t *instance, batch_t *batch);
 
+void uhci_interrupt(uhci_t *instance, uint16_t status);
+
 static inline uhci_t * dev_to_uhci(device_t *dev)
 	{ return (uhci_t*)dev->driver_data; }
+
 
 #endif
Index: uspace/drv/uhci-rhd/port.c
===================================================================
--- uspace/drv/uhci-rhd/port.c	(revision 6bb83c7617113ccde4bfaaec20df6a91f8b48ebd)
+++ uspace/drv/uhci-rhd/port.c	(revision 62066b4b9236cbb36a30b4ca96c26e641093692c)
@@ -131,49 +131,24 @@
 	return EOK;
 }
-/*----------------------------------------------------------------------------*/
-static int uhci_port_new_device(uhci_port_t *port)
-{
-	assert(port);
-	assert(usb_hc_connection_is_opened(&port->hc_connection));
-
-	usb_log_info("Adding new device on port %d.\n", port->number);
-
-	/* get address of the future device */
-	const usb_address_t usb_address = usb_hc_request_address(
-	    &port->hc_connection, true);
-
-	if (usb_address <= 0) {
-		usb_log_error("Recieved invalid address(%d).\n", usb_address);
-		return usb_address;
-	}
-	usb_log_debug("Sucessfully obtained address %d for port %d.\n",
-	    usb_address, port->number);
-
-	/* get default address */
-	int ret = usb_hc_reserve_default_address(&port->hc_connection, true);
-	if (ret != EOK) {
-		usb_log_error("Failed to reserve default address on port %d.\n",
-		    port->number);
-		int ret2 = usb_hc_unregister_device(&port->hc_connection,
-		    usb_address);
-		if (ret2 != EOK) {
-			usb_log_fatal("Failed to return requested address on port %d.\n",
-			   port->number);
-			return ret2;
-		}
-		usb_log_debug("Successfully returned reserved address on port %d.\n",
-			port->number);
-		return ret;
-	}
-	usb_log_debug("Sucessfully obtained default address for port %d.\n",
-	    port->number);
+
+/** Callback for enabling port during adding a new device.
+ *
+ * @param portno Port number (unused).
+ * @param arg Pointer to uhci_port_t of port with the new device.
+ * @return Error code.
+ */
+static int new_device_enable_port(int portno, void *arg)
+{
+	uhci_port_t *port = (uhci_port_t *) arg;
+
+	usb_log_debug("new_device_enable_port(%d)\n", port->number);
 
 	/*
-	 * the host then waits for at least 100 ms to allow completion of
+	 * The host then waits for at least 100 ms to allow completion of
 	 * an insertion process and for power at the device to become stable.
 	 */
 	async_usleep(100000);
 
-	/* enable port */
+	/* Enable the port. */
 	uhci_port_set_enabled(port, true);
 
@@ -197,78 +172,33 @@
 	}
 
-	/*
-	 * Initialize connection to the device.
-	 */
-	/* FIXME: check for errors. */
-	usb_device_connection_t new_dev_connection;
-	usb_endpoint_pipe_t new_dev_ctrl_pipe;
-	usb_device_connection_initialize_on_default_address(
-	    &new_dev_connection, &port->hc_connection);
-	usb_endpoint_pipe_initialize_default_control(&new_dev_ctrl_pipe,
-	    &new_dev_connection);
-
-	/*
-	 * Assign new address to the device. This function updates
-	 * the backing connection to still point to the same device.
-	 */
-	/* FIXME: check for errors. */
-	usb_endpoint_pipe_start_session(&new_dev_ctrl_pipe);
-	ret = usb_request_set_address(&new_dev_ctrl_pipe, usb_address);
-	usb_endpoint_pipe_end_session(&new_dev_ctrl_pipe);
-
-	if (ret != EOK) { /* address assigning went wrong */
-		usb_log_error("Failed(%d) to assign address to the device.\n", ret);
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+static int uhci_port_new_device(uhci_port_t *port)
+{
+	assert(port);
+	assert(usb_hc_connection_is_opened(&port->hc_connection));
+
+	usb_log_info("Detected new device on port %u.\n", port->number);
+
+	usb_address_t dev_addr;
+	int rc = usb_hc_new_device_wrapper(port->rh, &port->hc_connection,
+	    USB_SPEED_FULL,
+	    new_device_enable_port, port->number, port,
+	    &dev_addr, &port->attached_device);
+	if (rc != EOK) {
+		usb_log_error("Failed adding new device on port %u: %s.\n",
+		    port->number, str_error(rc));
 		uhci_port_set_enabled(port, false);
-		int release = usb_hc_release_default_address(&port->hc_connection);
-		if (release != EOK) {
-			usb_log_error("Failed to release default address on port %d.\n",
-			    port->number);
-			return release;
-		}
-		usb_log_debug("Sucessfully released default address on port %d.\n",
-		    port->number);
-		return ret;
-	}
-	usb_log_debug("Sucessfully assigned address %d for port %d.\n",
-	    usb_address, port->number);
-
-	/* release default address */
-	ret = usb_hc_release_default_address(&port->hc_connection);
-	if (ret != EOK) {
-		usb_log_error("Failed to release default address on port %d.\n",
-		    port->number);
-		return ret;
-	}
-	usb_log_debug("Sucessfully released default address on port %d.\n",
-	    port->number);
-
-	/* communicate and possibly report to devman */
-	assert(port->attached_device == 0);
-
-	ret = usb_device_register_child_in_devman(new_dev_connection.address,
-	    new_dev_connection.hc_handle, port->rh, &port->attached_device);
-
-	if (ret != EOK) { /* something went wrong */
-		usb_log_error("Failed(%d) in usb_drv_register_child.\n", ret);
-		uhci_port_set_enabled(port, false);
-		return ENOMEM;
-	}
-	usb_log_info("Sucessfully added device on port(%d) address(%d) handle %d.\n",
-		port->number, usb_address, port->attached_device);
-
-	/*
-	 * Register the device in the host controller.
-	 */
-	usb_hc_attached_device_t new_device = {
-		.address = new_dev_connection.address,
-		.handle = port->attached_device
-	};
-
-	ret = usb_hc_register_device(&port->hc_connection, &new_device);
-	// TODO: proper error check here
-	assert(ret == EOK);
-
-	return EOK;
-}
+		return rc;
+	}
+
+	usb_log_info("New device on port %u has address %d (handle %zu).\n",
+	    port->number, dev_addr, port->attached_device);
+
+	return EOK;
+}
+
 /*----------------------------------------------------------------------------*/
 static int uhci_port_remove_device(uhci_port_t *port)
Index: uspace/drv/uhci-rhd/root_hub.c
===================================================================
--- uspace/drv/uhci-rhd/root_hub.c	(revision 6bb83c7617113ccde4bfaaec20df6a91f8b48ebd)
+++ uspace/drv/uhci-rhd/root_hub.c	(revision 62066b4b9236cbb36a30b4ca96c26e641093692c)
@@ -47,5 +47,5 @@
 	assert(rh);
 	int ret;
-	ret = usb_drv_find_hc(rh, &instance->hc_handle);
+	ret = usb_hc_find(rh->handle, &instance->hc_handle);
 	usb_log_info("rh found(%d) hc handle: %d.\n", ret, instance->hc_handle);
 	if (ret != EOK) {
Index: uspace/drv/usbhub/usbhub.c
===================================================================
--- uspace/drv/usbhub/usbhub.c	(revision 6bb83c7617113ccde4bfaaec20df6a91f8b48ebd)
+++ uspace/drv/usbhub/usbhub.c	(revision 62066b4b9236cbb36a30b4ca96c26e641093692c)
@@ -52,6 +52,11 @@
 #include "usb/pipes.h"
 
+static int iface_get_hc_handle(device_t *device, devman_handle_t *handle)
+{
+	return usb_hc_find(device->handle, handle);
+}
+
 static usb_iface_t hub_usb_iface = {
-	.get_hc_handle = usb_drv_find_hc
+	.get_hc_handle = iface_get_hc_handle
 };
 
@@ -263,5 +268,5 @@
 	//get default address
 	//opResult = usb_drv_reserve_default_address(hc);
-	opResult = usb_hc_reserve_default_address(&hub->connection, false);
+	opResult = usb_hc_reserve_default_address(&hub->connection, USB_SPEED_LOW);
 	if (opResult != EOK) {
 		dprintf(USB_LOG_LEVEL_WARNING, "cannot assign default address, it is probably used");
@@ -320,5 +325,5 @@
 	usb_address_t new_device_address = usb_hc_request_address(
 			&hub->connection,
-			false/// \TODO fullspeed??
+			USB_SPEED_LOW/// \TODO fullspeed??
 			);
 	if (new_device_address < 0) {
Index: uspace/drv/vhc/connhost.c
===================================================================
--- uspace/drv/vhc/connhost.c	(revision 6bb83c7617113ccde4bfaaec20df6a91f8b48ebd)
+++ uspace/drv/vhc/connhost.c	(revision 62066b4b9236cbb36a30b4ca96c26e641093692c)
@@ -234,24 +234,4 @@
 }
 
-static int enqueue_transfer_setup(device_t *dev,
-    usb_target_t target, usb_transfer_type_t transfer_type,
-    void *buffer, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	usb_log_debug2("Transfer SETUP [%d.%d (%s); %zu].\n",
-	    target.address, target.endpoint,
-	    usb_str_transfer_type(transfer_type),
-	    size);
-
-	transfer_info_t *transfer
-	    = create_transfer_info(dev, USB_DIRECTION_OUT, arg);
-	transfer->out_callback = callback;
-
-	hc_add_transaction_to_device(true, target, transfer_type, buffer, size,
-	    universal_callback, transfer);
-
-	return EOK;
-}
-
 static int enqueue_transfer_in(device_t *dev,
     usb_target_t target, usb_transfer_type_t transfer_type,
@@ -292,32 +272,4 @@
 	return enqueue_transfer_in(dev, target, USB_TRANSFER_INTERRUPT,
 	    data, size,
-	    callback, arg);
-}
-
-static int control_write_setup(device_t *dev, usb_target_t target,
-    size_t max_packet_size,
-    void *data, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	return enqueue_transfer_setup(dev, target, USB_TRANSFER_CONTROL,
-	    data, size,
-	    callback, arg);
-}
-
-static int control_write_data(device_t *dev, usb_target_t target,
-    size_t max_packet_size,
-    void *data, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	return enqueue_transfer_out(dev, target, USB_TRANSFER_CONTROL,
-	    data, size,
-	    callback, arg);
-}
-
-static int control_write_status(device_t *dev, usb_target_t target,
-    usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-	return enqueue_transfer_in(dev, target, USB_TRANSFER_CONTROL,
-	    NULL, 0,
 	    callback, arg);
 }
@@ -341,32 +293,4 @@
 }
 
-static int control_read_setup(device_t *dev, usb_target_t target,
-    size_t max_packet_size,
-    void *data, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	return enqueue_transfer_setup(dev, target, USB_TRANSFER_CONTROL,
-	    data, size,
-	    callback, arg);
-}
-
-static int control_read_data(device_t *dev, usb_target_t target,
-    size_t max_packet_size,
-    void *data, size_t size,
-    usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-	return enqueue_transfer_in(dev, target, USB_TRANSFER_CONTROL,
-	    data, size,
-	    callback, arg);
-}
-
-static int control_read_status(device_t *dev, usb_target_t target,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	return enqueue_transfer_out(dev, target, USB_TRANSFER_CONTROL,
-	    NULL, 0,
-	    callback, arg);
-}
-
 static int control_read(device_t *dev, usb_target_t target,
     size_t max_packet_size,
@@ -390,5 +314,5 @@
 
 
-static int reserve_default_address(device_t *dev, bool ignored)
+static int reserve_default_address(device_t *dev, usb_speed_t ignored)
 {
 	usb_address_keeping_reserve_default(&addresses);
@@ -402,5 +326,6 @@
 }
 
-static int request_address(device_t *dev, bool ignored, usb_address_t *address)
+static int request_address(device_t *dev, usb_speed_t ignored,
+    usb_address_t *address)
 {
 	usb_address_t addr = usb_address_keeping_request(&addresses);
@@ -454,14 +379,5 @@
 	.interrupt_in = interrupt_in,
 
-	.control_write_setup = control_write_setup,
-	.control_write_data = control_write_data,
-	.control_write_status = control_write_status,
-
 	.control_write = control_write,
-
-	.control_read_setup = control_read_setup,
-	.control_read_data = control_read_data,
-	.control_read_status = control_read_status,
-
 	.control_read = control_read
 };
