Index: uspace/drv/pciintel/pci.c
===================================================================
--- uspace/drv/pciintel/pci.c	(revision c20da9fe5dbadfe54b414044bd57f1ca9c16729b)
+++ uspace/drv/pciintel/pci.c	(revision 063ead6f8f7011ea1895467b62663e88d0abb573)
@@ -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 c20da9fe5dbadfe54b414044bd57f1ca9c16729b)
+++ uspace/drv/uhci-hcd/batch.c	(revision 063ead6f8f7011ea1895467b62663e88d0abb573)
@@ -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/main.c
===================================================================
--- uspace/drv/uhci-hcd/main.c	(revision c20da9fe5dbadfe54b414044bd57f1ca9c16729b)
+++ uspace/drv/uhci-hcd/main.c	(revision 063ead6f8f7011ea1895467b62663e88d0abb573)
@@ -34,4 +34,6 @@
 #include <driver.h>
 #include <usb_iface.h>
+#include <usb/ddfiface.h>
+#include <device/hw_res.h>
 
 #include <errno.h>
@@ -46,12 +48,5 @@
 #define NAME "uhci-hcd"
 
-static int usb_iface_get_hc_handle(device_t *dev, devman_handle_t *handle)
-{
-	/* This shall be called only for the UHCI itself. */
-	assert(dev->parent == NULL);
-
-	*handle = dev->handle;
-	return EOK;
-}
+static int uhci_add_device(device_t *device);
 
 static int usb_iface_get_address(device_t *dev, devman_handle_t handle,
@@ -75,13 +70,38 @@
 }
 
+
 static usb_iface_t hc_usb_iface = {
-	.get_hc_handle = usb_iface_get_hc_handle,
+	.get_hc_handle = usb_iface_get_hc_handle_hc_impl,
 	.get_address = usb_iface_get_address
 };
-
+/*----------------------------------------------------------------------------*/
 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)
@@ -96,33 +116,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;
 	}
@@ -131,29 +159,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 c20da9fe5dbadfe54b414044bd57f1ca9c16729b)
+++ uspace/drv/uhci-hcd/pci.c	(revision 063ead6f8f7011ea1895467b62663e88d0abb573)
@@ -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 c20da9fe5dbadfe54b414044bd57f1ca9c16729b)
+++ uspace/drv/uhci-hcd/pci.h	(revision 063ead6f8f7011ea1895467b62663e88d0abb573)
@@ -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 c20da9fe5dbadfe54b414044bd57f1ca9c16729b)
+++ uspace/drv/uhci-hcd/transfer_list.c	(revision 063ead6f8f7011ea1895467b62663e88d0abb573)
@@ -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 c20da9fe5dbadfe54b414044bd57f1ca9c16729b)
+++ uspace/drv/uhci-hcd/uhci-hcd.ma	(revision 063ead6f8f7011ea1895467b62663e88d0abb573)
@@ -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 c20da9fe5dbadfe54b414044bd57f1ca9c16729b)
+++ uspace/drv/uhci-hcd/uhci.c	(revision 063ead6f8f7011ea1895467b62663e88d0abb573)
@@ -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 c20da9fe5dbadfe54b414044bd57f1ca9c16729b)
+++ uspace/drv/uhci-hcd/uhci.h	(revision 063ead6f8f7011ea1895467b62663e88d0abb573)
@@ -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
