Index: HelenOS.config
===================================================================
--- HelenOS.config	(revision f3da9b2e921b69b298ae508bcdad240890b6a9f2)
+++ HelenOS.config	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
@@ -554,2 +554,6 @@
 % Polling UHCI & OHCI (no interrupts)
 ! [PLATFORM=ia32|PLATFORM=amd64] CONFIG_USBHC_NO_INTERRUPTS (y/n)
+
+% Run devman in kconsole (not recommended)
+! CONFIG_DEVMAN_EARLY_LAUNCH (n/y)
+
Index: kernel/generic/src/console/console.c
===================================================================
--- kernel/generic/src/console/console.c	(revision f3da9b2e921b69b298ae508bcdad240890b6a9f2)
+++ kernel/generic/src/console/console.c	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
@@ -53,5 +53,14 @@
 #include <str.h>
 
+/*
+ * devman produces a lot of output and by giving so many pages
+ * we to allow /app/klog to catch-up.
+ */
+#ifdef CONFIG_DEVMAN_EARLY_LAUNCH
+#define KLOG_PAGES    64
+#else
 #define KLOG_PAGES    4
+#endif
+
 #define KLOG_LENGTH   (KLOG_PAGES * PAGE_SIZE / sizeof(wchar_t))
 #define KLOG_LATENCY  8
Index: kernel/generic/src/mm/as.c
===================================================================
--- kernel/generic/src/mm/as.c	(revision f3da9b2e921b69b298ae508bcdad240890b6a9f2)
+++ kernel/generic/src/mm/as.c	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
@@ -1949,5 +1949,5 @@
 sysarg_t sys_as_area_create(uintptr_t address, size_t size, unsigned int flags)
 {
-	if (as_area_create(AS, flags | AS_AREA_CACHEABLE, size, address,
+	if (as_area_create(AS, flags, size, address,
 	    AS_AREA_ATTR_NONE, &anon_backend, NULL))
 		return (sysarg_t) address;
Index: uspace/app/init/init.c
===================================================================
--- uspace/app/init/init.c	(revision f3da9b2e921b69b298ae508bcdad240890b6a9f2)
+++ uspace/app/init/init.c	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
@@ -313,6 +313,11 @@
 	getterm("term/vc5", "/app/bdsh", false);
 	getterm("term/vc6", "/app/klog", false);
+
+#ifdef CONFIG_DEVMAN_EARLY_LAUNCH
+	spawn("/srv/devman");
+#else
 	getterm("term/vc7", "/srv/devman", false);
-	
+#endif
+
 	return 0;
 }
Index: uspace/app/klog/klog.c
===================================================================
--- uspace/app/klog/klog.c	(revision f3da9b2e921b69b298ae508bcdad240890b6a9f2)
+++ uspace/app/klog/klog.c	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
@@ -44,4 +44,5 @@
 #include <io/klog.h>
 #include <sysinfo.h>
+#include <fibril_synch.h>
 
 #define NAME       "klog"
@@ -54,6 +55,12 @@
 static FILE *log;
 
+/* Serialize the output a bit. This will not avoid messed-up log completely
+   but chances for are pretty high (experimentally confirmed). */
+static FIBRIL_MUTEX_INITIALIZE(log_mutex);
+
 static void interrupt_received(ipc_callid_t callid, ipc_call_t *call)
 {
+	fibril_mutex_lock(&log_mutex);
+	
 	size_t klog_start = (size_t) IPC_GET_ARG1(*call);
 	size_t klog_len = (size_t) IPC_GET_ARG2(*call);
@@ -74,4 +81,6 @@
 		fsync(fileno(log));
 	}
+	
+	fibril_mutex_unlock(&log_mutex);
 }
 
Index: uspace/drv/ohci/Makefile
===================================================================
--- uspace/drv/ohci/Makefile	(revision f3da9b2e921b69b298ae508bcdad240890b6a9f2)
+++ uspace/drv/ohci/Makefile	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
@@ -37,4 +37,5 @@
 	main.c \
 	hc.c \
+	ohci.c \
 	root_hub.c \
 	pci.c
Index: uspace/drv/ohci/hc.c
===================================================================
--- uspace/drv/ohci/hc.c	(revision f3da9b2e921b69b298ae508bcdad240890b6a9f2)
+++ uspace/drv/ohci/hc.c	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
@@ -39,5 +39,4 @@
 #include <usb/debug.h>
 #include <usb/usb.h>
-#include <usb/hub.h>
 #include <usb/ddfiface.h>
 #include <usb/usbdevice.h>
@@ -45,6 +44,31 @@
 #include "hc.h"
 
-static int dummy_reset(int foo, void *arg);
 static int interrupt_emulator(hc_t *instance);
+/*----------------------------------------------------------------------------*/
+int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun)
+{
+	assert(instance);
+	assert(hub_fun);
+
+	usb_address_t hub_address =
+	    device_keeper_get_free_address(&instance->manager, USB_SPEED_FULL);
+	instance->rh.address = hub_address;
+	usb_device_keeper_bind(
+	    &instance->manager, hub_address, hub_fun->handle);
+
+	char *match_str = NULL;
+	int ret = asprintf(&match_str, "usb&mid");
+	ret = (match_str == NULL) ? ret : EOK;
+	if (ret < 0) {
+		usb_log_error("Failed to create root hub match-id string.\n");
+		return ret;
+	}
+
+	ret = ddf_fun_add_match_id(hub_fun, match_str, 100);
+	if (ret != EOK) {
+		usb_log_error("Failed add create root hub match-id.\n");
+	}
+	return ret;
+}
 /*----------------------------------------------------------------------------*/
 int hc_init(hc_t *instance, ddf_fun_t *fun, ddf_dev_t *dev,
@@ -68,44 +92,7 @@
 	}
 
+	rh_init(&instance->rh, dev, instance->registers);
 
-	rh_init(&instance->rh, dev, instance->registers);
 	/* TODO: implement */
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-int hc_register_hub(hc_t *instance)
-{
-	async_usleep(1000000);
-#define CHECK_RET_RETURN(ret, msg...) \
-	if (ret != EOK) { \
-		usb_log_error(msg); \
-		return ret; \
-	} else (void)0
-	assert(instance);
-	assert(instance->ddf_instance);
-	assert(instance->ddf_instance->handle);
-	ddf_dev_t *dev = instance->rh.device;
-	int ret = EOK;
-
-	usb_hc_connection_t conn;
-	ret =
-	    usb_hc_connection_initialize(&conn, instance->ddf_instance->handle);
-	CHECK_RET_RETURN(ret, "Failed to initialize hc connection.\n");
-
-	ret = usb_hc_connection_open(&conn);
-	CHECK_RET_RETURN(ret, "Failed to open hc connection.\n");
-
-	usb_address_t address;
-	devman_handle_t handle;
-	ret = usb_hc_new_device_wrapper(dev, &conn, USB_SPEED_FULL, dummy_reset,
-	    0, instance, &address, &handle, NULL, NULL, NULL);
-	if (ret != EOK) {
-		usb_log_error("Failed to add rh device.\n");
-		instance->rh.address = -1;
-		return ret;
-	}
-
-	ret = usb_hc_connection_close(&conn);
-	CHECK_RET_RETURN(ret, "Failed to close hc connection.\n");
 	return EOK;
 }
@@ -134,13 +121,5 @@
 }
 /*----------------------------------------------------------------------------*/
-static int dummy_reset(int foo, void *arg)
-{
-	hc_t *hc = (hc_t*)arg;
-	assert(hc);
-	hc->rh.address = 0;
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-static int interrupt_emulator(hc_t *instance)
+int interrupt_emulator(hc_t *instance)
 {
 	assert(instance);
Index: uspace/drv/ohci/hc.h
===================================================================
--- uspace/drv/ohci/hc.h	(revision f3da9b2e921b69b298ae508bcdad240890b6a9f2)
+++ uspace/drv/ohci/hc.h	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
@@ -57,8 +57,8 @@
 } hc_t;
 
+int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun);
+
 int hc_init(hc_t *instance, ddf_fun_t *fun, ddf_dev_t *dev,
      uintptr_t regs, size_t reg_size, bool interrupts);
-
-int hc_register_hub(hc_t *instance);
 
 int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch);
Index: uspace/drv/ohci/iface.h
===================================================================
--- uspace/drv/ohci/iface.h	(revision f3da9b2e921b69b298ae508bcdad240890b6a9f2)
+++ uspace/drv/ohci/iface.h	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
@@ -33,10 +33,8 @@
  * Common OHCI definitions.
  */
-#ifndef DRV_OHCI_OHCI_H
-#define DRV_OHCI_OHCI_H
+#ifndef DRV_OHCI_IFACE_H
+#define DRV_OHCI_IFACE_H
 
 #include <usbhc_iface.h>
-
-#define NAME "ohci"
 
 extern usbhc_iface_t hc_iface;
Index: uspace/drv/ohci/main.c
===================================================================
--- uspace/drv/ohci/main.c	(revision f3da9b2e921b69b298ae508bcdad240890b6a9f2)
+++ uspace/drv/ohci/main.c	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
@@ -34,57 +34,14 @@
  */
 #include <ddf/driver.h>
-#include <ddf/interrupt.h>
-#include <device/hw_res.h>
 #include <errno.h>
 #include <str_error.h>
 
-#include <usb_iface.h>
-#include <usb/ddfiface.h>
 #include <usb/debug.h>
 
-#include "pci.h"
-#include "iface.h"
-#include "hc.h"
+#include "ohci.h"
+
+#define NAME "ohci"
 
 static int ohci_add_device(ddf_dev_t *device);
-static int get_hc_handle(ddf_fun_t *fun, devman_handle_t *handle)
-{
-	assert(handle);
-  assert(fun != NULL);
-
-  *handle = fun->handle;
-  return EOK;
-}
-/*----------------------------------------------------------------------------*/
-static int get_address(
-    ddf_fun_t *fun, devman_handle_t handle, usb_address_t *address)
-{
-	assert(fun);
-	usb_device_keeper_t *manager = &fun_to_hc(fun)->manager;
-  usb_address_t addr = usb_device_keeper_find(manager, handle);
-  if (addr < 0) {
-    return addr;
-  }
-
-  if (address != NULL) {
-    *address = addr;
-  }
-
-  return EOK;
-}
-/*----------------------------------------------------------------------------*/
-/** IRQ handling callback, identifies device
- *
- * @param[in] dev DDF instance of the device to use.
- * @param[in] iid (Unused).
- * @param[in] call Pointer to the call that represents interrupt.
- */
-static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call)
-{
-	assert(dev);
-	hc_t *hc = (hc_t*)dev->driver_data;
-	assert(hc);
-	hc_interrupt(hc, 0);
-}
 /*----------------------------------------------------------------------------*/
 static driver_ops_t ohci_driver_ops = {
@@ -97,14 +54,4 @@
 };
 /*----------------------------------------------------------------------------*/
-static usb_iface_t hc_usb_iface = {
-	.get_address = get_address,
-	.get_hc_handle = get_hc_handle,
-};
-/*----------------------------------------------------------------------------*/
-static ddf_dev_ops_t hc_ops = {
-	.interfaces[USB_DEV_IFACE] = &hc_usb_iface,
-	.interfaces[USBHC_DEV_IFACE] = &hc_iface,
-};
-/*----------------------------------------------------------------------------*/
 /** Initializes a new ddf driver instance of OHCI hcd.
  *
@@ -112,86 +59,25 @@
  * @return Error code.
  */
-static int ohci_add_device(ddf_dev_t *device)
+int ohci_add_device(ddf_dev_t *device)
 {
+	usb_log_debug("ohci_add_device() called\n");
 	assert(device);
-#define CHECK_RET_RETURN(ret, message...) \
-if (ret != EOK) { \
-	usb_log_error(message); \
-	return ret; \
-}
-
-	uintptr_t mem_reg_base = 0;
-	size_t mem_reg_size = 0;
-	int irq = 0;
-
-	int ret =
-	    pci_get_my_registers(device, &mem_reg_base, &mem_reg_size, &irq);
-	CHECK_RET_RETURN(ret,
-	    "Failed(%d) to get memory addresses:.\n", ret, device->handle);
-	usb_log_info("Memory mapped regs at 0x%X (size %zu), IRQ %d.\n",
-	    mem_reg_base, mem_reg_size, irq);
-
-	ret = pci_disable_legacy(device);
-	CHECK_RET_RETURN(ret,
-	    "Failed(%d) disable legacy USB: %s.\n", ret, str_error(ret));
-
-	hc_t *hcd = malloc(sizeof(hc_t));
-	if (hcd == NULL) {
+	ohci_t *ohci = malloc(sizeof(ohci_t));
+	if (ohci == NULL) {
 		usb_log_error("Failed to allocate OHCI driver.\n");
 		return ENOMEM;
 	}
 
-	ddf_fun_t *hc_fun = ddf_fun_create(device, fun_exposed, "ohci-hc");
-	if (hc_fun == NULL) {
-		usb_log_error("Failed to create OHCI function.\n");
-		free(hcd);
-		return ENOMEM;
-	}
-
-
-	bool interrupts = false;
-#ifdef CONFIG_USBHC_NO_INTERRUPTS
-	usb_log_warning("Interrupts disabled in OS config, " \
-	    "falling back to polling.\n");
-#else
-	ret = pci_enable_interrupts(device);
+	int ret = ohci_init(ohci, device);
 	if (ret != EOK) {
-		usb_log_warning("Failed to enable interrupts: %s.\n",
+		usb_log_error("Failed to initialize OHCI driver: %s.\n",
 		    str_error(ret));
-		usb_log_info("HW interrupts not available, " \
-		    "falling back to polling.\n");
-	} else {
-		usb_log_debug("Hw interrupts enabled.\n");
-		interrupts = true;
-	}
-#endif
-
-	ret = hc_init(hcd, hc_fun, device, mem_reg_base, mem_reg_size, interrupts);
-	if (ret != EOK) {
-		usb_log_error("Failed to initialize OHCI driver.\n");
-		free(hcd);
 		return ret;
 	}
+	device->driver_data = ohci;
 
-	ret = register_interrupt_handler(device, irq, irq_handler, NULL);
-
-	hc_fun->ops = &hc_ops;
-	ret = ddf_fun_bind(hc_fun);
-	if (ret != EOK) {
-		usb_log_error("Failed to bind OHCI function.\n");
-		ddf_fun_destroy(hc_fun);
-		free(hcd);
-		return ret;
-	}
-	hc_fun->driver_data = hcd;
-
-	fid_t later = fibril_create((int(*)(void*))hc_register_hub, hcd);
-	fibril_add_ready(later);
-
-	usb_log_info("Controlling new OHCI device `%s' (handle %llu).\n",
-	    device->name, device->handle);
+	usb_log_info("Controlling new OHCI device `%s'.\n", device->name);
 
 	return EOK;
-#undef CHECK_RET_RETURN
 }
 /*----------------------------------------------------------------------------*/
Index: uspace/drv/ohci/ohci.c
===================================================================
--- uspace/drv/ohci/ohci.c	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
+++ uspace/drv/ohci/ohci.c	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup drvusbohci
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#include <errno.h>
+#include <str_error.h>
+#include <ddf/interrupt.h>
+#include <usb_iface.h>
+#include <usb/usb.h>
+#include <usb/ddfiface.h>
+#include <usb/debug.h>
+
+#include "ohci.h"
+#include "iface.h"
+#include "pci.h"
+
+/** IRQ handling callback, identifies device
+ *
+ * @param[in] dev DDF instance of the device to use.
+ * @param[in] iid (Unused).
+ * @param[in] call Pointer to the call that represents interrupt.
+ */
+static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call)
+{
+	assert(dev);
+	hc_t *hc = &((ohci_t*)dev->driver_data)->hc;
+	uint16_t status = IPC_GET_ARG1(*call);
+	assert(hc);
+	hc_interrupt(hc, status);
+}
+/*----------------------------------------------------------------------------*/
+/** Get address of the device identified by handle.
+ *
+ * @param[in] dev DDF instance of the device to use.
+ * @param[in] iid (Unused).
+ * @param[in] call Pointer to the call that represents interrupt.
+ */
+static int usb_iface_get_address(
+    ddf_fun_t *fun, devman_handle_t handle, usb_address_t *address)
+{
+	assert(fun);
+	usb_device_keeper_t *manager = &((ohci_t*)fun->dev->driver_data)->hc.manager;
+
+	usb_address_t addr = usb_device_keeper_find(manager, handle);
+	if (addr < 0) {
+		return addr;
+	}
+
+	if (address != NULL) {
+		*address = addr;
+	}
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Gets handle of the respective hc (this device, hc function).
+ *
+ * @param[in] root_hub_fun Root hub function seeking hc handle.
+ * @param[out] handle Place to write the handle.
+ * @return Error code.
+ */
+static int usb_iface_get_hc_handle(
+    ddf_fun_t *fun, devman_handle_t *handle)
+{
+	assert(handle);
+	ddf_fun_t *hc_fun = ((ohci_t*)fun->dev->driver_data)->hc_fun;
+	assert(hc_fun != NULL);
+
+	*handle = hc_fun->handle;
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** This iface is generic for both RH and HC. */
+static usb_iface_t usb_iface = {
+	.get_hc_handle = usb_iface_get_hc_handle,
+	.get_address = usb_iface_get_address
+};
+/*----------------------------------------------------------------------------*/
+static ddf_dev_ops_t hc_ops = {
+	.interfaces[USBHC_DEV_IFACE] = &hc_iface, /* see iface.h/c */
+};
+/*----------------------------------------------------------------------------*/
+static ddf_dev_ops_t rh_ops = {
+	.interfaces[USB_DEV_IFACE] = &usb_iface,
+};
+/*----------------------------------------------------------------------------*/
+/** Initialize hc and rh ddf structures and their respective drivers.
+ *
+ * @param[in] instance UHCI structure to use.
+ * @param[in] device DDF instance of the device to use.
+ *
+ * This function does all the preparatory work for hc and rh drivers:
+ *  - gets device hw resources
+ *  - disables UHCI legacy support
+ *  - asks for interrupt
+ *  - registers interrupt handler
+ */
+int ohci_init(ohci_t *instance, ddf_dev_t *device)
+{
+	assert(instance);
+	instance->hc_fun = NULL;
+	instance->rh_fun = NULL;
+#define CHECK_RET_DEST_FUN_RETURN(ret, message...) \
+if (ret != EOK) { \
+	usb_log_error(message); \
+	if (instance->hc_fun) \
+		ddf_fun_destroy(instance->hc_fun); \
+	if (instance->rh_fun) \
+		ddf_fun_destroy(instance->rh_fun); \
+	return ret; \
+}
+
+	uintptr_t mem_reg_base = 0;
+	size_t mem_reg_size = 0;
+	int irq = 0;
+
+	int ret =
+	    pci_get_my_registers(device, &mem_reg_base, &mem_reg_size, &irq);
+	CHECK_RET_DEST_FUN_RETURN(ret,
+	    "Failed(%d) to get memory addresses:.\n", ret, device->handle);
+	usb_log_debug("Memory mapped regs at 0x%X (size %zu), IRQ %d.\n",
+	    mem_reg_base, mem_reg_size, irq);
+
+	ret = pci_disable_legacy(device);
+	CHECK_RET_DEST_FUN_RETURN(ret,
+	    "Failed(%d) to disable legacy USB: %s.\n", ret, str_error(ret));
+
+	bool interrupts = false;
+#ifdef CONFIG_USBHC_NO_INTERRUPTS
+	usb_log_warning("Interrupts disabled in OS config, " \
+	    "falling back to polling.\n");
+#else
+	ret = pci_enable_interrupts(device);
+	if (ret != EOK) {
+		usb_log_warning("Failed to enable interrupts: %s.\n",
+		    str_error(ret));
+		usb_log_info("HW interrupts not available, " \
+		    "falling back to polling.\n");
+	} else {
+		usb_log_debug("Hw interrupts enabled.\n");
+		interrupts = true;
+	}
+#endif
+
+	instance->hc_fun = ddf_fun_create(device, fun_exposed, "ohci-hc");
+	ret = (instance->hc_fun == NULL) ? ENOMEM : EOK;
+	CHECK_RET_DEST_FUN_RETURN(ret,
+	    "Failed(%d) to create HC function.\n", ret);
+
+	ret = hc_init(&instance->hc, instance->hc_fun, device,
+	    mem_reg_base, mem_reg_size, interrupts);
+	CHECK_RET_DEST_FUN_RETURN(ret, "Failed(%d) to init ohci-hcd.\n", ret);
+	instance->hc_fun->ops = &hc_ops;
+	instance->hc_fun->driver_data = &instance->hc;
+	ret = ddf_fun_bind(instance->hc_fun);
+	CHECK_RET_DEST_FUN_RETURN(ret,
+	    "Failed(%d) to bind UHCI device function: %s.\n",
+	    ret, str_error(ret));
+#undef CHECK_RET_HC_RETURN
+
+#define CHECK_RET_FINI_RETURN(ret, message...) \
+if (ret != EOK) { \
+	usb_log_error(message); \
+	if (instance->hc_fun) \
+		ddf_fun_destroy(instance->hc_fun); \
+	if (instance->rh_fun) \
+		ddf_fun_destroy(instance->rh_fun); \
+	hc_fini(&instance->hc); \
+	return ret; \
+}
+
+	/* It does no harm if we register this on polling */
+	ret = register_interrupt_handler(device, irq, irq_handler, NULL);
+	CHECK_RET_FINI_RETURN(ret,
+	    "Failed(%d) to register interrupt handler.\n", ret);
+
+	instance->rh_fun = ddf_fun_create(device, fun_inner, "ohci-rh");
+	ret = (instance->rh_fun == NULL) ? ENOMEM : EOK;
+	CHECK_RET_FINI_RETURN(ret,
+	    "Failed(%d) to create root hub function.\n", ret);
+
+	hc_register_hub(&instance->hc, instance->rh_fun);
+
+	instance->rh_fun->ops = &rh_ops;
+	instance->rh_fun->driver_data = NULL;
+	ret = ddf_fun_bind(instance->rh_fun);
+	CHECK_RET_FINI_RETURN(ret,
+	    "Failed(%d) to register UHCI root hub.\n", ret);
+
+	return EOK;
+#undef CHECK_RET_FINI_RETURN
+}
+/**
+ * @}
+ */
Index: uspace/drv/ohci/ohci.h
===================================================================
--- uspace/drv/ohci/ohci.h	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
+++ uspace/drv/ohci/ohci.h	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver main structure for both host controller and root-hub.
+ */
+#ifndef DRV_OHCI_OHCI_H
+#define DRV_OHCI_OHCI_H
+#include <ddi.h>
+#include <ddf/driver.h>
+
+#include "hc.h"
+#include "root_hub.h"
+
+typedef struct ohci {
+	ddf_fun_t *hc_fun;
+	ddf_fun_t *rh_fun;
+
+	hc_t hc;
+	rh_t rh;
+} ohci_t;
+
+int ohci_init(ohci_t *instance, ddf_dev_t *device);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/ohci/root_hub.c
===================================================================
--- uspace/drv/ohci/root_hub.c	(revision f3da9b2e921b69b298ae508bcdad240890b6a9f2)
+++ uspace/drv/ohci/root_hub.c	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
@@ -43,4 +43,57 @@
 #include <usb/classes/hub.h>
 
+static const usb_standard_device_descriptor_t ohci_rh_device_descriptor =
+{
+		.configuration_count = 1,
+		.descriptor_type = USB_DESCTYPE_DEVICE,
+		.device_class = USB_CLASS_HUB,
+		.device_protocol = 0,
+		.device_subclass = 0,
+		.device_version = 0,
+		.length = sizeof(usb_standard_device_descriptor_t),
+		/// \TODO this value is guessed
+		.max_packet_size = 8,
+		.vendor_id = 0x16db,
+		.product_id = 0x0001,
+		/// \TODO these values migt be different
+		.str_serial_number = 0,
+		.usb_spec_version = 0,
+};
+
+static const usb_standard_configuration_descriptor_t ohci_rh_conf_descriptor =
+{
+	/// \TODO some values are default or guessed
+	.attributes = 1<<7,
+	.configuration_number = 1,
+	.descriptor_type = USB_DESCTYPE_CONFIGURATION,
+	.interface_count = 1,
+	.length = sizeof(usb_standard_configuration_descriptor_t),
+	.max_power = 100,
+	.str_configuration = 0,
+};
+
+static const usb_standard_interface_descriptor_t ohci_rh_iface_descriptor =
+{
+	.alternate_setting = 0,
+	.descriptor_type = USB_DESCTYPE_INTERFACE,
+	.endpoint_count = 1,
+	.interface_class = USB_CLASS_HUB,
+	/// \TODO is this correct?
+	.interface_number = 1,
+	.interface_protocol = 0,
+	.interface_subclass = 0,
+	.length = sizeof(usb_standard_interface_descriptor_t),
+	.str_interface = 0,
+};
+
+static const usb_standard_endpoint_descriptor_t ohci_rh_ep_descriptor =
+{
+	.attributes = USB_TRANSFER_INTERRUPT,
+	.descriptor_type = USB_DESCTYPE_ENDPOINT,
+	.endpoint_address = 1 + (1<<7),
+	.length = sizeof(usb_standard_endpoint_descriptor_t),
+	.max_packet_size = 8,
+	.poll_interval = 255,
+};
 
 /** Root hub initialization
@@ -330,7 +383,70 @@
 			(usb_device_request_setup_packet_t*)request->setup_buffer;
 	size_t size;
-	void * result_descriptor;
-	uint16_t setup_request_value = setup_request->value_high;
+	const void * result_descriptor = NULL;
+	const uint16_t setup_request_value = setup_request->value_high;
 			//(setup_request->value_low << 8);
+#if 0
+	bool del = false;
+	//this code was merged from development and has to be reviewed
+	switch (setup_request_value)
+	{
+	case USB_DESCTYPE_HUB: {
+		uint8_t * descriptor;
+		usb_create_serialized_hub_descriptor(
+		    instance, &descriptor, &size);
+		result_descriptor = descriptor;
+		break;
+	}
+	case USB_DESCTYPE_DEVICE: {
+		usb_log_debug("USB_DESCTYPE_DEVICE\n");
+		result_descriptor = &ohci_rh_device_descriptor;
+		size = sizeof(ohci_rh_device_descriptor);
+		break;
+	}
+	case USB_DESCTYPE_CONFIGURATION: {
+		usb_log_debug("USB_DESCTYPE_CONFIGURATION\n");
+		usb_standard_configuration_descriptor_t * descriptor =
+				malloc(sizeof(usb_standard_configuration_descriptor_t));
+		memcpy(descriptor, &ohci_rh_conf_descriptor,
+		    sizeof(usb_standard_configuration_descriptor_t));
+		/// \TODO should this include device descriptor?
+		const size_t hub_descriptor_size = 7 +
+				2* (instance->port_count / 8 +
+				((instance->port_count % 8 > 0) ? 1 : 0));
+		descriptor->total_length =
+				sizeof(usb_standard_configuration_descriptor_t)+
+				sizeof(usb_standard_endpoint_descriptor_t)+
+				sizeof(usb_standard_interface_descriptor_t)+
+				hub_descriptor_size;
+		result_descriptor = descriptor;
+		size = sizeof(usb_standard_configuration_descriptor_t);
+		del = true;
+		break;
+	}
+	case USB_DESCTYPE_INTERFACE: {
+		usb_log_debug("USB_DESCTYPE_INTERFACE\n");
+		result_descriptor = &ohci_rh_iface_descriptor;
+		size = sizeof(ohci_rh_iface_descriptor);
+		break;
+	}
+	case USB_DESCTYPE_ENDPOINT: {
+		usb_log_debug("USB_DESCTYPE_ENDPOINT\n");
+		result_descriptor = &ohci_rh_ep_descriptor;
+		size = sizeof(ohci_rh_ep_descriptor);
+		break;
+	}
+	default: {
+		usb_log_debug("USB_DESCTYPE_EINVAL %d \n",setup_request->value);
+		usb_log_debug("\ttype %d\n\trequest %d\n\tvalue %d\n\tindex %d\n\tlen %d\n ",
+				setup_request->request_type,
+				setup_request->request,
+				setup_request_value,
+				setup_request->index,
+				setup_request->length
+				);
+		return EINVAL;
+	}
+	}
+#endif
 	if(setup_request_value == USB_DESCTYPE_HUB){
 		usb_log_debug("USB_DESCTYPE_HUB\n");
@@ -378,5 +494,6 @@
 	request->transfered_size = size;
 	memcpy(request->buffer,result_descriptor,size);
-	free(result_descriptor);
+	if (result_descriptor)
+		free(result_descriptor);
 	return EOK;
 }
Index: uspace/drv/uhci-hcd/Makefile
===================================================================
--- uspace/drv/uhci-hcd/Makefile	(revision f3da9b2e921b69b298ae508bcdad240890b6a9f2)
+++ uspace/drv/uhci-hcd/Makefile	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
@@ -40,4 +40,5 @@
 	root_hub.c \
 	hw_struct/transfer_descriptor.c \
+	utils/slab.c \
 	pci.c \
 	batch.c
Index: uspace/drv/uhci-hcd/hc.c
===================================================================
--- uspace/drv/uhci-hcd/hc.c	(revision f3da9b2e921b69b298ae508bcdad240890b6a9f2)
+++ uspace/drv/uhci-hcd/hc.c	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
@@ -223,5 +223,5 @@
 	ret = instance ? EOK : ENOMEM;
 	CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to get frame list page.\n");
-	usb_log_debug("Initialized frame list.\n");
+	usb_log_debug("Initialized frame list at %p.\n", instance->frame_list);
 
 	/* Set all frames to point to the first queue head */
@@ -336,4 +336,8 @@
 	    instance->transfers[batch->speed][batch->transfer_type];
 	assert(list);
+	if (batch->transfer_type == USB_TRANSFER_CONTROL) {
+		usb_device_keeper_use_control(
+		    &instance->manager, batch->target.address);
+	}
 	transfer_list_add_batch(list, batch);
 
@@ -357,8 +361,25 @@
 	/* Lower 2 bits are transaction error and transaction complete */
 	if (status & 0x3) {
-		transfer_list_remove_finished(&instance->transfers_interrupt);
-		transfer_list_remove_finished(&instance->transfers_control_slow);
-		transfer_list_remove_finished(&instance->transfers_control_full);
-		transfer_list_remove_finished(&instance->transfers_bulk_full);
+		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 = done.next;
+			list_remove(item);
+			usb_transfer_batch_t *batch =
+			    list_get_instance(item, usb_transfer_batch_t, link);
+			if (batch->transfer_type == USB_TRANSFER_CONTROL) {
+				usb_device_keeper_release_control(
+				    &instance->manager, batch->target.address);
+			}
+			batch->next_step(batch);
+		}
 	}
 	/* bits 4 and 5 indicate hc error */
Index: uspace/drv/uhci-hcd/root_hub.c
===================================================================
--- uspace/drv/uhci-hcd/root_hub.c	(revision f3da9b2e921b69b298ae508bcdad240890b6a9f2)
+++ uspace/drv/uhci-hcd/root_hub.c	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
@@ -48,6 +48,5 @@
  * @return Error code.
  */
-int rh_init(
-    rh_t *instance, ddf_fun_t *fun, uintptr_t reg_addr, size_t reg_size)
+int rh_init(rh_t *instance, ddf_fun_t *fun, uintptr_t reg_addr, size_t reg_size)
 {
 	assert(fun);
Index: uspace/drv/uhci-hcd/transfer_list.c
===================================================================
--- uspace/drv/uhci-hcd/transfer_list.c	(revision f3da9b2e921b69b298ae508bcdad240890b6a9f2)
+++ uspace/drv/uhci-hcd/transfer_list.c	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
@@ -58,4 +58,6 @@
 	}
 	instance->queue_head_pa = addr_to_phys(instance->queue_head);
+	usb_log_debug2("Transfer list %s setup with QH: %p(%p).\n",
+	    name, instance->queue_head, instance->queue_head_pa);
 
 	qh_init(instance->queue_head);
@@ -118,4 +120,6 @@
 	qh_set_next_qh(last_qh, pa);
 
+	asm volatile ("": : :"memory");
+
 	/* Add to the driver list */
 	list_append(&batch->link, &instance->batch_list);
@@ -137,9 +141,8 @@
  * this transfer list leading to the deadlock if its done inline.
  */
-void transfer_list_remove_finished(transfer_list_t *instance)
-{
-	assert(instance);
-
-	LIST_INITIALIZE(done);
+void transfer_list_remove_finished(transfer_list_t *instance, link_t *done)
+{
+	assert(instance);
+	assert(done);
 
 	fibril_mutex_lock(&instance->guard);
@@ -153,5 +156,5 @@
 			/* Save for post-processing */
 			transfer_list_remove_batch(instance, batch);
-			list_append(current, &done);
+			list_append(current, done);
 		}
 		current = next;
@@ -159,11 +162,4 @@
 	fibril_mutex_unlock(&instance->guard);
 
-	while (!list_empty(&done)) {
-		link_t *item = done.next;
-		list_remove(item);
-		usb_transfer_batch_t *batch =
-		    list_get_instance(item, usb_transfer_batch_t, link);
-		batch->next_step(batch);
-	}
 }
 /*----------------------------------------------------------------------------*/
@@ -222,4 +218,5 @@
 		qpos = "NOT FIRST";
 	}
+	asm volatile ("": : :"memory");
 	/* Remove from the batch list */
 	list_remove(&batch->link);
Index: uspace/drv/uhci-hcd/transfer_list.h
===================================================================
--- uspace/drv/uhci-hcd/transfer_list.h	(revision f3da9b2e921b69b298ae508bcdad240890b6a9f2)
+++ uspace/drv/uhci-hcd/transfer_list.h	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
@@ -67,5 +67,5 @@
 void transfer_list_add_batch(transfer_list_t *instance, usb_transfer_batch_t *batch);
 
-void transfer_list_remove_finished(transfer_list_t *instance);
+void transfer_list_remove_finished(transfer_list_t *instance, link_t *done);
 
 void transfer_list_abort_all(transfer_list_t *instance);
Index: uspace/drv/uhci-hcd/uhci.c
===================================================================
--- uspace/drv/uhci-hcd/uhci.c	(revision f3da9b2e921b69b298ae508bcdad240890b6a9f2)
+++ uspace/drv/uhci-hcd/uhci.c	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
@@ -44,5 +44,4 @@
 #include "pci.h"
 
-
 /** IRQ handling callback, identifies device
  *
@@ -108,5 +107,5 @@
 /*----------------------------------------------------------------------------*/
 static ddf_dev_ops_t hc_ops = {
-	.interfaces[USB_DEV_IFACE] = &usb_iface,
+//	.interfaces[USB_DEV_IFACE] = &usb_iface,
 	.interfaces[USBHC_DEV_IFACE] = &hc_iface, /* see iface.h/c */
 };
Index: uspace/drv/uhci-hcd/utils/malloc32.h
===================================================================
--- uspace/drv/uhci-hcd/utils/malloc32.h	(revision f3da9b2e921b69b298ae508bcdad240890b6a9f2)
+++ uspace/drv/uhci-hcd/utils/malloc32.h	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
@@ -40,6 +40,9 @@
 #include <as.h>
 
+#include "slab.h"
+
 #define UHCI_STRCUTURES_ALIGNMENT 16
 #define UHCI_REQUIRED_PAGE_SIZE 4096
+
 
 /** Get physical address translation
@@ -54,5 +57,6 @@
 
 	uintptr_t result;
-	int ret = as_get_physical_mapping(addr, &result);
+	const int ret = as_get_physical_mapping(addr, &result);
+	assert(ret == EOK);
 
 	if (ret != EOK)
@@ -66,6 +70,10 @@
  * @return Address of the alligned and big enough memory place, NULL on failure.
  */
-static inline void * malloc32(size_t size)
-	{ return memalign(UHCI_STRCUTURES_ALIGNMENT, size); }
+static inline void * malloc32(size_t size) {
+	if (size <= SLAB_ELEMENT_SIZE)
+		return slab_malloc_g();
+	assert(false);
+	return memalign(UHCI_STRCUTURES_ALIGNMENT, size);
+}
 /*----------------------------------------------------------------------------*/
 /** Physical mallocator simulator
@@ -73,6 +81,11 @@
  * @param[in] addr Address of the place allocated by malloc32
  */
-static inline void free32(void *addr)
-	{ if (addr) free(addr); }
+static inline void free32(void *addr) {
+	if (!addr)
+		return;
+	if (slab_in_range_g(addr))
+		return slab_free_g(addr);
+	free(addr);
+}
 /*----------------------------------------------------------------------------*/
 /** Create 4KB page mapping
@@ -82,10 +95,9 @@
 static inline void * get_page(void)
 {
-	void * free_address = as_get_mappable_page(UHCI_REQUIRED_PAGE_SIZE);
-	assert(free_address);
+	void *free_address = as_get_mappable_page(UHCI_REQUIRED_PAGE_SIZE);
+	assert(free_address); /* TODO: remove this assert */
 	if (free_address == 0)
 		return NULL;
-	void* ret =
-	  as_area_create(free_address, UHCI_REQUIRED_PAGE_SIZE,
+	void *ret = as_area_create(free_address, UHCI_REQUIRED_PAGE_SIZE,
 		  AS_AREA_READ | AS_AREA_WRITE);
 	if (ret != free_address)
Index: uspace/drv/uhci-hcd/utils/slab.c
===================================================================
--- uspace/drv/uhci-hcd/utils/slab.c	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
+++ uspace/drv/uhci-hcd/utils/slab.c	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup usb
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#include <as.h>
+#include <assert.h>
+#include <fibril_synch.h>
+#include <usb/debug.h>
+
+#include "slab.h"
+
+#define SLAB_SIZE (PAGE_SIZE * 16)
+#define SLAB_ELEMENT_COUNT (SLAB_SIZE / SLAB_ELEMENT_SIZE)
+
+typedef struct slab {
+	void *page;
+	bool slabs[SLAB_ELEMENT_COUNT];
+	fibril_mutex_t guard;
+} slab_t;
+
+static slab_t global_slab;
+
+static void * slab_malloc(slab_t *intance);
+static bool slab_in_range(slab_t *intance, void *addr);
+static void slab_free(slab_t *intance, void *addr);
+/*----------------------------------------------------------------------------*/
+void * slab_malloc_g(void)
+{
+	return slab_malloc(&global_slab);
+}
+/*----------------------------------------------------------------------------*/
+void slab_free_g(void *addr)
+{
+	return slab_free(&global_slab, addr);
+}
+/*----------------------------------------------------------------------------*/
+bool slab_in_range_g(void *addr)
+{
+	return slab_in_range(&global_slab, addr);
+}
+/*----------------------------------------------------------------------------*/
+static void slab_init(slab_t *instance)
+{
+	static FIBRIL_MUTEX_INITIALIZE(init_mutex);
+	assert(instance);
+	fibril_mutex_lock(&init_mutex);
+	if (instance->page != NULL) {
+		/* already initialized */
+		fibril_mutex_unlock(&init_mutex);
+		return;
+	}
+	fibril_mutex_initialize(&instance->guard);
+	size_t i = 0;
+	for (;i < SLAB_ELEMENT_COUNT; ++i) {
+		instance->slabs[i] = true;
+	}
+	instance->page = as_get_mappable_page(SLAB_SIZE);
+	if (instance->page != NULL) {
+		void* ret =
+		    as_area_create(instance->page, SLAB_SIZE, AS_AREA_READ | AS_AREA_WRITE);
+		if (ret != instance->page) {
+			instance->page = NULL;
+		}
+	}
+	memset(instance->page, 0xa, SLAB_SIZE);
+	fibril_mutex_unlock(&init_mutex);
+	usb_log_debug2("SLAB initialized at %p.\n", instance->page);
+}
+/*----------------------------------------------------------------------------*/
+static void * slab_malloc(slab_t *instance) {
+	assert(instance);
+	if (instance->page == NULL)
+		slab_init(instance);
+
+	fibril_mutex_lock(&instance->guard);
+	void *addr = NULL;
+	size_t i = 0;
+	for (; i < SLAB_ELEMENT_COUNT; ++i) {
+		if (instance->slabs[i]) {
+			instance->slabs[i] = false;
+			addr = (instance->page + (i * SLAB_ELEMENT_SIZE));
+			break;
+		}
+	}
+	fibril_mutex_unlock(&instance->guard);
+
+	return addr;
+}
+/*----------------------------------------------------------------------------*/
+static bool slab_in_range(slab_t *instance, void *addr) {
+	assert(instance);
+	bool in_range = (instance->page != NULL) &&
+		(addr >= instance->page) && (addr < instance->page + SLAB_SIZE);
+	return in_range;
+}
+/*----------------------------------------------------------------------------*/
+static void slab_free(slab_t *instance, void *addr)
+{
+	assert(instance);
+	assert(slab_in_range(instance, addr));
+	memset(addr, 0xa, SLAB_ELEMENT_SIZE);
+
+	const size_t pos = (addr - instance->page) /  SLAB_ELEMENT_SIZE;
+
+	fibril_mutex_lock(&instance->guard);
+	assert(instance->slabs[pos] == false);
+	instance->slabs[pos] = true;
+	fibril_mutex_unlock(&instance->guard);
+}
+/**
+ * @}
+ */
Index: uspace/drv/uhci-hcd/utils/slab.h
===================================================================
--- uspace/drv/uhci-hcd/utils/slab.h	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
+++ uspace/drv/uhci-hcd/utils/slab.h	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup usb
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#ifndef DRV_UHCI_SLAB_H
+#define DRV_UHCI_SLAB_H
+
+#include <bool.h>
+
+#define SLAB_ELEMENT_SIZE 1024
+
+void * slab_malloc_g(void);
+
+void slab_free_g(void *addr);
+
+bool slab_in_range_g(void *addr);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/usbmid/explore.c
===================================================================
--- uspace/drv/usbmid/explore.c	(revision f3da9b2e921b69b298ae508bcdad240890b6a9f2)
+++ uspace/drv/usbmid/explore.c	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
@@ -40,5 +40,11 @@
 #include <usb/request.h>
 #include <usb/dp.h>
+#include <usb/ddfiface.h>
 #include "usbmid.h"
+
+/** Operations of the device itself. */
+static ddf_dev_ops_t mid_device_ops = {
+	.interfaces[USB_DEV_IFACE] = &usb_iface_hub_impl
+};
 
 /** Find starting indexes of all interface descriptors in a configuration.
@@ -105,37 +111,22 @@
  * @return Whether to accept this device from devman.
  */
-bool usbmid_explore_device(usbmid_device_t *dev)
+bool usbmid_explore_device(usb_device_t *dev)
 {
-	usb_standard_device_descriptor_t device_descriptor;
-	int rc = usb_request_get_device_descriptor(&dev->ctrl_pipe,
-	    &device_descriptor);
-	if (rc != EOK) {
-		usb_log_error("Getting device descriptor failed: %s.\n",
-		    str_error(rc));
-		return false;
-	}
-
-	if (device_descriptor.device_class != USB_CLASS_USE_INTERFACE) {
+	int rc;
+
+	int dev_class = dev->descriptors.device.device_class;
+	if (dev_class != USB_CLASS_USE_INTERFACE) {
 		usb_log_warning(
 		    "Device class: %d (%s), but expected class 0.\n",
-		    device_descriptor.device_class,
-		    usb_str_class(device_descriptor.device_class));
+		    dev_class, usb_str_class(dev_class));
 		usb_log_error("Not multi interface device, refusing.\n");
 		return false;
 	}
 
-	size_t config_descriptor_size;
-	uint8_t *config_descriptor_raw = NULL;
-	rc = usb_request_get_full_configuration_descriptor_alloc(
-	    &dev->ctrl_pipe, 0,
-	    (void **) &config_descriptor_raw, &config_descriptor_size);
-	if (rc != EOK) {
-		usb_log_error("Failed getting full config descriptor: %s.\n",
-		    str_error(rc));
-		return false;
-	}
-
-	usb_standard_configuration_descriptor_t *config_descriptor
-	    = (usb_standard_configuration_descriptor_t *) config_descriptor_raw;
+	/* Short cuts to save on typing ;-). */
+	uint8_t *config_descriptor_raw = dev->descriptors.configuration;
+	size_t config_descriptor_size = dev->descriptors.configuration_size;
+	usb_standard_configuration_descriptor_t *config_descriptor =
+	    (usb_standard_configuration_descriptor_t *) config_descriptor_raw;
 
 	size_t *interface_descriptors
@@ -154,5 +145,4 @@
 	if (interface_descriptors_count == (size_t) -1) {
 		usb_log_error("Problem parsing configuration descriptor.\n");
-		free(config_descriptor_raw);
 		free(interface_descriptors);
 		return false;
@@ -165,5 +155,4 @@
 		usb_log_error("Failed to set device configuration: %s.\n",
 		    str_error(rc));
-		free(config_descriptor_raw);
 		free(interface_descriptors);
 		return false;
@@ -172,16 +161,17 @@
 
 	/* Create control function */
-	ddf_fun_t *ctl_fun = ddf_fun_create(dev->dev, fun_exposed, "ctl");
+	ddf_fun_t *ctl_fun = ddf_fun_create(dev->ddf_dev, fun_exposed, "ctl");
 	if (ctl_fun == NULL) {
 		usb_log_error("Failed to create control function.\n");
-		free(config_descriptor_raw);
-		free(interface_descriptors);
-		return false;
-	}
+		free(interface_descriptors);
+		return false;
+	}
+
+	ctl_fun->ops = &mid_device_ops;
+
 	rc = ddf_fun_bind(ctl_fun);
 	if (rc != EOK) {
 		usb_log_error("Failed to bind control function: %s.\n",
 		    str_error(rc));
-		free(config_descriptor_raw);
 		free(interface_descriptors);
 		return false;
@@ -199,5 +189,5 @@
 		    (int) interface->interface_number,
 		    usb_str_class(interface->interface_class));
-		rc = usbmid_spawn_interface_child(dev, &device_descriptor,
+		rc = usbmid_spawn_interface_child(dev, &dev->descriptors.device,
 		    interface);
 		if (rc != EOK) {
@@ -207,6 +197,4 @@
 	}
 
-	free(config_descriptor_raw);
-
 	return true;
 }
Index: uspace/drv/usbmid/main.c
===================================================================
--- uspace/drv/usbmid/main.c	(revision f3da9b2e921b69b298ae508bcdad240890b6a9f2)
+++ uspace/drv/usbmid/main.c	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
@@ -49,13 +49,7 @@
  * @return Error code.
  */
-static int usbmid_add_device(ddf_dev_t *gen_dev)
+static int usbmid_add_device(usb_device_t *dev)
 {
-	usbmid_device_t *dev = usbmid_device_create(gen_dev);
-	if (dev == NULL) {
-		return ENOMEM;
-	}
-
-	usb_log_info("Taking care of new MID: addr %d (HC %zu)\n",
-	    dev->wire.address, dev->wire.hc_handle);
+	usb_log_info("Taking care of new MID `%s'.\n", dev->ddf_dev->name);
 
 	int rc;
@@ -65,5 +59,5 @@
 		usb_log_error("Failed to start session on control pipe: %s.\n",
 		    str_error(rc));
-		goto error_leave;
+		return rc;
 	}
 
@@ -77,27 +71,20 @@
 
 	if (!accept) {
-		rc = ENOTSUP;
-		goto error_leave;
+		return ENOTSUP;
 	}
 
-	gen_dev->driver_data = dev;
-
 	return EOK;
-
-
-error_leave:
-	free(dev);
-	return rc;
 }
 
 /** USB MID driver ops. */
-static driver_ops_t mid_driver_ops = {
+static usb_driver_ops_t mid_driver_ops = {
 	.add_device = usbmid_add_device,
 };
 
 /** USB MID driver. */
-static driver_t mid_driver = {
+static usb_driver_t mid_driver = {
 	.name = NAME,
-	.driver_ops = &mid_driver_ops
+	.ops = &mid_driver_ops,
+	.endpoints = NULL
 };
 
@@ -107,5 +94,6 @@
 
 	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
-	return ddf_driver_main(&mid_driver);
+
+	return usb_driver_main(&mid_driver);
 }
 
Index: uspace/drv/usbmid/usbmid.c
===================================================================
--- uspace/drv/usbmid/usbmid.c	(revision f3da9b2e921b69b298ae508bcdad240890b6a9f2)
+++ uspace/drv/usbmid/usbmid.c	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
@@ -79,55 +79,4 @@
 };
 
-/** Operations of the device itself. */
-static ddf_dev_ops_t mid_device_ops = {
-	.interfaces[USB_DEV_IFACE] = &usb_iface_hub_impl
-};
-
-/** Create new USB multi interface device.
- *
- * @param dev Backing generic DDF device.
- * @return New USB MID device.
- * @retval NULL Error occured.
- */
-usbmid_device_t *usbmid_device_create(ddf_dev_t *dev)
-{
-	usbmid_device_t *mid = malloc(sizeof(usbmid_device_t));
-	if (mid == NULL) {
-		usb_log_error("Out of memory (wanted %zu bytes).\n",
-		    sizeof(usbmid_device_t));
-		return NULL;
-	}
-
-	int rc;
-	rc = usb_device_connection_initialize_from_device(&mid->wire, dev);
-	if (rc != EOK) {
-		usb_log_error("Failed to initialize `USB wire': %s.\n",
-		    str_error(rc));
-		free(mid);
-		return NULL;
-	}
-
-	rc = usb_pipe_initialize_default_control(&mid->ctrl_pipe,
-	    &mid->wire);
-	if (rc != EOK) {
-		usb_log_error("Failed to initialize control pipe: %s.\n",
-		    str_error(rc));
-		free(mid);
-		return NULL;
-	}
-	rc = usb_pipe_probe_default_control(&mid->ctrl_pipe);
-	if (rc != EOK) {
-		usb_log_error("Probing default control pipe failed: %s.\n",
-		    str_error(rc));
-		free(mid);
-		return NULL;
-	}
-
-	mid->dev = dev;
-	(void) &mid_device_ops;
-
-	return mid;
-}
-
 /** Create new interface for USB MID device.
  *
@@ -160,5 +109,5 @@
  * @return Error code.
  */
-int usbmid_spawn_interface_child(usbmid_device_t *parent,
+int usbmid_spawn_interface_child(usb_device_t *parent,
     const usb_standard_device_descriptor_t *device_descriptor,
     const usb_standard_interface_descriptor_t *interface_descriptor)
@@ -182,5 +131,5 @@
 
 	/* Create the device. */
-	child = ddf_fun_create(parent->dev, fun_inner, child_name);
+	child = ddf_fun_create(parent->ddf_dev, fun_inner, child_name);
 	if (child == NULL) {
 		rc = ENOMEM;
Index: uspace/drv/usbmid/usbmid.h
===================================================================
--- uspace/drv/usbmid/usbmid.h	(revision f3da9b2e921b69b298ae508bcdad240890b6a9f2)
+++ uspace/drv/usbmid/usbmid.h	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
@@ -41,18 +41,7 @@
 #include <usb/pipes.h>
 #include <usb/debug.h>
+#include <usb/devdrv.h>
 
 #define NAME "usbmid"
-
-/** USB MID device container. */
-typedef struct {
-	/** Device container. */
-	ddf_dev_t *dev;
-
-	/** Representation of USB wire. */
-	usb_device_connection_t wire;
-	/** Default control pipe. */
-	usb_pipe_t ctrl_pipe;
-} usbmid_device_t;
-
 
 /** Container for single interface in a MID device. */
@@ -65,8 +54,7 @@
 } usbmid_interface_t;
 
-usbmid_device_t *usbmid_device_create(ddf_dev_t *);
 usbmid_interface_t *usbmid_interface_create(ddf_fun_t *, int);
-bool usbmid_explore_device(usbmid_device_t *);
-int usbmid_spawn_interface_child(usbmid_device_t *,
+bool usbmid_explore_device(usb_device_t *);
+int usbmid_spawn_interface_child(usb_device_t *,
     const usb_standard_device_descriptor_t *,
     const usb_standard_interface_descriptor_t *);
Index: uspace/lib/c/generic/malloc.c
===================================================================
--- uspace/lib/c/generic/malloc.c	(revision f3da9b2e921b69b298ae508bcdad240890b6a9f2)
+++ uspace/lib/c/generic/malloc.c	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
@@ -240,5 +240,5 @@
 	size_t asize = ALIGN_UP(size, PAGE_SIZE);
 	
-	astart = as_area_create(astart, asize, AS_AREA_WRITE | AS_AREA_READ);
+	astart = as_area_create(astart, asize, AS_AREA_WRITE | AS_AREA_READ | AS_AREA_CACHEABLE);
 	if (astart == (void *) -1)
 		return false;
Index: uspace/lib/usb/include/usb/host/device_keeper.h
===================================================================
--- uspace/lib/usb/include/usb/host/device_keeper.h	(revision f3da9b2e921b69b298ae508bcdad240890b6a9f2)
+++ uspace/lib/usb/include/usb/host/device_keeper.h	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
@@ -51,4 +51,5 @@
 	usb_speed_t speed;
 	bool occupied;
+	bool control_used;
 	uint16_t toggle_status[2];
 	devman_handle_t handle;
@@ -61,5 +62,5 @@
 	struct usb_device_info devices[USB_ADDRESS_COUNT];
 	fibril_mutex_t guard;
-	fibril_condvar_t default_address_occupied;
+	fibril_condvar_t change;
 	usb_address_t last_address;
 } usb_device_keeper_t;
@@ -97,4 +98,10 @@
     usb_address_t address);
 
+void usb_device_keeper_use_control(usb_device_keeper_t *instance,
+    usb_address_t address);
+
+void usb_device_keeper_release_control(usb_device_keeper_t *instance,
+    usb_address_t address);
+
 #endif
 /**
Index: uspace/lib/usb/src/host/device_keeper.c
===================================================================
--- uspace/lib/usb/src/host/device_keeper.c	(revision f3da9b2e921b69b298ae508bcdad240890b6a9f2)
+++ uspace/lib/usb/src/host/device_keeper.c	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
@@ -49,9 +49,10 @@
 	assert(instance);
 	fibril_mutex_initialize(&instance->guard);
-	fibril_condvar_initialize(&instance->default_address_occupied);
+	fibril_condvar_initialize(&instance->change);
 	instance->last_address = 0;
 	unsigned i = 0;
 	for (; i < USB_ADDRESS_COUNT; ++i) {
 		instance->devices[i].occupied = false;
+		instance->devices[i].control_used = false;
 		instance->devices[i].handle = 0;
 		instance->devices[i].toggle_status[0] = 0;
@@ -71,6 +72,5 @@
 	fibril_mutex_lock(&instance->guard);
 	while (instance->devices[USB_ADDRESS_DEFAULT].occupied) {
-		fibril_condvar_wait(&instance->default_address_occupied,
-		    &instance->guard);
+		fibril_condvar_wait(&instance->change, &instance->guard);
 	}
 	instance->devices[USB_ADDRESS_DEFAULT].occupied = true;
@@ -90,5 +90,5 @@
 	instance->devices[USB_ADDRESS_DEFAULT].occupied = false;
 	fibril_mutex_unlock(&instance->guard);
-	fibril_condvar_signal(&instance->default_address_occupied);
+	fibril_condvar_signal(&instance->change);
 }
 /*----------------------------------------------------------------------------*/
@@ -309,5 +309,26 @@
 	return instance->devices[address].speed;
 }
-
+/*----------------------------------------------------------------------------*/
+void usb_device_keeper_use_control(usb_device_keeper_t *instance,
+    usb_address_t address)
+{
+	assert(instance);
+	fibril_mutex_lock(&instance->guard);
+	while (instance->devices[address].control_used) {
+		fibril_condvar_wait(&instance->change, &instance->guard);
+	}
+	instance->devices[address].control_used = true;
+	fibril_mutex_unlock(&instance->guard);
+}
+/*----------------------------------------------------------------------------*/
+void usb_device_keeper_release_control(usb_device_keeper_t *instance,
+    usb_address_t address)
+{
+	assert(instance);
+	fibril_mutex_lock(&instance->guard);
+	instance->devices[address].control_used = false;
+	fibril_mutex_unlock(&instance->guard);
+	fibril_condvar_signal(&instance->change);
+}
 /**
  * @}
